mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-07 00:42:34 +00:00
Setup Inertia (#593)
This commit is contained in:
50
resources/views/app.blade.php
Normal file
50
resources/views/app.blade.php
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" @class(['dark' => ($appearance ?? 'system') == 'dark'])>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
{{-- Inline script to detect system dark mode preference and apply it immediately --}}
|
||||
<script>
|
||||
(function () {
|
||||
const appearance = '{{ $appearance ?? 'system' }}';
|
||||
|
||||
if (appearance === 'system') {
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
|
||||
if (prefersDark) {
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
{{-- Inline style to set the HTML background color based on our theme in app.css --}}
|
||||
<style>
|
||||
html {
|
||||
background-color: oklch(1 0 0);
|
||||
}
|
||||
|
||||
html.dark {
|
||||
background-color: oklch(0.145 0 0);
|
||||
}
|
||||
</style>
|
||||
|
||||
<title inertia>{{ config('app.name', 'Laravel') }}</title>
|
||||
|
||||
<link rel="icon" href="/favicon.ico" sizes="any" />
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
|
||||
<link rel="preconnect" href="https://fonts.bunny.net" />
|
||||
<link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600" rel="stylesheet" />
|
||||
|
||||
@routes
|
||||
@viteReactRefresh
|
||||
@vite(['resources/js/app.tsx', "resources/js/pages/{$page['component']}.tsx"])
|
||||
@inertiaHead
|
||||
</head>
|
||||
<body class="font-sans antialiased">
|
||||
@inertia
|
||||
</body>
|
||||
</html>
|
@ -1,5 +0,0 @@
|
||||
<div class="p-6 text-xs">
|
||||
<a href="https://github.com/vitodeploy/vito/releases/tag/{{ config("app.version") }}" target="_blank">
|
||||
V{{ show_vito_version() }}
|
||||
</a>
|
||||
</div>
|
@ -1,39 +0,0 @@
|
||||
<svg class="w-[30px] rounded-md" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="1024" height="1024" rx="50" fill="#312E81" />
|
||||
<rect width="1024" height="1024" rx="50" fill="url(#paint0_linear_29_4)" />
|
||||
<g filter="url(#filter0_d_29_4)">
|
||||
<path
|
||||
d="M512.206 814.3C500.806 814.3 491.506 811.6 484.306 806.2C477.106 800.8 471.406 792.7 467.206 781.9L219.706 215.8C215.506 205.6 214.306 197.2 216.106 190.6C217.906 183.4 221.806 177.7 227.806 173.5C234.406 169.3 241.906 167.2 250.306 167.2C261.706 167.2 270.106 169.9 275.506 175.3C281.506 180.1 286.306 187.3 289.906 196.9L527.506 748.6H498.706L735.406 196C739.606 187 744.706 180.1 750.706 175.3C756.706 169.9 765.106 167.2 775.906 167.2C784.306 167.2 791.206 169.3 796.606 173.5C802.606 177.7 806.206 183.4 807.406 190.6C809.206 197.8 808.006 206.2 803.806 215.8L556.306 781.9C552.106 792.7 546.406 800.8 539.206 806.2C532.606 811.6 523.606 814.3 512.206 814.3Z"
|
||||
fill="white"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter
|
||||
id="filter0_d_29_4"
|
||||
x="209.406"
|
||||
y="167.2"
|
||||
width="604.7"
|
||||
height="655.1"
|
||||
filterUnits="userSpaceOnUse"
|
||||
color-interpolation-filters="sRGB"
|
||||
>
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix" />
|
||||
<feColorMatrix
|
||||
in="SourceAlpha"
|
||||
type="matrix"
|
||||
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||
result="hardAlpha"
|
||||
/>
|
||||
<feOffset dy="4" />
|
||||
<feGaussianBlur stdDeviation="2" />
|
||||
<feComposite in2="hardAlpha" operator="out" />
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0" />
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_29_4" />
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_29_4" result="shape" />
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_29_4" x1="512" y1="0" x2="512" y2="1024" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#6366F1" />
|
||||
<stop offset="1" stop-color="#393B8B" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.2 KiB |
@ -1,5 +0,0 @@
|
||||
<div
|
||||
{{ $attributes->merge(["class" => "font-mono relative h-[500px] w-full overflow-auto whitespace-pre-line rounded-xl border border-gray-200 bg-black p-5 text-gray-50 dark:border-gray-800"]) }}
|
||||
>
|
||||
{{ $slot }}
|
||||
</div>
|
@ -1,166 +0,0 @@
|
||||
<div
|
||||
x-data="{
|
||||
user: '{{ $server->ssh_user }}',
|
||||
running: false,
|
||||
dir: '{{ cache()->get("console.$server->id.dir", "~") }}',
|
||||
command: '',
|
||||
output: '',
|
||||
serverName: '{{ $server->name }}',
|
||||
shellPrefix: '',
|
||||
clearAfterCommand: false,
|
||||
runUrl: '{{ route("servers.console.run", ["server" => $server]) }}',
|
||||
init() {
|
||||
this.setShellPrefix()
|
||||
$watch('user', async (value) => {
|
||||
await this.getWorkingDir()
|
||||
})
|
||||
const consoleOutput = document.getElementById('console-output')
|
||||
consoleOutput.addEventListener('mouseup', (event) => {
|
||||
if (window.getSelection()?.toString()) {
|
||||
return
|
||||
}
|
||||
this.focusCommand()
|
||||
})
|
||||
this.focusCommand()
|
||||
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.ctrlKey && event.key === 'l') {
|
||||
event.preventDefault()
|
||||
if (this.running) return
|
||||
this.output = ''
|
||||
}
|
||||
})
|
||||
},
|
||||
async run() {
|
||||
if (! this.command) return
|
||||
this.running = true
|
||||
let output = this.shellPrefix + ' ' + this.command + '\n'
|
||||
if (this.clearAfterCommand) {
|
||||
this.output = output
|
||||
} else {
|
||||
this.output += output
|
||||
}
|
||||
setTimeout(() => {
|
||||
document.getElementById('console-output').scrollTop =
|
||||
document.getElementById('console-output').scrollHeight
|
||||
}, 100)
|
||||
const fetchOptions = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
user: this.user,
|
||||
command: this.command,
|
||||
}),
|
||||
}
|
||||
|
||||
this.command = ''
|
||||
const response = await fetch(this.runUrl, fetchOptions)
|
||||
const reader = response.body.getReader()
|
||||
const decoder = new TextDecoder('utf-8')
|
||||
this.setShellPrefix()
|
||||
|
||||
while (true) {
|
||||
if (! this.running) {
|
||||
reader.cancel()
|
||||
this.output += '\nStopped!'
|
||||
break
|
||||
}
|
||||
const { value, done } = await reader.read()
|
||||
if (done) break
|
||||
|
||||
const textChunk = decoder.decode(value, { stream: true })
|
||||
|
||||
this.output += textChunk
|
||||
|
||||
setTimeout(() => {
|
||||
document.getElementById('console-output').scrollTop =
|
||||
document.getElementById('console-output').scrollHeight
|
||||
}, 100)
|
||||
}
|
||||
this.output += '\n'
|
||||
await this.getWorkingDir()
|
||||
this.running = false
|
||||
setTimeout(() => {
|
||||
document.getElementById('command').focus()
|
||||
}, 100)
|
||||
},
|
||||
stop() {
|
||||
this.running = false
|
||||
},
|
||||
setShellPrefix() {
|
||||
this.shellPrefix = `${this.user}@${this.serverName}:${this.dir}$`
|
||||
},
|
||||
focusCommand() {
|
||||
document.getElementById('command').focus()
|
||||
},
|
||||
async getWorkingDir() {
|
||||
const response = await fetch(
|
||||
'{{ route("servers.console.working-dir", ["server" => $server]) }}',
|
||||
)
|
||||
if (response.ok) {
|
||||
const data = await response.json()
|
||||
this.dir = data.dir
|
||||
this.setShellPrefix()
|
||||
}
|
||||
},
|
||||
}"
|
||||
>
|
||||
<div class="relative">
|
||||
<form class="flex items-center justify-between">
|
||||
<x-filament::input.wrapper>
|
||||
<x-filament::input.select id="user" name="user" x-model="user" class="w-full" x-bind:disabled="running">
|
||||
@foreach ($server->getSshUsers() as $user)
|
||||
<option value="{{ $user }}">{{ $user }}</option>
|
||||
@endforeach
|
||||
</x-filament::input.select>
|
||||
</x-filament::input.wrapper>
|
||||
<div class="flex items-center">
|
||||
<x-filament::button
|
||||
color="gray"
|
||||
type="button"
|
||||
x-on:click="output = ''"
|
||||
icon="heroicon-o-trash"
|
||||
tooltip="Clear"
|
||||
x-show="!running"
|
||||
>
|
||||
Clear
|
||||
</x-filament::button>
|
||||
<x-filament::button
|
||||
color="gray"
|
||||
type="button"
|
||||
id="btn-stop"
|
||||
x-on:click="stop"
|
||||
x-show="running"
|
||||
icon="heroicon-o-stop"
|
||||
tooltip="Stop"
|
||||
class="ml-2"
|
||||
>
|
||||
Stop
|
||||
</x-filament::button>
|
||||
</div>
|
||||
</form>
|
||||
<x-console-view id="console-output" class="mt-5">
|
||||
<div class="w-full" x-text="output"></div>
|
||||
</x-console-view>
|
||||
<div
|
||||
class="relative -mt-5 flex h-[50px] w-full items-center rounded-b-xl border-b border-l border-r border-gray-200 bg-black px-5 font-mono text-gray-50 dark:border-gray-800"
|
||||
>
|
||||
<form class="flex w-full items-center" x-show="!running" onsubmit="return false" id="console-form">
|
||||
<div x-text="shellPrefix"></div>
|
||||
<input
|
||||
type="text"
|
||||
class="h-5 flex-grow border-0 bg-transparent p-0 px-1 outline-none ring-0 focus:outline-none focus:ring-0"
|
||||
autofocus
|
||||
id="command"
|
||||
name="command"
|
||||
x-model="command"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<button type="submit" id="btn-run" x-on:click="run" class="hidden"></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,7 +0,0 @@
|
||||
<div
|
||||
@if (isset($getExtraAttributeBag))
|
||||
{{ $getExtraAttributeBag() }}
|
||||
@endif
|
||||
>
|
||||
{!! $content !!}
|
||||
</div>
|
@ -1 +0,0 @@
|
||||
@livewire($widget, $params ?? [], key($widget))
|
@ -1,6 +0,0 @@
|
||||
<div>
|
||||
<form>
|
||||
{{ $this->form }}
|
||||
</form>
|
||||
<x-filament-actions::modals />
|
||||
</div>
|
@ -1,4 +0,0 @@
|
||||
<div>
|
||||
{{ $this->infolist }}
|
||||
<x-filament-actions::modals />
|
||||
</div>
|
@ -1 +0,0 @@
|
||||
<a href="{{ $href }}" @if($external) target="_blank" @endif>{{ $text }}</a>
|
@ -1,11 +0,0 @@
|
||||
<div {{ $this->getExtraAttributesBag() }}>
|
||||
<x-filament-panels::page>
|
||||
@if (method_exists($this, "getSecondSubNavigation") && count($this->getSecondSubNavigation()) > 0)
|
||||
<x-filament-panels::page.sub-navigation.tabs class="!flex" :navigation="$this->getSecondSubNavigation()" />
|
||||
@endif
|
||||
|
||||
@foreach ($this->getWidgets() as $key => $widget)
|
||||
@livewire($widget[0], $widget[1] ?? [], key(class_basename($widget[0]) . "-" . $key))
|
||||
@endforeach
|
||||
</x-filament-panels::page>
|
||||
</div>
|
@ -1,13 +0,0 @@
|
||||
@props(["value" => 0])
|
||||
|
||||
<div class="bg-primary-200 dark:bg-primary-500 relative flex h-6 overflow-hidden rounded text-xs dark:bg-opacity-10">
|
||||
<div
|
||||
style="width: {{ $value }}%"
|
||||
class="bg-primary-500 flex flex-col justify-center whitespace-nowrap text-center text-white shadow-none transition-all duration-500 ease-out"
|
||||
></div>
|
||||
<span
|
||||
class="{{ $value >= 40 ? "text-white" : "text-black dark:text-white" }} absolute left-0 right-0 top-1 text-center font-semibold"
|
||||
>
|
||||
{{ $value }}%
|
||||
</span>
|
||||
</div>
|
@ -1,9 +0,0 @@
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
class="border-{{ $getColor() }}-500 bg-{{ $getColor() }}-100 text-{{ $getColor() }}-700 dark:bg-{{ $getColor() }}-500 dark:text-{{ $getColor() }}-500 rounded-lg border border-l-4 px-4 py-3 dark:bg-opacity-10"
|
||||
>
|
||||
{!! $getMessage() !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,18 +0,0 @@
|
||||
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field" :label-sr-only="$isLabelHidden()">
|
||||
<div
|
||||
wire:ignore
|
||||
x-data="codeEditorFormComponent({
|
||||
state: $wire.{{ $applyStateBindingModifiers('entangle(\'' . $getStatePath() . '\')') }},
|
||||
options: @js($getOptions()),
|
||||
})"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
id="{{ $getId() }}"
|
||||
{{ $attributes->merge(["class" => "mt-1 min-h-[400px] w-full border border-gray-100 dark:border-gray-700"]) }}
|
||||
class="ace-vito ace_dark"
|
||||
></div>
|
||||
<textarea id="textarea-{{ $getId() }}" style="display: none" x-model="state"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</x-dynamic-component>
|
@ -1,19 +0,0 @@
|
||||
<x-filament-forms::field-wrapper.label>
|
||||
{{ $getLabel() }}
|
||||
</x-filament-forms::field-wrapper.label>
|
||||
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }" class="mt-1 grid grid-cols-6 gap-2">
|
||||
@foreach (config("core.server_providers") as $p)
|
||||
<div
|
||||
class="flex w-full cursor-pointer items-center justify-center rounded-md border-2 bg-transparent px-3 pb-2 pt-3"
|
||||
@click="state = '{{ $p }}'; $wire.set('{{ $getStatePath() }}', state)"
|
||||
:class="{ 'border-primary-600': state === '{{ $p }}', 'border-primary-200 dark:border-primary-600 dark:border-opacity-20': state !== '{{ $p }}' }"
|
||||
>
|
||||
<div class="flex w-full flex-col items-center justify-center text-center">
|
||||
<x-icon :name="$p" class="h-7" />
|
||||
<span class="md:text-normal mt-2 hidden text-sm md:block">
|
||||
{{ $p }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
@ -1,27 +0,0 @@
|
||||
@props([
|
||||
"heading" => null,
|
||||
"logo" => true,
|
||||
"subheading" => null,
|
||||
])
|
||||
|
||||
<header class="fi-simple-header flex h-8 items-center justify-between">
|
||||
<div class="flex items-center gap-1">
|
||||
@if ($logo)
|
||||
<x-filament-panels::logo />
|
||||
@endif
|
||||
|
||||
@if (filled($heading))
|
||||
<h1
|
||||
class="fi-simple-header-heading text-center text-2xl font-bold tracking-tight text-gray-950 dark:text-white"
|
||||
>
|
||||
{{ $heading }}
|
||||
</h1>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if (filled($subheading))
|
||||
<p class="fi-simple-header-subheading text-center text-sm text-gray-500 dark:text-gray-400">
|
||||
{{ $subheading }}
|
||||
</p>
|
||||
@endif
|
||||
</header>
|
@ -1,53 +0,0 @@
|
||||
<x-filament::dropdown placement="bottom-start" :size="true" :teleport="true" class="pointer-choices -mx-2">
|
||||
<x-slot name="trigger">
|
||||
<button
|
||||
@if (filament()->isSidebarCollapsibleOnDesktop())
|
||||
x-data="{ tooltip: false }"
|
||||
x-effect="
|
||||
tooltip = $store.sidebar.isOpen
|
||||
? false
|
||||
: {
|
||||
content: @js($currentProject->name),
|
||||
placement: document.dir === 'rtl' ? 'left' : 'right',
|
||||
theme: $store.theme,
|
||||
}
|
||||
"
|
||||
x-tooltip.html="tooltip"
|
||||
@endif
|
||||
type="button"
|
||||
class="fi-tenant-menu-trigger group flex w-full items-center justify-center gap-x-3 rounded-lg p-2 text-sm font-medium outline-none transition duration-75 hover:bg-gray-100 focus-visible:bg-gray-100 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"
|
||||
>
|
||||
<div
|
||||
class="bg-primary-700-gradient text-md flex h-8 w-8 items-center justify-center rounded-lg capitalize text-white"
|
||||
>
|
||||
{{ $currentProject->name[0] }}
|
||||
</div>
|
||||
|
||||
<span
|
||||
@if (filament()->isSidebarCollapsibleOnDesktop())
|
||||
x-show="$store.sidebar.isOpen"
|
||||
@endif
|
||||
class="grid justify-items-start text-start"
|
||||
>
|
||||
<span class="text-gray-950 dark:text-white">
|
||||
{{ $currentProject->name }}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<x-filament::icon
|
||||
icon="heroicon-m-chevron-down"
|
||||
icon-alias="panels::tenant-menu.toggle-button"
|
||||
:x-show="filament()->isSidebarCollapsibleOnDesktop() ? '$store.sidebar.isOpen' : null"
|
||||
class="ms-auto h-5 w-5 shrink-0 text-gray-400 transition duration-75 group-hover:text-gray-500 group-focus-visible:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-400 dark:group-focus-visible:text-gray-400"
|
||||
/>
|
||||
</button>
|
||||
</x-slot>
|
||||
|
||||
<x-filament::dropdown.list>
|
||||
@foreach ($projects as $project)
|
||||
<x-filament::dropdown.list.item wire:click="updateProject({{ $project }})" class="cursor-pointer" tag="a">
|
||||
{{ $project->name }}
|
||||
</x-filament::dropdown.list.item>
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
</x-filament::dropdown>
|
Reference in New Issue
Block a user