fix: deployment queue

fix: cancel deployment
ui: changed to simpler toaster
This commit is contained in:
Andras Bacsai 2024-01-25 11:57:47 +01:00
parent 0c5e8600bd
commit 7a7157c155
10 changed files with 499 additions and 113 deletions

View File

@ -381,7 +381,7 @@ private function generate_image_names()
}
private function just_restart()
{
$this->application_deployment_queue->addLogEntry("Starting deployment of {$this->customRepository}:{$this->application->git_branch}.'");
$this->application_deployment_queue->addLogEntry("Starting deployment of {$this->customRepository}:{$this->application->git_branch}.");
$this->prepare_builder_image();
$this->check_git_if_build_needed();
$this->set_base_dir();

View File

@ -41,26 +41,22 @@ public function show_debug()
public function cancel()
{
try {
$kill_command = "kill -9 {$this->application_deployment_queue->current_process_id}";
if ($this->application_deployment_queue->current_process_id) {
$process = Process::run("ps -p {$this->application_deployment_queue->current_process_id} -o command --no-headers");
if (Str::of($process->output())->contains([$this->server->ip, 'EOF-COOLIFY-SSH'])) {
Process::run($kill_command);
}
$previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR);
$new_log_entry = [
'command' => $kill_command,
'output' => "Deployment cancelled by user.",
'type' => 'stderr',
'order' => count($previous_logs) + 1,
'timestamp' => Carbon::now('UTC'),
'hidden' => false,
];
$previous_logs[] = $new_log_entry;
$this->application_deployment_queue->update([
'logs' => json_encode($previous_logs, flags: JSON_THROW_ON_ERROR),
]);
}
$kill_command = "docker rm -f {$this->application_deployment_queue->deployment_uuid}";
$previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR);
$new_log_entry = [
'command' => $kill_command,
'output' => "Deployment cancelled by user.",
'type' => 'stderr',
'order' => count($previous_logs) + 1,
'timestamp' => Carbon::now('UTC'),
'hidden' => false,
];
$previous_logs[] = $new_log_entry;
$this->application_deployment_queue->update([
'logs' => json_encode($previous_logs, flags: JSON_THROW_ON_ERROR),
]);
instant_remote_process([$kill_command], $this->server);
} catch (\Throwable $e) {
return handleError($e, $this);
} finally {
@ -68,7 +64,7 @@ public function cancel()
'current_process_id' => null,
'status' => ApplicationDeploymentStatus::CANCELLED_BY_USER->value,
]);
queue_next_deployment($this->application);
// queue_next_deployment($this->application);
}
}
}

View File

