Merge branch 'feature' into feature/oauth
This commit is contained in:
@@ -419,7 +419,7 @@ const magicActions = [{
|
||||
},
|
||||
{
|
||||
id: 24,
|
||||
name: 'Goto: Boarding process',
|
||||
name: 'Goto: Onboarding process',
|
||||
icon: 'goto',
|
||||
sequence: ['main', 'redirect']
|
||||
},
|
||||
@@ -667,7 +667,7 @@ async function redirect() {
|
||||
targetUrl.pathname = `/team`
|
||||
break;
|
||||
case 24:
|
||||
targetUrl.pathname = `/boarding`
|
||||
targetUrl.pathname = `/onboarding`
|
||||
break;
|
||||
case 25:
|
||||
targetUrl.pathname = `/security/api-tokens`
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<div class="w-full">
|
||||
<div @class([
|
||||
'flex-1' => $isMultiline,
|
||||
'w-full' => !$isMultiline,
|
||||
])>
|
||||
@if ($label)
|
||||
<label for="small-input" class="flex items-center gap-1 mb-1 text-sm font-medium">{{ $label }}
|
||||
@if ($required)
|
||||
@@ -10,7 +13,7 @@
|
||||
</label>
|
||||
@endif
|
||||
@if ($type === 'password')
|
||||
<div class="relative" x-data>
|
||||
<div class="relative" x-data="{ type: 'password' }">
|
||||
@if ($allowToPeak)
|
||||
<div x-on:click="changePasswordFieldType"
|
||||
class="absolute inset-y-0 right-0 flex items-center pr-2 cursor-pointer hover:text-white">
|
||||
@@ -22,8 +25,9 @@
|
||||
</svg>
|
||||
</div>
|
||||
@endif
|
||||
<input value="{{ $value }}" {{ $attributes->merge(['class' => $defaultClass]) }}
|
||||
@required($required) @if ($id !== 'null') wire:model={{ $id }} @endif
|
||||
<input x-cloak x-show="type" value="{{ $value }}"
|
||||
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required)
|
||||
@if ($id !== 'null') wire:model={{ $id }} @endif
|
||||
wire:dirty.class.remove='text-white' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
||||
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}"
|
||||
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
|
||||
@@ -33,9 +37,11 @@
|
||||
@else
|
||||
<input @if ($value) value="{{ $value }}" @endif
|
||||
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly)
|
||||
@if ($id !== 'null') wire:model={{ $id }} @endif wire:dirty.class.remove='text-white' wire:dirty.class="input-warning"
|
||||
wire:loading.attr="disabled" type="{{ $type }}" @disabled($disabled)
|
||||
@if ($id !== 'null') id={{ $id }} @endif name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}">
|
||||
@if ($id !== 'null') wire:model={{ $id }} @endif
|
||||
wire:dirty.class.remove='text-white' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
||||
type="{{ $type }}" @disabled($disabled)
|
||||
@if ($id !== 'null') id={{ $id }} @endif name="{{ $name }}"
|
||||
placeholder="{{ $attributes->get('placeholder') }}">
|
||||
@endif
|
||||
@if (!$label && $helper)
|
||||
<x-helper :helper="$helper" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="form-control">
|
||||
<div class="flex-1 form-control">
|
||||
@if ($label)
|
||||
<label for="small-input" class="flex items-center gap-1 mb-1 text-sm font-medium">{{ $label }}
|
||||
@if ($required)
|
||||
@@ -9,13 +9,46 @@
|
||||
@endif
|
||||
</label>
|
||||
@endif
|
||||
<textarea placeholder="{{ $placeholder }}" {{ $attributes->merge(['class' => $defaultClass]) }}
|
||||
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}"
|
||||
@if ($type === 'password')
|
||||
<div class="relative" x-data="{ type: 'password' }">
|
||||
@if ($allowToPeak)
|
||||
<div x-on:click="changePasswordFieldType"
|
||||
class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer hover:text-white">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
|
||||
<path d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6" />
|
||||
</svg>
|
||||
</div>
|
||||
@endif
|
||||
<input x-cloak x-show="type === 'password'" value="{{ $value }}"
|
||||
{{ $attributes->merge(['class' => $defaultClassInput]) }} @required($required)
|
||||
@if ($id !== 'null') wire:model={{ $id }} @endif
|
||||
wire:dirty.class.remove='text-white' wire:dirty.class="input-warning" wire:loading.attr="disabled"
|
||||
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}"
|
||||
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
|
||||
aria-placeholder="{{ $attributes->get('placeholder') }}">
|
||||
<textarea x-cloak x-show="type !== 'password'" placeholder="{{ $placeholder }}"
|
||||
{{ $attributes->merge(['class' => $defaultClass]) }}
|
||||
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}"
|
||||
@else
|
||||
wire:model={{ $value ?? $id }}
|
||||
wire:dirty.class="input-warning" @endif
|
||||
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}"
|
||||
name="{{ $name }}" name={{ $id }}></textarea>
|
||||
|
||||
</div>
|
||||
@else
|
||||
<textarea placeholder="{{ $placeholder }}" {{ $attributes->merge(['class' => $defaultClass]) }}
|
||||
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}"
|
||||
@else
|
||||
wire:model={{ $value ?? $id }}
|
||||
wire:dirty.class="input-warning" @endif
|
||||
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}" name="{{ $name }}"
|
||||
name={{ $id }}></textarea>
|
||||
wire:model={{ $value ?? $id }}
|
||||
wire:dirty.class="input-warning" @endif
|
||||
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}"
|
||||
name="{{ $name }}" name={{ $id }}></textarea>
|
||||
@endif
|
||||
|
||||
@error($id)
|
||||
<label class="label">
|
||||
<span class="text-red-500 label-text-alt">{{ $message }}</span>
|
||||
|
||||
@@ -150,7 +150,17 @@
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
<li title="Notifications" class="hover:bg-coolgray-200">
|
||||
<a class="hover:bg-transparent hover:no-underline" href="{{ route('notification.index') }}">
|
||||
<svg class="{{ request()->is('notifications*') ? 'text-warning icon' : 'icon' }}"
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2"
|
||||
d="M10 5a2 2 0 1 1 4 0a7 7 0 0 1 4 6v3a4 4 0 0 0 2 3H4a4 4 0 0 0 2-3v-3a7 7 0 0 1 4-6M9 17v1a3 3 0 0 0 6 0v-1" />
|
||||
</svg>
|
||||
Notifications
|
||||
</a>
|
||||
</li>
|
||||
@if (isInstanceAdmin())
|
||||
<li title="Settings" class="hover:bg-coolgray-200">
|
||||
<a class="hover:bg-transparent hover:no-underline" href="/settings">
|
||||
@@ -167,14 +177,14 @@
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
<li title="Boarding" class="hover:bg-coolgray-200">
|
||||
<a class="hover:bg-transparent hover:no-underline" href="{{ route('boarding') }}">
|
||||
<svg class="{{ request()->is('boarding*') ? 'text-warning icon' : 'icon' }}"
|
||||
<li title="Onboarding" class="hover:bg-coolgray-200">
|
||||
<a class="hover:bg-transparent hover:no-underline" href="{{ route('onboarding') }}">
|
||||
<svg class="{{ request()->is('onboarding*') ? 'text-warning icon' : 'icon' }}"
|
||||
viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M224 128a8 8 0 0 1-8 8h-88a8 8 0 0 1 0-16h88a8 8 0 0 1 8 8m-96-56h88a8 8 0 0 0 0-16h-88a8 8 0 0 0 0 16m88 112h-88a8 8 0 0 0 0 16h88a8 8 0 0 0 0-16M82.34 42.34L56 68.69L45.66 58.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 132.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32m0 64L56 196.69l-10.34-10.35a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32 0l32-32a8 8 0 0 0-11.32-11.32" />
|
||||
</svg>
|
||||
Boarding
|
||||
Onboarding
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
|
||||
25
resources/views/components/notifications/navbar.blade.php
Normal file
25
resources/views/components/notifications/navbar.blade.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<div class="pb-6">
|
||||
<div class="flex items-end gap-2">
|
||||
<h1>Team Notifications</h1>
|
||||
</div>
|
||||
<nav class="flex pt-2 pb-10">
|
||||
<ol class="inline-flex items-center">
|
||||
<li>
|
||||
<div class="flex items-center">
|
||||
<span>Currently active team: <span
|
||||
class="text-warning">{{ session('currentTeam.name') }}</span></span>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<nav class="navbar-main">
|
||||
<a class="{{ request()->routeIs('notification.index') ? 'text-white' : '' }}"
|
||||
href="{{ route('notification.index') }}">
|
||||
<button>General</button>
|
||||
</a>
|
||||
<div class="flex-1"></div>
|
||||
<div class="-mt-9">
|
||||
<livewire:switch-team />
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
@@ -4,11 +4,13 @@
|
||||
href="{{ route('server.proxy', $parameters) }}">
|
||||
<button>Configuration</button>
|
||||
</a>
|
||||
@if (data_get($server, 'proxy.type') !== 'NONE')
|
||||
<a class="{{ request()->routeIs('server.proxy.dynamic-confs') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.proxy.dynamic-confs', $parameters) }}">
|
||||
<button>Dynamic Configurations</button>
|
||||
</a>
|
||||
@if ($server->proxyType() !== 'NONE')
|
||||
{{-- @if ($server->proxyType() === 'TRAEFIK_V2') --}}
|
||||
<a class="{{ request()->routeIs('server.proxy.dynamic-confs') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.proxy.dynamic-confs', $parameters) }}">
|
||||
<button>Dynamic Configurations</button>
|
||||
</a>
|
||||
{{-- @endif --}}
|
||||
<a class="{{ request()->routeIs('server.proxy.logs') ? 'text-white' : '' }}"
|
||||
href="{{ route('server.proxy.logs', $parameters) }}">
|
||||
<button>Logs</button>
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
{{ str($status)->before(':')->headline() }}
|
||||
</div>
|
||||
@if (!str($status)->startsWith('Proxy') && !str($status)->contains('('))
|
||||
<div class="text-xs text-success">({{ str($status)->after(':') }})</div>
|
||||
<div class="text-xs {{ str($status)->contains('unhealthy') ? 'text-warning' : 'text-success' }}">({{ str($status)->after(':') }})</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="pb-6">
|
||||
<div class="flex items-end gap-2">
|
||||
<h1>Team</h1>
|
||||
<a href="/team/new"><x-forms.button>+ Add Team</x-forms.button></a>
|
||||
<a href="/team/new"><x-forms.button>+ Add Team</x-forms.button></a>
|
||||
</div>
|
||||
<nav class="flex pt-2 pb-10">
|
||||
<ol class="inline-flex items-center">
|
||||
@@ -17,18 +17,15 @@
|
||||
<a class="{{ request()->routeIs('team.index') ? 'text-white' : '' }}" href="{{ route('team.index') }}">
|
||||
<button>General</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('team.member.index') ? 'text-white' : '' }}" href="{{ route('team.member.index') }}">
|
||||
<a class="{{ request()->routeIs('team.member.index') ? 'text-white' : '' }}"
|
||||
href="{{ route('team.member.index') }}">
|
||||
<button>Members</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('team.storage.index') ? 'text-white' : '' }}"
|
||||
href="{{ route('team.storage.index') }}">
|
||||
<button>S3 Storages</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('team.notification.index') ? 'text-white' : '' }}"
|
||||
href="{{ route('team.notification.index') }}">
|
||||
<button>Notifications</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('team.shared-variables.index') ? 'text-white' : '' }}"
|
||||
<a class="{{ request()->routeIs('team.shared-variables.index') ? 'text-white' : '' }}"
|
||||
href="{{ route('team.shared-variables.index') }}">
|
||||
<button>Shared Variables</button>
|
||||
</a>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
<ul x-data="{
|
||||
toasts: [],
|
||||
toastsHovered: false,
|
||||
timeout: null,
|
||||
expanded: false,
|
||||
layout: 'default',
|
||||
position: 'top-center',
|
||||
@@ -286,14 +287,12 @@
|
||||
}
|
||||
stackToasts();
|
||||
$watch('toastsHovered', function(value) {
|
||||
|
||||
if (layout == 'default') {
|
||||
if (position.includes('bottom')) {
|
||||
resetBottom();
|
||||
} else {
|
||||
resetTop();
|
||||
}
|
||||
|
||||
if (value) {
|
||||
// calculate the new positions
|
||||
expanded = true;
|
||||
@@ -319,13 +318,32 @@
|
||||
|
||||
<template x-for="(toast, index) in toasts" :key="toast.id">
|
||||
<li :id="toast.id" x-data="{
|
||||
toastHovered: false
|
||||
toastHovered: false,
|
||||
}" x-init="if (position.includes('bottom')) {
|
||||
$el.firstElementChild.classList.add('toast-bottom');
|
||||
$el.firstElementChild.classList.add('opacity-0', 'translate-y-full');
|
||||
} else {
|
||||
$el.firstElementChild.classList.add('opacity-0', '-translate-y-full');
|
||||
}
|
||||
$watch('toastsHovered', function(value) {
|
||||
if (value && this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
} else {
|
||||
this.timeout = setTimeout(function() {
|
||||
setTimeout(function() {
|
||||
$el.firstElementChild.classList.remove('opacity-100');
|
||||
$el.firstElementChild.classList.add('opacity-0');
|
||||
if (toasts.length == 1) {
|
||||
$el.firstElementChild.classList.remove('translate-y-0');
|
||||
$el.firstElementChild.classList.add('-translate-y-full');
|
||||
}
|
||||
setTimeout(function() {
|
||||
deleteToastWithId(toast.id)
|
||||
}, 300);
|
||||
}, 5);
|
||||
}, 2000)
|
||||
}
|
||||
});
|
||||
setTimeout(function() {
|
||||
|
||||
setTimeout(function() {
|
||||
@@ -342,7 +360,7 @@
|
||||
}, 5);
|
||||
}, 50);
|
||||
|
||||
setTimeout(function() {
|
||||
this.timeout = setTimeout(function() {
|
||||
setTimeout(function() {
|
||||
$el.firstElementChild.classList.remove('opacity-100');
|
||||
$el.firstElementChild.classList.add('opacity-0');
|
||||
@@ -390,12 +408,12 @@
|
||||
d="M2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12ZM11.9996 7C12.5519 7 12.9996 7.44772 12.9996 8V12C12.9996 12.5523 12.5519 13 11.9996 13C11.4474 13 10.9996 12.5523 10.9996 12V8C10.9996 7.44772 11.4474 7 11.9996 7ZM12.001 14.99C11.4488 14.9892 11.0004 15.4363 10.9997 15.9886L10.9996 15.9986C10.9989 16.5509 11.446 16.9992 11.9982 17C12.5505 17.0008 12.9989 16.5537 12.9996 16.0014L12.9996 15.9914C13.0004 15.4391 12.5533 14.9908 12.001 14.99Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<p class="leading-2 text-neutral-200"
|
||||
x-html="toast.message">
|
||||
<p class="leading-2 text-neutral-200" x-html="toast.message">
|
||||
</p>
|
||||
</div>
|
||||
<p x-show="toast.description" :class="{ 'pl-5': toast.type!='default' }"
|
||||
class="mt-1.5 text-xs leading-2 opacity-90 whitespace-pre-wrap" x-html="toast.description"></p>
|
||||
class="mt-1.5 text-xs leading-2 opacity-90 whitespace-pre-wrap"
|
||||
x-html="toast.description"></p>
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="toast.html">
|
||||
|
||||
@@ -76,11 +76,13 @@
|
||||
element = element.parentElement;
|
||||
}
|
||||
element = element.children[1];
|
||||
if (element.nodeName === 'INPUT') {
|
||||
if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
|
||||
if (element.type === 'password') {
|
||||
element.type = 'text';
|
||||
this.type = 'text';
|
||||
} else {
|
||||
element.type = 'password';
|
||||
this.type = 'password';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div>
|
||||
@if ($currentState === 'welcome')
|
||||
<h1 class="text-5xl font-bold">Welcome to Coolify</h1>
|
||||
<p class="py-6 text-xl text-center">Let me help you to set the basics.</p>
|
||||
<p class="py-6 text-xl text-center">Let me help you set up the basics.</p>
|
||||
<div class="flex justify-center ">
|
||||
<x-forms.button class="justify-center w-64 box" wire:click="$set('currentState','explanation')">Get
|
||||
Started
|
||||
@@ -24,12 +24,12 @@
|
||||
<x-highlighted text="Self-hosting with superpowers!" /></span>
|
||||
</x-slot:question>
|
||||
<x-slot:explanation>
|
||||
<p><x-highlighted text="Task automation:" /> You do not to manage your servers too much. Coolify do
|
||||
<p><x-highlighted text="Task automation:" /> You don't need to manage your servers anymore. Coolify does
|
||||
it for you.</p>
|
||||
<p><x-highlighted text="No vendor lock-in:" /> All configurations are stored on your server, so
|
||||
everything works without Coolify (except integrations and automations).</p>
|
||||
<p><x-highlighted text="Monitoring:" />You will get notified on your favourite platform (Discord,
|
||||
Telegram, Email, etc.) when something goes wrong, or an action needed from your side.</p>
|
||||
<p><x-highlighted text="No vendor lock-in:" /> All configurations are stored on your servers, so
|
||||
everything works without a connection to Coolify (except integrations and automations).</p>
|
||||
<p><x-highlighted text="Monitoring:" />You can get notified on your favourite platforms (Discord,
|
||||
Telegram, Email, etc.) when something goes wrong, or an action is needed from your side.</p>
|
||||
</x-slot:explanation>
|
||||
<x-slot:actions>
|
||||
<x-forms.button class="justify-center w-64 box" wire:click="explanation">Next
|
||||
@@ -40,8 +40,8 @@
|
||||
@if ($currentState === 'select-server-type')
|
||||
<x-boarding-step title="Server">
|
||||
<x-slot:question>
|
||||
Do you want to deploy your resources on your <x-highlighted text="Localhost" />
|
||||
or on a <x-highlighted text="Remote Server" />?
|
||||
Do you want to deploy your resources to your <x-highlighted text="Localhost" />
|
||||
or to a <x-highlighted text="Remote Server" />?
|
||||
</x-slot:question>
|
||||
<x-slot:actions>
|
||||
<x-forms.button class="justify-center w-64 box" wire:target="setServerType('localhost')"
|
||||
@@ -297,12 +297,12 @@
|
||||
You already have some projects. Do you want to use one of them or should I create a new one for
|
||||
you?
|
||||
@else
|
||||
I will create an initial project for you. You can change all the details later on.
|
||||
Let's create an initial project for you. You can change all the details later on.
|
||||
@endif
|
||||
</x-slot:question>
|
||||
<x-slot:actions>
|
||||
<x-forms.button class="justify-center w-64 box" wire:click="createNewProject">Let's create a new
|
||||
one!</x-forms.button>
|
||||
<x-forms.button class="justify-center w-64 box" wire:click="createNewProject">Create new
|
||||
project!</x-forms.button>
|
||||
<div>
|
||||
@if (count($projects) > 0)
|
||||
<form wire:submit='selectExistingProject' class="flex flex-col w-full gap-4 lg:w-96">
|
||||
@@ -319,9 +319,9 @@
|
||||
</div>
|
||||
</x-slot:actions>
|
||||
<x-slot:explanation>
|
||||
<p>Projects are bound together several resources into one virtual group. There are no
|
||||
limitations on the number of projects you could have.</p>
|
||||
<p>Each project should have at least one environment. This helps you to create a production &
|
||||
<p>Projects contain several resources combined into one virtual group. There are no
|
||||
limitations on the number of projects you can add.</p>
|
||||
<p>Each project should have at least one environment, this allows you to create a production &
|
||||
staging version of the same application, but grouped separately.</p>
|
||||
</x-slot:explanation>
|
||||
</x-boarding-step>
|
||||
@@ -331,7 +331,7 @@
|
||||
@if ($currentState === 'create-resource')
|
||||
<x-boarding-step title="Resources">
|
||||
<x-slot:question>
|
||||
I will redirect you to the new resource page, where you can create your first resource.
|
||||
Let's go to the new resource page, where you can create your first resource.
|
||||
</x-slot:question>
|
||||
<x-slot:actions>
|
||||
<div class="items-center justify-center w-64 box" wire:click="showNewResource">Let's do
|
||||
|
||||
@@ -15,18 +15,9 @@
|
||||
subscription is activated.<br> Please be patient.</span>
|
||||
</div>
|
||||
@endif
|
||||
@if ($projects->count() === 0 && $servers->count() === 0)
|
||||
No resources found. Add your first server & private key <a class="text-white underline"
|
||||
href="{{ route('server.create') }}">here</a> or go to the <a class="text-white underline" href="{{ route('boarding') }}">boarding page</a>.
|
||||
@endif
|
||||
@if ($projects->count() > 0)
|
||||
<h3 class="pb-4">Projects</h3>
|
||||
@if ($projects->count() === 1)
|
||||
<div class="grid grid-cols-1 gap-2">
|
||||
@else
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@endif
|
||||
@foreach ($projects as $project)
|
||||
<h3 class="pb-4">Projects</h3>
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@forelse ($projects as $project)
|
||||
<div class="gap-2 border border-transparent cursor-pointer box group">
|
||||
@if (data_get($project, 'environments')->count() === 1)
|
||||
<a class="flex flex-col flex-1 mx-6 hover:no-underline"
|
||||
@@ -61,88 +52,96 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@if ($projects->count() > 0)
|
||||
@empty
|
||||
<div>
|
||||
No projects found. Add your first server <a class="text-white underline"
|
||||
onclick="newEmptyProject.showModal()">here</a> or
|
||||
go to the <a class="text-white underline" href="{{ route('onboarding') }}">onboarding page.</a>
|
||||
<livewire:project.add-empty />
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
<h3 class="py-4">Servers</h3>
|
||||
@endif
|
||||
@if ($servers->count() === 1)
|
||||
<div class="grid grid-cols-1 gap-2">
|
||||
@else
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@endif
|
||||
@foreach ($servers as $server)
|
||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}" @class([
|
||||
'gap-2 border cursor-pointer box group',
|
||||
'border-transparent' => $server->settings->is_reachable,
|
||||
'border-red-500' => !$server->settings->is_reachable,
|
||||
])>
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">
|
||||
{{ $server->name }}
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ $server->description }}</div>
|
||||
<div class="flex gap-1 text-xs text-error">
|
||||
@if (!$server->settings->is_reachable)
|
||||
<span>Not reachable</span>
|
||||
@endif
|
||||
@if (!$server->settings->is_reachable && !$server->settings->is_usable)
|
||||
&
|
||||
@endif
|
||||
@if (!$server->settings->is_usable)
|
||||
<span>Not usable by Coolify</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Deployments</h3>
|
||||
@if (count($deployments_per_server) > 0)
|
||||
<x-loading />
|
||||
@endif
|
||||
<x-forms.button wire:click='cleanup_queue'>Cleanup Queues</x-forms.button>
|
||||
</div>
|
||||
<div wire:poll.1000ms="get_deployments" class="grid grid-cols-1">
|
||||
@forelse ($deployments_per_server as $server_name => $deployments)
|
||||
<h4 class="py-4">{{ $server_name }}</h4>
|
||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
||||
@foreach ($deployments as $deployment)
|
||||
<a href="{{ data_get($deployment, 'deployment_url') }}" @class([
|
||||
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
||||
'border-coolgray-500' => data_get($deployment, 'status') === 'queued',
|
||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
@forelse ($servers as $server)
|
||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||
@class([
|
||||
'gap-2 border cursor-pointer box group',
|
||||
'border-transparent' => $server->settings->is_reachable,
|
||||
'border-red-500' => !$server->settings->is_reachable,
|
||||
])>
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">
|
||||
{{ data_get($deployment, 'application_name') }}
|
||||
</div>
|
||||
@if (data_get($deployment, 'pull_request_id') !== 0)
|
||||
<div class="description">
|
||||
PR #{{ data_get($deployment, 'pull_request_id') }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="description">
|
||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||
</div>
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">
|
||||
{{ $server->name }}
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
<div>No deployments running.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
@endif
|
||||
<script>
|
||||
function gotoProject(uuid, environment = 'production') {
|
||||
window.location.href = '/project/' + uuid + '/' + environment;
|
||||
}
|
||||
</script>
|
||||
{{-- <x-forms.button wire:click='getIptables'>Get IPTABLES</x-forms.button> --}}
|
||||
<div class="description">
|
||||
{{ $server->description }}</div>
|
||||
<div class="flex gap-1 text-xs text-error">
|
||||
@if (!$server->settings->is_reachable)
|
||||
<span>Not reachable</span>
|
||||
@endif
|
||||
@if (!$server->settings->is_reachable && !$server->settings->is_usable)
|
||||
&
|
||||
@endif
|
||||
@if (!$server->settings->is_usable)
|
||||
<span>Not usable by Coolify</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@empty
|
||||
<div>
|
||||
No servers found.
|
||||
Add your first server <a class="text-white underline" href="{{ route('server.create') }}">here</a> or
|
||||
go to the <a class="text-white underline" href="{{ route('onboarding') }}">onboarding page.</a>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Deployments</h3>
|
||||
@if (count($deployments_per_server) > 0)
|
||||
<x-loading />
|
||||
@endif
|
||||
<x-forms.button wire:click='cleanup_queue'>Cleanup Queues</x-forms.button>
|
||||
</div>
|
||||
<div wire:poll.1000ms="get_deployments" class="grid grid-cols-1">
|
||||
@forelse ($deployments_per_server as $server_name => $deployments)
|
||||
<h4 class="py-4">{{ $server_name }}</h4>
|
||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-3">
|
||||
@foreach ($deployments as $deployment)
|
||||
<a href="{{ data_get($deployment, 'deployment_url') }}" @class([
|
||||
'gap-2 cursor-pointer box group border-l-2 border-dotted',
|
||||
'border-coolgray-500' => data_get($deployment, 'status') === 'queued',
|
||||
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
|
||||
])>
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="font-bold text-white">
|
||||
{{ data_get($deployment, 'application_name') }}
|
||||
</div>
|
||||
@if (data_get($deployment, 'pull_request_id') !== 0)
|
||||
<div class="description">
|
||||
PR #{{ data_get($deployment, 'pull_request_id') }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="description">
|
||||
{{ str(data_get($deployment, 'status'))->headline() }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1"></div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
<div>No deployments running.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
function gotoProject(uuid, environment = 'production') {
|
||||
window.location.href = '/project/' + uuid + '/' + environment;
|
||||
}
|
||||
</script>
|
||||
{{-- <x-forms.button wire:click='getIptables'>Get IPTABLES</x-forms.button> --}}
|
||||
</div>
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
<div class="text-5xl font-bold tracking-tight text-center text-white">Coolify</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex items-center justify-center pb-4 text-center">
|
||||
Set your initial password
|
||||
</div>
|
||||
|
||||
<form class="flex flex-col gap-2" wire:submit='submit'>
|
||||
<x-forms.input id="email" type="email" placeholder="Email" readonly label="Email" />
|
||||
<x-forms.input id="password" type="password" placeholder="New Password" label="New Password" required />
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
consider donating!</a>💜</span>
|
||||
<span>It enables us to keep creating features without paywalls, ensuring our work remains free and
|
||||
open.</span>
|
||||
<x-forms.button class="bg-coolgray-400" wire:click='disable'>Disable This Popup</x-forms.button>
|
||||
<x-forms.button class="bg-coolgray-400" wire:click='disableSponsorship'>Disable This
|
||||
Popup</x-forms.button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@@ -20,4 +21,16 @@
|
||||
</div>
|
||||
</x-banner>
|
||||
@endif
|
||||
@if (!currentTeam()->isAnyNotificationEnabled())
|
||||
<div class="toast">
|
||||
<div class="flex flex-col text-white rounded alert bg-coolgray-200">
|
||||
<span><span class="font-bold text-red-500">WARNING:</span> No notifications enabled.<br><br> It is highly recommended to enable at least
|
||||
one
|
||||
notification channel to receive important alerts.<br>Visit <a href="{{ route('notification.index') }}"
|
||||
class="text-white underline">/notification</a> to enable notifications.</span>
|
||||
<x-forms.button class="bg-coolgray-400" wire:click='disableNotifications'>Disable This
|
||||
Popup</x-forms.button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -6,13 +6,22 @@
|
||||
<h2>General</h2>
|
||||
<x-forms.button type="submit" label="Save">Save</x-forms.button>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<div class="flex flex-col gap-2 lg:flex-row">
|
||||
<x-forms.input id="name" label="Name" required />
|
||||
<x-forms.input id="email" label="Email" readonly />
|
||||
</div>
|
||||
</form>
|
||||
<h2 class="py-4">Subscription</h2>
|
||||
<a href="{{ route('team.index') }}">Check in Team Settings</a>
|
||||
<form wire:submit='resetPassword' class="flex flex-col max-w-xl pt-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Reset Password</h2>
|
||||
<x-forms.button type="submit" label="Save">Reset</x-forms.button>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<x-forms.input id="current_password" label="Current Password" required type="password" />
|
||||
<x-forms.input id="new_password" label="New Password" required type="password" />
|
||||
<x-forms.input id="new_password_confirmation" label="New Password Again" required type="password" />
|
||||
</div>
|
||||
</form>
|
||||
<h2 class="py-4">Two-factor Authentication</h2>
|
||||
@if (session('status') == 'two-factor-authentication-enabled')
|
||||
<div class="mb-4 font-medium">
|
||||
|
||||
@@ -45,11 +45,11 @@
|
||||
</div>
|
||||
@endif
|
||||
@if ($application->build_pack === 'dockercompose')
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave id="application.settings.is_raw_compose_deployment_enabled"
|
||||
label="Raw Compose Deployment"
|
||||
helper="WARNING: Advanced use cases only. Your docker compose file will be deployed as-is. Nothing is modified by Coolify. You need to configure the proxy parts. More info in the <a href='https://coolify.io/docs/docker/compose#raw-docker-compose-deployment'>documentation.</a>" />
|
||||
</div>
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave id="application.settings.is_raw_compose_deployment_enabled"
|
||||
label="Raw Compose Deployment"
|
||||
helper="WARNING: Advanced use cases only. Your docker compose file will be deployed as-is. Nothing is modified by Coolify. You need to configure the proxy parts. More info in the <a href='https://coolify.io/docs/docker/compose#raw-docker-compose-deployment'>documentation.</a>" />
|
||||
</div>
|
||||
@if (count($parsedServices) > 0 && !$application->settings->is_raw_compose_deployment_enabled)
|
||||
@foreach (data_get($parsedServices, 'services') as $serviceName => $service)
|
||||
@if (!isDatabaseImage(data_get($service, 'image')))
|
||||
@@ -210,10 +210,10 @@
|
||||
id="application.custom_docker_run_options" label="Custom Docker Options" />
|
||||
@endif
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='text-white underline' href='https://coolify.io/docs/custom-docker-options'>docs.</a>"
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||
id="application.custom_docker_run_options" label="Custom Docker Options" />
|
||||
<x-forms.input
|
||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='text-white underline' href='https://coolify.io/docs/custom-docker-options'>docs.</a>"
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||
id="application.custom_docker_run_options" label="Custom Docker Options" />
|
||||
@endif
|
||||
@if ($application->build_pack === 'dockercompose')
|
||||
<x-forms.button wire:click="loadComposeFile">Reload Compose File</x-forms.button>
|
||||
@@ -250,6 +250,21 @@
|
||||
<x-forms.textarea label="Container Labels" rows="15" id="customLabels"></x-forms.textarea>
|
||||
<x-forms.button wire:click="resetDefaultLabels">Reset to Coolify Generated Labels</x-forms.button>
|
||||
@endif
|
||||
|
||||
<h3 class="pt-8">Pre/Post Deployment Commands</h3>
|
||||
<div class="flex flex-col gap-2 xl:flex-row">
|
||||
<x-forms.input id="application.pre_deployment_command" label="Pre-deployment Command"
|
||||
helper="An optional script or command to execute in the existing container before the deployment begins." />
|
||||
<x-forms.input id="application.pre_deployment_command_container" label="Container Name"
|
||||
helper="The name of the container to execute within. You can leave it blank if your application only has one container." />
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 xl:flex-row">
|
||||
<x-forms.input placeholder="php artisan migrate" id="application.post_deployment_command"
|
||||
label="Post-deployment Command"
|
||||
helper="An optional script or command to execute in the newly built container after the deployment completes." />
|
||||
<x-forms.input id="application.post_deployment_command_container" label="Container Name"
|
||||
helper="The name of the container to execute within. You can leave it blank if your application only has one container." />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
</x-modal>
|
||||
<div class="pt-6">
|
||||
<livewire:project.database.backup-edit :backup="$backup" :s3s="$s3s" :status="data_get($database, 'status')" />
|
||||
<h3 class="py-4">Executions</h3>
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Executions</h3>
|
||||
<x-forms.button wire:click='cleanupFailed'>Cleanup Failed Backups</x-forms.button>
|
||||
</div>
|
||||
<livewire:project.database.backup-executions :backup="$backup" :executions="$executions" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
<div class='text-helper'>git@..</div>
|
||||
</div>
|
||||
<div class="flex gap-1">
|
||||
<div>Preselect branch (eg: static):</div>
|
||||
<div class='text-helper'>https://github.com/coollabsio/coolify-examples/tree/static</div>
|
||||
<div>Preselect branch (eg: main):</div>
|
||||
<div class='text-helper'>https://github.com/coollabsio/coolify-examples/tree/main</div>
|
||||
</div>
|
||||
<div>
|
||||
For example application deployments, checkout <a class="text-white underline"
|
||||
|
||||
@@ -289,10 +289,10 @@
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
@if ($isDatabase)
|
||||
{{-- @if ($isDatabase)
|
||||
<div class="text-center">Swarm clusters are excluded from this type of resource at the moment. It will
|
||||
be activated soon. Stay tuned.</div>
|
||||
@endif
|
||||
@endif --}}
|
||||
@endif
|
||||
@if ($current_step === 'destinations')
|
||||
<ul class="pb-10 steps">
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</div>
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox instantSave id="service.connect_to_docker_network" label="Connect To Predefined Network"
|
||||
helper="By default, you do not reach the Coolify defined networks.<br>Starting a docker compose based resource will have an internal network. <br>If you connect to a Coolify defined network, you maybe need to use different internal DNS names to connect to a resource.<br><br>For more information, check <a class='text-white underline' href='https://coolify.io/docs/docker/compose#connect-to-predefined-networks'>this</a>." />
|
||||
helper="By default, you do not reach the Coolify defined networks.<br>Starting a docker compose based resource will have an internal network. <br>If you connect to a Coolify defined network, you maybe need to use different internal DNS names to connect to a resource.<br><br>For more information, check <a class='text-white underline' target='_blank' href='https://coolify.io/docs/docker/compose#connect-to-predefined-networks'>this</a>." />
|
||||
</div>
|
||||
@if ($fields)
|
||||
<div>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<form class="flex flex-col gap-2 rounded" wire:submit='submit'>
|
||||
<x-forms.input placeholder="NODE_ENV" id="key" label="Name" required />
|
||||
<x-forms.input placeholder="production" id="value" label="Value" required />
|
||||
<x-forms.textarea x-show="$wire.is_multiline === true" x-cloak id="value" label="Value" required />
|
||||
<x-forms.input x-show="$wire.is_multiline === false" x-cloak placeholder="production" id="value" x-bind:label="$wire.is_multiline === false && 'Value'" required />
|
||||
@if (data_get($parameters, 'application_uuid'))
|
||||
<x-forms.checkbox id="is_build_time" label="Build Variable?" />
|
||||
@endif
|
||||
@endif
|
||||
<x-forms.checkbox id="is_multiline" label="Is Multiline?" />
|
||||
<x-forms.button type="submit" @click="slideOverOpen=false">
|
||||
Save
|
||||
</x-forms.button>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
<div>Environment variables (secrets) for this resource.</div>
|
||||
@if ($resource->type() === 'service')
|
||||
<div>If you cannot find a variable here, or need a new one, define it in the Docker Compose file.</div>
|
||||
<div>Hardcoded variables are not shown here.</div>
|
||||
@endif
|
||||
</div>
|
||||
@if ($view === 'normal')
|
||||
|
||||
@@ -20,10 +20,17 @@
|
||||
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
|
||||
@endif
|
||||
@else
|
||||
<x-forms.input id="env.key" />
|
||||
<x-forms.input type="password" id="env.value" />
|
||||
@if ($env->is_multiline)
|
||||
<x-forms.input isMultiline="{{ $env->is_multiline }}" id="env.key" />
|
||||
<x-forms.textarea type="password" id="env.value" />
|
||||
@else
|
||||
<x-forms.input id="env.key" />
|
||||
<x-forms.input type="password" id="env.value" />
|
||||
@endif
|
||||
@if ($env->is_shared)
|
||||
<x-forms.input disabled type="password" id="env.real_value" />
|
||||
@else
|
||||
<x-forms.checkbox instantSave id="env.is_multiline" label="Is Multiline?" />
|
||||
@endif
|
||||
@if ($type !== 'service' && !$isSharedVariable)
|
||||
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
|
||||
|
||||
@@ -7,16 +7,18 @@
|
||||
<div class="pt-2" wire:loading wire:target="loadContainers">
|
||||
Loading containers...
|
||||
</div>
|
||||
@foreach ($servers as $server)
|
||||
@forelse ($servers as $server)
|
||||
<h3 x-init="$wire.loadContainers({{ $server->id }})"></h3>
|
||||
<div wire:loading.remove wire:target="loadContainers">
|
||||
@forelse (data_get($server,'containers',[]) as $container)
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$resource" :container="data_get($container,'Names')" />
|
||||
<livewire:project.shared.get-logs :server="$server" :resource="$resource" :container="data_get($container, 'Names')" />
|
||||
@empty
|
||||
<div class="pt-2">No containers are not running on server: {{$server->name}}</div>
|
||||
<div class="pt-2">No containers are not running on server: {{ $server->name }}</div>
|
||||
@endforelse
|
||||
</div>
|
||||
@endforeach
|
||||
@empty
|
||||
<div>No functional server found for the application.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
@elseif ($type === 'database')
|
||||
<h1>Logs</h1>
|
||||
@@ -26,7 +28,11 @@
|
||||
@if ($loop->first)
|
||||
<h2 class="pb-4">Logs</h2>
|
||||
@endif
|
||||
<livewire:project.shared.get-logs :server="$servers[0]" :resource="$resource" :container="$container" />
|
||||
@if (data_get($servers, '0'))
|
||||
<livewire:project.shared.get-logs :server="data_get($servers, '0')" :resource="$resource" :container="$container" />
|
||||
@else
|
||||
<div> No functional server found for the database.</div>
|
||||
@endif
|
||||
@empty
|
||||
<div class="pt-2">No containers are not running.</div>
|
||||
@endforelse
|
||||
@@ -37,7 +43,11 @@
|
||||
@if ($loop->first)
|
||||
<h2 class="pb-4">Logs</h2>
|
||||
@endif
|
||||
<livewire:project.shared.get-logs :server="$servers[0]" :resource="$resource" :container="$container" />
|
||||
@if (data_get($servers, '0'))
|
||||
<livewire:project.shared.get-logs :server="data_get($servers, '0')" :resource="$resource" :container="$container" />
|
||||
@else
|
||||
<div> No functional server found for the service.</div>
|
||||
@endif
|
||||
@empty
|
||||
<div class="pt-2">No containers are not running.</div>
|
||||
@endforelse
|
||||
|
||||
@@ -1,16 +1,29 @@
|
||||
<div>
|
||||
@if (data_get($server, 'proxy.type'))
|
||||
@if ($server->proxyType())
|
||||
<div x-init="$wire.loadProxyConfiguration">
|
||||
@if ($selectedProxy === 'TRAEFIK_V2')
|
||||
@if ($selectedProxy !== 'NONE')
|
||||
<form wire:submit='submit'>
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Configuration</h2>
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
@if ($server->proxy->status === 'exited')
|
||||
<x-forms.button wire:click.prevent="change_proxy">Switch Proxy</x-forms.button>
|
||||
@else
|
||||
<x-forms.button disabled wire:click.prevent="change_proxy">Switch Proxy</x-forms.button>
|
||||
@endif
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
|
||||
</div>
|
||||
<div class="pt-3 pb-4 ">Traefik v2</div>
|
||||
<div class="pb-4 "> <svg class="inline-flex w-6 h-6 mr-2 text-warning" viewBox="0 0 256 256"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="M240.26 186.1L152.81 34.23a28.74 28.74 0 0 0-49.62 0L15.74 186.1a27.45 27.45 0 0 0 0 27.71A28.31 28.31 0 0 0 40.55 228h174.9a28.31 28.31 0 0 0 24.79-14.19a27.45 27.45 0 0 0 .02-27.71m-20.8 15.7a4.46 4.46 0 0 1-4 2.2H40.55a4.46 4.46 0 0 1-4-2.2a3.56 3.56 0 0 1 0-3.73L124 46.2a4.77 4.77 0 0 1 8 0l87.44 151.87a3.56 3.56 0 0 1 .02 3.73M116 136v-32a12 12 0 0 1 24 0v32a12 12 0 0 1-24 0m28 40a16 16 0 1 1-16-16a16 16 0 0 1 16 16" />
|
||||
</svg>Before switching proxies, please read <a class="text-white underline"
|
||||
href="https://coolify.io/docs/server/switching-proxies">this</a>.</div>
|
||||
@if ($server->proxyType() === 'TRAEFIK_V2')
|
||||
<div class="pb-4">Traefik v2</div>
|
||||
@elseif ($server->proxyType() === 'CADDY')
|
||||
<div class="pb-4 ">Caddy</div>
|
||||
@endif
|
||||
@if (
|
||||
$server->proxy->last_applied_settings &&
|
||||
$server->proxy->last_saved_settings !== $server->proxy->last_applied_settings)
|
||||
@@ -26,7 +39,7 @@
|
||||
<div wire:loading.remove wire:target="loadProxyConfiguration">
|
||||
@if ($proxy_settings)
|
||||
<div class="flex flex-col gap-2 pt-4">
|
||||
<x-forms.textarea label="Configuration file: traefik.conf" name="proxy_settings"
|
||||
<x-forms.textarea label="Configuration file" name="proxy_settings"
|
||||
wire:model="proxy_settings" rows="30" />
|
||||
<x-forms.button wire:click.prevent="reset_proxy_configuration">
|
||||
Reset configuration to default
|
||||
@@ -40,7 +53,7 @@
|
||||
<h2>Configuration</h2>
|
||||
<x-forms.button wire:click.prevent="change_proxy">Switch Proxy</x-forms.button>
|
||||
</div>
|
||||
<div class="pt-3 pb-4">Custom (None) Proxy Selected</div>
|
||||
<div class="pt-2 pb-4">Custom (None) Proxy Selected</div>
|
||||
@else
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Configuration</h2>
|
||||
@@ -57,14 +70,13 @@
|
||||
</x-forms.button>
|
||||
<x-forms.button class="box" wire:click="select_proxy('TRAEFIK_V2')">
|
||||
Traefik
|
||||
v2
|
||||
</x-forms.button>
|
||||
<x-forms.button class="box" wire:click="select_proxy('CADDY')">
|
||||
Caddy (experimental)
|
||||
</x-forms.button>
|
||||
<x-forms.button disabled class="box">
|
||||
Nginx
|
||||
</x-forms.button>
|
||||
<x-forms.button disabled class="box">
|
||||
Caddy
|
||||
</x-forms.button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
</p>
|
||||
</x-slot:modalBody>
|
||||
</x-modal>
|
||||
@if ($server->isFunctional() && data_get($server, 'proxy.type') !== 'NONE')
|
||||
@if ($server->isFunctional() && $server->proxyType() !== 'NONE')
|
||||
@if (data_get($server, 'proxy.status') === 'running')
|
||||
<div class="flex gap-4">
|
||||
@if ($currentRoute === 'server.proxy' && $traefikDashboardAvailable)
|
||||
@if ($currentRoute === 'server.proxy' && $traefikDashboardAvailable && $server->proxyType() === 'TRAEFIK_V2')
|
||||
<button>
|
||||
<a target="_blank" href="http://{{ $serverIp }}:8080">
|
||||
Traefik Dashboard
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
Add</button>
|
||||
</x-slide-over>
|
||||
</div>
|
||||
<div class='pb-4'>You can add dynamic Traefik configurations here.</div>
|
||||
<div class='pb-4'>You can add dynamic proxy configurations here.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div wire:loading wire:target="loadDynamicConfigurations">
|
||||
@@ -29,12 +29,12 @@
|
||||
@if ($contents?->isNotEmpty())
|
||||
@foreach ($contents as $fileName => $value)
|
||||
<div class="flex flex-col gap-2 py-2">
|
||||
@if (str_replace('|', '.', $fileName) === 'coolify.yaml')
|
||||
@if (str_replace('|', '.', $fileName) === 'coolify.yaml' || str_replace('|', '.', $fileName) === 'Caddyfile' || str_replace('|', '.', $fileName) === 'coolify.caddy' || str_replace('|', '.', $fileName) === 'default_redirect_404.caddy')
|
||||
<div>
|
||||
<h3 class="text-white">File: {{ str_replace('|', '.', $fileName) }}</h3>
|
||||
</div>
|
||||
<x-forms.textarea disabled name="proxy_settings"
|
||||
wire:model="contents.{{ $fileName }}" rows="10" />
|
||||
wire:model="contents.{{ $fileName }}" rows="5" />
|
||||
@else
|
||||
<livewire:server.proxy.dynamic-configuration-navbar :server_id="$server->id"
|
||||
:fileName="$fileName" :value="$value" :newFile="false"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<form wire:submit.prevent="addDynamicConfiguration" class="flex flex-col gap-4">
|
||||
<x-forms.input id="fileName" label="Filename (.yaml or .yml)" required />
|
||||
<x-forms.input id="fileName" label="Filename" required />
|
||||
<x-forms.textarea id="value" label="Configuration" required rows="20" />
|
||||
<x-forms.button type="submit" @click="slideOverOpen=false">Save</x-forms.button>
|
||||
</form>
|
||||
|
||||
@@ -45,7 +45,8 @@
|
||||
{{ data_get($resource, 'environment.name') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap"><a class=""
|
||||
href="{{ $resource->link() }}">{{ $resource->name }} <x-internal-link/></a>
|
||||
href="{{ $resource->link() }}">{{ $resource->name }}
|
||||
<x-internal-link /></a>
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ str($resource->type())->headline() }}</td>
|
||||
@@ -138,6 +139,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<x-forms.input id="github_app.webhook_secret" label="Webhook Secret" type="password" />
|
||||
</div>
|
||||
<div class="flex items-end gap-2 ">
|
||||
<h3 class="pt-4">Permissions</h3>
|
||||
<h2 class="pt-4">Permissions</h2>
|
||||
<x-forms.button wire:click.prevent="checkPermissions">Refetch</x-forms.button>
|
||||
<a href="{{ get_permissions_path($github_app) }}">
|
||||
<x-forms.button>
|
||||
@@ -93,6 +93,57 @@
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
<div class="w-full pt-10">
|
||||
<div class="h-full">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex gap-2">
|
||||
<h2>Resources</h2>
|
||||
</div>
|
||||
<div class="pb-4 title">Here you can find all resources that are used by this source.</div>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="inline-block min-w-full">
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-coolgray-400">
|
||||
<thead>
|
||||
<tr class="text-neutral-500">
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Project
|
||||
</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
|
||||
Environment</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Name</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-coolgray-400">
|
||||
@forelse ($applications->sortBy('name',SORT_NATURAL) as $resource)
|
||||
<tr class="text-white bg-coolblack hover:bg-coolgray-100">
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource->project(), 'name') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ data_get($resource, 'environment.name') }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap"><a class=""
|
||||
href="{{ $resource->link() }}">{{ $resource->name }}
|
||||
<x-internal-link /></a>
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">
|
||||
{{ str($resource->type())->headline() }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="flex items-center gap-2 pb-4">
|
||||
<h1>GitHub App</h1>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div>
|
||||
<x-team.navbar />
|
||||
<x-notifications.navbar />
|
||||
<h2 class="pb-4">Notifications</h2>
|
||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'email' }" class="flex h-full">
|
||||
<div class="flex flex-col gap-4 min-w-fit">
|
||||
|
||||
Reference in New Issue
Block a user