mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-02 14:36:17 +00:00
Migrate to HTMX (#114)
Dropped Livewire Added HTMX Added Blade code lint Drop Mysql and Redis Migrate to SQLite
This commit is contained in:
File diff suppressed because one or more lines are too long
@ -1,7 +1,9 @@
|
||||
@props(['status'])
|
||||
@props([
|
||||
"status",
|
||||
])
|
||||
|
||||
@if ($status)
|
||||
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}>
|
||||
<div {{ $attributes->merge(["class" => "font-medium text-sm text-green-600 dark:text-green-400"]) }}>
|
||||
{{ $status }}
|
||||
</div>
|
||||
@endif
|
||||
|
@ -1,12 +1,12 @@
|
||||
<div class="mb-6 @if(isset($aside)) flex justify-between @endif">
|
||||
<div class="@if(isset($aside)) flex justify-between @endif mb-6">
|
||||
<div>
|
||||
@if(isset($title))
|
||||
@if (isset($title))
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-300">
|
||||
{{ $title }}
|
||||
</h3>
|
||||
@endif
|
||||
|
||||
@if(isset($description))
|
||||
@if (isset($description))
|
||||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ $description }}
|
||||
</p>
|
||||
@ -14,7 +14,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@if(isset($aside))
|
||||
@if (isset($aside))
|
||||
{{ $aside }}
|
||||
@endif
|
||||
</div>
|
||||
|
@ -1,23 +1,29 @@
|
||||
<div class="mx-auto mb-10">
|
||||
<x-card-header>
|
||||
@if(isset($title))
|
||||
@if (isset($title))
|
||||
<x-slot name="title">{{ $title }}</x-slot>
|
||||
@endif
|
||||
@if(isset($description))
|
||||
|
||||
@if (isset($description))
|
||||
<x-slot name="description">{{ $description }}</x-slot>
|
||||
@endif
|
||||
@if(isset($aside))
|
||||
|
||||
@if (isset($aside))
|
||||
<x-slot name="aside">{{ $aside }}</x-slot>
|
||||
@endif
|
||||
</x-card-header>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="bg-white px-4 py-5 dark:bg-gray-800 sm:p-6 border border-gray-200 dark:border-gray-700 {{ isset($actions) ? 'sm:rounded-tl-md sm:rounded-tr-md': 'sm:rounded-md' }}">
|
||||
<div
|
||||
class="{{ isset($actions) ? "sm:rounded-tl-md sm:rounded-tr-md" : "sm:rounded-md" }} border border-gray-200 bg-white px-4 py-5 dark:border-gray-700 dark:bg-gray-800 sm:p-6"
|
||||
>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
||||
@if(isset($actions))
|
||||
<div class="flex items-center justify-end bg-gray-50 border border-r border-b border-l border-t-transparent dark:border-t-transparent border-gray-200 dark:border-gray-700 px-4 py-3 text-right dark:bg-gray-800 dark:bg-opacity-70 sm:rounded-bl-md sm:rounded-br-md sm:px-6">
|
||||
@if (isset($actions))
|
||||
<div
|
||||
class="flex items-center justify-end border border-b border-l border-r border-gray-200 border-t-transparent bg-gray-50 px-4 py-3 text-right dark:border-gray-700 dark:border-t-transparent dark:bg-gray-800 dark:bg-opacity-70 sm:rounded-bl-md sm:rounded-br-md sm:px-6"
|
||||
>
|
||||
{{ $actions }}
|
||||
</div>
|
||||
@endif
|
||||
|
@ -1,18 +0,0 @@
|
||||
@props(['name', 'input', 'title', 'description', 'method'])
|
||||
|
||||
<x-modal :name="$name">
|
||||
<form wire:submit="{{ $method }}" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Confirm') }}
|
||||
</h2>
|
||||
<p>{{ $description }}</p>
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
<x-danger-button class="ml-3" @confirmed.window="$dispatch('close')" wire:loading.attr="disabled">
|
||||
{{ __('Confirm') }}
|
||||
</x-danger-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
32
resources/views/components/confirmation-modal.blade.php
Normal file
32
resources/views/components/confirmation-modal.blade.php
Normal file
@ -0,0 +1,32 @@
|
||||
@props([
|
||||
"name",
|
||||
"title",
|
||||
"description",
|
||||
"method",
|
||||
"action" => "",
|
||||
])
|
||||
|
||||
<x-modal :name="$name">
|
||||
<form
|
||||
id="{{ $name }}-form"
|
||||
method="post"
|
||||
action="{{ $action }}"
|
||||
{{ $attributes }}
|
||||
class="p-6"
|
||||
>
|
||||
@csrf
|
||||
@method($method)
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __("Confirm") }}
|
||||
</h2>
|
||||
<p>{{ $description }}</p>
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __("Cancel") }}
|
||||
</x-secondary-button>
|
||||
<x-danger-button class="ml-3">
|
||||
{{ __("Confirm") }}
|
||||
</x-danger-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
@ -1,3 +1,5 @@
|
||||
<div class="h-96 w-full overflow-auto whitespace-pre-line rounded-md border border-gray-200 bg-gray-900 p-5 text-gray-50 dark:border-gray-800">
|
||||
<div
|
||||
class="h-96 w-full overflow-auto whitespace-pre-line rounded-md border border-gray-200 bg-gray-900 p-5 text-gray-50 dark:border-gray-800"
|
||||
>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
@ -1,3 +1,3 @@
|
||||
<div {!! $attributes->merge(['class' => 'py-12 max-w-7xl mx-auto px-6']) !!}>
|
||||
<div {!! $attributes->merge(["class" => "py-12 max-w-7xl mx-auto px-6"]) !!}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
@ -1,3 +1,5 @@
|
||||
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex w-max items-center justify-center rounded-md border border-transparent bg-red-600 px-4 py-1 h-9 font-semibold capitalize text-white transition hover:bg-red-500 focus:border-red-700 focus:outline-none focus:ring focus:ring-red-200 active:bg-red-600 disabled:opacity-25']) }}>
|
||||
<button
|
||||
{{ $attributes->merge(["type" => "submit", "class" => "inline-flex w-max items-center justify-center rounded-md border border-transparent bg-red-600 px-4 py-1 h-9 font-semibold capitalize text-white transition hover:bg-red-500 focus:border-red-700 focus:outline-none focus:ring focus:ring-red-200 active:bg-red-600 disabled:opacity-25"]) }}
|
||||
>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
|
@ -1,3 +1,5 @@
|
||||
@props(['value'])
|
||||
@props([
|
||||
"value",
|
||||
])
|
||||
|
||||
{{ date_with_timezone($value, auth()->user()->timezone) }}
|
||||
|
@ -1 +1,5 @@
|
||||
<a {{ $attributes->merge(['class' => 'block w-full px-4 py-2 text-left text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-700 transition duration-150 ease-in-out flex items-center justify-start']) }}>{{ $slot }}</a>
|
||||
<a
|
||||
{{ $attributes->merge(["class" => "block w-full px-4 py-2 text-left text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-700 transition duration-150 ease-in-out flex items-center justify-start"]) }}
|
||||
>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
|
@ -1,27 +1,27 @@
|
||||
@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white dark:bg-gray-800'])
|
||||
@props(["align" => "right", "width" => "48", "contentClasses" => "bg-white py-1 dark:bg-gray-800"])
|
||||
|
||||
@php
|
||||
switch ($align) {
|
||||
case 'left':
|
||||
$alignmentClasses = 'origin-top-left left-0';
|
||||
break;
|
||||
case 'top':
|
||||
$alignmentClasses = 'origin-top';
|
||||
break;
|
||||
case 'right':
|
||||
default:
|
||||
$alignmentClasses = 'origin-top-right right-0';
|
||||
break;
|
||||
}
|
||||
switch ($align) {
|
||||
case "left":
|
||||
$alignmentClasses = "left-0 origin-top-left";
|
||||
break;
|
||||
case "top":
|
||||
$alignmentClasses = "origin-top";
|
||||
break;
|
||||
case "right":
|
||||
default:
|
||||
$alignmentClasses = "right-0 origin-top-right";
|
||||
break;
|
||||
}
|
||||
|
||||
switch ($width) {
|
||||
case '48':
|
||||
$width = 'w-48';
|
||||
break;
|
||||
case 'full':
|
||||
$width = 'w-full';
|
||||
break;
|
||||
}
|
||||
switch ($width) {
|
||||
case "48":
|
||||
$width = "w-48";
|
||||
break;
|
||||
case "full":
|
||||
$width = "w-full";
|
||||
break;
|
||||
}
|
||||
@endphp
|
||||
|
||||
<div class="relative" x-data="{ open: false }" @click.outside="open = false" @close.stop="open = false">
|
||||
@ -29,17 +29,19 @@
|
||||
{{ $trigger }}
|
||||
</div>
|
||||
|
||||
<div x-show="open"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="transform opacity-0 scale-95"
|
||||
x-transition:enter-end="transform opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-75"
|
||||
x-transition:leave-start="transform opacity-100 scale-100"
|
||||
x-transition:leave-end="transform opacity-0 scale-95"
|
||||
class="absolute z-50 mt-2 {{ $width }} rounded-md shadow-lg {{ $alignmentClasses }}"
|
||||
style="display: none;"
|
||||
@click="open = false">
|
||||
<div class="rounded-md ring-1 ring-black ring-opacity-5 {{ $contentClasses }}">
|
||||
<div
|
||||
x-show="open"
|
||||
x-transition:enter="transition duration-200 ease-out"
|
||||
x-transition:enter-start="scale-95 transform opacity-0"
|
||||
x-transition:enter-end="scale-100 transform opacity-100"
|
||||
x-transition:leave="transition duration-75 ease-in"
|
||||
x-transition:leave-start="scale-100 transform opacity-100"
|
||||
x-transition:leave-end="scale-95 transform opacity-0"
|
||||
class="{{ $width }} {{ $alignmentClasses }} absolute z-50 mt-2 rounded-md shadow-lg"
|
||||
style="display: none"
|
||||
@click="open = false"
|
||||
>
|
||||
<div class="{{ $contentClasses }} rounded-md ring-1 ring-black ring-opacity-5">
|
||||
{{ $content }}
|
||||
</div>
|
||||
</div>
|
||||
|
48
resources/views/components/htmx-error-handler.blade.php
Normal file
48
resources/views/components/htmx-error-handler.blade.php
Normal file
@ -0,0 +1,48 @@
|
||||
<div>
|
||||
<style>
|
||||
#htmx-error-modal-backdrop {
|
||||
display: none; /* Hide by default */
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
|
||||
}
|
||||
#htmx-error-modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 50px auto; /* 200px from the top and centered */
|
||||
padding: 0;
|
||||
width: calc(100% - 100px); /* Full width minus the margin */
|
||||
height: calc(100% - 100px); /* Full height minus the margin */
|
||||
position: relative;
|
||||
}
|
||||
#htmx-error-modal-content iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
<div id="htmx-error-modal-backdrop" onclick="closeHtmxErrorModal()">
|
||||
<div id="htmx-error-modal-content" onclick="event.stopPropagation()"></div>
|
||||
</div>
|
||||
<script>
|
||||
function closeHtmxErrorModal() {
|
||||
document.getElementById('htmx-error-modal-backdrop').style.display = 'none';
|
||||
document.getElementById('htmx-error-modal-content').innerHTML = '';
|
||||
}
|
||||
document.body.addEventListener('htmx:beforeOnLoad', function (evt) {
|
||||
if (evt.detail.xhr.status >= 400) {
|
||||
let iframe = document.createElement('iframe');
|
||||
document.getElementById('htmx-error-modal-content').appendChild(iframe);
|
||||
iframe.src = 'about:blank';
|
||||
iframe.contentWindow.document.open();
|
||||
iframe.contentWindow.document.write(evt.detail.xhr.responseText);
|
||||
iframe.contentWindow.document.close();
|
||||
document.getElementById('htmx-error-modal-backdrop').style.display = 'block';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</div>
|
@ -1,15 +1,18 @@
|
||||
@props(['href'])
|
||||
@props([
|
||||
"href",
|
||||
])
|
||||
|
||||
@php
|
||||
$class = 'w-max inline-flex items-center justify-center px-2 py-1 font-semibold capitalize transition hover:opacity-50 outline-0 focus:ring focus:ring-primary-200 disabled:opacity-25 dark:focus:ring-primary-700 dark:focus:ring-opacity-40';
|
||||
$class =
|
||||
"inline-flex w-max items-center justify-center px-2 py-1 font-semibold capitalize outline-0 transition hover:opacity-50 focus:ring focus:ring-primary-200 disabled:opacity-25 dark:focus:ring-primary-700 dark:focus:ring-opacity-40";
|
||||
@endphp
|
||||
|
||||
@if(isset($href))
|
||||
<a href="{{ $href }}" {{ $attributes->merge(['class' => $class]) }}>
|
||||
@if (isset($href))
|
||||
<a href="{{ $href }}" {{ $attributes->merge(["class" => $class]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
@else
|
||||
<button {{ $attributes->merge(['type' => 'submit', 'class' => $class]) }}>
|
||||
<button {{ $attributes->merge(["type" => "submit", "class" => $class]) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
@endif
|
||||
|
@ -1,7 +1,9 @@
|
||||
@props(['messages'])
|
||||
@props([
|
||||
"messages",
|
||||
])
|
||||
|
||||
@if ($messages)
|
||||
<ul {{ $attributes->merge(['class' => 'text-sm text-red-600 dark:text-red-400 space-y-1']) }}>
|
||||
<ul {{ $attributes->merge(["class" => "text-sm text-red-600 dark:text-red-400 space-y-1"]) }}>
|
||||
@foreach ((array) $messages as $message)
|
||||
<li>{{ $message }}</li>
|
||||
@endforeach
|
||||
|
@ -1 +1,5 @@
|
||||
<p {{ $attributes->merge(['class' => 'mt-2 text-sm text-gray-500 dark:text-gray-300']) }}>{{ $slot }}</p>
|
||||
<p
|
||||
{{ $attributes->merge(["class" => "mt-2 text-sm text-gray-500 dark:text-gray-300"]) }}
|
||||
>
|
||||
{{ $slot }}
|
||||
</p>
|
||||
|
@ -1,5 +1,9 @@
|
||||
@props(['value'])
|
||||
@props([
|
||||
"value",
|
||||
])
|
||||
|
||||
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-700 dark:text-gray-300']) }}>
|
||||
<label
|
||||
{{ $attributes->merge(["class" => "block font-medium text-sm text-gray-700 dark:text-gray-300"]) }}
|
||||
>
|
||||
{{ $value ?? $slot }}
|
||||
</label>
|
||||
|
@ -1,3 +1,5 @@
|
||||
<div class="rounded-t-md rounded-b-md flex h-20 items-center justify-between border border-gray-200 bg-white p-7 text-center dark:border-gray-700 dark:bg-gray-800">
|
||||
<div
|
||||
class="flex h-20 items-center justify-between rounded-b-md rounded-t-md border border-gray-200 bg-white p-7 text-center dark:border-gray-700 dark:bg-gray-800"
|
||||
>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
14
resources/views/components/live.blade.php
Normal file
14
resources/views/components/live.blade.php
Normal file
@ -0,0 +1,14 @@
|
||||
@props([
|
||||
"interval" => "30s",
|
||||
"id",
|
||||
])
|
||||
|
||||
<div
|
||||
id="{{ $id }}"
|
||||
hx-get="{{ request()->getUri() }}"
|
||||
hx-trigger="every {{ $interval }}"
|
||||
hx-select="#{{ $id }}"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
{{ $slot }}
|
||||
</div>
|
@ -1,19 +1,19 @@
|
||||
@props([
|
||||
'name',
|
||||
'show' => false,
|
||||
'maxWidth' => '2xl'
|
||||
"name",
|
||||
"show" => false,
|
||||
"maxWidth" => "2xl",
|
||||
])
|
||||
|
||||
@php
|
||||
$maxWidth = [
|
||||
'sm' => 'sm:max-w-sm',
|
||||
'md' => 'sm:max-w-md',
|
||||
'lg' => 'sm:max-w-lg',
|
||||
'xl' => 'sm:max-w-xl',
|
||||
'2xl' => 'sm:max-w-2xl',
|
||||
'3xl' => 'sm:max-w-3xl',
|
||||
'4xl' => 'sm:max-w-4xl',
|
||||
][$maxWidth];
|
||||
$maxWidth = [
|
||||
"sm" => "sm:max-w-sm",
|
||||
"md" => "sm:max-w-md",
|
||||
"lg" => "sm:max-w-lg",
|
||||
"xl" => "sm:max-w-xl",
|
||||
"2xl" => "sm:max-w-2xl",
|
||||
"3xl" => "sm:max-w-3xl",
|
||||
"4xl" => "sm:max-w-4xl",
|
||||
][$maxWidth];
|
||||
@endphp
|
||||
|
||||
<div
|
||||
@ -33,47 +33,49 @@
|
||||
nextFocusableIndex() { return (this.focusables().indexOf(document.activeElement) + 1) % (this.focusables().length + 1) },
|
||||
prevFocusableIndex() { return Math.max(0, this.focusables().indexOf(document.activeElement)) -1 },
|
||||
}"
|
||||
x-init="$watch('show', value => {
|
||||
if (value) {
|
||||
document.body.classList.add('overflow-y-hidden');
|
||||
{{ $attributes->has('focusable') ? 'setTimeout(() => firstFocusable().focus(), 100)' : '' }}
|
||||
} else {
|
||||
document.body.classList.remove('overflow-y-hidden');
|
||||
}
|
||||
})"
|
||||
x-on:open-modal.window="$event.detail == '{{ $name }}' ? show = true : null"
|
||||
x-on:close-modal.window="$event.detail == '{{ $name }}' ? show = false : null"
|
||||
x-init="
|
||||
$watch('show', (value) => {
|
||||
if (value) {
|
||||
document.body.classList.add('overflow-y-hidden')
|
||||
{{ $attributes->has("focusable") ? "setTimeout(() => firstFocusable().focus(), 100)" : "" }}
|
||||
} else {
|
||||
document.body.classList.remove('overflow-y-hidden')
|
||||
}
|
||||
})
|
||||
"
|
||||
x-on:open-modal.window="$event.detail == '{{ $name }}' ? (show = true) : null"
|
||||
x-on:close-modal.window="$event.detail == '{{ $name }}' ? (show = false) : null"
|
||||
x-on:close.stop="show = false"
|
||||
x-on:keydown.escape.window="show = false"
|
||||
x-on:keydown.tab.prevent="$event.shiftKey || nextFocusable().focus()"
|
||||
x-on:keydown.shift.tab.prevent="prevFocusable().focus()"
|
||||
x-show="show"
|
||||
class="fixed inset-0 overflow-y-auto px-4 py-6 sm:px-0 z-50"
|
||||
style="display: {{ $show ? 'block' : 'none' }};"
|
||||
class="fixed inset-0 z-50 overflow-y-auto px-4 py-6 sm:px-0"
|
||||
style="display: {{ $show ? "block" : "none" }}"
|
||||
>
|
||||
<div
|
||||
x-show="show"
|
||||
class="fixed inset-0 transform transition-all"
|
||||
x-on:click="show = false"
|
||||
x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter="duration-300 ease-out"
|
||||
x-transition:enter-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="ease-in duration-200"
|
||||
x-transition:leave="duration-200 ease-in"
|
||||
x-transition:leave-start="opacity-100"
|
||||
x-transition:leave-end="opacity-0"
|
||||
>
|
||||
<div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
|
||||
<div class="absolute inset-0 bg-gray-500 opacity-75 dark:bg-gray-900"></div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
x-show="show"
|
||||
class="mb-6 bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
|
||||
x-transition:enter="ease-out duration-300"
|
||||
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave="ease-in duration-200"
|
||||
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
class="{{ $maxWidth }} mb-6 transform overflow-hidden rounded-lg bg-white shadow-xl transition-all dark:bg-gray-800 sm:mx-auto sm:w-full"
|
||||
x-transition:enter="duration-300 ease-out"
|
||||
x-transition:enter-start="translate-y-4 opacity-0 sm:translate-y-0 sm:scale-95"
|
||||
x-transition:enter-end="translate-y-0 opacity-100 sm:scale-100"
|
||||
x-transition:leave="duration-200 ease-in"
|
||||
x-transition:leave-start="translate-y-0 opacity-100 sm:scale-100"
|
||||
x-transition:leave-end="translate-y-4 opacity-0 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
@ -1,11 +1,14 @@
|
||||
@props(['active'])
|
||||
@props([
|
||||
"active",
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = ($active ?? false)
|
||||
? 'px-2 inline-flex items-center px-1 pt-1 border-b-2 border-primary-400 dark:border-primary-600 text-sm font-medium leading-5 text-gray-900 dark:text-gray-100 focus:outline-none focus:border-primary-700 transition duration-150 ease-in-out'
|
||||
: 'px-2 inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-700 focus:outline-none focus:text-gray-700 dark:focus:text-gray-300 focus:border-gray-300 dark:focus:border-gray-700 transition duration-150 ease-in-out';
|
||||
$classes =
|
||||
$active ?? false
|
||||
? "inline-flex items-center border-b-2 border-primary-400 px-1 px-2 pt-1 text-sm font-medium leading-5 text-gray-900 transition duration-150 ease-in-out focus:border-primary-700 focus:outline-none dark:border-primary-600 dark:text-gray-100"
|
||||
: "inline-flex items-center border-b-2 border-transparent px-1 px-2 pt-1 text-sm font-medium leading-5 text-gray-500 transition duration-150 ease-in-out hover:border-gray-300 hover:text-gray-700 focus:border-gray-300 focus:text-gray-700 focus:outline-none dark:text-gray-400 dark:hover:border-gray-700 dark:hover:text-gray-300 dark:focus:border-gray-700 dark:focus:text-gray-300";
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
<a {{ $attributes->merge(["class" => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
|
@ -1,15 +1,18 @@
|
||||
@props(['href'])
|
||||
@props([
|
||||
"href",
|
||||
])
|
||||
|
||||
@php
|
||||
$class = 'w-max inline-flex items-center justify-center rounded-md border border-transparent bg-primary-600 px-4 py-1 h-9 font-semibold text-white transition hover:bg-primary-700 focus:border-primary-700 focus:border-primary-300 outline-0 focus:ring focus:ring-primary-200 focus:ring-opacity-50 active:bg-primary-700 disabled:opacity-25 dark:focus:border-primary-700 dark:focus:ring-primary-700 dark:focus:ring-opacity-40';
|
||||
$class =
|
||||
"inline-flex h-9 w-max items-center justify-center rounded-md border border-transparent bg-primary-600 px-4 py-1 font-semibold text-white outline-0 transition hover:bg-primary-700 focus:border-primary-300 focus:border-primary-700 focus:ring focus:ring-primary-200 focus:ring-opacity-50 active:bg-primary-700 disabled:opacity-25 dark:focus:border-primary-700 dark:focus:ring-primary-700 dark:focus:ring-opacity-40";
|
||||
@endphp
|
||||
|
||||
@if(isset($href))
|
||||
<button onclick="location.href = '{{ $href }}'" {{ $attributes->merge(['class' => $class]) }}>
|
||||
@if (isset($href))
|
||||
<button onclick="location.href = '{{ $href }}'" {{ $attributes->merge(["class" => $class]) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
@else
|
||||
<button {{ $attributes->merge(['type' => 'submit', 'class' => $class]) }}>
|
||||
<button {{ $attributes->merge(["type" => "submit", "class" => $class]) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
@endif
|
||||
|
@ -1,11 +1,14 @@
|
||||
@props(['active'])
|
||||
@props([
|
||||
"active",
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = ($active ?? false)
|
||||
? 'block w-full pl-3 pr-4 py-2 border-l-4 border-primary-400 dark:border-primary-600 text-left text-base font-medium text-primary-700 dark:text-primary-300 bg-primary-50 dark:bg-primary-900/50 focus:outline-none focus:text-primary-800 dark:focus:text-primary-200 focus:bg-primary-100 dark:focus:bg-primary-900 focus:border-primary-700 dark:focus:border-primary-300 transition duration-150 ease-in-out'
|
||||
: 'block w-full pl-3 pr-4 py-2 border-l-4 border-transparent text-left text-base font-medium text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:outline-none focus:text-gray-800 dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600 transition duration-150 ease-in-out';
|
||||
$classes =
|
||||
$active ?? false
|
||||
? "block w-full border-l-4 border-primary-400 bg-primary-50 py-2 pl-3 pr-4 text-left text-base font-medium text-primary-700 transition duration-150 ease-in-out focus:border-primary-700 focus:bg-primary-100 focus:text-primary-800 focus:outline-none dark:border-primary-600 dark:bg-primary-900/50 dark:text-primary-300 dark:focus:border-primary-300 dark:focus:bg-primary-900 dark:focus:text-primary-200"
|
||||
: "block w-full border-l-4 border-transparent py-2 pl-3 pr-4 text-left text-base font-medium text-gray-600 transition duration-150 ease-in-out hover:border-gray-300 hover:bg-gray-50 hover:text-gray-800 focus:border-gray-300 focus:bg-gray-50 focus:text-gray-800 focus:outline-none dark:text-gray-400 dark:hover:border-gray-600 dark:hover:bg-gray-700 dark:hover:text-gray-200 dark:focus:border-gray-600 dark:focus:bg-gray-700 dark:focus:text-gray-200";
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
<a {{ $attributes->merge(["class" => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
|
@ -1,24 +1,31 @@
|
||||
@props(['href', 'type', 'span', 'disabled'])
|
||||
@props([
|
||||
"href",
|
||||
"type",
|
||||
"span",
|
||||
"disabled",
|
||||
])
|
||||
|
||||
@php
|
||||
$class = 'inline-flex items-center px-4 py-1 h-9 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-500 rounded-md font-semibold text-gray-700 dark:text-gray-300 shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 disabled:opacity-25 transition ease-in-out duration-150';
|
||||
$class =
|
||||
"inline-flex h-9 items-center rounded-md border border-gray-300 bg-white px-4 py-1 font-semibold text-gray-700 shadow-sm transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 disabled:opacity-25 dark:border-gray-500 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700 dark:focus:ring-offset-gray-800";
|
||||
@endphp
|
||||
|
||||
@if(isset($href))
|
||||
@if(isset($disabled))
|
||||
@if (isset($href))
|
||||
@if (isset($disabled))
|
||||
@php
|
||||
$class .= ' opacity-25 cursor-default';
|
||||
$class .= " opacity-25 cursor-default";
|
||||
@endphp
|
||||
<span {{ $attributes->merge(['class' => $class]) }}>
|
||||
|
||||
<span {{ $attributes->merge(["class" => $class]) }}>
|
||||
{{ $slot }}
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $href }}" {{ $attributes->merge(['class' => $class]) }}>
|
||||
<a href="{{ $href }}" {{ $attributes->merge(["class" => $class]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
@endif
|
||||
@else
|
||||
<button {{ $attributes->merge(['type' => $type ?? 'submit', 'class' => $class]) }}>
|
||||
<button {{ $attributes->merge(["type" => $type ?? "submit", "class" => $class]) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
@endif
|
||||
|
@ -1,11 +1,14 @@
|
||||
@props(['active'])
|
||||
@props([
|
||||
"active",
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = ($active ?? false)
|
||||
? 'h-10 flex items-center justify-start rounded-lg px-3 py-2 hover:bg-gray-100 dark:hover:bg-gray-800 bg-primary-50 dark:bg-primary-500 dark:bg-opacity-20 text-primary-500 font-semibold'
|
||||
: 'h-10 flex items-center justify-start rounded-lg px-3 py-2 hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-800 dark:text-gray-300 font-semibold';
|
||||
$classes =
|
||||
$active ?? false
|
||||
? "flex h-10 items-center justify-start rounded-lg bg-primary-50 px-3 py-2 font-semibold text-primary-500 hover:bg-gray-100 dark:bg-primary-500 dark:bg-opacity-20 dark:hover:bg-gray-800"
|
||||
: "flex h-10 items-center justify-start rounded-lg px-3 py-2 font-semibold text-gray-800 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800";
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
<a {{ $attributes->merge(["class" => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
|
@ -1,17 +1,23 @@
|
||||
<div {!! $attributes->merge(['class' => 'flex justify-between md:col-span-1 mb-5']) !!}>
|
||||
@if(isset($title) || isset($description))
|
||||
<div
|
||||
{!! $attributes->merge(["class" => "flex justify-between md:col-span-1 mb-5"]) !!}
|
||||
>
|
||||
@if (isset($title) || isset($description))
|
||||
<div>
|
||||
@if(isset($title))
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-300">{{ $title }}</h3>
|
||||
@if (isset($title))
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-300">
|
||||
{{ $title }}
|
||||
</h3>
|
||||
@endif
|
||||
@if(isset($description))
|
||||
|
||||
@if (isset($description))
|
||||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ $description }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
@if(isset($aside))
|
||||
|
||||
@if (isset($aside))
|
||||
<div>
|
||||
{{ $aside }}
|
||||
</div>
|
||||
|
@ -1,5 +1,8 @@
|
||||
@props(['disabled' => false])
|
||||
@props(["disabled" => false])
|
||||
|
||||
<select {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-primary-500 dark:focus:border-primary-600 focus:ring-primary-500 dark:focus:ring-primary-600 rounded-md shadow-sm']) !!}>
|
||||
<select
|
||||
{{ $disabled ? "disabled" : "" }}
|
||||
{!! $attributes->merge(["class" => "border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-primary-500 dark:focus:border-primary-600 focus:ring-primary-500 dark:focus:ring-primary-600 rounded-md shadow-sm"]) !!}
|
||||
>
|
||||
{{ $slot }}
|
||||
</select>
|
||||
|
@ -1,12 +1,16 @@
|
||||
@props(['active'])
|
||||
@props([
|
||||
"active",
|
||||
])
|
||||
|
||||
@php
|
||||
$class = 'flex w-full items-center justify-center rounded-md border-2 bg-primary-50 px-3 pt-3 pb-2 dark:bg-primary-500 dark:bg-opacity-10 cursor-pointer';
|
||||
$classes = ($active ?? false)
|
||||
? $class . ' border-primary-600'
|
||||
: $class . ' border-primary-200 dark:border-primary-600 dark:border-opacity-20'
|
||||
$class =
|
||||
"flex w-full cursor-pointer items-center justify-center rounded-md border-2 bg-primary-50 px-3 pb-2 pt-3 dark:bg-primary-500 dark:bg-opacity-10";
|
||||
$classes =
|
||||
$active ?? false
|
||||
? $class . " border-primary-600"
|
||||
: $class . " border-primary-200 dark:border-primary-600 dark:border-opacity-20"
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->merge(['class' => $classes]) }}>
|
||||
<a {{ $attributes->merge(["class" => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</a>
|
||||
|
@ -1,11 +1,14 @@
|
||||
@props(['active'])
|
||||
@props([
|
||||
"active",
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = ($active ?? false)
|
||||
? 'h-10 rounded-md px-4 py-3 text-md font-semibold flex items-center bg-gray-900 text-primary-500 transition duration-150 ease-in-out transition-all duration-100'
|
||||
: 'h-10 rounded-md px-4 py-3 text-md font-semibold flex items-center text-gray-500 transition duration-150 ease-in-out transition-all duration-100 hover:bg-gray-900';
|
||||
$classes =
|
||||
$active ?? false
|
||||
? "text-md flex h-10 items-center rounded-md bg-gray-900 px-4 py-3 font-semibold text-primary-500 transition transition-all duration-100 duration-150 ease-in-out"
|
||||
: "text-md flex h-10 items-center rounded-md px-4 py-3 font-semibold text-gray-500 transition transition-all duration-100 duration-150 ease-in-out hover:bg-gray-900";
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
<a {{ $attributes->merge(["class" => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
|
@ -1,3 +1,5 @@
|
||||
<div {!! $attributes->merge(['class' => 'bg-white border boarder-gray-200 dark:border-gray-700 dark:bg-gray-800 p-6 rounded-md']) !!}>
|
||||
<div
|
||||
{!! $attributes->merge(["class" => "bg-white border boarder-gray-200 dark:border-gray-700 dark:bg-gray-800 p-6 rounded-md"]) !!}
|
||||
>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
@ -1,12 +1,16 @@
|
||||
@props(['active'])
|
||||
@props([
|
||||
"active",
|
||||
])
|
||||
|
||||
@php
|
||||
$class = 'flex w-full items-center justify-center rounded-md border-2 bg-primary-50 px-3 pt-3 pb-2 dark:bg-primary-500 dark:bg-opacity-10 cursor-pointer';
|
||||
$classes = ($active ?? false)
|
||||
? $class . ' border-primary-600'
|
||||
: $class . ' border-primary-200 dark:border-primary-600 dark:border-opacity-20'
|
||||
$class =
|
||||
"flex w-full cursor-pointer items-center justify-center rounded-md border-2 bg-primary-50 px-3 pb-2 pt-3 dark:bg-primary-500 dark:bg-opacity-10";
|
||||
$classes =
|
||||
$active ?? false
|
||||
? $class . " border-primary-600"
|
||||
: $class . " border-primary-200 dark:border-primary-600 dark:border-opacity-20"
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->merge(['class' => $classes]) }}>
|
||||
<div {{ $attributes->merge(["class" => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
@ -1,4 +1,6 @@
|
||||
@props(['status'])
|
||||
@props([
|
||||
"status",
|
||||
])
|
||||
|
||||
@php
|
||||
$class = [
|
||||
@ -10,6 +12,6 @@
|
||||
];
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->merge(['class' => $class[$status]]) }}>
|
||||
<div {{ $attributes->merge(["class" => $class[$status]]) }}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
@ -1,4 +1,6 @@
|
||||
<div {!! $attributes->merge(['class' => 'inline-block min-w-full overflow-x-auto rounded-md bg-white align-middle border border-gray-200 dark:border-gray-700 dark:bg-gray-800']) !!}>
|
||||
<div
|
||||
{!! $attributes->merge(["class" => "inline-block min-w-full overflow-x-auto rounded-md bg-white align-middle border border-gray-200 dark:border-gray-700 dark:bg-gray-800"]) !!}
|
||||
>
|
||||
<table class="min-w-full">
|
||||
{{ $slot }}
|
||||
</table>
|
||||
|
@ -1,3 +1,5 @@
|
||||
<td {!! $attributes->merge(['class' => 'whitespace-nowrap border-t border-gray-200 px-6 py-4 text-gray-700 dark:border-gray-700 dark:text-gray-300 w-1']) !!}>
|
||||
<td
|
||||
{!! $attributes->merge(["class" => "whitespace-nowrap border-t border-gray-200 px-6 py-4 text-gray-700 dark:border-gray-700 dark:text-gray-300 w-1"]) !!}
|
||||
>
|
||||
{{ $slot }}
|
||||
</td>
|
||||
|
@ -1,3 +1,7 @@
|
||||
@props(['disabled' => false])
|
||||
@props(["disabled" => false])
|
||||
|
||||
<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-primary-500 dark:focus:border-primary-600 focus:ring-primary-500 dark:focus:ring-primary-600 rounded-md shadow-sm']) !!}>
|
||||
<input
|
||||
hx-disable
|
||||
{{ $disabled ? "disabled" : "" }}
|
||||
{!! $attributes->merge(["class" => "border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-primary-500 dark:focus:border-primary-600 focus:ring-primary-500 dark:focus:ring-primary-600 rounded-md shadow-sm"]) !!}
|
||||
/>
|
||||
|
@ -1,3 +1,8 @@
|
||||
@props(['disabled' => false])
|
||||
@props(["disabled" => false])
|
||||
|
||||
<textarea {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-primary-500 dark:focus:border-primary-600 focus:ring-primary-500 dark:focus:ring-primary-600 rounded-md shadow-sm w-full']) !!}>{{ $slot }}</textarea>
|
||||
<textarea
|
||||
{{ $disabled ? "disabled" : "" }}
|
||||
{!! $attributes->merge(["class" => "border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-primary-500 dark:focus:border-primary-600 focus:ring-primary-500 dark:focus:ring-primary-600 rounded-md shadow-sm w-full"]) !!}
|
||||
>
|
||||
{{ $slot }}</textarea
|
||||
>
|
||||
|
@ -1,3 +1,5 @@
|
||||
<th {!! $attributes->merge(['class' => 'whitespace-nowrap bg-gray-50 px-6 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-500 dark:bg-gray-700 dark:text-gray-400']) !!}>
|
||||
<th
|
||||
{!! $attributes->merge(["class" => "whitespace-nowrap bg-gray-50 px-6 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-500 dark:bg-gray-700 dark:text-gray-400"]) !!}
|
||||
>
|
||||
{{ $slot }}
|
||||
</th>
|
||||
|
@ -1,13 +1,16 @@
|
||||
<div>
|
||||
<div id="toast" hx-swap-oob="true">
|
||||
<script>
|
||||
window.addEventListener('toast', (e) => {
|
||||
window.toastr[e.detail.type](e.detail.message)
|
||||
window.toastr[e.detail.type](e.detail.message);
|
||||
});
|
||||
</script>
|
||||
@if(session()->has('toast.type') && session()->has('toast.message'))
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
window.toastr['{{ session()->get('toast.type') }}']('{{ session()->get('toast.message') }}');
|
||||
@if (session()->has("toast.type") && session()->has("toast.message"))
|
||||
<script defer>
|
||||
if (window.toastr) {
|
||||
window.toastr['{{ session()->get("toast.type") }}']('{{ session()->get("toast.message") }}');
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.toastr['{{ session()->get("toast.type") }}']('{{ session()->get("toast.message") }}');
|
||||
});
|
||||
</script>
|
||||
@endif
|
||||
|
42
resources/views/components/user-dropdown.blade.php
Normal file
42
resources/views/components/user-dropdown.blade.php
Normal file
@ -0,0 +1,42 @@
|
||||
<div class="flex items-center text-gray-600 dark:text-gray-300">
|
||||
<x-dropdown align="right" width="48">
|
||||
<x-slot name="trigger">
|
||||
<button class="flex items-center">
|
||||
<x-heroicon-o-cog-6-tooth class="h-7 w-7" />
|
||||
</button>
|
||||
</x-slot>
|
||||
<x-slot name="content">
|
||||
<x-dropdown-link :href="route('profile')">
|
||||
{{ __("Profile") }}
|
||||
</x-dropdown-link>
|
||||
<x-dropdown-link :href="route('projects')">
|
||||
{{ __("Projects") }}
|
||||
</x-dropdown-link>
|
||||
<x-dropdown-link :href="route('server-providers')">
|
||||
{{ __("Server Providers") }}
|
||||
</x-dropdown-link>
|
||||
<x-dropdown-link :href="route('source-controls')">
|
||||
{{ __("Source Controls") }}
|
||||
</x-dropdown-link>
|
||||
<x-dropdown-link :href="route('storage-providers')">
|
||||
{{ __("Storage Providers") }}
|
||||
</x-dropdown-link>
|
||||
<x-dropdown-link :href="route('notification-channels')">
|
||||
{{ __("Notification Channels") }}
|
||||
</x-dropdown-link>
|
||||
<x-dropdown-link :href="route('ssh-keys')">
|
||||
{{ __("SSH Keys") }}
|
||||
</x-dropdown-link>
|
||||
<!-- Authentication -->
|
||||
<form method="POST" action="{{ route("logout") }}">
|
||||
@csrf
|
||||
<x-dropdown-link
|
||||
:href="route('logout')"
|
||||
onclick="event.preventDefault(); this.closest('form').submit();"
|
||||
>
|
||||
{{ __("Log Out") }}
|
||||
</x-dropdown-link>
|
||||
</form>
|
||||
</x-slot>
|
||||
</x-dropdown>
|
||||
</div>
|
Reference in New Issue
Block a user