Refactor UI components to use 'coolbox' class for consistent styling across various views

- Updated dashboard, destination, project, and server views to replace 'box' class with 'coolbox' for improved visual consistency.
- Modified links and buttons in shared variables and scheduled tasks views to utilize 'coolbox' class.
- Ensured all relevant components reflect the new styling approach, enhancing user experience and interface coherence.
This commit is contained in:
Andras Bacsai
2025-11-28 13:55:54 +01:00
parent d71efadce4
commit d905ae107b
24 changed files with 219 additions and 118 deletions
+4
View File
@@ -179,6 +179,10 @@
@apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem];
}
@utility coolbox {
@apply flex transition-all duration-150 dark:bg-coolgray-100 bg-white p-2 rounded-lg border border-neutral-200 dark:border-coolgray-400 hover:ring-2 dark:hover:ring-yellow-400 hover:ring-coollabs cursor-pointer min-h-[4rem];
}
@utility on-box {
@apply rounded-sm hover:bg-neutral-300 dark:hover:bg-coolgray-500/20;
}
@@ -1,7 +1,6 @@
<div @class([
'transition-all duration-150 box-without-bg dark:bg-coolgray-100 bg-white group p-2 rounded-lg border border-neutral-200 dark:border-coolgray-400 hover:ring-2 dark:hover:ring-yellow-400 hover:ring-coollabs',
'cursor-pointer' => !$upgrade,
'hover:border-l-red-500 cursor-not-allowed' => $upgrade,
'coolbox group',
'!cursor-not-allowed hover:border-l-red-500' => $upgrade,
])>
<div class="flex items-center">
<div class="w-[4.5rem] h-[4.5rem] flex items-center justify-center text-black dark:text-white shrink-0 rounded-lg overflow-hidden">
@@ -17,7 +17,7 @@
@if ($foundUsers->count() > 0)
<div class="flex flex-wrap gap-2 pt-4">
@foreach ($foundUsers as $user)
<div class="box w-64 group" wire:click="switchUser({{ $user->id }})">
<div class="coolbox w-64 group" wire:click="switchUser({{ $user->id }})">
<div class="flex flex-col gap-2">
<div class="box-title">{{ $user->name }}</div>
<div class="box-description">{{ $user->email }}</div>
+2 -2
View File
@@ -35,7 +35,7 @@
@if ($projects->count() > 0)
<div class="grid grid-cols-1 gap-4 xl:grid-cols-2">
@foreach ($projects as $project)
<div class="relative gap-2 cursor-pointer box group">
<div class="relative gap-2 cursor-pointer coolbox group">
<a href="{{ $project->navigateTo() }}" class="absolute inset-0"></a>
<div class="flex flex-1 mx-6">
<div class="flex flex-col justify-center flex-1">
@@ -103,7 +103,7 @@
@foreach ($servers as $server)
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
@class([
'gap-2 border cursor-pointer box group',
'gap-2 border cursor-pointer coolbox group',
'border-red-500' =>
!$server->settings->is_reachable || $server->settings->force_disabled,
])>
@@ -17,7 +17,7 @@
@forelse ($servers as $server)
@forelse ($server->destinations() as $destination)
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
<a class="box group"
<a class="coolbox group"
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
<div class="flex flex-col justify-center mx-6">
<div class="box-title">{{ $destination->name }}</div>
@@ -26,7 +26,7 @@
</a>
@endif
@if ($destination->getMorphClass() === 'App\Models\SwarmDocker')
<a class="box group"
<a class="coolbox group"
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
<div class="flex flex-col mx-6">
<div class="box-title">{{ $destination->name }}</div>
@@ -13,7 +13,7 @@
<div class="subtitle">All your projects are here.</div>
<div class="grid grid-cols-1 gap-4 xl:grid-cols-2 -mt-1">
@foreach ($projects as $project)
<div class="relative gap-2 cursor-pointer box group">
<div class="relative gap-2 cursor-pointer coolbox group">
<a href="{{ $project->navigateTo() }}" class="absolute inset-0"></a>
<div class="flex flex-1 mx-6">
<div class="flex flex-col justify-center flex-1">
@@ -7,7 +7,7 @@
<div class="flex flex-col justify-center gap-2 text-left ">
@forelse ($private_keys as $key)
@if ($private_key_id == $key->id)
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-100 box"
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-100 coolbox"
wire:click="setPrivateKey('{{ $key->id }}')" wire:key="{{ $key->id }}">
<div class="flex flex-col mx-6">
<div class="box-title">
@@ -20,7 +20,7 @@
</div>
</div>
@else
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-100 box"
<div class="gap-2 py-4 cursor-pointer group hover:bg-coollabs bg-coolgray-100 coolbox"
wire:click="setPrivateKey('{{ $key->id }}')" wire:key="{{ $key->id }}">
<div class="flex flex-col mx-6">
<div class="box-title">
@@ -21,7 +21,7 @@
<div class="flex flex-col justify-center gap-2 text-left">
@foreach ($github_apps as $ghapp)
<div class="flex">
<div class="w-full gap-2 py-4 bg-white cursor-pointer group hover:bg-coollabs dark:bg-coolgray-200 box"
<div class="w-full gap-2 py-4 bg-white cursor-pointer group hover:bg-coollabs dark:bg-coolgray-200 coolbox"
wire:click.prevent="loadRepositories({{ $ghapp->id }})"
wire:key="{{ $ghapp->id }}">
<div class="flex mr-4">
@@ -1,8 +1,9 @@
<div x-data x-init="$wire.loadServers">
<div x-data="searchResources()">
@if ($current_step === 'type')
<div x-init="window.addEventListener('scroll', () => isSticky = window.pageYOffset > 100)" class="sticky z-10 top-0 py-4 backdrop-blur-sm border-b border-neutral-200 dark:border-coolgray-400">
<div class="flex flex-col gap-4 lg:flex-row mb-4">
<div x-init="window.addEventListener('scroll', () => isSticky = window.pageYOffset > 100)"
class="sticky z-10 top-0 backdrop-blur-sm border-b border-neutral-200 dark:border-coolgray-400">
<div class="flex flex-col gap-4 lg:flex-row">
<h1>New Resource</h1>
<div class="w-full lg:w-96">
<x-forms.select wire:model.live="selectedEnvironment">
@@ -23,25 +24,34 @@
<div x-show="loading || categories.length === 0"
class="flex items-center justify-between gap-2 py-1.5 px-3 w-64 text-sm rounded-sm border-0 ring-2 ring-inset ring-neutral-200 dark:ring-coolgray-300 bg-neutral-100 dark:bg-coolgray-200 cursor-not-allowed whitespace-nowrap opacity-50">
<span class="text-sm text-neutral-400 dark:text-neutral-600">Filter by category</span>
<svg class="w-4 h-4 text-neutral-400 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
<svg class="w-4 h-4 text-neutral-400 shrink-0" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 9l-7 7-7-7" />
</svg>
</div>
<!-- Active State -->
<div x-show="!loading && categories.length > 0"
@click="openCategoryDropdown = !openCategoryDropdown; $nextTick(() => { if (openCategoryDropdown) $refs.categorySearchInput.focus() })"
class="flex items-center justify-between gap-2 py-1.5 px-3 w-64 text-sm rounded-sm border-0 ring-2 ring-inset ring-neutral-200 dark:ring-coolgray-300 bg-white dark:bg-coolgray-100 cursor-pointer hover:ring-coolgray-400 transition-all whitespace-nowrap">
<span class="text-sm truncate" x-text="selectedCategory === '' ? 'Filter by category' : selectedCategory" :class="selectedCategory === '' ? 'text-neutral-400 dark:text-neutral-600' : 'capitalize text-black dark:text-white'"></span>
<svg class="w-4 h-4 transition-transform text-neutral-400 shrink-0" :class="{ 'rotate-180': openCategoryDropdown }" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
<span class="text-sm truncate"
x-text="selectedCategory === '' ? 'Filter by category' : selectedCategory"
:class="selectedCategory === '' ? 'text-neutral-400 dark:text-neutral-600' :
'capitalize text-black dark:text-white'"></span>
<svg class="w-4 h-4 transition-transform text-neutral-400 shrink-0"
:class="{ 'rotate-180': openCategoryDropdown }" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 9l-7 7-7-7" />
</svg>
</div>
<!-- Dropdown Menu -->
<div x-show="openCategoryDropdown" x-transition
class="absolute z-50 w-full mt-1 bg-white dark:bg-coolgray-100 border border-neutral-300 dark:border-coolgray-400 rounded shadow-lg overflow-hidden">
<div class="sticky top-0 p-2 bg-white dark:bg-coolgray-100 border-b border-neutral-300 dark:border-coolgray-400">
<input type="text" x-ref="categorySearchInput" x-model="categorySearch" placeholder="Search categories..."
<div
class="sticky top-0 p-2 bg-white dark:bg-coolgray-100 border-b border-neutral-300 dark:border-coolgray-400">
<input type="text" x-ref="categorySearchInput" x-model="categorySearch"
placeholder="Search categories..."
class="w-full px-2 py-1 text-sm rounded border border-neutral-300 dark:border-coolgray-400 bg-white dark:bg-coolgray-200 focus:outline-none focus:ring-2 focus:ring-coolgray-400"
@click.stop>
</div>
@@ -51,7 +61,9 @@
:class="{ 'bg-neutral-50 dark:bg-coolgray-300': selectedCategory === '' }">
<span class="text-sm">All Categories</span>
</div>
<template x-for="category in categories.filter(cat => categorySearch === '' || cat.toLowerCase().includes(categorySearch.toLowerCase()))" :key="category">
<template
x-for="category in categories.filter(cat => categorySearch === '' || cat.toLowerCase().includes(categorySearch.toLowerCase()))"
:key="category">
<div @click="selectedCategory = category; categorySearch = ''; openCategoryDropdown = false"
class="px-3 py-2 cursor-pointer hover:bg-neutral-100 dark:hover:bg-coolgray-200 capitalize"
:class="{ 'bg-neutral-50 dark:bg-coolgray-300': selectedCategory === category }">
@@ -66,7 +78,8 @@
<div x-show="loading">Loading...</div>
<div x-show="!loading" class="flex flex-col gap-4 py-4">
<h2 x-show="filteredGitBasedApplications.length > 0">Applications</h2>
<div x-show="filteredGitBasedApplications.length > 0 || filteredDockerBasedApplications.length > 0" class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div x-show="filteredGitBasedApplications.length > 0 || filteredDockerBasedApplications.length > 0"
class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div x-show="filteredGitBasedApplications.length > 0" class="space-y-4">
<h4>Git Based</h4>
<div class="grid justify-start grid-cols-1 gap-4 text-left">
@@ -75,13 +88,13 @@
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }">
<x-resource-view>
<x-slot:title><span x-text="application.name"></span></x-slot>
<x-slot:description>
<span x-html="window.sanitizeHTML(application.description)"></span>
</x-slot>
<x-slot:logo>
<img class="w-full h-full p-2 transition-all duration-200 dark:bg-white/10 bg-black/10 object-contain"
:src="application.logo">
</x-slot:logo>
<x-slot:description>
<span x-html="window.sanitizeHTML(application.description)"></span>
</x-slot>
<x-slot:logo>
<img class="w-full h-full p-2 transition-all duration-200 dark:bg-white/10 bg-black/10 object-contain"
:src="application.logo">
</x-slot:logo>
</x-resource-view>
</div>
</template>
@@ -95,10 +108,10 @@
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }">
<x-resource-view>
<x-slot:title><span x-text="application.name"></span></x-slot>
<x-slot:description><span x-text="application.description"></span></x-slot>
<x-slot:logo> <img
class="w-full h-full p-2 transition-all duration-200 dark:bg-white/10 bg-black/10 object-contain"
:src="application.logo"></x-slot>
<x-slot:description><span x-text="application.description"></span></x-slot>
<x-slot:logo> <img
class="w-full h-full p-2 transition-all duration-200 dark:bg-white/10 bg-black/10 object-contain"
:src="application.logo"></x-slot>
</x-resource-view>
</div>
</template>
@@ -107,23 +120,23 @@
</div>
<div x-show="filteredDatabases.length > 0" class="mt-8">
<h2 class="mb-4">Databases</h2>
<div x-show="filteredDatabases.length > 0"
class="grid justify-start grid-cols-1 gap-4 text-left xl:grid-cols-3">
<template x-for="database in filteredDatabases" :key="database.id">
<div x-on:click="setType(database.id)"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }">
<x-resource-view>
<x-slot:title><span x-text="database.name"></span></x-slot>
<div x-show="filteredDatabases.length > 0"
class="grid justify-start grid-cols-1 gap-4 text-left xl:grid-cols-3">
<template x-for="database in filteredDatabases" :key="database.id">
<div x-on:click="setType(database.id)"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }">
<x-resource-view>
<x-slot:title><span x-text="database.name"></span></x-slot>
<x-slot:description><span x-text="database.description"></span></x-slot>
<x-slot:logo>
<span x-show="database.logo">
<span x-html="database.logo"></span>
</span>
</x-slot>
</x-resource-view>
</div>
</template>
</div>
<x-slot:logo>
<span x-show="database.logo">
<span x-html="database.logo"></span>
</span>
</x-slot>
</x-resource-view>
</div>
</template>
</div>
</div>
<div x-show="filteredServices.length > 0" class="mt-8">
<div class="flex items-center gap-4" x-init="loadResources">
@@ -131,46 +144,49 @@
<x-forms.button x-on:click="loadResources">Reload List</x-forms.button>
</div>
<x-callout type="info" title="Trademarks Policy" class="mt-4 mb-6">
The respective trademarks mentioned here are owned by the respective companies, and use of them does not imply any affiliation or endorsement.
The respective trademarks mentioned here are owned by the respective companies, and use of them
does not imply any affiliation or endorsement.
</x-callout>
<div class="grid justify-start grid-cols-1 gap-4 text-left xl:grid-cols-3">
<template x-for="service in filteredServices" :key="service.name">
<div x-on:click="setType('one-click-service-' + service.name)"
<div class="relative" x-on:click="setType('one-click-service-' + service.name)"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }">
<x-resource-view>
<x-slot:title>
<template x-if="service.name">
<span x-text="service.name"></span>
</template>
</x-slot>
<x-slot:description>
<template x-if="service.slogan">
<span x-text="service.slogan"></span>
</template>
</x-slot>
<x-slot:logo>
<template x-if="service.logo">
<img class="w-full h-full p-2 transition-all duration-200 dark:bg-white/10 bg-black/10 object-contain"
:src='service.logo'
x-on:error.window="$event.target.src = service.logo_github_url"
onerror="this.onerror=null; this.src=this.getAttribute('data-fallback');"
x-on:error="$event.target.src = '/coolify-logo.svg'"
:data-fallback='service.logo_github_url' />
</template>
</x-slot:logo>
<x-slot:documentation>
<template x-if="service.documentation">
<div class="flex items-center px-2" title="Read the documentation.">
<a class="p-2 rounded-sm hover:bg-gray-100 dark:hover:bg-coolgray-200 hover:no-underline dark:group-hover:text-white text-neutral-600"
onclick="event.stopPropagation()" :href="service.documentation"
target="_blank">
Docs
</a>
</div>
</template>
</x-slot:documentation>
</x-slot>
<x-slot:description>
<template x-if="service.slogan">
<span x-text="service.slogan"></span>
</template>
</x-slot>
<x-slot:logo>
<template x-if="service.logo">
<img class="w-full h-full p-2 transition-all duration-200 dark:bg-white/10 bg-black/10 object-contain"
:src='service.logo'
x-on:error.window="$event.target.src = service.logo_github_url"
onerror="this.onerror=null; this.src=this.getAttribute('data-fallback');"
x-on:error="$event.target.src = '/coolify-logo.svg'"
:data-fallback='service.logo_github_url' />
</template>
</x-slot:logo>
</x-resource-view>
<template x-if="shouldShowDocIcon(service)">
<a :href="getDocLink(service) || coolifyDocsUrl(service.name)" target="_blank"
@click.stop @mouseenter="resolveDocLink(service)"
class="absolute top-2 right-2 p-1.5 rounded hover:bg-neutral-200 dark:hover:bg-coolgray-300 transition-colors"
:class="{ 'opacity-50': docCheckInProgress[service.name] }"
title="View documentation">
<svg class="w-4 h-4 text-neutral-600 dark:text-neutral-400" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
</a>
</template>
</div>
</template>
</div>
@@ -197,6 +213,8 @@
gitBasedApplications: [],
dockerBasedApplications: [],
databases: [],
docLinkCache: {}, // Cache resolved doc URLs: { serviceName: url | null }
docCheckInProgress: {}, // Track ongoing checks: { serviceName: boolean }
setType(type) {
if (this.selecting) return;
this.selecting = true;
@@ -221,6 +239,81 @@
this.$refs.searchInput.focus();
});
},
extractBaseServiceName(serviceName) {
// Convert to lowercase and replace spaces with dashes to match original format
const normalized = serviceName.toLowerCase().replace(/\s+/g, '-');
// Remove flavor suffixes: -with-*, -without-*
return normalized.replace(/-(with|without)-.+$/, '');
},
coolifyDocsUrl(serviceName) {
const baseName = this.extractBaseServiceName(serviceName);
return 'https://coolify.io/docs/services/' + baseName;
},
officialDocsUrl(service) {
return service.documentation || null;
},
async checkUrlExists(url) {
if (!url) return false;
try {
const response = await fetch(url, {
method: 'HEAD'
});
return response.ok;
} catch (e) {
// CORS error or network error - assume URL exists
return true;
}
},
async resolveDocLink(service) {
const serviceName = service.name;
// Already cached?
if (this.docLinkCache.hasOwnProperty(serviceName)) {
return this.docLinkCache[serviceName];
}
// Already checking?
if (this.docCheckInProgress[serviceName]) {
return null;
}
this.docCheckInProgress[serviceName] = true;
// 1. Try Coolify docs first
const coolifyUrl = this.coolifyDocsUrl(serviceName);
const coolifyExists = await this.checkUrlExists(coolifyUrl);
if (coolifyExists) {
this.docLinkCache[serviceName] = coolifyUrl;
this.docCheckInProgress[serviceName] = false;
return coolifyUrl;
}
// 2. Fall back to official docs
const officialUrl = this.officialDocsUrl(service);
if (officialUrl) {
const officialExists = await this.checkUrlExists(officialUrl);
if (officialExists) {
this.docLinkCache[serviceName] = officialUrl;
this.docCheckInProgress[serviceName] = false;
return officialUrl;
}
}
// 3. Both failed - cache null to hide icon
this.docLinkCache[serviceName] = null;
this.docCheckInProgress[serviceName] = false;
return null;
},
getDocLink(service) {
return this.docLinkCache[service.name];
},
shouldShowDocIcon(service) {
const cached = this.docLinkCache[service.name];
// Show icon if: not checked yet OR has a valid URL
return cached === undefined || cached !== null;
},
filterAndSort(items, isSort = true) {
const searchLower = this.search.trim().toLowerCase();
let filtered = Object.values(items);
@@ -231,9 +324,10 @@
filtered = filtered.filter(item => {
if (!item.category) return false;
// Handle comma-separated categories
const categories = item.category.includes(',')
? item.category.split(',').map(c => c.trim().toLowerCase())
: [item.category.toLowerCase()];
const categories = item.category.includes(',') ?
item.category.split(',').map(c => c.trim().toLowerCase()) : [item.category
.toLowerCase()
];
return categories.includes(selectedCategoryLower);
});
}
@@ -297,7 +391,7 @@
</a> </div>
@else
@forelse($servers as $server)
<div class="w-full box group" wire:click="setServer({{ $server }})">
<div class="w-full coolbox group" wire:click="setServer({{ $server }})">
<div class="flex flex-col mx-6">
<div class="box-title">
{{ $server->name }}
@@ -310,7 +404,8 @@
@empty
<div>
<div>No validated & reachable servers found. <a class="underline dark:text-white" href="/servers">
<div>No validated & reachable servers found. <a class="underline dark:text-white"
href="/servers">
Go to servers page
</a></div>
</div>
@@ -326,7 +421,7 @@
<div class="flex flex-col justify-center gap-4 text-left xl:flex-row xl:flex-wrap">
@if ($server->isSwarm())
@foreach ($swarmDockers as $swarmDocker)
<div class="w-full box group" wire:click="setDestination('{{ $swarmDocker->uuid }}')">
<div class="w-full coolbox group" wire:click="setDestination('{{ $swarmDocker->uuid }}')">
<div class="flex flex-col mx-6">
<div class="font-bold dark:group-hover:text-white">
Swarm Docker <span class="text-xs">({{ $swarmDocker->name }})</span>
@@ -336,7 +431,7 @@
@endforeach
@else
@foreach ($standaloneDockers as $standaloneDocker)
<div class="w-full box group" wire:click="setDestination('{{ $standaloneDocker->uuid }}')">
<div class="w-full coolbox group" wire:click="setDestination('{{ $standaloneDocker->uuid }}')">
<div class="flex flex-col mx-6">
<div class="box-title">
Standalone Docker <span class="text-xs">({{ $standaloneDocker->name }})</span>
@@ -370,7 +465,8 @@
<div class="flex items-center px-2" title="Read the documentation.">
<a class="p-2 hover:underline dark:group-hover:text-white dark:text-white text-neutral-6000"
onclick="event.stopPropagation()" href="https://hub.docker.com/_/postgres/" target="_blank">
onclick="event.stopPropagation()" href="https://hub.docker.com/_/postgres/"
target="_blank">
Documentation
</a>
</div>
@@ -388,7 +484,8 @@
<div class="flex-1"></div>
<div class="flex items-center px-2" title="Read the documentation.">
<a class="p-2 hover:underline dark:group-hover:text-white dark:text-white text-neutral-600"
onclick="event.stopPropagation()" href="https://github.com/supabase/postgres" target="_blank">
onclick="event.stopPropagation()" href="https://github.com/supabase/postgres"
target="_blank">
Documentation
</a>
</div>
@@ -426,7 +523,8 @@
<div class="flex items-center px-2" title="Read the documentation.">
<a class="p-2 hover:underline dark:group-hover:text-white dark:text-white text-neutral-600"
onclick="event.stopPropagation()" href="https://github.com/pgvector/pgvector" target="_blank">
onclick="event.stopPropagation()" href="https://github.com/pgvector/pgvector"
target="_blank">
Documentation
</a>
</div>
@@ -441,4 +539,4 @@
<x-forms.button type="submit">Add Database</x-forms.button>
</form>
@endif
</div>
</div>
@@ -54,7 +54,7 @@
@if ($environment->isEmpty())
@can('createAnyResource')
<a href="{{ route('project.resource.create', ['project_uuid' => data_get($parameters, 'project_uuid'), 'environment_uuid' => data_get($environment, 'uuid')]) }}"
class="items-center justify-center box">+ Add Resource</a>
class="items-center justify-center coolbox">+ Add Resource</a>
@else
<div
class="flex flex-col items-center justify-center p-8 text-center border border-dashed border-neutral-300 dark:border-coolgray-300 rounded-lg">
@@ -94,7 +94,7 @@
class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
<template x-for="item in filteredApplications" :key="item.uuid">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<a class="h-24 coolbox group" :href="item.hrefLink">
<div class="flex flex-col w-full">
<div class="flex gap-2 px-4">
<div class="pb-2 truncate box-title" x-text="item.name"></div>
@@ -143,7 +143,7 @@
class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
<template x-for="item in filteredDatabases" :key="item.uuid">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<a class="h-24 coolbox group" :href="item.hrefLink">
<div class="flex flex-col w-full">
<div class="flex gap-2 px-4">
<div class="pb-2 truncate box-title" x-text="item.name"></div>
@@ -192,7 +192,7 @@
class="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2 xl:grid-cols-3">
<template x-for="item in filteredServices" :key="item.uuid">
<span>
<a class="h-24 box group" :href="item.hrefLink">
<a class="h-24 coolbox group" :href="item.hrefLink">
<div class="flex flex-col w-full">
<div class="flex gap-2 px-4">
<div class="pb-2 truncate box-title" x-text="item.name"></div>
@@ -90,7 +90,7 @@
<div class="grid grid-cols-1 gap-4">
@foreach ($networks as $network)
<div wire:click="addServer('{{ $network->id }}','{{ data_get($network, 'server.id') }}')"
class="relative flex flex-col dark:text-white box group">
class="relative flex flex-col dark:text-white coolbox group">
<div>
<div class="box-title">
Server: {{ data_get($network, 'server.name') }}
@@ -14,7 +14,7 @@
<div class="flex flex-col flex-wrap gap-2 pt-4">
@forelse($resource->scheduled_tasks as $task)
@if ($resource->type() == 'application')
<a class="box"
<a class="coolbox"
href="{{ route('project.application.scheduled-tasks', [...$parameters, 'task_uuid' => $task->uuid]) }}">
<span class="flex flex-col">
<span class="text-lg font-bold">{{ $task->name }}
@@ -29,7 +29,7 @@
</span>
</a>
@elseif ($resource->type() == 'service')
<a class="box"
<a class="coolbox"
href="{{ route('project.service.scheduled-tasks', [...$parameters, 'task_uuid' => $task->uuid]) }}">
<span class="flex flex-col">
<span class="text-lg font-bold">{{ $task->name }}
@@ -21,7 +21,7 @@
<div class="text-xs truncate subtitle lg:text-sm">{{ $project->name }}.</div>
<div class="grid gap-2 lg:grid-cols-2">
@forelse ($project->environments->sortBy('created_at') as $environment)
<div class="gap-2 box group">
<div class="gap-2 coolbox group">
<div class="flex flex-1 mx-6">
<a class="flex flex-col justify-center flex-1"
href="{{ route('project.resource.index', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid]) }}">
@@ -16,7 +16,7 @@
@forelse ($privateKeys as $key)
@can('view', $key)
{{-- Admin/Owner: Clickable link --}}
<a class="box group"
<a class="coolbox group"
href="{{ route('security.private-key.show', ['private_key_uuid' => data_get($key, 'uuid')]) }}">
<div class="flex flex-col justify-center mx-6">
<div class="box-title">
@@ -33,7 +33,7 @@
</a>
@else
{{-- Member: Visible but not clickable --}}
<div class="box opacity-60 cursor-not-allowed hover:bg-transparent dark:hover:bg-transparent" title="You don't have permission to view this private key">
<div class="coolbox opacity-60 !cursor-not-allowed hover:bg-transparent dark:hover:bg-transparent" title="You don't have permission to view this private key">
<div class="flex flex-col justify-center mx-6">
<div class="box-title">
{{ data_get($key, 'name') }}
@@ -4,7 +4,7 @@
<div>
<x-modal-input title="Connect a Hetzner Server">
<x-slot:content>
<div class="relative gap-2 cursor-pointer box group">
<div class="relative gap-2 cursor-pointer coolbox group">
<div class="flex items-center gap-4 mx-6">
<svg class="w-10 h-10 flex-shrink-0" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<rect width="200" height="200" fill="#D50C2D" rx="8" />
@@ -15,7 +15,7 @@
@forelse ($servers as $server)
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
@class([
'gap-2 border cursor-pointer box group',
'gap-2 border cursor-pointer coolbox group',
'border-red-500' =>
!$server->settings->is_reachable || $server->settings->force_disabled,
])>
@@ -170,13 +170,13 @@
<div class="subtitle">Select a proxy you would like to use on this server.</div>
@can('update', $server)
<div class="grid gap-4">
<x-forms.button class="box" wire:click="selectProxy('NONE')">
<x-forms.button class="coolbox" wire:click="selectProxy('NONE')">
Custom (None)
</x-forms.button>
<x-forms.button class="box" wire:click="selectProxy('TRAEFIK')">
<x-forms.button class="coolbox" wire:click="selectProxy('TRAEFIK')">
Traefik
</x-forms.button>
<x-forms.button class="box" wire:click="selectProxy('CADDY')">
<x-forms.button class="coolbox" wire:click="selectProxy('CADDY')">
Caddy
</x-forms.button>
{{-- <x-forms.button disabled class="box">
@@ -11,7 +11,7 @@
<h2>Project: {{ data_get($project, 'name') }}</h2>
<div class="pt-0 pb-3">{{ data_get($project, 'description') }}</div>
@forelse ($project->environments as $environment)
<a class="box group"
<a class="coolbox group"
href="{{ route('shared-variables.environment.show', [
'project_uuid' => $project->uuid,
'environment_uuid' => $environment->uuid,
@@ -8,19 +8,19 @@
<div class="subtitle">Set Team / Project / Environment wide variables.</div>
<div class="flex flex-col gap-2 -mt-1">
<a class="box group" href="{{ route('shared-variables.team.index') }}">
<a class="coolbox group" href="{{ route('shared-variables.team.index') }}">
<div class="flex flex-col justify-center mx-6">
<div class="box-title">Team wide</div>
<div class="box-description">Usable for all resources in a team.</div>
</div>
</a>
<a class="box group" href="{{ route('shared-variables.project.index') }}">
<a class="coolbox group" href="{{ route('shared-variables.project.index') }}">
<div class="flex flex-col justify-center mx-6">
<div class="box-title">Project wide</div>
<div class="box-description">Usable for all resources in a project.</div>
</div>
</a>
<a class="box group" href="{{ route('shared-variables.environment.index') }}">
<a class="coolbox group" href="{{ route('shared-variables.environment.index') }}">
<div class="flex flex-col justify-center mx-6">
<div class="box-title">Environment wide</div>
<div class="box-description">Usable for all resources in an environment.</div>
@@ -8,7 +8,7 @@
<div class="subtitle">List of your projects.</div>
<div class="flex flex-col gap-2">
@forelse ($projects as $project)
<a class="box group"
<a class="coolbox group"
href="{{ route('shared-variables.project.show', ['project_uuid' => data_get($project, 'uuid')]) }}">
<div class="flex flex-col justify-center mx-6 ">
<div class="box-title">{{ $project->name }}</div>
@@ -35,7 +35,7 @@
</svg>
<span>You must complete this step before you can use this source!</span>
</div>
<a class="items-center justify-center box" href="{{ getInstallationPath($github_app) }}">
<a class="items-center justify-center coolbox" href="{{ getInstallationPath($github_app) }}">
Install Repositories on GitHub
</a>
@else
@@ -13,7 +13,7 @@
<div class="subtitle">S3 storages for backups.</div>
<div class="grid gap-4 lg:grid-cols-2 -mt-1">
@forelse ($s3 as $storage)
<a href="/storages/{{ $storage->uuid }}" @class(['gap-2 border cursor-pointer box group'])>
<a href="/storages/{{ $storage->uuid }}" @class(['gap-2 border cursor-pointer coolbox group'])>
<div class="flex flex-col justify-center mx-6">
<div class="box-title">
{{ $storage->name }}
+4 -4
View File
@@ -8,7 +8,7 @@
<div class="flex flex-wrap gap-2 ">
@forelse ($tags as $oneTag)
<a :class="{{ $tag?->id == $oneTag->id }} && 'dark:bg-coollabs'"
class="min-w-32 box-without-bg dark:bg-coolgray-100 dark:text-white font-bold dark:hover:bg-coollabs-100 flex justify-center items-center"
class="min-w-32 coolbox dark:text-white font-bold flex justify-center items-center"
href="{{ route('tags.show', ['tagName' => $oneTag->name]) }}">{{ data_get_str($oneTag, 'name')->limit(30) }}</a>
@empty
<div>No tags yet defined yet. Go to a resource and add a tag there.</div>
@@ -34,7 +34,7 @@
<div class="grid grid-cols-1 gap-2 pt-4 lg:grid-cols-2 xl:grid-cols-3">
@if (isset($applications) && count($applications) > 0)
@foreach ($applications as $application)
<a href="{{ $application->link() }}" class="box group">
<a href="{{ $application->link() }}" class="coolbox group">
<div class="flex flex-col justify-center">
<div class="box-title">
{{ $application->project()->name }}/{{ $application->environment->name }}
@@ -47,7 +47,7 @@
@endif
@if (isset($services) && count($services) > 0)
@foreach ($services as $service)
<a href="{{ $service->link() }}" class="flex flex-col box group">
<a href="{{ $service->link() }}" class="flex flex-col coolbox group">
<div class="flex flex-col">
<div class="box-title">
{{ $service->project()->name }}/{{ $service->environment->name }}
@@ -71,7 +71,7 @@
<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',
'gap-2 cursor-pointer coolbox group border-l-2 border-dotted',
'dark:border-coolgray-300' => data_get($deployment, 'status') === 'queued',
'border-yellow-500' => data_get($deployment, 'status') === 'in_progress',
])>
+1 -1
View File
@@ -14,7 +14,7 @@
<div class="grid gap-4 lg:grid-cols-2 -mt-1">
@forelse ($sources as $source)
@if ($source->getMorphClass() === 'App\Models\GithubApp')
<a class="flex gap-2 text-center hover:no-underline box group"
<a class="flex gap-2 text-center hover:no-underline coolbox group"
href="{{ route('source.github.show', ['github_app_uuid' => data_get($source, 'uuid')]) }}">
{{-- <x-git-icon class="dark:text-white w-8 h-8 mt-1" git="{{ $source->getMorphClass() }}" /> --}}
<div class="text-left dark:group-hover:text-white flex flex-col justify-center mx-6">