feat: tags and tag deploy webhooks
This commit is contained in:
@@ -76,7 +76,7 @@ a {
|
||||
}
|
||||
|
||||
.box-without-bg {
|
||||
@apply flex p-2 transition-colors min-h-full hover:text-white hover:no-underline min-h-[4rem];
|
||||
@apply flex p-2 transition-colors hover:text-white hover:no-underline min-h-[4rem];
|
||||
}
|
||||
|
||||
.description {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
class="transition rounded w-11 h-11" src="{{ asset('coolify-transparent.png') }}"></a>
|
||||
<ul class="flex flex-col h-full gap-4 menu flex-nowrap">
|
||||
<li title="Dashboard">
|
||||
<a class="hover:bg-transparent" href="/">
|
||||
<a class="hover:bg-transparent" href="/">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="{{ request()->is('/') ? 'text-warning icon' : 'icon' }}"
|
||||
fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
@@ -13,7 +13,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li title="Servers">
|
||||
<a class="hover:bg-transparent" href="/servers">
|
||||
<a class="hover:bg-transparent" href="/servers">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="{{ request()->is('server/*') || request()->is('servers') ? 'text-warning icon' : 'icon' }}"
|
||||
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
@@ -28,7 +28,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li title="Projects">
|
||||
<a class="hover:bg-transparent" href="/projects">
|
||||
<a class="hover:bg-transparent" href="/projects">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="{{ request()->is('project/*') || request()->is('projects') ? 'text-warning icon' : 'icon' }}"
|
||||
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
@@ -41,7 +41,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li title="Command Center">
|
||||
<a class="hover:bg-transparent" href="/command-center">
|
||||
<a class="hover:bg-transparent" href="/command-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="{{ request()->is('command-center') ? 'text-warning icon' : 'icon' }}" viewBox="0 0 24 24"
|
||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
@@ -53,7 +53,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li title="Source">
|
||||
<a class="hover:bg-transparent" href="{{ route('source.all') }}">
|
||||
<a class="hover:bg-transparent" href="{{ route('source.all') }}">
|
||||
<svg class="icon" viewBox="0 0 15 15" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor"
|
||||
d="m6.793 1.207l.353.354l-.353-.354ZM1.207 6.793l-.353-.354l.353.354Zm0 1.414l.354-.353l-.354.353Zm5.586 5.586l-.354.353l.354-.353Zm1.414 0l-.353-.354l.353.354Zm5.586-5.586l.353.354l-.353-.354Zm0-1.414l-.354.353l.354-.353ZM8.207 1.207l.354-.353l-.354.353ZM6.44.854L.854 6.439l.707.707l5.585-5.585L6.44.854ZM.854 8.56l5.585 5.585l.707-.707l-5.585-5.585l-.707.707Zm7.707 5.585l5.585-5.585l-.707-.707l-5.585 5.585l.707.707Zm5.585-7.707L8.561.854l-.707.707l5.585 5.585l.707-.707Zm0 2.122a1.5 1.5 0 0 0 0-2.122l-.707.707a.5.5 0 0 1 0 .708l.707.707ZM6.44 14.146a1.5 1.5 0 0 0 2.122 0l-.707-.707a.5.5 0 0 1-.708 0l-.707.707ZM.854 6.44a1.5 1.5 0 0 0 0 2.122l.707-.707a.5.5 0 0 1 0-.708L.854 6.44Zm6.292-4.878a.5.5 0 0 1 .708 0L8.56.854a1.5 1.5 0 0 0-2.122 0l.707.707Zm-2 1.293l1 1l.708-.708l-1-1l-.708.708ZM7.5 5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 6V5Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 4.5H8ZM7.5 4a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 3v1Zm0-1A1.5 1.5 0 0 0 6 4.5h1a.5.5 0 0 1 .5-.5V3Zm.646 2.854l1.5 1.5l.707-.708l-1.5-1.5l-.707.708ZM10.5 8a.5.5 0 0 1-.5-.5H9A1.5 1.5 0 0 0 10.5 9V8Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 12 7.5h-1Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 10.5 6v1Zm0-1A1.5 1.5 0 0 0 9 7.5h1a.5.5 0 0 1 .5-.5V6ZM7 5.5v4h1v-4H7Zm.5 5.5a.5.5 0 0 1-.5-.5H6A1.5 1.5 0 0 0 7.5 12v-1Zm.5-.5a.5.5 0 0 1-.5.5v1A1.5 1.5 0 0 0 9 10.5H8Zm-.5-.5a.5.5 0 0 1 .5.5h1A1.5 1.5 0 0 0 7.5 9v1Zm0-1A1.5 1.5 0 0 0 6 10.5h1a.5.5 0 0 1 .5-.5V9Z" />
|
||||
@@ -61,7 +61,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li title="Security">
|
||||
<a class="hover:bg-transparent" href="{{ route('security.private-key.index') }}">
|
||||
<a class="hover:bg-transparent" href="{{ route('security.private-key.index') }}">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
@@ -70,7 +70,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li title="Teams">
|
||||
<a class="hover:bg-transparent" href="{{ route('team.index') }}">
|
||||
<a class="hover:bg-transparent" href="{{ route('team.index') }}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" 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" />
|
||||
@@ -83,6 +83,18 @@
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li title="Tags">
|
||||
<a class="hover:bg-transparent" href="{{ route('tags.index') }}">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2">
|
||||
<path
|
||||
d="M3 8v4.172a2 2 0 0 0 .586 1.414l5.71 5.71a2.41 2.41 0 0 0 3.408 0l3.592-3.592a2.41 2.41 0 0 0 0-3.408l-5.71-5.71A2 2 0 0 0 9.172 6H5a2 2 0 0 0-2 2" />
|
||||
<path d="m18 19l1.592-1.592a4.82 4.82 0 0 0 0-6.816L15 6m-8 4h-.01" />
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<div class="flex-1"></div>
|
||||
@if (isInstanceAdmin() && !isCloud())
|
||||
@@ -103,7 +115,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li title="Profile">
|
||||
<a class="hover:bg-transparent" href="/profile">
|
||||
<a class="hover:bg-transparent" href="/profile">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon" 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" />
|
||||
@@ -116,7 +128,7 @@
|
||||
|
||||
@if (isInstanceAdmin())
|
||||
<li title="Settings" class="mt-auto">
|
||||
<a class="hover:bg-transparent" href="/settings">
|
||||
<a class="hover:bg-transparent" href="/settings">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="{{ request()->is('settings*') ? 'text-warning icon' : 'icon' }}" viewBox="0 0 24 24"
|
||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||
|
||||
@@ -22,20 +22,7 @@
|
||||
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">
|
||||
}" class="relative space-y-5">
|
||||
<template x-teleport="body">
|
||||
<ul x-data="{
|
||||
toasts: [],
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
@click.prevent="activeTab = 'resource-operations'; window.location.hash = 'resource-operations'"
|
||||
href="#">Resource Operations
|
||||
</a>
|
||||
<a :class="activeTab === 'tags' && 'text-white'"
|
||||
@click.prevent="activeTab = 'tags'; window.location.hash = 'tags'" href="#">Tags
|
||||
</a>
|
||||
<a :class="activeTab === 'danger' && 'text-white'"
|
||||
@click.prevent="activeTab = 'danger'; window.location.hash = 'danger'" href="#">Danger Zone
|
||||
</a>
|
||||
@@ -112,6 +115,9 @@
|
||||
<div x-cloak x-show="activeTab === 'resource-operations'">
|
||||
<livewire:project.shared.resource-operations :resource="$application" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'tags'">
|
||||
<livewire:project.shared.tags :resource="$application" />
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'danger'">
|
||||
<livewire:project.shared.danger :resource="$application" />
|
||||
</div>
|
||||
|
||||
@@ -112,9 +112,7 @@
|
||||
helper="If set, it will tag the built image with this tag too. <br><br>Example: If you set it to 'latest', it will push the image with the commit sha tag + with the latest tag."
|
||||
label="Docker Image Tag" />
|
||||
@endif
|
||||
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
@@ -46,24 +46,34 @@
|
||||
@else
|
||||
<div x-data="searchComponent()">
|
||||
<x-forms.input placeholder="Search for name, fqdn..." class="w-full" x-model="search" />
|
||||
<div class="grid gap-2 pt-4 lg:grid-cols-2">
|
||||
<div class="grid gap-4 pt-4 lg:grid-cols-4">
|
||||
<template x-for="item in filteredApplications" :key="item.id">
|
||||
<a class="relative box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
|
||||
<div class="description" x-text="item.description"></div>
|
||||
<div class="description" x-text="item.fqdn"></div>
|
||||
<span class="relative">
|
||||
<a class="h-24 box group" :href="item.hrefLink">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="pb-2 font-bold text-white" x-text="item.name"></div>
|
||||
<div class="description" x-text="item.description"></div>
|
||||
<div class="description" x-text="item.fqdn"></div>
|
||||
</div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
</a>
|
||||
<div class="flex gap-1 pt-1 group-hover:text-white group min-h-6">
|
||||
<template x-for="tag in item.tags">
|
||||
<div class="px-2 py-1 cursor-pointer description bg-coolgray-100 hover:bg-coolgray-300"
|
||||
@click.prevent="gotoTag(tag.name)" x-text="tag.name"></div>
|
||||
</template>
|
||||
<div class="flex items-center px-2 text-xs cursor-pointer text-neutral-500/20 group-hover:text-white hover:bg-coolgray-300"
|
||||
@click.prevent="goto(item)">Add tag</div>
|
||||
</div>
|
||||
<template x-if="item.status.startsWith('running')">
|
||||
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('exited')">
|
||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
<template x-if="item.status.startsWith('restarting')">
|
||||
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||
</template>
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
<template x-for="item in filteredPostgresqls" :key="item.id">
|
||||
<a class="relative box group" :href="item.hrefLink">
|
||||
@@ -184,6 +194,13 @@
|
||||
mysqls: @js($mysqls),
|
||||
mariadbs: @js($mariadbs),
|
||||
services: @js($services),
|
||||
gotoTag(tag) {
|
||||
window.location.href = '/tags/' + tag;
|
||||
},
|
||||
goto(item) {
|
||||
const hrefLink = item.hrefLink;
|
||||
window.location.href = `${hrefLink}#tags`;
|
||||
},
|
||||
get filteredApplications() {
|
||||
if (this.search === '') {
|
||||
return this.applications;
|
||||
|
||||
13
resources/views/livewire/project/shared/tags.blade.php
Normal file
13
resources/views/livewire/project/shared/tags.blade.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<div>
|
||||
<h2>Tags</h2>
|
||||
@foreach ($this->resource->tags as $tag)
|
||||
<div>
|
||||
<div>{{ $tag->name }}</div>
|
||||
<x-forms.button isError wire:click="deleteTag('{{ $tag->id }}','{{ $tag->name }}')">Delete</x-forms.button>
|
||||
</div>
|
||||
@endforeach
|
||||
<form wire:submit='submit'>
|
||||
<x-forms.input label="Add/Assign a tag" wire:model="new_tag" wire:confirm="Are you sure you want to delete this post?" />
|
||||
<x-forms.button type="submit">Add</x-forms.button>
|
||||
</form>
|
||||
</div>
|
||||
10
resources/views/livewire/tags/index.blade.php
Normal file
10
resources/views/livewire/tags/index.blade.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<div>
|
||||
<h1>Tags</h1>
|
||||
<div class="flex gap-2 pt-10">
|
||||
@forelse ($tags as $tag)
|
||||
<a class="box" href="{{ route('tags.show', ['tag_name' => $tag->name]) }}">{{ $tag->name }}</a>
|
||||
@empty
|
||||
<p>No tags yet</p>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
18
resources/views/livewire/tags/show.blade.php
Normal file
18
resources/views/livewire/tags/show.blade.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<div>
|
||||
<h1>Tag: {{ $tag->name }}</h1>
|
||||
<div class="">Tag details</div>
|
||||
<div class="lg:w-[500px] pt-4">
|
||||
<x-forms.input readonly label="Tag Deploy Webhook URL" id="webhook" />
|
||||
</div>
|
||||
<div class="pt-4">
|
||||
<div class="flex items-end gap-2">
|
||||
<h3>Resources</h3>
|
||||
<x-forms.button>Redeploy All</x-forms.button>
|
||||
</div>
|
||||
<div class="grid gap-2 pt-4 lg:grid-cols-2">
|
||||
@foreach ($resources as $resource)
|
||||
<div class="box">{{ data_get($resource, 'name') }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user