ui: redesign applications & settings

fix: follow logs
This commit is contained in:
Andras Bacsai 2022-09-22 12:30:28 +02:00
parent 6dd7f6274a
commit 9066952759
17 changed files with 875 additions and 778 deletions

View File

@ -156,6 +156,7 @@ prisma.setting.findFirst().then(async (settings) => {
setInterval(async () => {
scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:copySSLCertificates")
}, 2000)
// cleanupPrismaEngines
// setInterval(async () => {
// scheduler.workers.has('infrastructure') && scheduler.workers.get('infrastructure').postMessage("action:cleanupPrismaEngines")

View File

@ -9,8 +9,8 @@ Bree.extend(TSBree);
const options: any = {
defaultExtension: 'js',
// logger: new Cabin(),
logger: false,
logger: new Cabin(),
// logger: false,
workerMessageHandler: async ({ name, message }) => {
if (name === 'deployApplication' && message?.deploying) {
if (scheduler.workers.has('autoUpdater') || scheduler.workers.has('cleanupStorage')) {

View File

@ -312,7 +312,7 @@
</div>
<div class="drawer-side">
<label for="main-drawer" class="drawer-overlay w-full" />
<ul class="menu bg-coolgray-300 w-60 p-2 space-y-3 pt-4 ">
<ul class="menu bg-coolgray-200 w-60 p-2 space-y-3 pt-4 ">
<li>
<a
class="no-underline icons hover:text-white hover:bg-pink-500"

View File

@ -0,0 +1,21 @@
<script lang="ts">
import { page } from '$app/stores';
</script>
<ul class="menu border bg-coolgray-100 border-coolgray-200 rounded-box p-2 space-y-2">
<li class="menu-title">
<span>General</span>
</li>
<li class="rounded" class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}`}>
<a href={`/applications/${$page.params.id}`} class="no-underline w-full">Build & Deploy</a>
</li>
<li class="menu-title">
<span>Other</span>
</li>
<li
class="rounded"
class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/features`}
>
<a href={`/applications/${$page.params.id}/features`} class="no-underline w-full">Features</a>
</li>
</ul>

View File

@ -72,6 +72,7 @@
} from '$lib/store';
import { errorNotification, handlerNotFoundLoad } from '$lib/common';
import Tooltip from '$lib/components/Tooltip.svelte';
import Menu from './_Menu.svelte';
let statusInterval: any;
let forceDelete = false;
@ -188,79 +189,33 @@
});
</script>
<nav class="header lg:flex-row flex-col-reverse">
<div class="flex flex-row space-x-2 font-bold pt-10 lg:pt-0">
<div class="flex flex-col items-center justify-center">
<div class="title">
{#if $page.url.pathname === `/applications/${id}`}
Configurations
{:else if $page.url.pathname === `/applications/${id}/secrets`}
Secrets
{:else if $page.url.pathname === `/applications/${id}/storages`}
Persistent Storages
{:else if $page.url.pathname === `/applications/${id}/previews`}
Preview Deployments
{:else if $page.url.pathname === `/applications/${id}/logs`}
Application Logs
{:else if $page.url.pathname === `/applications/${id}/logs/build`}
Build Logs
{:else if $page.url.pathname === `/applications/${id}/configuration/source`}
Select a Git Source
{:else if $page.url.pathname === `/applications/${id}/configuration/destination`}
Select a Destination
{:else if $page.url.pathname === `/applications/${id}/configuration/buildpack`}
Select a Build Pack
{/if}
</div>
<div class="mx-auto max-w-screen-2xl px-6 grid grid-cols-1 lg:grid-cols-2">
<nav class="header flex flex-row order-2 lg:order-1 px-0 lg:px-4">
<div class="title lg:pb-10">
{#if $page.url.pathname === `/applications/${id}` || $page.url.pathname === `/applications/${id}/features`}
Configurations
{:else if $page.url.pathname === `/applications/${id}/secrets`}
Secrets
{:else if $page.url.pathname === `/applications/${id}/storages`}
Persistent Storages
{:else if $page.url.pathname === `/applications/${id}/previews`}
Preview Deployments
{:else if $page.url.pathname === `/applications/${id}/logs`}
Application Logs
{:else if $page.url.pathname === `/applications/${id}/logs/build`}
Build Logs
{:else if $page.url.pathname === `/applications/${id}/configuration/source`}
Select a Git Source
{:else if $page.url.pathname === `/applications/${id}/configuration/destination`}
Select a Destination
{:else if $page.url.pathname === `/applications/${id}/configuration/buildpack`}
Select a Build Pack
{/if}
</div>
{#if application.gitSource?.htmlUrl && application.repository && application.branch}
<a
id="git"
href="{application.gitSource.htmlUrl}/{application.repository}/tree/{application.branch}"
target="_blank"
class="w-6 h-6 lg:w-10 lg:h-10"
>
{#if application.gitSource?.type === 'gitlab'}
<svg viewBox="0 0 128 128" class="icons">
<path
fill="#FC6D26"
d="M126.615 72.31l-7.034-21.647L105.64 7.76c-.716-2.206-3.84-2.206-4.556 0l-13.94 42.903H40.856L26.916 7.76c-.717-2.206-3.84-2.206-4.557 0L8.42 50.664 1.385 72.31a4.792 4.792 0 001.74 5.358L64 121.894l60.874-44.227a4.793 4.793 0 001.74-5.357"
/><path fill="#E24329" d="M64 121.894l23.144-71.23H40.856L64 121.893z" /><path
fill="#FC6D26"
d="M64 121.894l-23.144-71.23H8.42L64 121.893z"
/><path
fill="#FCA326"
d="M8.42 50.663L1.384 72.31a4.79 4.79 0 001.74 5.357L64 121.894 8.42 50.664z"
/><path
fill="#E24329"
d="M8.42 50.663h32.436L26.916 7.76c-.717-2.206-3.84-2.206-4.557 0L8.42 50.664z"
/><path fill="#FC6D26" d="M64 121.894l23.144-71.23h32.437L64 121.893z" /><path
fill="#FCA326"
d="M119.58 50.663l7.035 21.647a4.79 4.79 0 01-1.74 5.357L64 121.894l55.58-71.23z"
/><path
fill="#E24329"
d="M119.58 50.663H87.145l13.94-42.902c.717-2.206 3.84-2.206 4.557 0l13.94 42.903z"
/>
</svg>
{:else if application.gitSource?.type === 'github'}
<svg viewBox="0 0 128 128" class="icons">
<g fill="#ffffff"
><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M64 5.103c-33.347 0-60.388 27.035-60.388 60.388 0 26.682 17.303 49.317 41.297 57.303 3.017.56 4.125-1.31 4.125-2.905 0-1.44-.056-6.197-.082-11.243-16.8 3.653-20.345-7.125-20.345-7.125-2.747-6.98-6.705-8.836-6.705-8.836-5.48-3.748.413-3.67.413-3.67 6.063.425 9.257 6.223 9.257 6.223 5.386 9.23 14.127 6.562 17.573 5.02.542-3.903 2.107-6.568 3.834-8.076-13.413-1.525-27.514-6.704-27.514-29.843 0-6.593 2.36-11.98 6.223-16.21-.628-1.52-2.695-7.662.584-15.98 0 0 5.07-1.623 16.61 6.19C53.7 35 58.867 34.327 64 34.304c5.13.023 10.3.694 15.127 2.033 11.526-7.813 16.59-6.19 16.59-6.19 3.287 8.317 1.22 14.46.593 15.98 3.872 4.23 6.215 9.617 6.215 16.21 0 23.194-14.127 28.3-27.574 29.796 2.167 1.874 4.097 5.55 4.097 11.183 0 8.08-.07 14.583-.07 16.572 0 1.607 1.088 3.49 4.148 2.897 23.98-7.994 41.263-30.622 41.263-57.294C124.388 32.14 97.35 5.104 64 5.104z"
/><path
d="M26.484 91.806c-.133.3-.605.39-1.035.185-.44-.196-.685-.605-.543-.906.13-.31.603-.395 1.04-.188.44.197.69.61.537.91zm2.446 2.729c-.287.267-.85.143-1.232-.28-.396-.42-.47-.983-.177-1.254.298-.266.844-.14 1.24.28.394.426.472.984.17 1.255zM31.312 98.012c-.37.258-.976.017-1.35-.52-.37-.538-.37-1.183.01-1.44.373-.258.97-.025 1.35.507.368.545.368 1.19-.01 1.452zm3.261 3.361c-.33.365-1.036.267-1.552-.23-.527-.487-.674-1.18-.343-1.544.336-.366 1.045-.264 1.564.23.527.486.686 1.18.333 1.543zm4.5 1.951c-.147.473-.825.688-1.51.486-.683-.207-1.13-.76-.99-1.238.14-.477.823-.7 1.512-.485.683.206 1.13.756.988 1.237zm4.943.361c.017.498-.563.91-1.28.92-.723.017-1.308-.387-1.315-.877 0-.503.568-.91 1.29-.924.717-.013 1.306.387 1.306.88zm4.598-.782c.086.485-.413.984-1.126 1.117-.7.13-1.35-.172-1.44-.653-.086-.498.422-.997 1.122-1.126.714-.123 1.354.17 1.444.663zm0 0"
/></g
>
</svg>
{/if}
</a>
<Tooltip triggeredBy="#git">Open on Git</Tooltip>
{/if}
</div>
<div class="lg:block hidden flex-1" />
<div class="flex flex-row flex-wrap space-x-3 justify-center lg:justify-start lg:py-0 px-12 lg:px-0">
</nav>
<div
class="header flex flex-row items-start justify-center lg:justify-end space-x-2 order-1 lg:order-2"
>
{#if $location}
<a id="open" href={$location} target="_blank" class="icons bg-transparent"
><svg
@ -431,14 +386,15 @@
<Tooltip triggeredBy="#deploy">Deploy</Tooltip>
</form>
{/if}
<div class="hidden lg:block border border-coolgray-500 h-8" />
<a
href={$isDeploymentEnabled ? `/applications/${id}` : null}
sveltekit:prefetch
class="hover:text-yellow-500 rounded"
class:text-yellow-500={$page.url.pathname === `/applications/${id}`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}`}
class:text-yellow-500={$page.url.pathname === `/applications/${id}` ||
$page.url.pathname === `/applications/${id}/features`}
class:bg-coolgray-500={$page.url.pathname === `/applications/${id}` ||
$page.url.pathname === `/applications/${id}/features`}
>
<button
disabled={!$isDeploymentEnabled}
@ -653,5 +609,18 @@
<Tooltip triggeredBy="#delete" placement="left">Delete</Tooltip>
{/if}
</div>
</nav>
<slot />
</div>
<div class="mx-auto max-w-screen-2xl px-6 grid grid-cols-1 lg:grid-cols-4">
{#if $page.url.pathname === `/applications/${$page.params.id}` || $page.url.pathname === `/applications/${$page.params.id}/features`}
<nav class="header flex flex-col lg:pt-0">
<Menu />
</nav>
<div class="pt-0 px-5 col-span-0 lg:col-span-3 pb-24">
<slot />
</div>
{:else}
<div class="pt-0 px-5 col-span-0 lg:col-span-4 pb-24">
<slot />
</div>
{/if}
</div>

View File

@ -0,0 +1,160 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ fetch, params, stuff, url }) => {
try {
if (stuff?.application?.id) {
return {
props: {
application: stuff.application,
settings: stuff.settings
}
};
}
const response = await get(`/applications/${params.id}`);
return {
props: {
...response
}
};
} catch (error) {
return {
status: 500,
error: new Error(`Could not load ${url}`)
};
}
};
</script>
<script lang="ts">
export let application: any;
export let settings: any;
import { page } from '$app/stores';
import { get, post } from '$lib/api';
import {
addToast,
appSession,
checkIfDeploymentEnabledApplications,
setLocation,
status,
isDeploymentEnabled
} from '$lib/store';
import { t } from '$lib/translations';
import { errorNotification, getDomain, notNodeDeployments, staticDeployments } from '$lib/common';
import Setting from '$lib/components/Setting.svelte';
const { id } = $page.params;
let debug = application.settings.debug;
let previews = application.settings.previews;
let dualCerts = application.settings.dualCerts;
let autodeploy = application.settings.autodeploy;
let isBot = application.settings.isBot;
let isDBBranching = application.settings.isDBBranching;
async function changeSettings(name: any) {
if (name === 'debug') {
debug = !debug;
}
if (name === 'previews') {
previews = !previews;
}
if (name === 'dualCerts') {
dualCerts = !dualCerts;
}
if (name === 'autodeploy') {
autodeploy = !autodeploy;
}
if (name === 'isBot') {
if ($status.application.isRunning) return;
isBot = !isBot;
application.settings.isBot = isBot;
application.fqdn = null;
setLocation(application, settings);
}
if (name === 'isDBBranching') {
isDBBranching = !isDBBranching;
}
try {
await post(`/applications/${id}/settings`, {
previews,
debug,
dualCerts,
isBot,
autodeploy,
isDBBranching,
branch: application.branch,
projectId: application.projectId
});
return addToast({
message: $t('application.settings_saved'),
type: 'success'
});
} catch (error) {
if (name === 'debug') {
debug = !debug;
}
if (name === 'previews') {
previews = !previews;
}
if (name === 'dualCerts') {
dualCerts = !dualCerts;
}
if (name === 'autodeploy') {
autodeploy = !autodeploy;
}
if (name === 'isBot') {
isBot = !isBot;
}
if (name === 'isDBBranching') {
isDBBranching = !isDBBranching;
}
return errorNotification(error);
} finally {
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
}
}
</script>
<div class="w-full">
<div class="mx-auto w-full">
<div class="flex flex-row border-b border-coolgray-500 mb-6 space-x-2">
<div class="title font-bold pb-3">Features</div>
</div>
<div class="px-4 lg:pb-10 pb-6">
{#if !application.settings.isPublicRepository}
<div class="grid grid-cols-2 items-center">
<Setting
id="autodeploy"
isCenter={false}
bind:setting={autodeploy}
on:click={() => changeSettings('autodeploy')}
title={$t('application.enable_automatic_deployment')}
description={$t('application.enable_auto_deploy_webhooks')}
/>
</div>
{/if}
{#if !application.settings.isBot && !application.settings.isPublicRepository}
<div class="grid grid-cols-2 items-center">
<Setting
id="previews"
isCenter={false}
bind:setting={previews}
on:click={() => changeSettings('previews')}
title={$t('application.enable_mr_pr_previews')}
description={$t('application.enable_preview_deploy_mr_pr_requests')}
/>
</div>
{/if}
<div class="grid grid-cols-2 items-center w-full">
<Setting
id="debug"
isCenter={false}
bind:setting={debug}
on:click={() => changeSettings('debug')}
title={$t('application.debug_logs')}
description={$t('application.enable_debug_log_during_build')}
/>
</div>
</div>
</div>
</div>

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,8 @@
<script lang="ts">
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
const dispatch = createEventDispatcher();
import { onDestroy, onMount } from 'svelte';
import { page } from '$app/stores';
import { get, post } from '$lib/api';
import { t } from '$lib/translations';
import LoadingLogs from '$lib/components/LoadingLogs.svelte';
import { errorNotification } from '$lib/common';
import Tooltip from '$lib/components/Tooltip.svelte';
import { day } from '$lib/dayjs';
@ -15,19 +11,30 @@
let logs: any = [];
let currentStatus: any;
let streamInterval: any;
let followingBuild: any;
let followingLogs: any;
let followingInterval: any;
let logsEl: any;
let fromDb = false;
let cancelInprogress = false;
let position = 0;
const { id } = $page.params;
const cleanAnsiCodes = (str: string) => str.replace(/\x1B\[(\d+)m/g, '');
function detect() {
if (position < logsEl.scrollTop) {
position = logsEl.scrollTop;
} else {
if (followingLogs) {
clearInterval(followingInterval);
followingLogs = false;
}
position = logsEl.scrollTop;
}
}
function followBuild() {
followingBuild = !followingBuild;
if (followingBuild) {
followingLogs = !followingLogs;
if (followingLogs) {
followingInterval = setInterval(() => {
logsEl.scrollTop = logsEl.scrollHeight;
window.scrollTo(0, document.body.scrollHeight);
@ -63,11 +70,10 @@
status = data.status;
currentStatus = status;
fromDb = data.fromDb;
logs = logs.concat(
data.logs.map((log: any) => ({ ...log, line: cleanAnsiCodes(log.line) }))
);
dispatch('updateBuildStatus', { status, took: data.took });
} catch (error) {
return errorNotification(error);
}
@ -98,23 +104,18 @@
});
</script>
<div class="relative ">
<div class="relative" class:pt-10={currentStatus !== 'running'}>
{#if currentStatus === 'running'}
<LoadingLogs />
{/if}
{#if currentStatus === 'queued'}
<div class="text-center font-bold text-xl">{$t('application.build.queued_waiting_exec')}</div>
{:else}
<div class="flex justify-end sticky top-0 p-2 mx-1">
<div class="flex justify-start sticky top-0 pb-2 space-x-2">
<button
id="follow"
on:click={followBuild}
class="bg-transparent btn btn-sm btn-link hover:text-green-500 hover:bg-coolgray-500"
class:text-green-500={followingBuild}
class="btn btn-sm bg-coollabs"
class:bg-coolgray-300={followingLogs}
class:text-applications={followingLogs}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
class="w-6 h-6 mr-2"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
@ -128,51 +129,63 @@
<line x1="12" y1="8" x2="12" y2="16" />
<line x1="16" y1="12" x2="12" y2="16" />
</svg>
{followingLogs ? 'Following Logs...' : 'Follow Logs'}
</button>
<Tooltip triggeredBy="#follow">Follow Logs</Tooltip>
{#if currentStatus === 'running'}
<button
id="cancel"
on:click={cancelBuild}
class:animation-spin={cancelInprogress}
class="bg-transparent btn btn-sm btn-link hover:text-red-500 hover:bg-coolgray-500"
<button
on:click={cancelBuild}
class:animation-spin={cancelInprogress}
class="btn btn-sm"
class:bg-error={!cancelInprogress}
class:bg-coolgray-300={cancelInprogress}
class:text-error={cancelInprogress}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6 mr-2"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
{#if cancelInprogress}
Cancelling...
{:else}
<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" />
<circle cx="12" cy="12" r="9" />
<path d="M10 10l4 4m0 -4l-4 4" />
</svg>
{/if}
</button>
<Tooltip triggeredBy="#cancel">Cancel build</Tooltip>
{/if}
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<circle cx="12" cy="12" r="9" />
<path d="M10 10l4 4m0 -4l-4 4" />
</svg>
{cancelInprogress ? 'Cancelling...' : 'Cancel Build'}
</button>
<button id="streaming" class="btn btn-sm bg-transparent border-none loading" />
<Tooltip triggeredBy="#streaming">Streaming logs</Tooltip>
</div>
{#if logs.length > 0}
<div class="font-mono w-full rounder bg-coolgray-200 p-5 overflow-x-auto overflox-y-auto max-h-[80vh] rounded-md mb-20 flex flex-col whitespace-nowrap -mt-12 scrollbar-thumb-coollabs scrollbar-track-coolgray-200 scrollbar-w-1">
{#each logs as log}
{#if fromDb}
<div>{log.line + '\n'}</div>
{:else}
<div>[{day.unix(log.time).format('HH:mm:ss.SSS')}] {log.line + '\n'}</div>
{/if}
{/each}
</div>
{:else}
<div class="font-mono w-full rounder bg-coolgray-200 p-5 overflow-x-auto overflox-y-auto max-h-[80vh] rounded-md mb-20 flex flex-col whitespace-nowrap -mt-12 scrollbar-thumb-coollabs scrollbar-track-coolgray-200 scrollbar-w-1">
No logs found.
{/if}
{#if currentStatus === 'queued'}
<div
class="font-mono w-full bg-coolgray-200 p-5 overflow-x-auto overflox-y-auto max-h-[80vh] rounded mb-20 flex flex-col whitespace-nowrap scrollbar-thumb-coollabs scrollbar-track-coolgray-200 scrollbar-w-1"
>
{$t('application.build.queued_waiting_exec')}
</div>
{:else if logs.length > 0}
<div
bind:this={logsEl}
on:scroll={detect}
class="font-mono w-full bg-coolgray-200 p-5 overflow-x-auto overflox-y-auto max-h-[80vh] rounded mb-20 flex flex-col scrollbar-thumb-coollabs scrollbar-track-coolgray-200 scrollbar-w-1"
>
{#each logs as log}
{#if fromDb}
<div>{log.line + '\n'}</div>
{:else}
<div>[{day.unix(log.time).format('HH:mm:ss.SSS')}] {log.line + '\n'}</div>
{/if}
{/each}
</div>
{:else}
<div
class="font-mono w-full bg-coolgray-200 p-5 overflow-x-auto overflox-y-auto max-h-[80vh] rounded mb-20 flex flex-col whitespace-nowrap scrollbar-thumb-coollabs scrollbar-track-coolgray-200 scrollbar-w-1"
>
No logs found yet.
</div>
{/if}
{/if}
</div>

View File

@ -107,9 +107,9 @@
}
</script>
<div class="block flex-row justify-start space-x-2 px-5 pt-6 sm:px-10 md:flex">
<div class="block flex-row justify-start space-x-2 px-5 sm:px-10 md:flex">
<div class="mb-4 min-w-[16rem] space-y-2 md:mb-0 ">
<button class="btn btn-sm text-xs w-full bg-error" on:click={resetQueue}
<button class="btn btn-sm w-full bg-error" on:click={resetQueue}
>Reset Build Queue</button
>
<div class="top-4 md:sticky">
@ -167,7 +167,7 @@
<div class="flex space-x-2 pb-10">
<button
disabled={noMoreBuilds}
class=" btn btn-sm w-full text-xs"
class=" btn btn-sm w-full"
on:click={loadMoreBuilds}>{$t('application.build.load_more')}</button
>
</div>

View File

@ -91,26 +91,21 @@
}
</script>
<div class="flex flex-row justify-center space-x-2 px-10 pt-6">
<div class="flex flex-row justify-center space-x-2 px-10">
{#if logs.length === 0}
<div class="text-xl font-bold tracking-tighter">{$t('application.build.waiting_logs')}</div>
{:else}
<div class="relative w-full">
<div class="text-right " />
{#if loadLogsInterval}
<LoadingLogs />
{/if}
<div class="flex justify-end sticky top-0 p-1 mx-1">
<div class="flex justify-start sticky space-x-2 pb-2">
<button
id="follow"
on:click={followBuild}
class="bg-transparent btn btn-sm btn-link"
class:text-green-500={followingLogs}
class="btn btn-sm bg-coollabs"
class:bg-coolgray-300={followingLogs}
class:text-applications={followingLogs}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6"
class="w-6 h-6 mr-2"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
@ -124,10 +119,18 @@
<line x1="12" y1="8" x2="12" y2="16" />
<line x1="16" y1="12" x2="12" y2="16" />
</svg>
{followingLogs ? 'Following Logs...' : 'Follow Logs'}
</button>
<Tooltip triggeredBy="#follow">Follow Logs</Tooltip>
{#if loadLogsInterval}
<button id="streaming" class="btn btn-sm bg-transparent border-none loading" />
<Tooltip triggeredBy="#streaming">Streaming logs</Tooltip>
{/if}
</div>
<div class="font-mono w-full rounder bg-coolgray-200 p-5 overflow-x-auto overflox-y-auto max-h-[80vh] rounded-md mb-20 flex flex-col whitespace-nowrap -mt-12 scrollbar-thumb-coollabs scrollbar-track-coolgray-200 scrollbar-w-1">
<div
bind:this={logsEl}
on:scroll={detect}
class="font-mono w-full bg-coolgray-200 p-5 overflow-x-auto overflox-y-auto max-h-[80vh] rounded mb-20 flex flex-col scrollbar-thumb-coollabs scrollbar-track-coolgray-200 scrollbar-w-1"
>
{#each logs as log}
<p>{log + '\n'}</p>
{/each}

View File

@ -3,29 +3,22 @@
import { appSession } from '$lib/store';
</script>
<ul class="menu bg-coolgray-200 rounded">
<ul class="menu border bg-coolgray-100 border-coolgray-200 rounded-box p-2 space-y-2">
<li class="menu-title">
<span>General</span>
</li>
{#if $appSession.teamId === '0'}
<li
class="hover:bg-coollabs duration-150"
class:bordered={$page.url.pathname === '/settings/coolify'}
class:bg-coolgray-500={$page.url.pathname === '/settings/coolify'}
>
<a href="/settings/coolify" class="no-underline w-full">Coolify Settings</a>
<li class="rounded" class:bg-coollabs={$page.url.pathname === `/settings/coolify`}>
<a href={`/settings/coolify`} class="no-underline w-full">Coolify Settings</a>
</li>
{/if}
<li
class="hover:bg-coollabs duration-150"
class:bordered={$page.url.pathname === '/settings/ssh'}
class:bg-coolgray-500={$page.url.pathname === '/settings/ssh'}
>
<a href="/settings/ssh" class="no-underline w-full">SSH Keys</a>
<li class="menu-title">
<span>Keys & Certificates</span>
</li>
<li
class="hover:bg-coollabs duration-150"
class:bordered={$page.url.pathname === '/settings/certificates'}
class:bg-coolgray-400={$page.url.pathname === '/settings/certificates'}
>
<a href="/settings/certificates" class="no-underline w-full">SSL Certificates</a>
<li class="rounded" class:bg-coollabs={$page.url.pathname === `/settings/ssh`}>
<a href={`/settings/ssh`} class="no-underline w-full">SSH Keys</a>
</li>
<li class="rounded" class:bg-coollabs={$page.url.pathname === `/settings/certificates`}>
<a href={`/settings/certificates`} class="no-underline w-full">SSL Certificates</a>
</li>
</ul>

View File

@ -20,12 +20,14 @@
};
</script>
<div class="mx-auto max-w-6xl px-6 grid grid-cols-1 lg:grid-cols-4">
<nav class="header flex flex-col">
<div class="title pb-10">Settings</div>
<Menu />
<div class="mx-auto max-w-screen-2xl px-6 grid grid-cols-1 lg:grid-cols-4">
<nav class="header flex flex-col px-0">
<div class="title pb-[3.7rem]">Settings</div>
<div class="px-4">
<Menu />
</div>
</nav>
<div class="pt-0 lg:pt-24 px-5 lg:px-0 col-span-0 lg:col-span-3">
<div class="pt-0 lg:pt-[7rem] px-4 lg:px-7 col-span-0 lg:col-span-3">
<slot />
</div>
</div>

View File

@ -55,17 +55,20 @@
}
</script>
<div class="title font-bold pb-3">SSL Certificates</div>
<div class="w-full">
{#if certificates.length === 0}
<div class="text-sm">No SSL Certificate found</div>
<label
for="my-modal"
class="btn btn-primary mt-6"
on:click={() => (isModalActive = true)}>Add SSL Certificate</label
<label for="my-modal" class="btn btn-primary mt-6" on:click={() => (isModalActive = true)}
>Add SSL Certificate</label
>
{:else}
<div class="mx-auto w-full p-6 bg-coolgray-200 rounded shadow-xl">
<div class="mx-auto w-full">
<div class="flex border-b border-coolgray-500 mb-6">
<div class="title font-bold pb-3 pr-4">SSL Certificates</div>
<label for="my-modal" class="btn btn-sm btn-primary" on:click={() => (isModalActive = true)}
>Add SSL Certificate</label
>
</div>
<table class="table w-full">
<thead>
<tr>
@ -80,7 +83,7 @@
<td>{cert.commonName}</td>
<td>{cert.createdAt}</td>
<td
><button on:click={() => deleteCertificate(cert.id)} class="btn btn-error"
><button on:click={() => deleteCertificate(cert.id)} class="btn btn-sm btn-error"
>Delete</button
></td
>
@ -88,9 +91,6 @@
{/each}
</tbody>
</table>
<label for="my-modal" class="btn btn-primary mt-6" on:click={() => (isModalActive = true)}
>Add SSL Certificate</label
>
</div>
{/if}
</div>
@ -129,12 +129,9 @@
/>
</div>
<label for="my-modal">
<button type="submit" class="btn btn-primary mt-4">Upload</button
></label
>
<button on:click={() => (isModalActive = false)} type="button" class="btn"
>Cancel</button
<button type="submit" class="btn btn-sm btn-primary mt-4">Upload</button></label
>
<button on:click={() => (isModalActive = false)} type="button" class="btn btn-sm btn-error">Cancel</button>
</form>
</div>
</div>

View File

@ -196,11 +196,38 @@
}
</script>
<div class="title font-bold pb-3">Coolify Settings</div>
<div class="mx-auto w-full">
<form on:submit|preventDefault={handleSubmit}>
<div class="flex flex-row border-b border-coolgray-500 mb-6">
<div class="title font-bold pb-3 pr-4">Coolify Settings</div>
<div class="flex flex-row space-x-2">
<button
class="btn btn-sm btn-primary"
type="submit"
class:bg-orange-600={forceSave}
class:hover:bg-orange-400={forceSave}
class:loading={loading.save}
disabled={loading.save}
>{loading.save
? $t('forms.saving')
: forceSave
? $t('forms.confirm_continue')
: $t('forms.save')}</button
>
<div class="mx-auto w-full p-6 bg-coolgray-200 rounded shadow-xl">
<div class="flex lg:flex-row flex-col">
<form on:submit|preventDefault={handleSubmit}>
{#if isFqdnSet}
<button on:click|preventDefault={removeFqdn} disabled={loading.remove} class="btn"
>{loading.remove ? $t('forms.removing') : $t('forms.remove_domain')}</button
>
{/if}
<button
on:click={restartCoolify}
class:loading={loading.restart}
class="btn btn-sm btn-error">Restart Coolify</button
>
</div>
</div>
<div class="flex lg:flex-row flex-col">
<div class="grid grid-flow-row gap-2 px-4 pr-5">
<div class="grid grid-cols-2 items-center">
<div>
@ -208,7 +235,7 @@
<Explainer position="dropdown-bottom" explanation={$t('setting.ssl_explainer')} />
</div>
<input
class="w-full bg-coolgray-100"
class="w-full"
bind:value={fqdn}
readonly={!$appSession.isAdmin || isFqdnSet}
disabled={!$appSession.isAdmin || isFqdnSet}
@ -273,7 +300,7 @@
<div class="flex flex-row items-center space-x-2">
<input
class="w-full px-2 bg-coolgray-100"
class="w-full px-2 "
type="number"
bind:value={minPort}
min="1024"
@ -281,7 +308,7 @@
/>
<p>-</p>
<input
class="w-full px-2 bg-coolgray-100"
class="w-full px-2 "
type="number"
bind:value={maxPort}
min={minPort}
@ -306,7 +333,7 @@
</div>
<input
class="w-full bg-coolgray-100"
class="w-full "
placeholder="1.1.1.1,8.8.8.8"
bind:value={DNSServers}
/>
@ -342,36 +369,6 @@
</div>
{/if}
</div>
<div
class="flex flex-col lg:flex-row flex-wrap items-center space-x-3 justify-center lg:justify-start pt-8"
>
<div class="flex lg:flex-row lg:space-x-4 flex-col space-y-2 lg:space-y-0">
<button
class="btn btn-primary"
type="submit"
class:bg-orange-600={forceSave}
class:hover:bg-orange-400={forceSave}
class:loading={loading.save}
disabled={loading.save}
>{loading.save
? $t('forms.saving')
: forceSave
? $t('forms.confirm_continue')
: $t('forms.save')}</button
>
{#if isFqdnSet}
<button on:click|preventDefault={removeFqdn} disabled={loading.remove} class="btn"
>{loading.remove ? $t('forms.removing') : $t('forms.remove_domain')}</button
>
{/if}
<button
on:click={restartCoolify}
class:loading={loading.restart}
class="btn bg-red-600 hover:bg-red-700">Restart Coolify</button
>
</div>
</div>
</form>
</div>
</div>
</form>
</div>

View File

@ -57,19 +57,20 @@
}
</script>
<div class="title font-bold pb-3">SSH Keys</div>
<div class="w-full">
{#if sshKeys.length === 0}
<div class="text-sm">No SSH keys found</div>
<label
for="my-modal"
class="btn btn-primary mt-6"
on:click={() => (isModalActive = true)}>Add SSH Key</label
>
{:else}
<div
class="mx-auto w-full p-6 bg-coolgray-200 rounded shadow-xl"
<label for="my-modal" class="btn btn-primary mt-6" on:click={() => (isModalActive = true)}
>Add SSH Key</label
>
{:else}
<div class="mx-auto w-full">
<div class="flex border-b border-coolgray-500 mb-6">
<div class="title font-bold pb-3 pr-4">SSH Keys</div>
<label for="my-modal" class="btn btn-sm btn-primary" on:click={() => (isModalActive = true)}
>Add SSH Key</label
>
</div>
<table class="table w-full">
<thead>
<tr>
@ -84,7 +85,7 @@
<td>{key.name}</td>
<td>{key.createdAt}</td>
<td
><button on:click={() => deleteSSHKey(key.id)} class="btn btn-error"
><button on:click={() => deleteSSHKey(key.id)} class="btn btn-sm btn-error"
>Delete</button
></td
>
@ -92,11 +93,6 @@
{/each}
</tbody>
</table>
<label
for="my-modal"
class="btn btn-primary mt-6"
on:click={() => (isModalActive = true)}>Add SSH Key</label
>
</div>
{/if}
</div>
@ -116,12 +112,7 @@
<div class="modal-action">
<form on:submit|preventDefault={handleSubmit}>
<label for="name" class="">Name</label>
<input
id="name"
required
bind:value={newSSHKey.name}
class="w-full bg-coolgray-100"
/>
<input id="name" required bind:value={newSSHKey.name} class="w-full bg-coolgray-100" />
<label for="privateKey" class="pt-4">Private Key</label>
<textarea
id="privateKey"
@ -132,11 +123,12 @@
rows={15}
/>
<label for="my-modal">
<button type="submit" class="btn btn-primary mt-4">Save</button
></label
<button type="submit" class="btn btn-sm btn-primary mt-4">Save</button></label
>
<button on:click={() => (isModalActive = false)} type="button" class="btn"
>Cancel</button
<button
on:click={() => (isModalActive = false)}
type="button"
class="btn btn-sm btn-error">Cancel</button
>
</form>
</div>

View File

@ -25,10 +25,10 @@ body {
}
input, .input {
@apply h-12 w-96 rounded border border-transparent bg-transparent bg-coolgray-200 p-2 text-xs tracking-tight text-white placeholder-stone-600 outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 disabled:border disabled:border-dashed disabled:border-coolgray-300 disabled:bg-transparent md:text-sm;
@apply h-12 w-96 rounded border border-transparent bg-coolgray-200 p-2 text-xs tracking-tight text-white placeholder-stone-600 outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 disabled:border disabled:border-dashed disabled:border-coolgray-200 disabled:bg-transparent disabled:bg-coolblack md:text-sm;
}
textarea {
@apply min-w-[14rem] rounded border border-transparent bg-transparent bg-coolgray-200 p-2 text-xs tracking-tight text-white placeholder-stone-600 outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 disabled:border disabled:border-dashed disabled:border-coolgray-300 disabled:bg-transparent md:text-sm;
@apply min-w-[14rem] rounded border border-transparent bg-coolgray-200 p-2 text-xs tracking-tight text-white placeholder-stone-600 outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 disabled:border disabled:border-dashed disabled:border-coolgray-200 disabled:bg-transparent md:text-sm;
}
#svelte .custom-select-wrapper .selectContainer.disabled input {
@ -40,7 +40,7 @@ textarea {
}
#svelte .custom-select-wrapper .selectContainer {
@apply h-12 w-96 rounded border border-coolgray-300 bg-coolgray-200 p-2 px-0 text-xs tracking-tight outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 md:text-sm w-full;
@apply h-12 w-96 rounded bg-coolgray-100 p-2 px-0 text-xs tracking-tight outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 md:text-sm w-full ;
}
#svelte .listContainer {

View File

@ -49,7 +49,7 @@ module.exports = {
"iam": "#C026D3",
coollabs: '#6B16ED',
'coollabs-100': '#7317FF',
coolblack: '#161616',
coolblack: '#141414',
'coolgray-100': '#181818',
'coolgray-200': '#202020',
'coolgray-300': '#242424',