mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-02 22:46:16 +00:00
init
This commit is contained in:
5
resources/css/app.css
Normal file
5
resources/css/app.css
Normal file
@ -0,0 +1,5 @@
|
||||
@import "toastr.css";
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
256
resources/css/toastr.css
Normal file
256
resources/css/toastr.css
Normal file
@ -0,0 +1,256 @@
|
||||
.toast-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.toast-message {
|
||||
-ms-word-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.toast-message a,
|
||||
.toast-message label {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.toast-message a:hover {
|
||||
color: #CCCCCC;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.toast-close-button {
|
||||
position: relative;
|
||||
right: -0.3em;
|
||||
top: -0.3em;
|
||||
float: right;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
-webkit-text-shadow: 0 1px 0 #ffffff;
|
||||
text-shadow: 0 1px 0 #ffffff;
|
||||
opacity: 0.8;
|
||||
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
|
||||
filter: alpha(opacity=80);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.toast-close-button:hover,
|
||||
.toast-close-button:focus {
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
opacity: 0.4;
|
||||
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
|
||||
filter: alpha(opacity=40);
|
||||
}
|
||||
|
||||
.rtl .toast-close-button {
|
||||
left: -0.3em;
|
||||
float: left;
|
||||
right: 0.3em;
|
||||
}
|
||||
|
||||
/*Additional properties for button version
|
||||
iOS requires the button element instead of an anchor tag.
|
||||
If you want the anchor version, it requires `href="#"`.*/
|
||||
button.toast-close-button {
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.toast-top-center {
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.toast-bottom-center {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.toast-top-full-width {
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.toast-bottom-full-width {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.toast-top-left {
|
||||
top: 12px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
.toast-top-right {
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
}
|
||||
|
||||
.toast-bottom-right {
|
||||
right: 12px;
|
||||
bottom: 12px;
|
||||
}
|
||||
|
||||
.toast-bottom-left {
|
||||
bottom: 12px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
#toast-container {
|
||||
position: fixed;
|
||||
z-index: 999999;
|
||||
pointer-events: none;
|
||||
/*overrides*/
|
||||
}
|
||||
|
||||
#toast-container * {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#toast-container > div {
|
||||
@apply rounded-lg;
|
||||
position: relative;
|
||||
pointer-events: auto;
|
||||
overflow: hidden;
|
||||
margin: 0 0 6px;
|
||||
padding: 15px 15px 15px 50px;
|
||||
width: 300px;
|
||||
background-position: 15px center;
|
||||
background-repeat: no-repeat;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
#toast-container > div.rtl {
|
||||
direction: rtl;
|
||||
padding: 15px 50px 15px 15px;
|
||||
background-position: right 15px center;
|
||||
}
|
||||
|
||||
#toast-container > div:hover {
|
||||
@apply shadow-md cursor-pointer;
|
||||
}
|
||||
|
||||
#toast-container > .toast-info {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important;
|
||||
}
|
||||
|
||||
#toast-container > .toast-error {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important;
|
||||
}
|
||||
|
||||
#toast-container > .toast-success {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important;
|
||||
}
|
||||
|
||||
#toast-container > .toast-warning {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important;
|
||||
}
|
||||
|
||||
#toast-container.toast-top-center > div,
|
||||
#toast-container.toast-bottom-center > div {
|
||||
width: 300px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#toast-container.toast-top-full-width > div,
|
||||
#toast-container.toast-bottom-full-width > div {
|
||||
width: 96%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.toast {
|
||||
background-color: #030303;
|
||||
}
|
||||
|
||||
.toast-success {
|
||||
@apply bg-green-500;
|
||||
}
|
||||
|
||||
.toast-error {
|
||||
@apply bg-red-500;
|
||||
}
|
||||
|
||||
.toast-info {
|
||||
@apply bg-primary-500;
|
||||
}
|
||||
|
||||
.toast-warning {
|
||||
@apply bg-yellow-500;
|
||||
}
|
||||
|
||||
.toast-progress {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 4px;
|
||||
background-color: #000000;
|
||||
opacity: 0.4;
|
||||
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
|
||||
filter: alpha(opacity=40);
|
||||
}
|
||||
|
||||
/*Responsive Design*/
|
||||
@media all and (max-width: 240px) {
|
||||
#toast-container > div {
|
||||
padding: 8px 8px 8px 50px;
|
||||
width: 11em;
|
||||
}
|
||||
|
||||
#toast-container > div.rtl {
|
||||
padding: 8px 50px 8px 8px;
|
||||
}
|
||||
|
||||
#toast-container .toast-close-button {
|
||||
right: -0.2em;
|
||||
top: -0.2em;
|
||||
}
|
||||
|
||||
#toast-container .rtl .toast-close-button {
|
||||
left: -0.2em;
|
||||
right: 0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 241px) and (max-width: 480px) {
|
||||
#toast-container > div {
|
||||
padding: 8px 8px 8px 50px;
|
||||
width: 18em;
|
||||
}
|
||||
|
||||
#toast-container > div.rtl {
|
||||
padding: 8px 50px 8px 8px;
|
||||
}
|
||||
|
||||
#toast-container .toast-close-button {
|
||||
right: -0.2em;
|
||||
top: -0.2em;
|
||||
}
|
||||
|
||||
#toast-container .rtl .toast-close-button {
|
||||
left: -0.2em;
|
||||
right: 0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 481px) and (max-width: 768px) {
|
||||
#toast-container > div {
|
||||
padding: 15px 15px 15px 50px;
|
||||
width: 25em;
|
||||
}
|
||||
|
||||
#toast-container > div.rtl {
|
||||
padding: 15px 50px 15px 15px;
|
||||
}
|
||||
}
|
24
resources/js/app.js
Normal file
24
resources/js/app.js
Normal file
@ -0,0 +1,24 @@
|
||||
import './bootstrap';
|
||||
import Echo from "laravel-echo"
|
||||
import Pusher from "pusher-js"
|
||||
import Alpine from 'alpinejs';
|
||||
import Clipboard from "@ryangjchandler/alpine-clipboard";
|
||||
|
||||
Alpine.plugin(Clipboard)
|
||||
|
||||
window.Echo = new Echo({
|
||||
broadcaster: 'pusher',
|
||||
key: 'app-key',
|
||||
wsHost: 'localhost',
|
||||
wsPort: 6001,
|
||||
cluster: '',
|
||||
forceTLS: false,
|
||||
disableStats: true,
|
||||
});
|
||||
|
||||
window.Pusher = Pusher;
|
||||
|
||||
window.Alpine = Alpine;
|
||||
|
||||
Alpine.start();
|
||||
|
43
resources/js/bootstrap.js
vendored
Normal file
43
resources/js/bootstrap.js
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* We'll load the axios HTTP library which allows us to easily issue requests
|
||||
* to our Laravel back-end. This library automatically handles sending the
|
||||
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
||||
*/
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
window.axios = axios;
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
/**
|
||||
* Echo exposes an expressive API for subscribing to channels and listening
|
||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
||||
* allows your team to easily build robust real-time web applications.
|
||||
*/
|
||||
|
||||
// import Echo from 'laravel-echo';
|
||||
|
||||
// import Pusher from 'pusher-js';
|
||||
// window.Pusher = Pusher;
|
||||
|
||||
// window.Echo = new Echo({
|
||||
// broadcaster: 'pusher',
|
||||
// key: import.meta.env.VITE_PUSHER_APP_KEY,
|
||||
// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER ?? 'mt1',
|
||||
// wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
|
||||
// wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
|
||||
// wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
|
||||
// forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
|
||||
// enabledTransports: ['ws', 'wss'],
|
||||
// });
|
||||
|
||||
import toastr from 'toastr';
|
||||
|
||||
window.toastr = toastr;
|
||||
|
||||
window.toastr.options = {
|
||||
"debug": false,
|
||||
"positionClass": "toast-bottom-right",
|
||||
"preventDuplicates": true,
|
||||
}
|
27
resources/views/auth/confirm-password.blade.php
Normal file
27
resources/views/auth/confirm-password.blade.php
Normal file
@ -0,0 +1,27 @@
|
||||
<x-guest-layout>
|
||||
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
|
||||
</div>
|
||||
|
||||
<form method="POST" action="{{ route('password.confirm') }}">
|
||||
@csrf
|
||||
|
||||
<!-- Password -->
|
||||
<div>
|
||||
<x-input-label for="password" :value="__('Password')" />
|
||||
|
||||
<x-text-input id="password" class="block mt-1 w-full"
|
||||
type="password"
|
||||
name="password"
|
||||
required autocomplete="current-password" />
|
||||
|
||||
<x-input-error :messages="$errors->get('password')" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end mt-4">
|
||||
<x-primary-button>
|
||||
{{ __('Confirm') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-guest-layout>
|
25
resources/views/auth/forgot-password.blade.php
Normal file
25
resources/views/auth/forgot-password.blade.php
Normal file
@ -0,0 +1,25 @@
|
||||
<x-guest-layout>
|
||||
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
|
||||
</div>
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="mb-4" :status="session('status')" />
|
||||
|
||||
<form method="POST" action="{{ route('password.email') }}">
|
||||
@csrf
|
||||
|
||||
<!-- Email Address -->
|
||||
<div>
|
||||
<x-input-label for="email" :value="__('Email')" />
|
||||
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
|
||||
<x-input-error :messages="$errors->get('email')" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
<x-primary-button>
|
||||
{{ __('Email Password Reset Link') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-guest-layout>
|
47
resources/views/auth/login.blade.php
Normal file
47
resources/views/auth/login.blade.php
Normal file
@ -0,0 +1,47 @@
|
||||
<x-guest-layout>
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="mb-4" :status="session('status')" />
|
||||
|
||||
<form method="POST" action="{{ route('login') }}">
|
||||
@csrf
|
||||
|
||||
<!-- Email Address -->
|
||||
<div>
|
||||
<x-input-label for="email" :value="__('Email')" />
|
||||
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus autocomplete="username" />
|
||||
<x-input-error :messages="$errors->get('email')" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<!-- Password -->
|
||||
<div class="mt-4">
|
||||
<x-input-label for="password" :value="__('Password')" />
|
||||
|
||||
<x-text-input id="password" class="block mt-1 w-full"
|
||||
type="password"
|
||||
name="password"
|
||||
required autocomplete="current-password" />
|
||||
|
||||
<x-input-error :messages="$errors->get('password')" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<!-- Remember Me -->
|
||||
<div class="block mt-4">
|
||||
<label for="remember_me" class="inline-flex items-center">
|
||||
<input id="remember_me" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="remember">
|
||||
<span class="ml-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Remember me') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
@if (Route::has('password.request'))
|
||||
<a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('password.request') }}">
|
||||
{{ __('Forgot your password?') }}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<x-primary-button class="ml-3">
|
||||
{{ __('Log in') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-guest-layout>
|
39
resources/views/auth/reset-password.blade.php
Normal file
39
resources/views/auth/reset-password.blade.php
Normal file
@ -0,0 +1,39 @@
|
||||
<x-guest-layout>
|
||||
<form method="POST" action="{{ route('password.store') }}">
|
||||
@csrf
|
||||
|
||||
<!-- Password Reset Token -->
|
||||
<input type="hidden" name="token" value="{{ $request->route('token') }}">
|
||||
|
||||
<!-- Email Address -->
|
||||
<div>
|
||||
<x-input-label for="email" :value="__('Email')" />
|
||||
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email', $request->email)" required autofocus autocomplete="username" />
|
||||
<x-input-error :messages="$errors->get('email')" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<!-- Password -->
|
||||
<div class="mt-4">
|
||||
<x-input-label for="password" :value="__('Password')" />
|
||||
<x-text-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
|
||||
<x-input-error :messages="$errors->get('password')" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<!-- Confirm Password -->
|
||||
<div class="mt-4">
|
||||
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
|
||||
|
||||
<x-text-input id="password_confirmation" class="block mt-1 w-full"
|
||||
type="password"
|
||||
name="password_confirmation" required autocomplete="new-password" />
|
||||
|
||||
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
<x-primary-button>
|
||||
{{ __('Reset Password') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-guest-layout>
|
1
resources/views/components/application-logo.blade.php
Normal file
1
resources/views/components/application-logo.blade.php
Normal file
File diff suppressed because one or more lines are too long
7
resources/views/components/auth-session-status.blade.php
Normal file
7
resources/views/components/auth-session-status.blade.php
Normal file
@ -0,0 +1,7 @@
|
||||
@props(['status'])
|
||||
|
||||
@if ($status)
|
||||
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600 dark:text-green-400']) }}>
|
||||
{{ $status }}
|
||||
</div>
|
||||
@endif
|
21
resources/views/components/card-header.blade.php
Normal file
21
resources/views/components/card-header.blade.php
Normal file
@ -0,0 +1,21 @@
|
||||
<div class="mb-6 @if(isset($aside)) flex justify-between @endif">
|
||||
<div>
|
||||
@if(isset($title))
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-300">
|
||||
{{ $title }}
|
||||
</h3>
|
||||
@endif
|
||||
|
||||
@if(isset($description))
|
||||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ $description }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@if(isset($aside))
|
||||
{{ $aside }}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
25
resources/views/components/card.blade.php
Normal file
25
resources/views/components/card.blade.php
Normal file
@ -0,0 +1,25 @@
|
||||
<div class="mx-auto mb-10">
|
||||
<x-card-header>
|
||||
@if(isset($title))
|
||||
<x-slot name="title">{{ $title }}</x-slot>
|
||||
@endif
|
||||
@if(isset($description))
|
||||
<x-slot name="description">{{ $description }}</x-slot>
|
||||
@endif
|
||||
@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' }}">
|
||||
{{ $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">
|
||||
{{ $actions }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
18
resources/views/components/confirm-modal.blade.php
Normal file
18
resources/views/components/confirm-modal.blade.php
Normal file
@ -0,0 +1,18 @@
|
||||
@props(['name', 'input', 'title', 'description', 'method'])
|
||||
|
||||
<x-modal :name="$name">
|
||||
<form wire:submit.prevent="{{ $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>
|
3
resources/views/components/console-view.blade.php
Normal file
3
resources/views/components/console-view.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<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>
|
3
resources/views/components/container.blade.php
Normal file
3
resources/views/components/container.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<div {!! $attributes->merge(['class' => 'py-12 max-w-7xl mx-auto px-6']) !!}>
|
||||
{{ $slot }}
|
||||
</div>
|
3
resources/views/components/danger-button.blade.php
Normal file
3
resources/views/components/danger-button.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<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>
|
3
resources/views/components/datetime.blade.php
Normal file
3
resources/views/components/datetime.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
@props(['value'])
|
||||
|
||||
{{ date_with_timezone($value, auth()->user()->timezone) }}
|
1
resources/views/components/dropdown-link.blade.php
Normal file
1
resources/views/components/dropdown-link.blade.php
Normal file
@ -0,0 +1 @@
|
||||
<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-800 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-800 transition duration-150 ease-in-out flex items-center justify-start']) }}>{{ $slot }}</a>
|
46
resources/views/components/dropdown.blade.php
Normal file
46
resources/views/components/dropdown.blade.php
Normal file
@ -0,0 +1,46 @@
|
||||
@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white dark:bg-gray-700'])
|
||||
|
||||
@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 ($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">
|
||||
<div @click="open = ! open">
|
||||
{{ $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 }}">
|
||||
{{ $content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
15
resources/views/components/icon-button.blade.php
Normal file
15
resources/views/components/icon-button.blade.php
Normal file
@ -0,0 +1,15 @@
|
||||
@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';
|
||||
@endphp
|
||||
|
||||
@if(isset($href))
|
||||
<a href="{{ $href }}" {{ $attributes->merge(['class' => $class]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
@else
|
||||
<button {{ $attributes->merge(['type' => 'submit', 'class' => $class]) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
@endif
|
9
resources/views/components/input-error.blade.php
Normal file
9
resources/views/components/input-error.blade.php
Normal file
@ -0,0 +1,9 @@
|
||||
@props(['messages'])
|
||||
|
||||
@if ($messages)
|
||||
<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
|
||||
</ul>
|
||||
@endif
|
5
resources/views/components/input-label.blade.php
Normal file
5
resources/views/components/input-label.blade.php
Normal file
@ -0,0 +1,5 @@
|
||||
@props(['value'])
|
||||
|
||||
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-700 dark:text-gray-300']) }}>
|
||||
{{ $value ?? $slot }}
|
||||
</label>
|
3
resources/views/components/item-card.blade.php
Normal file
3
resources/views/components/item-card.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<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">
|
||||
{{ $slot }}
|
||||
</div>
|
80
resources/views/components/modal.blade.php
Normal file
80
resources/views/components/modal.blade.php
Normal file
@ -0,0 +1,80 @@
|
||||
@props([
|
||||
'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];
|
||||
@endphp
|
||||
|
||||
<div
|
||||
x-data="{
|
||||
show: @js($show),
|
||||
focusables() {
|
||||
// All focusable element types...
|
||||
let selector = 'a, button, input:not([type=\'hidden\']), textarea, select, details, [tabindex]:not([tabindex=\'-1\'])'
|
||||
return [...$el.querySelectorAll(selector)]
|
||||
// All non-disabled elements...
|
||||
.filter(el => ! el.hasAttribute('disabled'))
|
||||
},
|
||||
firstFocusable() { return this.focusables()[0] },
|
||||
lastFocusable() { return this.focusables().slice(-1)[0] },
|
||||
nextFocusable() { return this.focusables()[this.nextFocusableIndex()] || this.firstFocusable() },
|
||||
prevFocusable() { return this.focusables()[this.prevFocusableIndex()] || this.lastFocusable() },
|
||||
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-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' }};"
|
||||
>
|
||||
<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-start="opacity-0"
|
||||
x-transition:enter-end="opacity-100"
|
||||
x-transition:leave="ease-in duration-200"
|
||||
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>
|
||||
|
||||
<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"
|
||||
>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
11
resources/views/components/nav-link.blade.php
Normal file
11
resources/views/components/nav-link.blade.php
Normal file
@ -0,0 +1,11 @@
|
||||
@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';
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
15
resources/views/components/primary-button.blade.php
Normal file
15
resources/views/components/primary-button.blade.php
Normal file
@ -0,0 +1,15 @@
|
||||
@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';
|
||||
@endphp
|
||||
|
||||
@if(isset($href))
|
||||
<a href="{{ $href }}" {{ $attributes->merge(['class' => $class]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
@else
|
||||
<button {{ $attributes->merge(['type' => 'submit', 'class' => $class]) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
@endif
|
11
resources/views/components/responsive-nav-link.blade.php
Normal file
11
resources/views/components/responsive-nav-link.blade.php
Normal file
@ -0,0 +1,11 @@
|
||||
@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';
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
24
resources/views/components/secondary-button.blade.php
Normal file
24
resources/views/components/secondary-button.blade.php
Normal file
@ -0,0 +1,24 @@
|
||||
@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';
|
||||
@endphp
|
||||
|
||||
@if(isset($href))
|
||||
@if(isset($disabled))
|
||||
@php
|
||||
$class .= ' opacity-25 cursor-default';
|
||||
@endphp
|
||||
<span {{ $attributes->merge(['class' => $class]) }}>
|
||||
{{ $slot }}
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $href }}" {{ $attributes->merge(['class' => $class]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
@endif
|
||||
@else
|
||||
<button {{ $attributes->merge(['type' => $type ?? 'submit', 'class' => $class]) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
@endif
|
19
resources/views/components/section.blade.php
Normal file
19
resources/views/components/section.blade.php
Normal file
@ -0,0 +1,19 @@
|
||||
<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>
|
||||
@endif
|
||||
@if(isset($description))
|
||||
<p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ $description }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
@if(isset($aside))
|
||||
<div>
|
||||
{{ $aside }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
5
resources/views/components/select-input.blade.php
Normal file
5
resources/views/components/select-input.blade.php
Normal file
@ -0,0 +1,5 @@
|
||||
@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']) !!}>
|
||||
{{ $slot }}
|
||||
</select>
|
12
resources/views/components/server-provider-item.blade.php
Normal file
12
resources/views/components/server-provider-item.blade.php
Normal file
@ -0,0 +1,12 @@
|
||||
@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'
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->merge(['class' => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</div>
|
11
resources/views/components/sidebar-link.blade.php
Normal file
11
resources/views/components/sidebar-link.blade.php
Normal file
@ -0,0 +1,11 @@
|
||||
@props(['active'])
|
||||
|
||||
@php
|
||||
$classes = ($active ?? false)
|
||||
? 'text-md font-semibold flex items-center text-primary-500 transition duration-150 ease-in-out mb-4'
|
||||
: 'text-md font-semibold flex items-center hover:text-primary-600 text-gray-600 dark:text-gray-500 transition duration-150 ease-in-out mb-4';
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
3
resources/views/components/simple-card.blade.php
Normal file
3
resources/views/components/simple-card.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<div {!! $attributes->merge(['class' => 'bg-white border boarder-gray-200 dark:border-gray-700 dark:bg-gray-800 p-6 rounded-md']) !!}>
|
||||
{{ $slot }}
|
||||
</div>
|
12
resources/views/components/site-type-item.blade.php
Normal file
12
resources/views/components/site-type-item.blade.php
Normal file
@ -0,0 +1,12 @@
|
||||
@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'
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->merge(['class' => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</div>
|
15
resources/views/components/status.blade.php
Normal file
15
resources/views/components/status.blade.php
Normal file
@ -0,0 +1,15 @@
|
||||
@props(['status'])
|
||||
|
||||
@php
|
||||
$class = [
|
||||
"success" => "rounded-full bg-green-50 px-2 py-1 text-xs uppercase text-green-500 dark:bg-green-500 dark:bg-opacity-10",
|
||||
"danger" => "rounded-full bg-red-50 px-2 py-1 text-xs uppercase text-red-500 dark:bg-red-500 dark:bg-opacity-10",
|
||||
"warning" => "rounded-full bg-yellow-50 px-2 py-1 text-xs uppercase text-yellow-500 dark:bg-yellow-500 dark:bg-opacity-10",
|
||||
"disabled" => "rounded-full bg-gray-50 px-2 py-1 text-xs uppercase text-gray-500 dark:bg-gray-500 dark:bg-opacity-30 dark:text-gray-400",
|
||||
"info" => "rounded-full bg-primary-50 px-2 py-1 text-xs uppercase text-primary-500 dark:bg-primary-500 dark:bg-opacity-10",
|
||||
];
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->merge(['class' => $class[$status]]) }}>
|
||||
{{ $slot }}
|
||||
</div>
|
5
resources/views/components/table.blade.php
Normal file
5
resources/views/components/table.blade.php
Normal file
@ -0,0 +1,5 @@
|
||||
<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>
|
||||
</div>
|
3
resources/views/components/td.blade.php
Normal file
3
resources/views/components/td.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<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>
|
3
resources/views/components/text-input.blade.php
Normal file
3
resources/views/components/text-input.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
@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']) !!}>
|
3
resources/views/components/textarea.blade.php
Normal file
3
resources/views/components/textarea.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
@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>
|
3
resources/views/components/th.blade.php
Normal file
3
resources/views/components/th.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<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>
|
14
resources/views/components/toast.blade.php
Normal file
14
resources/views/components/toast.blade.php
Normal file
@ -0,0 +1,14 @@
|
||||
<div>
|
||||
<script>
|
||||
window.addEventListener('toast', (e) => {
|
||||
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') }}');
|
||||
});
|
||||
</script>
|
||||
@endif
|
||||
</div>
|
5
resources/views/cronjobs/index.blade.php
Normal file
5
resources/views/cronjobs/index.blade.php
Normal file
@ -0,0 +1,5 @@
|
||||
<x-server-layout :server="$server">
|
||||
<x-slot name="pageTitle">{{ __("Cronjobs") }}</x-slot>
|
||||
|
||||
<livewire:cronjobs.cronjobs-list :server="$server"/>
|
||||
</x-server-layout>
|
4
resources/views/daemons/index.blade.php
Normal file
4
resources/views/daemons/index.blade.php
Normal file
@ -0,0 +1,4 @@
|
||||
<x-server-layout :server="$server">
|
||||
<x-slot name="pageTitle">{{ __("Daemons") }}</x-slot>
|
||||
|
||||
</x-server-layout>
|
9
resources/views/databases/index.blade.php
Normal file
9
resources/views/databases/index.blade.php
Normal file
@ -0,0 +1,9 @@
|
||||
<x-server-layout :server="$server">
|
||||
<x-slot name="pageTitle">{{ __("Databases") }}</x-slot>
|
||||
|
||||
<div class="space-y-10">
|
||||
<livewire:databases.database-list :server="$server" />
|
||||
|
||||
<livewire:databases.database-user-list :server="$server" />
|
||||
</div>
|
||||
</x-server-layout>
|
5
resources/views/firewall/index.blade.php
Normal file
5
resources/views/firewall/index.blade.php
Normal file
@ -0,0 +1,5 @@
|
||||
<x-server-layout :server="$server">
|
||||
<x-slot name="pageTitle">{{ __("Firewall") }}</x-slot>
|
||||
|
||||
<livewire:firewall.firewall-rules-list :server="$server"/>
|
||||
</x-server-layout>
|
57
resources/views/layouts/app.blade.php
Normal file
57
resources/views/layouts/app.blade.php
Normal file
@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>
|
||||
@if(isset($pageTitle))
|
||||
{{ $pageTitle }} -
|
||||
@endif
|
||||
{{ config('app.name', 'Laravel') }}
|
||||
</title>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
|
||||
|
||||
<!-- Scripts -->
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
|
||||
@livewireStyles
|
||||
|
||||
<script src="{{ asset('static/libs/ace/ace.js') }}"></script>
|
||||
<script src="{{ asset('static/libs/ace/theme-github.js') }}"></script>
|
||||
<script src="{{ asset('static/libs/ace/theme-one-dark.js') }}"></script>
|
||||
<script src="{{ asset('static/libs/ace/mode-sh.js') }}"></script>
|
||||
</head>
|
||||
<body class="font-sans antialiased bg-gray-100 dark:bg-gray-900 dark:text-gray-300 min-h-screen">
|
||||
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
|
||||
@include('layouts.navigation')
|
||||
|
||||
<!-- Page Heading -->
|
||||
@if (isset($header))
|
||||
<header class="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
|
||||
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
{{ $header }}
|
||||
</div>
|
||||
</header>
|
||||
@endif
|
||||
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
{{ $slot }}
|
||||
</main>
|
||||
</div>
|
||||
<x-toast />
|
||||
@livewireScripts
|
||||
<script>
|
||||
document.addEventListener('livewire:load', () => {
|
||||
Livewire.onPageExpired((response, message) => {
|
||||
({href: window.location.href} = window.location);
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
30
resources/views/layouts/guest.blade.php
Normal file
30
resources/views/layouts/guest.blade.php
Normal file
@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>{{ config('app.name', 'Laravel') }}</title>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
|
||||
|
||||
<!-- Scripts -->
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
</head>
|
||||
<body class="font-sans text-gray-900 antialiased">
|
||||
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900">
|
||||
<div>
|
||||
<a href="/">
|
||||
<x-application-logo class="w-20 h-20 fill-current text-gray-500 rounded-lg" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden rounded-lg">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
63
resources/views/layouts/navigation.blade.php
Normal file
63
resources/views/layouts/navigation.blade.php
Normal file
@ -0,0 +1,63 @@
|
||||
<nav x-data="{ open: false }" class="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
|
||||
<!-- Primary Navigation Menu -->
|
||||
<div class="max-w-7xl mx-auto px-6">
|
||||
<div class="flex justify-between h-16">
|
||||
<div class="flex">
|
||||
<!-- Logo -->
|
||||
<div class="shrink-0 flex items-center">
|
||||
<x-application-logo class="block h-9 w-auto fill-current text-gray-800 dark:text-gray-200 rounded-lg" />
|
||||
</div>
|
||||
|
||||
<!-- Navigation Links -->
|
||||
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
|
||||
<x-nav-link :href="route('servers')" :active="request()->routeIs('servers') || request()->is('servers/*')">
|
||||
<x-heroicon-o-server-stack class="w-6 h-6 mr-1" />
|
||||
{{ __('Servers') }}
|
||||
</x-nav-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Settings Dropdown -->
|
||||
<livewire:user-dropdown />
|
||||
|
||||
<!-- Hamburger -->
|
||||
<div class="-mr-2 flex items-center sm:hidden">
|
||||
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out">
|
||||
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Responsive Navigation Menu -->
|
||||
<div :class="{'block': open, 'hidden': ! open}" class="hidden sm:hidden">
|
||||
<!-- Responsive Settings Options -->
|
||||
<div class="pt-4 pb-1 border-t border-gray-200 dark:border-gray-600">
|
||||
<div class="px-4">
|
||||
<div class="font-medium text-base text-gray-800 dark:text-gray-200">{{ Auth::user()->name }}</div>
|
||||
<div class="font-medium text-sm text-gray-500">{{ Auth::user()->email }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 space-y-1">
|
||||
<x-responsive-nav-link :href="route('profile')">
|
||||
{{ __('Profile') }}
|
||||
</x-responsive-nav-link>
|
||||
|
||||
<x-responsive-nav-link :href="route('profile')">
|
||||
{{ __('Settings') }}
|
||||
</x-responsive-nav-link>
|
||||
|
||||
<!-- Authentication -->
|
||||
<form method="POST" action="{{ route('logout') }}">
|
||||
@csrf
|
||||
<x-responsive-nav-link :href="route('logout')" onclick="event.preventDefault(); this.closest('form').submit();">
|
||||
{{ __('Log Out') }}
|
||||
</x-responsive-nav-link>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
34
resources/views/layouts/profile.blade.php
Normal file
34
resources/views/layouts/profile.blade.php
Normal file
@ -0,0 +1,34 @@
|
||||
<x-app-layout>
|
||||
@if(isset($pageTitle))
|
||||
<x-slot name="pageTitle">{{ $pageTitle }}</x-slot>
|
||||
@endif
|
||||
|
||||
<x-container class="flex">
|
||||
<div class="hidden lg:block lg:flex-none w-64">
|
||||
<x-sidebar-link :href="route('profile')" :active="request()->routeIs('profile')">
|
||||
<x-heroicon-o-user class="w-6 h-6 mr-1" />
|
||||
{{ __('Profile') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('server-providers')" :active="request()->routeIs('server-providers')">
|
||||
<x-heroicon-o-server-stack class="w-6 h-6 mr-1" />
|
||||
{{ __('Server Providers') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('source-controls')" :active="request()->routeIs('source-controls')">
|
||||
<x-heroicon-o-code-bracket class="w-6 h-6 mr-1" />
|
||||
{{ __('Source Controls') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('notification-channels')" :active="request()->routeIs('notification-channels')">
|
||||
<x-heroicon-o-bell class="w-6 h-6 mr-1" />
|
||||
{{ __('Notification Channels') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('ssh-keys')" :active="request()->routeIs('ssh-keys')">
|
||||
<x-heroicon-o-key class="w-6 h-6 mr-1" />
|
||||
{{ __('SSH Keys') }}
|
||||
</x-sidebar-link>
|
||||
</div>
|
||||
|
||||
<div class="w-full">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</x-container>
|
||||
</x-app-layout>
|
60
resources/views/layouts/server.blade.php
Normal file
60
resources/views/layouts/server.blade.php
Normal file
@ -0,0 +1,60 @@
|
||||
<x-app-layout>
|
||||
@if(isset($pageTitle))
|
||||
<x-slot name="pageTitle">{{ $pageTitle }} - {{ $server->name }}</x-slot>
|
||||
@endif
|
||||
|
||||
<x-container class="flex">
|
||||
@if(in_array($server->status, [\App\Enums\ServerStatus::READY, \App\Enums\ServerStatus::DISCONNECTED]))
|
||||
<div class="hidden lg:block lg:flex-none w-64">
|
||||
<x-sidebar-link :href="route('servers.show', ['server' => $server])" :active="request()->routeIs('servers.show')">
|
||||
<x-heroicon-o-home class="w-6 h-6 mr-1" />
|
||||
{{ __('Overview') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.sites', ['server' => $server])" :active="request()->routeIs('servers.sites') || request()->is('servers/*/sites/*')">
|
||||
<x-heroicon-o-globe-alt class="w-6 h-6 mr-1" />
|
||||
{{ __('Sites') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.databases', ['server' => $server])" :active="request()->routeIs('servers.databases')">
|
||||
<x-heroicon-o-circle-stack class="w-6 h-6 mr-1" />
|
||||
{{ __('Databases') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.php', ['server' => $server])" :active="request()->routeIs('servers.php')">
|
||||
<x-heroicon-o-code-bracket class="w-6 h-6 mr-1" />
|
||||
{{ __('PHP') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.firewall', ['server' => $server])" :active="request()->routeIs('servers.firewall')">
|
||||
<x-heroicon-o-fire class="w-6 h-6 mr-1" />
|
||||
{{ __('Firewall') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.cronjobs', ['server' => $server])" :active="request()->routeIs('servers.cronjobs')">
|
||||
<x-heroicon-o-clock class="w-6 h-6 mr-1" />
|
||||
{{ __('Cronjobs') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.ssh-keys', ['server' => $server])" :active="request()->routeIs('servers.ssh-keys')">
|
||||
<x-heroicon-o-key class="w-6 h-6 mr-1" />
|
||||
{{ __('SSH Keys') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.services', ['server' => $server])" :active="request()->routeIs('servers.services')">
|
||||
<x-heroicon-o-cog class="w-6 h-6 mr-1" />
|
||||
{{ __('Services') }}
|
||||
</x-sidebar-link>
|
||||
{{--<x-sidebar-link :href="route('servers.daemons', ['server' => $server])" :active="request()->routeIs('servers.daemons')">--}}
|
||||
{{-- <x-heroicon-o-queue-list class="w-6 h-6 mr-1" />--}}
|
||||
{{-- {{ __('Daemons') }}--}}
|
||||
{{--</x-sidebar-link>--}}
|
||||
<x-sidebar-link :href="route('servers.settings', ['server' => $server])" :active="request()->routeIs('servers.settings')">
|
||||
<x-heroicon-o-cog-6-tooth class="w-6 h-6 mr-1" />
|
||||
{{ __('Settings') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.logs', ['server' => $server])" :active="request()->routeIs('servers.logs')">
|
||||
<x-heroicon-o-square-3-stack-3d class="w-6 h-6 mr-1" />
|
||||
{{ __('Logs') }}
|
||||
</x-sidebar-link>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="w-full space-y-10">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</x-container>
|
||||
</x-app-layout>
|
44
resources/views/layouts/site.blade.php
Normal file
44
resources/views/layouts/site.blade.php
Normal file
@ -0,0 +1,44 @@
|
||||
<x-app-layout>
|
||||
@if(isset($pageTitle))
|
||||
<x-slot name="pageTitle">{{ $site->domain }} - {{ $pageTitle }}</x-slot>
|
||||
@endif
|
||||
|
||||
<x-container class="flex">
|
||||
@if($site->status == \App\Enums\SiteStatus::READY)
|
||||
<div class="hidden lg:block lg:flex-none w-64">
|
||||
<x-sidebar-link :href="route('servers.sites.show', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.show')">
|
||||
<x-heroicon-o-home class="w-6 h-6 mr-1" />
|
||||
{{ __('Overview') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.sites.application', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.application')">
|
||||
<x-heroicon-o-window class="w-6 h-6 mr-1" />
|
||||
{{ __('Application') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.sites.ssl', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.ssl')">
|
||||
<x-heroicon-o-lock-closed class="w-6 h-6 mr-1" />
|
||||
{{ __('SSL') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.sites.queues', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.queues')">
|
||||
<x-heroicon-o-queue-list class="w-6 h-6 mr-1" />
|
||||
{{ __('Queues') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.sites.settings', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.settings')">
|
||||
<x-heroicon-o-cog-6-tooth class="w-6 h-6 mr-1" />
|
||||
{{ __('Settings') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.sites.logs', ['server' => $site->server, 'site' => $site])" :active="request()->routeIs('servers.sites.logs')">
|
||||
<x-heroicon-o-square-3-stack-3d class="w-6 h-6 mr-1" />
|
||||
{{ __('Logs') }}
|
||||
</x-sidebar-link>
|
||||
<x-sidebar-link :href="route('servers.sites', ['server' => $site->server])">
|
||||
<x-heroicon-o-arrow-left class="w-6 h-6 mr-1" />
|
||||
{{ __('Go Back') }}
|
||||
</x-sidebar-link>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="w-full space-y-10">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</x-container>
|
||||
</x-app-layout>
|
32
resources/views/livewire/application/change-branch.blade.php
Normal file
32
resources/views/livewire/application/change-branch.blade.php
Normal file
@ -0,0 +1,32 @@
|
||||
<div x-data="">
|
||||
<x-secondary-button x-on:click="$dispatch('open-modal', 'change-branch')">{{ __("Branch") }}</x-secondary-button>
|
||||
<x-modal name="change-branch">
|
||||
<form wire:submit.prevent="change" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Change Branch') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="branch" :value="__('Branch')" />
|
||||
<x-text-input wire:model.defer="branch" id="branch" name="branch" type="text" class="mt-1 w-full" />
|
||||
@error('branch')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex items-center justify-end">
|
||||
@if (session('status') === 'updating-branch')
|
||||
<p class="mr-2">{{ __('Updating branch...') }}</p>
|
||||
@endif
|
||||
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3">
|
||||
{{ __('Save') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
||||
</div>
|
5
resources/views/livewire/application/deploy.blade.php
Normal file
5
resources/views/livewire/application/deploy.blade.php
Normal file
@ -0,0 +1,5 @@
|
||||
<div>
|
||||
@if($site->deploymentScript && $site->deploymentScript->content)
|
||||
<x-primary-button wire:click="deploy" wire:loading.attr="disabled">{{ __("Deploy") }}</x-primary-button>
|
||||
@endif
|
||||
</div>
|
@ -0,0 +1,32 @@
|
||||
<div x-data="">
|
||||
<x-secondary-button x-on:click="$dispatch('open-modal', 'deployment-script')">{{ __("Deployment Script") }}</x-secondary-button>
|
||||
<x-modal name="deployment-script">
|
||||
<form wire:submit.prevent="save" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Deployment Script') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="script" :value="__('Script')" />
|
||||
<x-textarea wire:model.defer="script" rows="10" id="script" name="script" class="mt-1 w-full" />
|
||||
@error('script')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex items-center justify-end">
|
||||
@if (session('status') === 'script-updated')
|
||||
<p class="mr-2">{{ __('Saved') }}</p>
|
||||
@endif
|
||||
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3">
|
||||
{{ __('Save') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
||||
</div>
|
@ -0,0 +1,51 @@
|
||||
<div x-data="">
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Deployments") }}</x-slot>
|
||||
</x-card-header>
|
||||
<x-table>
|
||||
<tr>
|
||||
<x-th>{{ __("Commit") }}</x-th>
|
||||
<x-th>{{ __("Date") }}</x-th>
|
||||
<x-th>{{ __("Status") }}</x-th>
|
||||
<x-th></x-th>
|
||||
</tr>
|
||||
@foreach($deployments as $deployment)
|
||||
<tr>
|
||||
<x-td>
|
||||
<a href="{{ $deployment->commit_data['url'] }}" target="_blank" class="text-primary-600 font-semibold">{{ $deployment->commit_data['message'] }}</a>
|
||||
</x-td>
|
||||
<x-td>
|
||||
<x-datetime :value="$deployment->created_at" />
|
||||
</x-td>
|
||||
<x-td>
|
||||
<div class="inline-flex">
|
||||
@include('livewire.application.partials.deployment-status', ['status' => $deployment->status])
|
||||
</div>
|
||||
</x-td>
|
||||
<x-td>
|
||||
@if($deployment->status != \App\Enums\DeploymentStatus::DEPLOYING)
|
||||
<x-icon-button wire:click="showLog({{ $deployment->id }})" wire:loading.attr="disabled">
|
||||
<x-heroicon-o-eye class="w-6 h-6" />
|
||||
</x-icon-button>
|
||||
@endif
|
||||
</x-td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table>
|
||||
<div class="mt-5">
|
||||
{{ $deployments->withQueryString()->links() }}
|
||||
</div>
|
||||
<x-modal name="show-log" max-width="4xl">
|
||||
<div class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-5">
|
||||
{{ __('View Log') }}
|
||||
</h2>
|
||||
<x-console-view>{{ $logContent }}</x-console-view>
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Close') }}
|
||||
</x-secondary-button>
|
||||
</div>
|
||||
</div>
|
||||
</x-modal>
|
||||
</div>
|
21
resources/views/livewire/application/laravel-app.blade.php
Normal file
21
resources/views/livewire/application/laravel-app.blade.php
Normal file
@ -0,0 +1,21 @@
|
||||
<div>
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Application") }}</x-slot>
|
||||
<x-slot name="description">{{ __("Here you can manage your application") }}</x-slot>
|
||||
<x-slot name="aside">
|
||||
<div class="flex items-center">
|
||||
<div class="mr-2">
|
||||
<livewire:application.change-branch :site="$site" />
|
||||
</div>
|
||||
<div class="mr-2">
|
||||
<livewire:application.deployment-script :site="$site" />
|
||||
</div>
|
||||
<div>
|
||||
<livewire:application.deploy :site="$site" />
|
||||
</div>
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
|
||||
<livewire:application.deployments-list :site="$site" />
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
@if($status == \App\Enums\DeploymentStatus::DEPLOYING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\DeploymentStatus::FINISHED)
|
||||
<x-status status="success">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\DeploymentStatus::FAILED)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
3
resources/views/livewire/application/php-app.blade.php
Normal file
3
resources/views/livewire/application/php-app.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<div>
|
||||
|
||||
</div>
|
@ -0,0 +1,3 @@
|
||||
<div>
|
||||
|
||||
</div>
|
69
resources/views/livewire/cronjobs/create-cronjob.blade.php
Normal file
69
resources/views/livewire/cronjobs/create-cronjob.blade.php
Normal file
@ -0,0 +1,69 @@
|
||||
<div>
|
||||
<x-primary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'create-cronjob')">
|
||||
{{ __('Create Cronjob') }}
|
||||
</x-primary-button>
|
||||
|
||||
<x-modal name="create-cronjob">
|
||||
<form wire:submit.prevent="create" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Create Cronjob') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="command" :value="__('Command')" />
|
||||
<x-text-input wire:model.defer="command" id="command" name="command" type="text" class="mt-1 w-full" />
|
||||
@error('command')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="user" :value="__('User')" />
|
||||
<x-select-input wire:model.defer="user" id="user" name="user" class="mt-1 w-full">
|
||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
||||
<option value="root" @if($user === 'root') selected @endif>root</option>
|
||||
<option value="{{ $server->ssh_user }}" @if($user === $server->ssh_user) selected @endif>{{ $server->ssh_user }}</option>
|
||||
</x-select-input>
|
||||
@error('user')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="frequency" :value="__('Frequency')" />
|
||||
<x-select-input wire:model="frequency" id="frequency" name="frequency" class="mt-1 w-full">
|
||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
||||
<option value="* * * * *" @if($frequency === '* * * * *') selected @endif>{{ __("Every minute") }}</option>
|
||||
<option value="0 * * * *" @if($frequency === '0 * * * *') selected @endif>{{ __("Hourly") }}</option>
|
||||
<option value="0 0 * * *" @if($frequency === '0 0 * * *') selected @endif>{{ __("Daily") }}</option>
|
||||
<option value="0 0 * * 0" @if($frequency === '0 0 * * 0') selected @endif>{{ __("Weekly") }}</option>
|
||||
<option value="0 0 1 * *" @if($frequency === '0 0 1 * *') selected @endif>{{ __("Monthly") }}</option>
|
||||
<option value="custom">{{ __("Custom") }}</option>
|
||||
</x-select-input>
|
||||
@error('frequency')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
@if($frequency === 'custom')
|
||||
<div class="mt-6">
|
||||
<x-input-label for="custom" :value="__('Custom Frequency')" />
|
||||
<x-text-input wire:model.defer="custom" id="custom" name="custom" type="text" class="mt-1 w-full" placeholder="* * * * *" />
|
||||
@error('custom')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3" @created.window="$dispatch('close')">
|
||||
{{ __('Create') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
||||
</div>
|
45
resources/views/livewire/cronjobs/cronjobs-list.blade.php
Normal file
45
resources/views/livewire/cronjobs/cronjobs-list.blade.php
Normal file
@ -0,0 +1,45 @@
|
||||
<div>
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Cronjobs") }}</x-slot>
|
||||
<x-slot name="description">{{ __("Your server's Cronjobs are here. You can manage them") }}</x-slot>
|
||||
<x-slot name="aside">
|
||||
<livewire:cronjobs.create-cronjob :server="$server" />
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
<div x-data="" class="space-y-3">
|
||||
@if(count($cronjobs) > 0)
|
||||
@foreach($cronjobs as $cronjob)
|
||||
<x-item-card>
|
||||
<div class="flex flex-grow flex-col items-start justify-center">
|
||||
<span class="mb-1 flex items-center lowercase text-red-600">
|
||||
{{ $cronjob->command }}
|
||||
</span>
|
||||
<span class="text-sm text-gray-400">
|
||||
{{ $cronjob->frequency_label }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
@include('livewire.cronjobs.partials.status', ['status' => $cronjob->status])
|
||||
<div class="inline">
|
||||
<x-icon-button x-on:click="$wire.deleteId = '{{ $cronjob->id }}'; $dispatch('open-modal', 'delete-cronjob')">
|
||||
<x-heroicon-o-trash class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</x-item-card>
|
||||
@endforeach
|
||||
<x-confirm-modal
|
||||
name="delete-cronjob"
|
||||
:title="__('Confirm')"
|
||||
:description="__('Are you sure that you want to delete this cronjob?')"
|
||||
method="delete"
|
||||
/>
|
||||
@else
|
||||
<x-simple-card>
|
||||
<div class="text-center">
|
||||
{{ __("You haven't connected to any server providers yet!") }}
|
||||
</div>
|
||||
</x-simple-card>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
@if($status == \App\Enums\CronjobStatus::READY)
|
||||
<x-status status="success">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\CronjobStatus::CREATING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\CronjobStatus::DELETING)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
46
resources/views/livewire/databases/database-list.blade.php
Normal file
46
resources/views/livewire/databases/database-list.blade.php
Normal file
@ -0,0 +1,46 @@
|
||||
<div x-data="">
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Databases") }}</x-slot>
|
||||
<x-slot name="description">{{ __("You can see and manage your databases here") }}</x-slot>
|
||||
<x-slot name="aside">
|
||||
<div>
|
||||
<x-primary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'create-database')">
|
||||
{{ __('Create Database') }}
|
||||
</x-primary-button>
|
||||
|
||||
@include('livewire.databases.partials.create-database-modal')
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
@if(count($databases) > 0)
|
||||
<x-table>
|
||||
<tr>
|
||||
<x-td>{{ __("Name") }}</x-td>
|
||||
<x-td>{{ __("Created") }}</x-td>
|
||||
<x-td>{{ __("Status") }}</x-td>
|
||||
<x-td></x-td>
|
||||
</tr>
|
||||
@foreach($databases as $database)
|
||||
<tr>
|
||||
<x-td>{{ $database->name }}</x-td>
|
||||
<x-td>
|
||||
<x-datetime :value="$database->created_at"/>
|
||||
</x-td>
|
||||
<x-td>
|
||||
<div class="inline-flex">
|
||||
@include('livewire.databases.partials.database-status', ['status' => $database->status])
|
||||
</div>
|
||||
</x-td>
|
||||
<x-td class="flex w-full justify-end">
|
||||
<x-icon-button x-on:click="$wire.deleteId = '{{ $database->id }}'; $dispatch('open-modal', 'delete-database')">
|
||||
<x-heroicon-o-trash class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
</x-td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table>
|
||||
@include('livewire.databases.partials.delete-database-modal')
|
||||
@else
|
||||
<x-simple-card class="text-center">{{ __("You don't have any databases yet") }}</x-simple-card>
|
||||
@endif
|
||||
</div>
|
@ -0,0 +1,56 @@
|
||||
<div x-data="">
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Database Users") }}</x-slot>
|
||||
<x-slot name="description">{{ __("You can see and manage your database users here") }}</x-slot>
|
||||
<x-slot name="aside">
|
||||
<div>
|
||||
<x-primary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'create-database-user')">
|
||||
{{ __('Create Database User') }}
|
||||
</x-primary-button>
|
||||
|
||||
@include('livewire.databases.partials.create-database-user-modal')
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
@if(count($databaseUsers) > 0)
|
||||
<x-table>
|
||||
<tr>
|
||||
<x-td>{{ __("Username") }}</x-td>
|
||||
<x-td>{{ __("Created") }}</x-td>
|
||||
<x-td>{{ __("Linked Databases") }}</x-td>
|
||||
<x-td>{{ __("Status") }}</x-td>
|
||||
<x-td></x-td>
|
||||
</tr>
|
||||
@foreach($databaseUsers as $databaseUser)
|
||||
<tr>
|
||||
<x-td>{{ $databaseUser->username }}</x-td>
|
||||
<x-td>
|
||||
<x-datetime :value="$databaseUser->created_at" />
|
||||
</x-td>
|
||||
<x-td>[{{ $databaseUser->databases ? implode(', ', $databaseUser->databases) : '-' }}]</x-td>
|
||||
<x-td>
|
||||
<div class="inline-flex">
|
||||
@include('livewire.databases.partials.database-user-status', ['status' => $databaseUser->status])
|
||||
</div>
|
||||
</x-td>
|
||||
<x-td class="flex w-full justify-end">
|
||||
<x-icon-button x-on:click="$wire.deleteId = '{{ $databaseUser->id }}'; $dispatch('open-modal', 'delete-database-user')">
|
||||
<x-heroicon-o-trash class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
<x-icon-button wire:click="viewPassword({{ $databaseUser->id }})">
|
||||
<x-heroicon-o-eye class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
<x-icon-button wire:click="showLink({{ $databaseUser->id }})">
|
||||
<x-heroicon-o-link class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
</x-td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table>
|
||||
@include('livewire.databases.partials.delete-database-user-modal')
|
||||
@include('livewire.databases.partials.database-user-password-modal')
|
||||
@include('livewire.databases.partials.link-database-user-modal')
|
||||
@else
|
||||
<x-simple-card class="text-center">{{ __("You don't have any database users yet") }}</x-simple-card>
|
||||
@endif
|
||||
</div>
|
@ -0,0 +1,68 @@
|
||||
<x-modal name="create-database">
|
||||
<form wire:submit.prevent="create" class="p-6" x-data="{user: false, remote: false}">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Create Database') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="name" :value="__('Name')" />
|
||||
<x-text-input wire:model.defer="name" id="name" name="name" type="text" class="mt-1 w-full" />
|
||||
@error('name')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<label for="create_user" class="inline-flex items-center">
|
||||
<input id="create_user" wire:model.defer="user" type="checkbox" x-model="user" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="create_user">
|
||||
<span class="ml-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Create a user for this database') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div x-show="user">
|
||||
<div class="mt-6">
|
||||
<x-input-label for="db-username" :value="__('Username')" />
|
||||
<x-text-input wire:model.defer="username" id="db-username" name="username" type="text" class="mt-1 w-full" />
|
||||
@error('username')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="db-password" :value="__('Password')" />
|
||||
<x-text-input wire:model.defer="password" id="db-password" name="password" type="text" class="mt-1 w-full" />
|
||||
@error('password')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<label for="db-remote" class="inline-flex items-center">
|
||||
<input id="db-remote" wire:model="remote" type="checkbox" x-model="remote" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="remote">
|
||||
<span class="ml-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Enable remote access') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div x-show="remote">
|
||||
<div class="mt-6">
|
||||
<x-input-label for="db-host" :value="__('Host')" />
|
||||
<x-text-input wire:model.defer="host" id="db-host" name="host" type="text" class="mt-1 w-full" />
|
||||
<x-input-label for="db-host" :value="__('You might also need to open the database port in Firewall')" class="mt-1"/>
|
||||
@error('host')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3" @database-created.window="$dispatch('close')">
|
||||
{{ __('Create') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
@ -0,0 +1,51 @@
|
||||
<x-modal name="create-database-user">
|
||||
<form wire:submit.prevent="create" class="p-6" x-data="{remote: false}">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Create Database User') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="user-username" :value="__('Username')" />
|
||||
<x-text-input wire:model.defer="username" id="user-username" name="username" type="text" class="mt-1 w-full" />
|
||||
@error('username')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="user-password" :value="__('Password')" />
|
||||
<x-text-input wire:model.defer="password" id="user-password" name="password" type="text" class="mt-1 w-full" />
|
||||
@error('password')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<label for="user-remote" class="inline-flex items-center">
|
||||
<input id="user-remote" wire:model="remote" type="checkbox" x-model="remote" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="remote">
|
||||
<span class="ml-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Enable remote access') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div x-show="remote">
|
||||
<div class="mt-6">
|
||||
<x-input-label for="user-host" :value="__('Host')" />
|
||||
<x-text-input wire:model.defer="host" id="user-host" name="host" type="text" class="mt-1 w-full" />
|
||||
<x-input-label for="user-host" :value="__('You might also need to open the database port in Firewall')" class="mt-1"/>
|
||||
@error('host')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3" @database-user-created.window="$dispatch('close')">
|
||||
{{ __('Create') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
@ -0,0 +1,12 @@
|
||||
@if($status == \App\Enums\DatabaseStatus::READY)
|
||||
<x-status status="success">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\DatabaseStatus::CREATING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\DatabaseStatus::DELETING)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\DatabaseStatus::FAILED)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
@ -0,0 +1,23 @@
|
||||
<x-modal name="database-user-password">
|
||||
<form wire:submit.prevent="create" class="p-6" x-data="{remote: false}">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('View Password') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label :value="__('Password')" />
|
||||
<x-text-input wire:model.defer="viewPassword" type="text" class="mt-1 w-full" disabled />
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Close') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button x-data="{ copied: false }" x-clipboard.raw="{{ $viewPassword }}" class="ml-2">
|
||||
<div x-show="copied" class="flex items-center">{{ __("Copied") }}</div>
|
||||
<div x-show="!copied" x-on:click="copied = true; setTimeout(() => {copied = false}, 2000)">{{ __("Copy") }}</div>
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
@ -0,0 +1,12 @@
|
||||
@if($status == \App\Enums\DatabaseUserStatus::READY)
|
||||
<x-status status="success">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\DatabaseUserStatus::CREATING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\DatabaseUserStatus::DELETING)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\DatabaseUserStatus::FAILED)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
@ -0,0 +1,6 @@
|
||||
<x-confirm-modal
|
||||
name="delete-database"
|
||||
:title="__('Confirm')"
|
||||
:description="__('Are you sure that you want to delete this database?')"
|
||||
method="delete"
|
||||
/>
|
@ -0,0 +1,6 @@
|
||||
<x-confirm-modal
|
||||
name="delete-database-user"
|
||||
:title="__('Confirm')"
|
||||
:description="__('Are you sure that you want to delete this database?')"
|
||||
method="delete"
|
||||
/>
|
@ -0,0 +1,28 @@
|
||||
<x-modal name="link-database-user">
|
||||
<form wire:submit.prevent="link" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Link User to Databases') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
@foreach($databases as $database)
|
||||
<div class="mb-2">
|
||||
<label for="db-{{ $database->id }}" class="inline-flex items-center">
|
||||
<input id="db-{{ $database->id }}" wire:model.defer="link" value="{{ $database->name }}" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="link">
|
||||
<span class="ml-2 text-sm text-gray-600 dark:text-gray-400">{{ $database->name }}</span>
|
||||
</label>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Close') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-2" @linked.window="$dispatch('close')">
|
||||
{{ __('Save') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
@ -0,0 +1,72 @@
|
||||
<div>
|
||||
<x-primary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'create-rule')">
|
||||
{{ __('Create new Rule') }}
|
||||
</x-primary-button>
|
||||
|
||||
<x-modal name="create-rule">
|
||||
<form wire:submit.prevent="create" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Create new Rule') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="type" :value="__('Rule Type')" />
|
||||
<x-select-input wire:model.defer="type" id="type" name="type" class="mt-1 w-full">
|
||||
<option value="allow" @if($type === 'allow') selected @endif>{{ __("Allow") }}</option>
|
||||
<option value="deny" @if($type === 'deny') selected @endif>{{ __("Deny") }}</option>
|
||||
</x-select-input>
|
||||
@error('type')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6 grid grid-cols-1 lg:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<x-input-label for="protocol" :value="__('Protocol')" />
|
||||
<x-select-input wire:model="protocol" id="protocol" name="protocol" class="mt-1 w-full">
|
||||
@foreach(config('core.firewall_protocols_port') as $key => $value)
|
||||
<option value="{{ $key }}" @if($key === $protocol) selected @endif>{{ $key }}</option>
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('protocol')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-input-label for="port" :value="__('Port')" />
|
||||
<x-text-input wire:model.defer="port" id="port" name="port" type="text" class="mt-1 w-full" />
|
||||
@error('port')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-input-label for="source" :value="__('Source')" />
|
||||
<x-text-input wire:model.defer="source" id="source" name="source" type="text" class="mt-1 w-full" />
|
||||
@error('source')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-input-label for="mask" :value="__('Mask')" />
|
||||
<x-text-input wire:model.defer="mask" id="mask" name="mask" type="text" class="mt-1 w-full" />
|
||||
@error('mask')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3" @created.window="$dispatch('close')">
|
||||
{{ __('Create') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
||||
</div>
|
@ -0,0 +1,52 @@
|
||||
<div>
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Firewall Rules") }}</x-slot>
|
||||
<x-slot name="description">{{ __("Your server's firewall rules are here. You can manage them") }}</x-slot>
|
||||
<x-slot name="aside">
|
||||
<livewire:firewall.create-firewall-rule :server="$server" />
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
<div x-data="" class="space-y-3">
|
||||
@foreach($rules as $rule)
|
||||
<x-item-card>
|
||||
<div class="flex flex-grow flex-col items-start justify-center">
|
||||
<span class="mb-1 flex items-center uppercase">
|
||||
{{ $rule->protocol }}
|
||||
<x-status :status="$rule->type == 'allow' ? 'success' : 'danger'" class="ml-1">{{ $rule->type }}</x-status>
|
||||
</span>
|
||||
<span class="text-sm text-gray-400">
|
||||
{{ __("From") }} {{ $rule->source }}/{{ $rule->mask }} {{ __("Port") }} {{ $rule->port }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
@include('livewire.firewall.partials.status', ['status' => $rule->status])
|
||||
<div class="inline">
|
||||
<x-icon-button x-on:click="$wire.deleteId = '{{ $rule->id }}'; $dispatch('open-modal', 'delete-rule')">
|
||||
<x-heroicon-o-trash class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</x-item-card>
|
||||
@endforeach
|
||||
<x-item-card>
|
||||
<div class="flex flex-grow flex-col items-start justify-center">
|
||||
<span class="mb-1 flex items-center uppercase">
|
||||
{{ __("All") }}
|
||||
<x-status status="danger" class="ml-1">{{ __("Deny") }}</x-status>
|
||||
</span>
|
||||
<span class="text-sm text-gray-400">
|
||||
{{ __("From") }} 0.0.0.0/0
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
{{ __("Default") }}
|
||||
</div>
|
||||
</x-item-card>
|
||||
<x-confirm-modal
|
||||
name="delete-rule"
|
||||
:title="__('Confirm')"
|
||||
:description="__('Are you sure that you want to delete this rule?')"
|
||||
method="delete"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
@if($status == \App\Enums\FirewallRuleStatus::READY)
|
||||
<x-status status="success">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\FirewallRuleStatus::CREATING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\FirewallRuleStatus::DELETING)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
@ -0,0 +1,66 @@
|
||||
<div>
|
||||
<x-primary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'add-channel')">
|
||||
{{ __('Add new Channel') }}
|
||||
</x-primary-button>
|
||||
|
||||
<x-modal name="add-channel">
|
||||
<form wire:submit.prevent="add" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Add new Channel') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="provider" value="Provider" />
|
||||
<x-select-input wire:model="provider" id="provider" name="provider" class="mt-1 w-full">
|
||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
||||
@foreach(config('core.notification_channels_providers') as $p)
|
||||
@if($p !== 'custom')
|
||||
<option value="{{ $p }}" @if($provider === $p) selected @endif>{{ $p }}</option>
|
||||
@endif
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('provider')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="label" :value="__('Label')" />
|
||||
<x-text-input wire:model.defer="label" id="label" name="label" type="text" class="mt-1 w-full" />
|
||||
@error('label')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
@if($provider == \App\Enums\NotificationChannel::EMAIL)
|
||||
<div class="mt-6">
|
||||
<x-input-label for="email" :value="__('Email')" />
|
||||
<x-text-input wire:model.defer="email" id="email" name="email" type="text" class="mt-1 w-full" />
|
||||
@error('email')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(in_array($provider, [\App\Enums\NotificationChannel::SLACK, \App\Enums\NotificationChannel::DISCORD]))
|
||||
<div class="mt-6">
|
||||
<x-input-label for="webhook_url" :value="__('Webhook URL')" />
|
||||
<x-text-input wire:model.defer="webhook_url" id="webhook_url" name="webhook_url" type="text" class="mt-1 w-full" />
|
||||
@error('webhook_url')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3" @added.window="$dispatch('close')">
|
||||
{{ __('Add') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
||||
</div>
|
@ -0,0 +1,45 @@
|
||||
<div>
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Notification Channels") }}</x-slot>
|
||||
<x-slot name="description">{{ __("Add or modify your notification channels") }}</x-slot>
|
||||
<x-slot name="aside">
|
||||
<livewire:notification-channels.add-channel />
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
<div x-data="" class="space-y-3">
|
||||
@if(count($channels) > 0)
|
||||
@foreach($channels as $channel)
|
||||
<x-item-card>
|
||||
<div class="flex-none">
|
||||
<img src="{{ asset('static/images/' . $channel->provider . '.svg') }}" class="h-10 w-10" alt="">
|
||||
</div>
|
||||
<div class="ml-3 flex flex-grow flex-col items-start justify-center">
|
||||
<span class="mb-1">{{ $channel->label }}</span>
|
||||
<span class="text-sm text-gray-400">
|
||||
<x-datetime :value="$channel->created_at" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="inline">
|
||||
<x-icon-button x-on:click="$wire.deleteId = '{{ $channel->id }}'; $dispatch('open-modal', 'delete-channel')">
|
||||
<x-heroicon-o-trash class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</x-item-card>
|
||||
@endforeach
|
||||
<x-confirm-modal
|
||||
name="delete-channel"
|
||||
:title="__('Confirm')"
|
||||
:description="__('Are you sure that you want to delete this channel?')"
|
||||
method="delete"
|
||||
/>
|
||||
@else
|
||||
<x-simple-card>
|
||||
<div class="text-center">
|
||||
{{ __("You haven't connected to any channels yet!") }}
|
||||
</div>
|
||||
</x-simple-card>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
43
resources/views/livewire/partials/pagination.blade.php
Normal file
43
resources/views/livewire/partials/pagination.blade.php
Normal file
@ -0,0 +1,43 @@
|
||||
<div>
|
||||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="Pagination Navigation" class="flex justify-between">
|
||||
<span>
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<x-secondary-button href="javascript:" disabled>
|
||||
{!! __('pagination.previous') !!}
|
||||
</x-secondary-button>
|
||||
@else
|
||||
@if(method_exists($paginator,'getCursorName'))
|
||||
<x-secondary-button type="button" dusk="previousPage" wire:click="setPage('{{$paginator->previousCursor()->encode()}}','{{ $paginator->getCursorName() }}')" wire:loading.attr="disabled">
|
||||
{!! __('pagination.previous') !!}
|
||||
</x-secondary-button>
|
||||
@else
|
||||
<x-secondary-button type="button" wire:click="previousPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}">
|
||||
{!! __('pagination.previous') !!}
|
||||
</x-secondary-button>
|
||||
@endif
|
||||
@endif
|
||||
</span>
|
||||
|
||||
<span>
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
@if(method_exists($paginator,'getCursorName'))
|
||||
<x-secondary-button type="button" dusk="nextPage" wire:click="setPage('{{$paginator->nextCursor()->encode()}}','{{ $paginator->getCursorName() }}')" wire:loading.attr="disabled">
|
||||
{!! __('pagination.next') !!}
|
||||
</x-secondary-button>
|
||||
@else
|
||||
<x-secondary-button type="button" wire:click="nextPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}">
|
||||
{!! __('pagination.next') !!}
|
||||
</x-secondary-button>
|
||||
@endif
|
||||
@else
|
||||
<x-secondary-button href="javascript:" disabled>
|
||||
{!! __('pagination.next') !!}
|
||||
</x-secondary-button>
|
||||
@endif
|
||||
</span>
|
||||
</nav>
|
||||
@endif
|
||||
</div>
|
41
resources/views/livewire/php/default-cli.blade.php
Normal file
41
resources/views/livewire/php/default-cli.blade.php
Normal file
@ -0,0 +1,41 @@
|
||||
<div>
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Default PHP Cli") }}</x-slot>
|
||||
<x-slot name="description">{{ __("You can see and manage your PHP installations") }}</x-slot>
|
||||
</x-card-header>
|
||||
|
||||
<a class="block">
|
||||
<x-item-card>
|
||||
<div class="flex items-start justify-center">
|
||||
<span class="mr-2">PHP {{ $defaultPHP->version }}</span>
|
||||
@include('livewire.services.partials.status', ['status' => $defaultPHP->status])
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="inline">
|
||||
<x-dropdown>
|
||||
<x-slot name="trigger">
|
||||
<x-secondary-button>
|
||||
{{ __("Change") }}
|
||||
<x-heroicon-m-chevron-down class="w-4 ml-1" />
|
||||
</x-secondary-button>
|
||||
</x-slot>
|
||||
<x-slot name="content">
|
||||
@foreach($phps as $php)
|
||||
@if($php->version != $defaultPHP->version)
|
||||
<x-dropdown-link class="cursor-pointer" wire:click="change('{{ $php->version }}')">
|
||||
PHP {{ $php->version }}
|
||||
</x-dropdown-link>
|
||||
@endif
|
||||
@endforeach
|
||||
@if(count($phps) == 1)
|
||||
<x-dropdown-link>
|
||||
{{ __("No other versions") }}
|
||||
</x-dropdown-link>
|
||||
@endif
|
||||
</x-slot>
|
||||
</x-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</x-item-card>
|
||||
</a>
|
||||
</div>
|
61
resources/views/livewire/php/installed-versions.blade.php
Normal file
61
resources/views/livewire/php/installed-versions.blade.php
Normal file
@ -0,0 +1,61 @@
|
||||
<div>
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Installed PHPs") }}</x-slot>
|
||||
<x-slot name="description">{{ __("You can see and manage your PHP installations") }}</x-slot>
|
||||
<x-slot name="aside">
|
||||
@include('livewire.php.partials.install-new-php')
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
|
||||
@if(count($phps) > 0)
|
||||
<div class="space-y-3">
|
||||
@foreach($phps as $php)
|
||||
<a class="block">
|
||||
<x-item-card>
|
||||
<div class="flex items-start justify-center">
|
||||
<span class="mr-2">PHP {{ $php->version }}</span>
|
||||
@include('livewire.services.partials.status', ['status' => $php->status])
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="inline">
|
||||
<x-dropdown>
|
||||
<x-slot name="trigger">
|
||||
<x-secondary-button>
|
||||
{{ __("Actions") }}
|
||||
<x-heroicon-m-chevron-down class="w-4 ml-1" />
|
||||
</x-secondary-button>
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
{{--<x-dropdown-link class="cursor-pointer">--}}
|
||||
{{-- {{ __("Install Extension") }}--}}
|
||||
{{--</x-dropdown-link>--}}
|
||||
<x-dropdown-link class="cursor-pointer" x-on:click="$dispatch('open-modal', 'update-php-ini')" wire:click="loadIni({{ $php->id }})">
|
||||
{{ __("Edit php.ini") }}
|
||||
</x-dropdown-link>
|
||||
<x-dropdown-link class="cursor-pointer" wire:click="restart({{ $php->id }})">
|
||||
{{ __("Restart FPM") }}
|
||||
</x-dropdown-link>
|
||||
<x-dropdown-link class="cursor-pointer" x-on:click="$wire.uninstallId = {{ $php->id }}; $dispatch('open-modal', 'uninstall-php')">
|
||||
<span class="text-red-600">
|
||||
{{ __("Uninstall") }}
|
||||
</span>
|
||||
</x-dropdown-link>
|
||||
</x-slot>
|
||||
</x-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</x-item-card>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@include('livewire.php.partials.uninstall-php')
|
||||
@include('livewire.php.partials.update-php-ini')
|
||||
@else
|
||||
<x-simple-card>
|
||||
<div class="text-center">
|
||||
{{ __("You don't have any PHP version installed!") }}
|
||||
</div>
|
||||
</x-simple-card>
|
||||
@endif
|
||||
</div>
|
@ -0,0 +1,18 @@
|
||||
<x-dropdown>
|
||||
<x-slot name="trigger">
|
||||
<x-primary-button>
|
||||
{{ __("Install") }}
|
||||
<x-heroicon-m-chevron-down class="w-4 ml-1" />
|
||||
</x-primary-button>
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="content">
|
||||
@foreach(config('core.php_versions') as $php)
|
||||
@if(!$phps->whereIn('version', $php)->first() && $php !== 'none')
|
||||
<x-dropdown-link class="cursor-pointer" wire:click="install('{{ $php }}')">
|
||||
PHP {{ $php }}
|
||||
</x-dropdown-link>
|
||||
@endif
|
||||
@endforeach
|
||||
</x-slot>
|
||||
</x-dropdown>
|
@ -0,0 +1,6 @@
|
||||
<x-confirm-modal
|
||||
name="uninstall-php"
|
||||
:title="__('Uninstall PHP')"
|
||||
:description="__('Are you sure you want to uninstall this version?')"
|
||||
method="uninstall"
|
||||
/>
|
@ -0,0 +1,25 @@
|
||||
<x-modal name="update-php-ini">
|
||||
<form wire:submit.prevent="saveIni" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Update php.ini') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="ini" value="php.ini" />
|
||||
<x-textarea wire:model.defer="ini" id="ini" name="ini" class="mt-1 w-full" rows="15" />
|
||||
@error('ini')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3">
|
||||
{{ __('Save') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
45
resources/views/livewire/profile/update-password.blade.php
Normal file
45
resources/views/livewire/profile/update-password.blade.php
Normal file
@ -0,0 +1,45 @@
|
||||
<x-card>
|
||||
<x-slot name="title">
|
||||
{{ __('Update Password') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __('Ensure your account is using a long, random password to stay secure.') }}
|
||||
</x-slot>
|
||||
|
||||
<form id="update-password" wire:submit.prevent="update" class="mt-6 space-y-6">
|
||||
@csrf
|
||||
@method('put')
|
||||
|
||||
<div>
|
||||
<x-input-label for="current_password" :value="__('Current Password')" />
|
||||
<x-text-input wire:model.defer="current_password" id="current_password" name="current_password" type="password" class="mt-1 block w-full" autocomplete="current-password" />
|
||||
@error('current_password')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-input-label for="password" :value="__('New Password')" />
|
||||
<x-text-input wire:model.defer="password" id="password" name="password" type="password" class="mt-1 block w-full" autocomplete="new-password" />
|
||||
@error('password')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
|
||||
<x-text-input wire:model.defer="password_confirmation" id="password_confirmation" name="password_confirmation" type="password" class="mt-1 block w-full" autocomplete="new-password" />
|
||||
@error('password_confirmation')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<x-slot name="actions">
|
||||
@if (session('status') === 'password-updated')
|
||||
<p class="mr-2">{{ __('Saved') }}</p>
|
||||
@endif
|
||||
<x-primary-button form="update-password" wire:loading.attr="disabled">{{ __('Save') }}</x-primary-button>
|
||||
</x-slot>
|
||||
</x-card>
|
@ -0,0 +1,56 @@
|
||||
@php
|
||||
$user = auth()->user();
|
||||
@endphp
|
||||
<x-card>
|
||||
<x-slot name="title">
|
||||
{{ __('Profile Information') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __("Update your account's profile information and email address.") }}
|
||||
</x-slot>
|
||||
|
||||
<form id="send-verification" wire:submit.prevent="sendVerificationEmail">
|
||||
</form>
|
||||
|
||||
<form id="update-profile-information" wire:submit.prevent="submit" class="mt-6 space-y-6">
|
||||
<div>
|
||||
<x-input-label for="name" :value="__('Name')" />
|
||||
<x-text-input wire:model.defer="name" id="name" name="name" type="text" class="mt-1 block w-full" required autocomplete="name" />
|
||||
@error('name')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-input-label for="email" :value="__('Email')" />
|
||||
<x-text-input wire:model.defer="email" id="email" name="email" type="email" class="mt-1 block w-full" required autocomplete="username" />
|
||||
@error('email')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
|
||||
@if ($user instanceof \Illuminate\Contracts\Auth\MustVerifyEmail && ! $user->hasVerifiedEmail())
|
||||
<div>
|
||||
<p class="text-sm mt-2 text-gray-800 dark:text-gray-200">
|
||||
{{ __('Your email address is unverified.') }}
|
||||
<button form="send-verification" class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800">
|
||||
{{ __('Click here to re-send the verification email.') }}
|
||||
</button>
|
||||
</p>
|
||||
@if (session('status') === 'verification-link-sent')
|
||||
<p class="mt-2 font-medium text-sm text-green-600 dark:text-green-400">
|
||||
{{ __('A new verification link has been sent to your email address.') }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<x-slot name="actions">
|
||||
@if (session('status') === 'profile-updated')
|
||||
<p class="mr-2">{{ __('Saved') }}</p>
|
||||
@endif
|
||||
<x-primary-button form="update-profile-information" wire:loading.attr="disabled">{{ __('Save') }}</x-primary-button>
|
||||
</x-slot>
|
||||
</x-card>
|
75
resources/views/livewire/queues/create-queue.blade.php
Normal file
75
resources/views/livewire/queues/create-queue.blade.php
Normal file
@ -0,0 +1,75 @@
|
||||
<div>
|
||||
<x-primary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'create-queue')">
|
||||
{{ __('Create Queue') }}
|
||||
</x-primary-button>
|
||||
|
||||
<x-modal name="create-queue">
|
||||
<form wire:submit.prevent="create" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Create Queue') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="command" :value="__('Command')" />
|
||||
<x-text-input wire:model.defer="command" id="command" name="command" type="text" class="mt-1 w-full" />
|
||||
@error('command')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="user" :value="__('User')" />
|
||||
<x-select-input wire:model.defer="user" id="user" name="user" class="mt-1 w-full">
|
||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
||||
<option value="root" @if($user === 'root') selected @endif>root</option>
|
||||
<option value="{{ $site->server->ssh_user }}" @if($user === $site->server->ssh_user) selected @endif>{{ $site->server->ssh_user }}</option>
|
||||
</x-select-input>
|
||||
@error('user')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="auto_start" :value="__('Auto Start')" />
|
||||
<x-select-input wire:model="auto_start" id="auto_start" name="auto_start" class="mt-1 w-full">
|
||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
||||
<option value="1" @if($auto_start) selected @endif>{{ __("Yes") }}</option>
|
||||
<option value="0" @if(!$auto_start) selected @endif>{{ __("No") }}</option>
|
||||
</x-select-input>
|
||||
@error('auto_start')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="auto_restart" :value="__('Auto Restart')" />
|
||||
<x-select-input wire:model="auto_restart" id="auto_restart" name="auto_restart" class="mt-1 w-full">
|
||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
||||
<option value="1" @if($auto_restart) selected @endif>{{ __("Yes") }}</option>
|
||||
<option value="0" @if(!$auto_restart) selected @endif>{{ __("No") }}</option>
|
||||
</x-select-input>
|
||||
@error('auto_restart')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="numprocs" :value="__('Numprocs')" />
|
||||
<x-text-input wire:model.defer="numprocs" id="numprocs" name="numprocs" type="text" class="mt-1 w-full" placeholder="2" />
|
||||
@error('numprocs')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3" @created.window="$dispatch('close')">
|
||||
{{ __('Create') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
||||
</div>
|
27
resources/views/livewire/queues/partials/status.blade.php
Normal file
27
resources/views/livewire/queues/partials/status.blade.php
Normal file
@ -0,0 +1,27 @@
|
||||
@if($status == \App\Enums\QueueStatus::RUNNING)
|
||||
<x-status status="success">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\QueueStatus::CREATING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\QueueStatus::FAILED)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\QueueStatus::RESTARTING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\QueueStatus::STARTING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\QueueStatus::STOPPING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\QueueStatus::STOPPED)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\QueueStatus::FAILED)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\QueueStatus::DELETING)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
54
resources/views/livewire/queues/queues-list.blade.php
Normal file
54
resources/views/livewire/queues/queues-list.blade.php
Normal file
@ -0,0 +1,54 @@
|
||||
<div>
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Queues") }}</x-slot>
|
||||
<x-slot name="description">{{ __("You can manage and create queues for your site") }}</x-slot>
|
||||
<x-slot name="aside">
|
||||
<livewire:queues.create-queue :site="$site" />
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
<div x-data="" class="space-y-3">
|
||||
@if(count($queues) > 0)
|
||||
@foreach($queues as $queue)
|
||||
<x-item-card>
|
||||
<div class="flex flex-grow flex-col items-start justify-center">
|
||||
<span class="mb-1 flex items-center lowercase text-red-600">
|
||||
{{ $queue->command }}
|
||||
</span>
|
||||
<span class="text-sm text-gray-400">
|
||||
{{ __("User:") }} {{ $queue->user }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
@include('livewire.queues.partials.status', ['status' => $queue->status])
|
||||
<div class="inline-flex">
|
||||
<x-icon-button wire:click="start({{ $queue }})" wire:loading.attr="disabled">
|
||||
<x-heroicon-o-play class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
<x-icon-button wire:click="stop({{ $queue }})" wire:loading.attr="disabled">
|
||||
<x-heroicon-o-stop class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
<x-icon-button wire:click="restart({{ $queue }})" wire:loading.attr="disabled">
|
||||
<x-heroicon-o-arrow-path class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
<x-icon-button x-on:click="$wire.deleteId = '{{ $queue->id }}'; $dispatch('open-modal', 'delete-queue')">
|
||||
<x-heroicon-o-trash class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</x-item-card>
|
||||
@endforeach
|
||||
<x-confirm-modal
|
||||
name="delete-queue"
|
||||
:title="__('Confirm')"
|
||||
:description="__('Are you sure that you want to delete this queue?')"
|
||||
method="delete"
|
||||
/>
|
||||
@else
|
||||
<x-simple-card>
|
||||
<div class="text-center">
|
||||
{{ __("You don't have any queues yet!") }}
|
||||
</div>
|
||||
</x-simple-card>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
43
resources/views/livewire/server-logs/logs-list.blade.php
Normal file
43
resources/views/livewire/server-logs/logs-list.blade.php
Normal file
@ -0,0 +1,43 @@
|
||||
<div x-data="">
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("Logs") }}</x-slot>
|
||||
</x-card-header>
|
||||
<x-table>
|
||||
<tr>
|
||||
<x-th>{{ __("Event") }}</x-th>
|
||||
<x-th>{{ __("Date") }}</x-th>
|
||||
<x-th></x-th>
|
||||
</tr>
|
||||
@foreach($logs as $log)
|
||||
<tr>
|
||||
<x-td>{{ $log->type }}</x-td>
|
||||
<x-td>
|
||||
<x-datetime :value="$log->created_at" />
|
||||
</x-td>
|
||||
<x-td>
|
||||
<x-icon-button wire:click="showLog({{ $log->id }})" wire:loading.attr="disabled">
|
||||
<x-heroicon-o-eye class="w-6 h-6" />
|
||||
</x-icon-button>
|
||||
</x-td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table>
|
||||
@if(is_null($count))
|
||||
<div class="mt-5">
|
||||
{{ $logs->withQueryString()->links() }}
|
||||
</div>
|
||||
@endif
|
||||
<x-modal name="show-log" max-width="4xl">
|
||||
<div class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-5">
|
||||
{{ __('View Log') }}
|
||||
</h2>
|
||||
<x-console-view>{{ $logContent }}</x-console-view>
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Close') }}
|
||||
</x-secondary-button>
|
||||
</div>
|
||||
</div>
|
||||
</x-modal>
|
||||
</div>
|
@ -0,0 +1,74 @@
|
||||
<div>
|
||||
<x-primary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'connect-provider')">
|
||||
{{ __('Connect') }}
|
||||
</x-primary-button>
|
||||
|
||||
<x-modal name="connect-provider" :show="$open">
|
||||
<form wire:submit.prevent="connect" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Connect to a Server Provider') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="provider" value="Provider" />
|
||||
<x-select-input wire:model="provider" id="provider" name="provider" class="mt-1 w-full">
|
||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
||||
@foreach(config('core.server_providers') as $p)
|
||||
@if($p !== 'custom')
|
||||
<option value="{{ $p }}" @if($provider === $p) selected @endif>{{ $p }}</option>
|
||||
@endif
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('provider')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="name" value="Name" />
|
||||
<x-text-input wire:model.defer="name" id="name" name="name" type="text" class="mt-1 w-full" />
|
||||
@error('name')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
@if($provider === 'aws')
|
||||
<div class="mt-6">
|
||||
<x-input-label for="key" value="Access Key" />
|
||||
<x-text-input wire:model.defer="key" id="key" name="key" type="text" class="mt-1 w-full" />
|
||||
@error('key')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="secret" value="Secret" />
|
||||
<x-text-input wire:model.defer="secret" id="secret" name="secret" type="text" class="mt-1 w-full" />
|
||||
@error('secret')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(in_array($provider, ['hetzner', 'digitalocean', 'vultr', 'linode']))
|
||||
<div class="mt-6">
|
||||
<x-input-label for="token" value="API Key" />
|
||||
<x-text-input wire:model.defer="token" id="token" name="token" type="text" class="mt-1 w-full" />
|
||||
@error('token')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3" @connected.window="$dispatch('close')">
|
||||
{{ __('Connect') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
||||
</div>
|
@ -0,0 +1,45 @@
|
||||
<div>
|
||||
<x-card-header>
|
||||
<x-slot name="title">Server Providers</x-slot>
|
||||
<x-slot name="description">You can connect to your server providers to create servers using their APIs</x-slot>
|
||||
<x-slot name="aside">
|
||||
<livewire:server-providers.connect-provider />
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
<div x-data="" class="space-y-3">
|
||||
@if(count($providers) > 0)
|
||||
@foreach($providers as $provider)
|
||||
<x-item-card>
|
||||
<div class="flex-none">
|
||||
<img src="{{ asset('static/images/' . $provider->provider . '.svg') }}" class="h-10 w-10" alt="">
|
||||
</div>
|
||||
<div class="ml-3 flex flex-grow flex-col items-start justify-center">
|
||||
<span class="mb-1">{{ $provider->profile }}</span>
|
||||
<span class="text-sm text-gray-400">
|
||||
<x-datetime :value="$provider->created_at"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="inline">
|
||||
<x-icon-button x-on:click="$wire.deleteId = '{{ $provider->id }}'; $dispatch('open-modal', 'delete-provider')">
|
||||
<x-heroicon-o-trash class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</x-item-card>
|
||||
@endforeach
|
||||
<x-confirm-modal
|
||||
name="delete-provider"
|
||||
:title="__('Confirm')"
|
||||
:description="__('Are you sure that you want to delete this provider?')"
|
||||
method="delete"
|
||||
/>
|
||||
@else
|
||||
<x-simple-card>
|
||||
<div class="text-center">
|
||||
{{ __("You haven't connected to any server providers yet!") }}
|
||||
</div>
|
||||
</x-simple-card>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1 @@
|
||||
<x-primary-button wire:click="check">{{ __("Check Connection") }}</x-primary-button>
|
@ -0,0 +1,38 @@
|
||||
<x-card>
|
||||
<x-slot name="title">{{ __("Edit Server") }}</x-slot>
|
||||
|
||||
<x-slot name="description">{{ __("You can edit your server's some of fields") }}</x-slot>
|
||||
|
||||
<form id="update-server" wire:submit.prevent="update" class="mt-6 space-y-6">
|
||||
<div>
|
||||
<x-input-label for="name" :value="__('Name')" />
|
||||
<x-text-input wire:model.defer="name" id="name" name="name" type="text" class="mt-1 block w-full" required autocomplete="name" />
|
||||
@error('name')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-input-label for="ip" :value="__('IP Address')" />
|
||||
<x-text-input wire:model.defer="ip" id="ip" name="ip" type="text" class="mt-1 block w-full" required autocomplete="ip" />
|
||||
@error('ip')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-input-label for="port" :value="__('SSH Port')" />
|
||||
<x-text-input wire:model.defer="port" id="port" name="port" type="text" class="mt-1 block w-full" required autocomplete="port" />
|
||||
@error('port')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<x-slot name="actions">
|
||||
@if (session('status') === 'server-updated')
|
||||
<p class="mr-2">{{ __('Saved') }}</p>
|
||||
@endif
|
||||
<x-primary-button form="update-server" wire:loading.attr="disabled">{{ __('Save') }}</x-primary-button>
|
||||
</x-slot>
|
||||
</x-card>
|
@ -0,0 +1 @@
|
||||
<x-secondary-button wire:click="reboot" wire:loading.attr="disabled">{{ __("Reboot") }}</x-secondary-button>
|
@ -0,0 +1,58 @@
|
||||
<x-card>
|
||||
<x-slot name="title">{{ __("Details") }}</x-slot>
|
||||
<x-slot name="description">{{ __("More details about your server") }}</x-slot>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>{{ __("Created At") }}</div>
|
||||
<div>
|
||||
<x-datetime :value="$server->created_at" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="py-5">
|
||||
<div class="border-t border-gray-200 dark:border-gray-700"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>{{ __("Provider") }}</div>
|
||||
<div class="capitalize">{{ $server->provider }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="py-5">
|
||||
<div class="border-t border-gray-200 dark:border-gray-700"></div>
|
||||
</div>
|
||||
</div>
|
||||
{{--<div class="flex items-center justify-between">--}}
|
||||
{{-- <div>{{ __("Server ID") }}</div>--}}
|
||||
{{-- <div class="flex items-center">--}}
|
||||
{{-- <span class="rounded-md bg-gray-100 p-1 dark:bg-gray-700">{{ $server->id }}</span>--}}
|
||||
{{-- <span class="ml-2">{{ __("You will need this when you use the API") }}</span>--}}
|
||||
{{-- </div>--}}
|
||||
{{--</div>--}}
|
||||
{{--<div>--}}
|
||||
{{-- <div class="py-5">--}}
|
||||
{{-- <div class="border-t border-gray-200 dark:border-gray-700"></div>--}}
|
||||
{{-- </div>--}}
|
||||
{{--</div>--}}
|
||||
<div class="flex items-center justify-between">
|
||||
<div>{{ __("Status") }}</div>
|
||||
<div class="flex items-center">
|
||||
@include('livewire.servers.partials.status', ['status' => $server->status])
|
||||
<div class="inline-flex ml-2">
|
||||
<livewire:server-settings.check-connection :server="$server" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="py-5">
|
||||
<div class="border-t border-gray-200 dark:border-gray-700"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>{{ __("Reboot Server") }}</div>
|
||||
<div class="flex items-center">
|
||||
<div class="inline-flex">
|
||||
<livewire:server-settings.reboot-server :server="$server" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-card>
|
@ -0,0 +1,36 @@
|
||||
<div>
|
||||
<x-secondary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'add-existing-key')">
|
||||
{{ __('Add existing Key') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-modal name="add-existing-key">
|
||||
<form wire:submit.prevent="add" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Add existing Key') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="key_id" :value="__('SSH Key')" />
|
||||
<x-select-input wire:model.defer="key_id" id="key_id" name="key_id" class="mt-1 w-full">
|
||||
<option value="" selected disabled>{{ __("Select") }}</option>
|
||||
@foreach($keys as $key)
|
||||
<option value="{{ $key->id }}" @if($key->id === $key_id) selected @endif>{{ $key->name }}</option>
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('key_id')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3" @added.window="$dispatch('close')">
|
||||
{{ __('Add') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
||||
</div>
|
@ -0,0 +1,39 @@
|
||||
<div>
|
||||
<x-primary-button x-data="" x-on:click.prevent="$dispatch('open-modal', 'add-key')">
|
||||
{{ __('Add new Key') }}
|
||||
</x-primary-button>
|
||||
|
||||
<x-modal name="add-key">
|
||||
<form wire:submit.prevent="add" class="p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
|
||||
{{ __('Add new Key') }}
|
||||
</h2>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="name" :value="__('Name')" />
|
||||
<x-text-input wire:model.defer="name" id="name" name="name" type="text" class="mt-1 w-full" />
|
||||
@error('name')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<x-input-label for="public_key" :value="__('Public Key')" />
|
||||
<x-textarea wire:model.defer="public_key" id="public_key" name="public_key" class="mt-1 w-full" rows="5" />
|
||||
@error('public_key')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex justify-end">
|
||||
<x-secondary-button type="button" x-on:click="$dispatch('close')">
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
|
||||
<x-primary-button class="ml-3" @added.window="$dispatch('close')">
|
||||
{{ __('Add') }}
|
||||
</x-primary-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-modal>
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
@if($status == \App\Enums\SshKeyStatus::ADDED)
|
||||
<x-status status="success">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\SshKeyStatus::ADDING)
|
||||
<x-status status="warning">{{ $status }}</x-status>
|
||||
@endif
|
||||
@if($status == \App\Enums\SshKeyStatus::DELETING)
|
||||
<x-status status="danger">{{ $status }}</x-status>
|
||||
@endif
|
@ -0,0 +1,50 @@
|
||||
<div>
|
||||
<x-card-header>
|
||||
<x-slot name="title">{{ __("SSH Keys") }}</x-slot>
|
||||
<x-slot name="description">{{ __("Add or modify your ssh keys") }}</x-slot>
|
||||
<x-slot name="aside">
|
||||
<div class="flex items-center">
|
||||
<div>
|
||||
<livewire:server-ssh-keys.add-new-key :server="$server" />
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<livewire:server-ssh-keys.add-existing-key :server="$server" />
|
||||
</div>
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-card-header>
|
||||
<div x-data="" class="space-y-3">
|
||||
@if(count($keys) > 0)
|
||||
@foreach($keys as $key)
|
||||
<x-item-card>
|
||||
<div class="flex flex-grow flex-col items-start justify-center">
|
||||
<span class="mb-1">{{ $key->name }}</span>
|
||||
<span class="text-sm text-gray-400">
|
||||
<x-datetime :value="$key->created_at" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
@include('livewire.server-ssh-keys.partials.status', ['status' => $key->pivot->status])
|
||||
<div class="inline">
|
||||
<x-icon-button x-on:click="$wire.deleteId = '{{ $key->id }}'; $dispatch('open-modal', 'delete-key')">
|
||||
<x-heroicon-o-trash class="w-4 h-4" />
|
||||
</x-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</x-item-card>
|
||||
@endforeach
|
||||
<x-confirm-modal
|
||||
name="delete-key"
|
||||
:title="__('Confirm')"
|
||||
:description="__('Are you sure that you want to delete this key?')"
|
||||
method="delete"
|
||||
/>
|
||||
@else
|
||||
<x-simple-card>
|
||||
<div class="text-center">
|
||||
{{ __("You haven't connected to any keys yet!") }}
|
||||
</div>
|
||||
</x-simple-card>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
158
resources/views/livewire/servers/create-server.blade.php
Normal file
158
resources/views/livewire/servers/create-server.blade.php
Normal file
@ -0,0 +1,158 @@
|
||||
<x-container x-data="">
|
||||
<x-card>
|
||||
<x-slot name="title">{{ __("Create new Server") }}</x-slot>
|
||||
<x-slot name="description">{{ __("Use this form to create a new server") }}</x-slot>
|
||||
<form id="create-server" wire:submit.prevent="submit" class="mt-6 space-y-6">
|
||||
<div>
|
||||
<x-input-label>{{ __("Select a server provider") }}</x-input-label>
|
||||
<div class="grid grid-cols-6 gap-2 mt-1">
|
||||
@foreach(config('core.server_providers') as $p)
|
||||
<x-server-provider-item x-on:click="$wire.provider = '{{ $p }}'" :active="$provider === $p">
|
||||
<div class="flex w-full flex-col items-center justify-center text-center">
|
||||
<img src="{{ asset('static/images/' . $p . '.svg') }}" class="h-7" alt="Server">
|
||||
<span class="md:text-normal mt-2 hidden text-sm md:block">{{ $p }}</span>
|
||||
</div>
|
||||
</x-server-provider-item>
|
||||
@endforeach
|
||||
</div>
|
||||
@error('provider')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
@if($provider === 'custom')
|
||||
@include('livewire.servers.partials.public-key')
|
||||
@else
|
||||
<div>
|
||||
<x-input-label for="server_provider" value="Provider Profile" />
|
||||
<div class="flex items-center mt-1">
|
||||
<x-select-input wire:model="server_provider" id="server_provider" name="server_provider" class="w-full">
|
||||
<option value="" disabled selected>{{ __("Select") }}</option>
|
||||
@foreach($serverProviders as $sp)
|
||||
<option value="{{ $sp->id }}" @if($sp->id === $server_provider) selected @endif>
|
||||
{{ $sp->profile }}
|
||||
</option>
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
<x-secondary-button :href="route('server-providers', ['provider' => $provider])" class="flex-none ml-2">{{ __('Connect') }}</x-secondary-button>
|
||||
</div>
|
||||
@error('server_provider')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
@if(count($serverProviders) == 0)
|
||||
<x-input-error class="mt-2" :messages="__('You have not connected to any providers!')" />
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div>
|
||||
<x-input-label for="name" :value="__('Name')" />
|
||||
<x-text-input wire:model.defer="name" id="name" name="name" type="text" class="mt-1 block w-full" autocomplete="name" />
|
||||
@error('name')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
@if($provider !== 'custom')
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<x-input-label for="plan" value="Plan" />
|
||||
<x-select-input wire:model.defer="plan" id="plan" name="plan" class="mt-1 w-full">
|
||||
<option value="" disabled selected>{{ __("Select") }}</option>
|
||||
@foreach(config('serverproviders')[$provider]['plans'] as $value)
|
||||
<option value="{{ $value['value'] }}" @if($value['value'] === $plan) selected @endif>{{ $value['title'] }}</option>
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('plan')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
<div>
|
||||
<x-input-label for="region" value="Region" />
|
||||
<x-select-input wire:model.defer="region" id="region" name="region" class="mt-1 w-full">
|
||||
<option value="" disabled selected>{{ __("Select") }}</option>
|
||||
@foreach(config('serverproviders')[$provider]['regions'] as $key => $value)
|
||||
<option value="{{ $value['value'] }}" @if($value['value'] === $plan) selected @endif>{{ $value['title'] }}</option>
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('region')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($provider === 'custom')
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<x-input-label for="ip" :value="__('SSH IP Address')" />
|
||||
<x-text-input wire:model.defer="ip" id="ip" name="ip" type="text" class="mt-1 block w-full" autocomplete="ip" />
|
||||
@error('ip')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
<div>
|
||||
<x-input-label for="port" :value="__('SSH Port')" />
|
||||
<x-text-input wire:model.defer="port" id="port" name="port" type="text" class="mt-1 block w-full" autocomplete="port" />
|
||||
@error('port')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div>
|
||||
<x-input-label for="os" value="Operating System" />
|
||||
<x-select-input wire:model.defer="os" id="os" name="os" class="mt-1 w-full">
|
||||
@foreach(config('core.operating_systems') as $operatingSystem)
|
||||
<option value="{{ $operatingSystem }}" @if($operatingSystem === $os) selected @endif>
|
||||
{{ str($operatingSystem)->replace('_', ' ')->ucfirst() }} LTS
|
||||
</option>
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('os')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-3">
|
||||
<div>
|
||||
<x-input-label for="webserver" value="Webserver" />
|
||||
<x-select-input wire:model.defer="webserver" id="webserver" name="webserver" class="mt-1 w-full">
|
||||
@foreach(config('core.webservers') as $ws)
|
||||
<option value="{{ $ws }}" @if($ws === $webserver) selected @endif>{{ $ws }}</option>
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('webserver')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
<div>
|
||||
<x-input-label for="database" value="Database" />
|
||||
<x-select-input wire:model.defer="database" id="database" name="database" class="mt-1 w-full">
|
||||
@foreach(config('core.databases') as $db)
|
||||
<option value="{{ $db }}" @if($db === $database) selected @endif>{{ $db }}</option>
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('database')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
<div>
|
||||
<x-input-label for="php" value="PHP" />
|
||||
<x-select-input wire:model.defer="php" id="php" name="php" class="mt-1 w-full">
|
||||
@foreach(config('core.php_versions') as $p)
|
||||
<option value="{{ $p }}" @if($p === $php) selected @endif>{{ $p }}</option>
|
||||
@endforeach
|
||||
</x-select-input>
|
||||
@error('php')
|
||||
<x-input-error class="mt-2" :messages="$message" />
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<x-slot name="actions">
|
||||
<x-primary-button form="create-server" wire:loading.attr="disabled">{{ __('Create') }}</x-primary-button>
|
||||
</x-slot>
|
||||
</x-card>
|
||||
</x-container>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user