@ -27,7 +27,7 @@ class Form extends Component
'server.settings.is_swarm_manager' => 'required|boolean',
'server.settings.is_swarm_worker' => 'required|boolean',
'server.settings.is_build_server' => 'required|boolean',
'server.settings.concurrent_builds' => 'required|integer',
'server.settings.concurrent_builds' => 'required|integer|min:1',
'wildcard_domain' => 'nullable|url',
];
protected $validationAttributes = [

View File

@ -10,6 +10,9 @@
function queue_application_deployment(int $application_id, int $server_id, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $is_new_deployment = false)
{
$server = Application::find($application_id)->destination->server;
$deployments_per_server = ApplicationDeploymentQueue::where('server_id', $server_id)->where('status', 'queued')->orWhere('status', 'in_progress')->get();
$deployment = ApplicationDeploymentQueue::create([
'application_id' => $application_id,
'server_id' => $server_id,
@ -21,14 +24,12 @@ function queue_application_deployment(int $application_id, int $server_id, strin
'commit' => $commit,
'git_type' => $git_type
]);
$server = Application::find($application_id)->destination->server;
$deployments = ApplicationDeploymentQueue::where('application_id', $application_id);
$queued_deployments = $deployments->where('status', 'queued')->get()->sortByDesc('created_at');
$running_deployments = $deployments->where('status', 'in_progress')->get()->sortByDesc('created_at');
$deployments_per_server = ApplicationDeploymentQueue::where('server_id', $server_id)->where('status', 'queued')->orWhere('status', 'in_progress')->get();
ray($deployments_per_server->count(), $server->settings->concurrent_builds);
ray('Q:' . $queued_deployments->count() . 'R:' . $running_deployments->count() . '| Queuing deployment: ' . $deployment_uuid . ' of applicationID: ' . $application_id . ' pull request: ' . $pull_request_id . ' with commit: ' . $commit . ' and is it forced: ' . $force_rebuild);
if ($queued_deployments->count() > 1) {
@ -58,8 +59,7 @@ function queue_application_deployment(int $application_id, int $server_id, strin
function queue_next_deployment(Application $application, bool $isNew = false)
{
$next_found = ApplicationDeploymentQueue::where('status', 'queued')->get()->sortByDesc('created_at')->first();
ray('Next found: ' . $next_found);
$next_found = ApplicationDeploymentQueue::where('status', 'queued')->get()->sortBy('created_at')->first();
if ($next_found) {
if ($isNew) {
dispatch(new ApplicationDeploymentNewJob(

View File

@ -24,7 +24,6 @@
"league/flysystem-sftp-v3": "^3.0",
"livewire/livewire": "^3.0",
"lorisleiva/laravel-actions": "^2.7",
"masmerise/livewire-toaster": "^2.0",
"nubs/random-name-generator": "^2.2",
"phpseclib/phpseclib": "~3.0",
"poliander/cron": "^3.0",

73
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "de3b59fade9b132d2582a40dcf3c00f9",
"content-hash": "19b19082b605e09867e6ae65fb8135f6",
"packages": [
{
"name": "amphp/amp",
@ -4485,77 +4485,6 @@
],
"time": "2023-02-05T15:03:45+00:00"
},
{
"name": "masmerise/livewire-toaster",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/masmerise/livewire-toaster.git",
"reference": "89aa127df5d17b915b0818761bdf83e8915036c2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/masmerise/livewire-toaster/zipball/89aa127df5d17b915b0818761bdf83e8915036c2",
"reference": "89aa127df5d17b915b0818761bdf83e8915036c2",
"shasum": ""
},
"require": {
"laravel/framework": "^10.0",
"livewire/livewire": "^3.0",
"php": "~8.2"
},
"conflict": {
"stevebauman/unfinalize": "*"
},
"require-dev": {
"dive-be/php-crowbar": "^1.0",
"laravel/pint": "^1.0",
"nunomaduro/larastan": "^2.0",
"orchestra/testbench": "^8.0",
"phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Toaster": "Masmerise\\Toaster\\Toaster"
},
"providers": [
"Masmerise\\Toaster\\ToasterServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Masmerise\\Toaster\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Muhammed Sari",
"email": "support@muhammedsari.me",
"role": "Developer"
}
],
"description": "Beautiful toast notifications for Laravel / Livewire.",
"homepage": "https://github.com/masmerise/livewire-toaster",
"keywords": [
"alert",
"laravel",
"livewire",
"toast",
"toaster"
],
"support": {
"issues": "https://github.com/masmerise/livewire-toaster/issues",
"source": "https://github.com/masmerise/livewire-toaster/tree/2.0.3"
},
"time": "2023-09-28T12:07:49+00:00"
},
{
"name": "monolog/monolog",
"version": "3.5.0",

View File

@ -1,6 +1,5 @@
import { createApp } from "vue";
import MagicBar from "./components/MagicBar.vue";
import '../../vendor/masmerise/livewire-toaster/resources/js';
import "../../vendor/wire-elements/modal/resources/js/modal";
const app = createApp({});

View File

@ -0,0 +1,439 @@
<div x-data="{
title: 'Default Toast Notification',
description: '',
type: 'default',
position: 'top-center',
expanded: false,
popToast(custom) {
let html = '';
if (typeof custom != 'undefined') {
html = custom;
}
toast(this.title, { description: this.description, type: this.type, position: this.position, html: html })
}
}" x-init="window.toast = function(message, options = {}) {
let description = '';
let type = 'default';
let position = 'top-center';
let html = '';
if (typeof options.description != 'undefined') description = options.description;
if (typeof options.type != 'undefined') type = options.type;
if (typeof options.position != 'undefined') position = options.position;
if (typeof options.html != 'undefined') html = options.html;
window.dispatchEvent(new CustomEvent('toast-show', { detail: { type: type, message: message, description: description, position: position, html: html } }));
}
window.customToastHTML = `
<div class='relative flex items-start justify-center p-4'>
<div class='flex flex-col'>
<p class='text-sm font-medium text-gray-800'>New Friend Request</p>
<p class='mt-1 text-xs leading-none text-gray-800'>Friend request from John Doe.</p>
<div class='flex mt-3'>
<button type='button' @click='burnToast(toast.id)' class='inline-flex items-center px-2 py-1 text-xs font-semibold text-white bg-indigo-600 rounded shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'>Accept</button>
<button type='button' @click='burnToast(toast.id)' class='inline-flex items-center px-2 py-1 ml-3 text-xs font-semibold text-gray-900 bg-white rounded shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50'>Decline</button>
</div>
</div>
</div>
`" class="relative space-y-5">
<template x-teleport="body">
<ul x-data="{
toasts: [],
toastsHovered: false,
expanded: false,
layout: 'default',
position: 'top-center',
paddingBetweenToasts: 15,
deleteToastWithId(id) {
for (let i = 0; i < this.toasts.length; i++) {
if (this.toasts[i].id === id) {
this.toasts.splice(i, 1);
break;
}
}
},
burnToast(id) {
burnToast = this.getToastWithId(id);
burnToastElement = document.getElementById(burnToast.id);
if (burnToastElement) {
if (this.toasts.length == 1) {
if (this.layout == 'default') {
this.expanded = false;
}
burnToastElement.classList.remove('translate-y-0');
if (this.position.includes('bottom')) {
burnToastElement.classList.add('translate-y-full');
} else {
burnToastElement.classList.add('-translate-y-full');
}
burnToastElement.classList.add('-translate-y-full');
}
burnToastElement.classList.add('opacity-0');
let that = this;
setTimeout(function() {
that.deleteToastWithId(id);
setTimeout(function() {
that.stackToasts();
}, 1)
}, 300);
}
},
getToastWithId(id) {
for (let i = 0; i < this.toasts.length; i++) {
if (this.toasts[i].id === id) {
return this.toasts[i];
}
}
},
stackToasts() {
this.positionToasts();
this.calculateHeightOfToastsContainer();
let that = this;
setTimeout(function() {
that.calculateHeightOfToastsContainer();
}, 300);
},
positionToasts() {
if (this.toasts.length == 0) return;
let topToast = document.getElementById(this.toasts[0].id);
topToast.style.zIndex = 100;
if (this.expanded) {
if (this.position.includes('bottom')) {
topToast.style.top = 'auto';
topToast.style.bottom = '0px';
} else {
topToast.style.top = '0px';
}
}
let bottomPositionOfFirstToast = this.getBottomPositionOfElement(topToast);
if (this.toasts.length == 1) return;
let middleToast = document.getElementById(this.toasts[1].id);
middleToast.style.zIndex = 90;
if (this.expanded) {
middleToastPosition = topToast.getBoundingClientRect().height +
this.paddingBetweenToasts + 'px';
if (this.position.includes('bottom')) {
middleToast.style.top = 'auto';
middleToast.style.bottom = middleToastPosition;
} else {
middleToast.style.top = middleToastPosition;
}
middleToast.style.scale = '100%';
middleToast.style.transform = 'translateY(0px)';
} else {
middleToast.style.scale = '94%';
if (this.position.includes('bottom')) {
middleToast.style.transform = 'translateY(-16px)';
} else {
this.alignBottom(topToast, middleToast);
middleToast.style.transform = 'translateY(16px)';
}
}
if (this.toasts.length == 2) return;
let bottomToast = document.getElementById(this.toasts[2].id);
bottomToast.style.zIndex = 80;
if (this.expanded) {
bottomToastPosition = topToast.getBoundingClientRect().height +
this.paddingBetweenToasts +
middleToast.getBoundingClientRect().height +
this.paddingBetweenToasts + 'px';
if (this.position.includes('bottom')) {
bottomToast.style.top = 'auto';
bottomToast.style.bottom = bottomToastPosition;
} else {
bottomToast.style.top = bottomToastPosition;
}
bottomToast.style.scale = '100%';
bottomToast.style.transform = 'translateY(0px)';
} else {
bottomToast.style.scale = '88%';
if (this.position.includes('bottom')) {
bottomToast.style.transform = 'translateY(-32px)';
} else {
this.alignBottom(topToast, bottomToast);
bottomToast.style.transform = 'translateY(32px)';
}
}
if (this.toasts.length == 3) return;
let burnToast = document.getElementById(this.toasts[3].id);
burnToast.style.zIndex = 70;
if (this.expanded) {
burnToastPosition = topToast.getBoundingClientRect().height +
this.paddingBetweenToasts +
middleToast.getBoundingClientRect().height +
this.paddingBetweenToasts +
bottomToast.getBoundingClientRect().height +
this.paddingBetweenToasts + 'px';
if (this.position.includes('bottom')) {
burnToast.style.top = 'auto';
burnToast.style.bottom = burnToastPosition;
} else {
burnToast.style.top = burnToastPosition;
}
burnToast.style.scale = '100%';
burnToast.style.transform = 'translateY(0px)';
} else {
burnToast.style.scale = '82%';
this.alignBottom(topToast, burnToast);
burnToast.style.transform = 'translateY(48px)';
}
burnToast.firstElementChild.classList.remove('opacity-100');
burnToast.firstElementChild.classList.add('opacity-0');
let that = this;
// Burn 🔥 (remove) last toast
setTimeout(function() {
that.toasts.pop();
}, 300);
if (this.position.includes('bottom')) {
middleToast.style.top = 'auto';
}
return;
},
alignBottom(element1, element2) {
// Get the top position and height of the first element
let top1 = element1.offsetTop;
let height1 = element1.offsetHeight;
// Get the height of the second element
let height2 = element2.offsetHeight;
// Calculate the top position for the second element
let top2 = top1 + (height1 - height2);
// Apply the calculated top position to the second element
element2.style.top = top2 + 'px';
},
alignTop(element1, element2) {
// Get the top position of the first element
let top1 = element1.offsetTop;
// Apply the same top position to the second element
element2.style.top = top1 + 'px';
},
resetBottom() {
for (let i = 0; i < this.toasts.length; i++) {
if (document.getElementById(this.toasts[i].id)) {
let toastElement = document.getElementById(this.toasts[i].id);
toastElement.style.bottom = '0px';
}
}
},
resetTop() {
for (let i = 0; i < this.toasts.length; i++) {
if (document.getElementById(this.toasts[i].id)) {
let toastElement = document.getElementById(this.toasts[i].id);
toastElement.style.top = '0px';
}
}
},
getBottomPositionOfElement(el) {
return (el.getBoundingClientRect().height + el.getBoundingClientRect().top);
},
calculateHeightOfToastsContainer() {
if (this.toasts.length == 0) {
$el.style.height = '0px';
return;
}
lastToast = this.toasts[this.toasts.length - 1];
lastToastRectangle = document.getElementById(lastToast.id).getBoundingClientRect();
firstToast = this.toasts[0];
firstToastRectangle = document.getElementById(firstToast.id).getBoundingClientRect();
if (this.toastsHovered) {
if (this.position.includes('bottom')) {
$el.style.height = ((firstToastRectangle.top + firstToastRectangle.height) - lastToastRectangle.top) + 'px';
} else {
$el.style.height = ((lastToastRectangle.top + lastToastRectangle.height) - firstToastRectangle.top) + 'px';
}
} else {
$el.style.height = firstToastRectangle.height + 'px';
}
}
}"
@set-toasts-layout.window="
layout=event.detail.layout;
if(layout == 'expanded'){
expanded=true;
} else {
expanded=false;
}
stackToasts();
"
@toast-show.window="
event.stopPropagation();
if(event.detail.position){
position = event.detail.position;
}
toasts.unshift({
id: 'toast-' + Math.random().toString(16).slice(2),
show: false,
message: event.detail.message,
description: event.detail.description,
type: event.detail.type,
html: event.detail.html
});
"
@mouseenter="toastsHovered=true;" @mouseleave="toastsHovered=false" x-init="if (layout == 'expanded') {
expanded = true;
}
stackToasts();
$watch('toastsHovered', function(value) {
if (layout == 'default') {
if (position.includes('bottom')) {
resetBottom();
} else {
resetTop();
}
if (value) {
// calculate the new positions
expanded = true;
if (layout == 'default') {
stackToasts();
}
} else {
if (layout == 'default') {
expanded = false;
//setTimeout(function(){
stackToasts();
//}, 10);
setTimeout(function() {
stackToasts();
}, 10)
}
}
}
});"
class="fixed block w-full group z-[99] sm:max-w-xs"
:class="{ 'right-0 top-0 sm:mt-6 sm:mr-6': position=='top-right', 'left-0 top-0 sm:mt-6 sm:ml-6': position=='top-left', 'left-1/2 -translate-x-1/2 top-0 sm:mt-6': position=='top-center', 'right-0 bottom-0 sm:mr-6 sm:mb-6': position=='bottom-right', 'left-0 bottom-0 sm:ml-6 sm:mb-6': position=='bottom-left', 'left-1/2 -translate-x-1/2 bottom-0 sm:mb-6': position=='bottom-center' }"
x-cloak>
<template x-for="(toast, index) in toasts" :key="toast.id">
<li :id="toast.id" x-data="{
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');
}
setTimeout(function() {
setTimeout(function() {
if (position.includes('bottom')) {
$el.firstElementChild.classList.remove('opacity-0', 'translate-y-full');
} else {
$el.firstElementChild.classList.remove('opacity-0', '-translate-y-full');
}
$el.firstElementChild.classList.add('opacity-100', 'translate-y-0');
setTimeout(function() {
stackToasts();
}, 10);
}, 5);
}, 50);
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);
}, 4000);"
@mouseover="toastHovered=true" @mouseout="toastHovered=false"
class="absolute w-full duration-300 ease-out select-none sm:max-w-xs"
:class="{ 'toast-no-description': !toast.description }">
<span
class="relative flex flex-col items-start shadow-[0_5px_15px_-3px_rgb(0_0_0_/_0.08)] w-full transition-all duration-300 ease-out bg-coolgray-200 border border-coolgray-100 sm:rounded-md sm:max-w-xs group"
:class="{ 'p-4': !toast.html, 'p-0': toast.html }">
<template x-if="!toast.html">
<div class="relative">
<div class="flex items-center"
:class="{ 'text-green-500': toast.type=='success', 'text-blue-500': toast.type=='info', 'text-orange-400': toast.type=='warning', 'text-red-500': toast.type=='danger', 'text-gray-800': toast.type=='default' }">
<svg x-show="toast.type=='success'" class="w-[18px] h-[18px] mr-1.5 -ml-1"
viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM16.7744 9.63269C17.1238 9.20501 17.0604 8.57503 16.6327 8.22559C16.2051 7.87615 15.5751 7.93957 15.2256 8.36725L10.6321 13.9892L8.65936 12.2524C8.24484 11.8874 7.61295 11.9276 7.248 12.3421C6.88304 12.7566 6.92322 13.3885 7.33774 13.7535L9.31046 15.4903C10.1612 16.2393 11.4637 16.1324 12.1808 15.2547L16.7744 9.63269Z"
fill="currentColor"></path>
</svg>
<svg x-show="toast.type=='info'" class="w-[18px] h-[18px] mr-1.5 -ml-1"
viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM12 9C12.5523 9 13 8.55228 13 8C13 7.44772 12.5523 7 12 7C11.4477 7 11 7.44772 11 8C11 8.55228 11.4477 9 12 9ZM13 12C13 11.4477 12.5523 11 12 11C11.4477 11 11 11.4477 11 12V16C11 16.5523 11.4477 17 12 17C12.5523 17 13 16.5523 13 16V12Z"
fill="currentColor"></path>
</svg>
<svg x-show="toast.type=='warning'" class="w-[18px] h-[18px] mr-1.5 -ml-1"
viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M9.44829 4.46472C10.5836 2.51208 13.4105 2.51168 14.5464 4.46401L21.5988 16.5855C22.7423 18.5509 21.3145 21 19.05 21L4.94967 21C2.68547 21 1.25762 18.5516 2.4004 16.5862L9.44829 4.46472ZM11.9995 8C12.5518 8 12.9995 8.44772 12.9995 9V13C12.9995 13.5523 12.5518 14 11.9995 14C11.4473 14 10.9995 13.5523 10.9995 13V9C10.9995 8.44772 11.4473 8 11.9995 8ZM12.0009 15.99C11.4486 15.9892 11.0003 16.4363 10.9995 16.9886L10.9995 16.9986C10.9987 17.5509 11.4458 17.9992 11.9981 18C12.5504 18.0008 12.9987 17.5537 12.9995 17.0014L12.9995 16.9914C13.0003 16.4391 12.5532 15.9908 12.0009 15.99Z"
fill="currentColor"></path>
</svg>
<svg x-show="toast.type=='danger'" class="w-[18px] h-[18px] mr-1.5 -ml-1"
viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
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="font-medium leading-none text-neutral-200"
x-text="toast.message">
</p>
</div>
<p x-show="toast.description" :class="{ 'pl-5': toast.type!='default' }"
class="mt-1.5 text-xs leading-none opacity-70" x-text="toast.description"></p>
</div>
</template>
<template x-if="toast.html">
<div x-html="toast.html"></div>
</template>
<span @click="burnToast(toast.id)"
class="absolute right-0 p-1.5 mr-2.5 text-neutral-400 duration-100 ease-in-out rounded-full opacity-0 cursor-pointer hover:bg-coolgray-400 hover:text-neutral-300"
:class="{
'top-1/2 -translate-y-1/2': !toast.description && !toast.html,
'top-0 mt-2.5': (toast
.description || toast.html),
'opacity-100': toastHovered,
'opacity-0': !
toastHovered
}">
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
</svg>
</span>
</span>
</li>
</template>
</ul>
</template>
</div>

View File

@ -42,7 +42,7 @@
<button>close</button>
</form>
</dialog>
<x-toaster-hub />
<x-toast />
<x-version class="fixed left-2 bottom-1" />
<script data-navigate-once>
@auth
@ -89,7 +89,9 @@ function revive() {
fetch('/api/health')
.then(response => {
if (response.ok) {
Toaster.success('Coolify is back online. Reloading...')
window.toast('Coolify is back online. Reloading...', {
type: 'success',
})
if (checkHealthInterval) clearInterval(checkHealthInterval);
setTimeout(() => {
window.location.reload();
@ -110,7 +112,9 @@ function upgrade() {
if (response.ok) {
console.log('It\'s alive. Waiting for server to be dead...');
} else {
Toaster.success('Update done, restarting Coolify!')
window.toast('Update done, restarting Coolify!', {
type: 'success',
})
console.log('It\'s dead. Reviving... Standby... Bzz... Bzz...')
if (checkIfIamDeadInterval) clearInterval(checkIfIamDeadInterval);
revive();
@ -134,16 +138,36 @@ function copyToClipboard(text) {
}
})
window.Livewire.on('info', (message) => {
if (message) Toaster.info(message)
if (message.length > 0) {
window.toast(message[0], {
type: 'info',
description: message[1],
})
}
})
window.Livewire.on('error', (message) => {
if (message) Toaster.error(message)
if (message.length > 0) {
window.toast(message[0], {
type: 'danger',
description: message[1],
})
}
})
window.Livewire.on('warning', (message) => {
if (message) Toaster.warning(message)
if (message.length > 0) {
window.toast(message[0], {
type: 'warning',
description: message[1],
})
}
})
window.Livewire.on('success', (message) => {
if (message) Toaster.success(message)
if (message.length > 0) {
window.toast(message[0], {
type: 'success',
description: message[1],
})
}
})
window.Livewire.on('installDocker', () => {
installDocker.showModal();

View File

@ -87,10 +87,10 @@
@if ($server->isFunctional())
<h3 class="py-4">Settings</h3>
<div class="flex gap-2">
<x-forms.input id="cleanup_after_percentage" label="Disk cleanup threshold (%)" required
helper="Disk cleanup job will be executed if disk usage is more than this number." />
<x-forms.input id="server.settings.concurrent_builds" label="Number of concurrent builds" required
helper="You can define how many concurrent builds processes / deployments should run at the same time." />
<x-forms.input id="cleanup_after_percentage" label="Disk cleanup threshold (%)" required
helper="Disk cleanup job will be executed if disk usage is more than this number." />
<x-forms.input id="server.settings.concurrent_builds" label="Number of concurrent builds" required
helper="You can define how many concurrent builds processes / deployments should run at the same time." />
</div>
@endif
</form>