1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -12,3 +12,4 @@ client
 | 
				
			|||||||
apps/api/db/*.db
 | 
					apps/api/db/*.db
 | 
				
			||||||
local-serve
 | 
					local-serve
 | 
				
			||||||
apps/api/db/migration.db-journal
 | 
					apps/api/db/migration.db-journal
 | 
				
			||||||
 | 
					apps/api/core*
 | 
				
			||||||
@@ -161,7 +161,7 @@ async function initServer() {
 | 
				
			|||||||
	} catch (error) { }
 | 
						} catch (error) { }
 | 
				
			||||||
	try {
 | 
						try {
 | 
				
			||||||
		const isOlder = compareVersions('3.8.1', version);
 | 
							const isOlder = compareVersions('3.8.1', version);
 | 
				
			||||||
		if (isOlder === -1) {
 | 
							if (isOlder === 1) {
 | 
				
			||||||
			await prisma.build.updateMany({ where: { status: { in: ['running', 'queued'] } }, data: { status: 'failed' } });
 | 
								await prisma.build.updateMany({ where: { status: { in: ['running', 'queued'] } }, data: { status: 'failed' } });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} catch (error) { }
 | 
						} catch (error) { }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@ import fs from 'fs/promises';
 | 
				
			|||||||
import yaml from 'js-yaml';
 | 
					import yaml from 'js-yaml';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { copyBaseConfigurationFiles, makeLabelForStandaloneApplication, saveBuildLog, setDefaultConfiguration } from '../lib/buildPacks/common';
 | 
					import { copyBaseConfigurationFiles, makeLabelForStandaloneApplication, saveBuildLog, setDefaultConfiguration } from '../lib/buildPacks/common';
 | 
				
			||||||
import { createDirectories, decrypt, defaultComposeConfiguration, executeDockerCmd, getDomain, prisma } from '../lib/common';
 | 
					import { createDirectories, decrypt, defaultComposeConfiguration, executeDockerCmd, getDomain, prisma, decryptApplication } from '../lib/common';
 | 
				
			||||||
import * as importers from '../lib/importers';
 | 
					import * as importers from '../lib/importers';
 | 
				
			||||||
import * as buildpacks from '../lib/buildPacks';
 | 
					import * as buildpacks from '../lib/buildPacks';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -27,7 +27,7 @@ import * as buildpacks from '../lib/buildPacks';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		const th = throttle(async () => {
 | 
							const th = throttle(async () => {
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				const queuedBuilds = await prisma.build.findMany({ where: { status: 'queued' }, orderBy: { createdAt: 'asc' } });
 | 
									const queuedBuilds = await prisma.build.findMany({ where: { status: { in: ['queued', 'running'] } }, orderBy: { createdAt: 'asc' } });
 | 
				
			||||||
				const { concurrentBuilds } = await prisma.setting.findFirst({})
 | 
									const { concurrentBuilds } = await prisma.setting.findFirst({})
 | 
				
			||||||
				if (queuedBuilds.length > 0) {
 | 
									if (queuedBuilds.length > 0) {
 | 
				
			||||||
					parentPort.postMessage({ deploying: true });
 | 
										parentPort.postMessage({ deploying: true });
 | 
				
			||||||
@@ -37,8 +37,13 @@ import * as buildpacks from '../lib/buildPacks';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					for (const queueBuild of queuedBuilds) {
 | 
										for (const queueBuild of queuedBuilds) {
 | 
				
			||||||
						actions.push(async () => {
 | 
											actions.push(async () => {
 | 
				
			||||||
							const application = await prisma.application.findUnique({ where: { id: queueBuild.applicationId }, include: { destinationDocker: true, gitSource: { include: { githubApp: true, gitlabApp: true } }, persistentStorage: true, secrets: true, settings: true, teams: true } })
 | 
												let application = await prisma.application.findUnique({ where: { id: queueBuild.applicationId }, include: { destinationDocker: true, gitSource: { include: { githubApp: true, gitlabApp: true } }, persistentStorage: true, secrets: true, settings: true, teams: true } })
 | 
				
			||||||
							const { id: buildId, type, sourceBranch = null, pullmergeRequestId = null, forceRebuild } = queueBuild
 | 
												let { id: buildId, type, sourceBranch = null, pullmergeRequestId = null, forceRebuild } = queueBuild
 | 
				
			||||||
 | 
												application = decryptApplication(application)
 | 
				
			||||||
 | 
												try {
 | 
				
			||||||
 | 
													if (queueBuild.status === 'running') {
 | 
				
			||||||
 | 
														await saveBuildLog({ line: 'Building halted, restarting...', buildId, applicationId: application.id });
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
								const {
 | 
													const {
 | 
				
			||||||
									id: applicationId,
 | 
														id: applicationId,
 | 
				
			||||||
									repository,
 | 
														repository,
 | 
				
			||||||
@@ -98,7 +103,6 @@ import * as buildpacks from '../lib/buildPacks';
 | 
				
			|||||||
										})
 | 
															})
 | 
				
			||||||
									)
 | 
														)
 | 
				
			||||||
									.digest('hex');
 | 
														.digest('hex');
 | 
				
			||||||
							try {
 | 
					 | 
				
			||||||
								const { debug } = settings;
 | 
													const { debug } = settings;
 | 
				
			||||||
								if (concurrency === 1) {
 | 
													if (concurrency === 1) {
 | 
				
			||||||
									await prisma.build.updateMany({
 | 
														await prisma.build.updateMany({
 | 
				
			||||||
@@ -258,7 +262,6 @@ import * as buildpacks from '../lib/buildPacks';
 | 
				
			|||||||
									];
 | 
														];
 | 
				
			||||||
									if (secrets.length > 0) {
 | 
														if (secrets.length > 0) {
 | 
				
			||||||
										secrets.forEach((secret) => {
 | 
															secrets.forEach((secret) => {
 | 
				
			||||||
											secret.value = decrypt(secret.value)
 | 
					 | 
				
			||||||
											if (pullmergeRequestId) {
 | 
																if (pullmergeRequestId) {
 | 
				
			||||||
												if (secret.isPRMRSecret) {
 | 
																	if (secret.isPRMRSecret) {
 | 
				
			||||||
													envs.push(`${secret.name}=${secret.value}`);
 | 
																		envs.push(`${secret.name}=${secret.value}`);
 | 
				
			||||||
@@ -353,13 +356,16 @@ import * as buildpacks from '../lib/buildPacks';
 | 
				
			|||||||
									where: { id: buildId, status: { in: ['queued', 'running'] } },
 | 
														where: { id: buildId, status: { in: ['queued', 'running'] } },
 | 
				
			||||||
									data: { status: 'failed' }
 | 
														data: { status: 'failed' }
 | 
				
			||||||
								});
 | 
													});
 | 
				
			||||||
								await saveBuildLog({ line: error, buildId, applicationId });
 | 
													await saveBuildLog({ line: error, buildId, applicationId: application.id });
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						});
 | 
											});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					await pAll.default(actions, { concurrency })
 | 
										await pAll.default(actions, { concurrency })
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} catch (error) {
 | 
								} catch (error) {
 | 
				
			||||||
 | 
									console.log(error)
 | 
				
			||||||
			} finally {
 | 
								} finally {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@ import * as serviceFields from './serviceFields'
 | 
				
			|||||||
import { saveBuildLog } from './buildPacks/common';
 | 
					import { saveBuildLog } from './buildPacks/common';
 | 
				
			||||||
import { scheduler } from './scheduler';
 | 
					import { scheduler } from './scheduler';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const version = '3.8.3';
 | 
					export const version = '3.8.4';
 | 
				
			||||||
export const isDev = process.env.NODE_ENV === 'development';
 | 
					export const isDev = process.env.NODE_ENV === 'development';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const algorithm = 'aes-256-ctr';
 | 
					const algorithm = 'aes-256-ctr';
 | 
				
			||||||
@@ -1977,6 +1977,12 @@ export async function cleanupDockerStorage(dockerId, lowDiskSpace, force) {
 | 
				
			|||||||
		} catch (error) {
 | 
							} catch (error) {
 | 
				
			||||||
			//console.log(error);
 | 
								//console.log(error);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							// Cleanup build caches
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								await executeDockerCmd({ dockerId, command: `docker builder prune -a -f` })
 | 
				
			||||||
 | 
							} catch (error) {
 | 
				
			||||||
 | 
								//console.log(error);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2022,3 +2028,27 @@ export function defaultComposeConfiguration(network: string): any {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					export function decryptApplication(application: any) {
 | 
				
			||||||
 | 
					    if (application) {
 | 
				
			||||||
 | 
					        if (application?.gitSource?.githubApp?.clientSecret) {
 | 
				
			||||||
 | 
					            application.gitSource.githubApp.clientSecret = decrypt(application.gitSource.githubApp.clientSecret) || null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (application?.gitSource?.githubApp?.webhookSecret) {
 | 
				
			||||||
 | 
					            application.gitSource.githubApp.webhookSecret = decrypt(application.gitSource.githubApp.webhookSecret) || null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (application?.gitSource?.githubApp?.privateKey) {
 | 
				
			||||||
 | 
					            application.gitSource.githubApp.privateKey = decrypt(application.gitSource.githubApp.privateKey) || null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (application?.gitSource?.gitlabApp?.appSecret) {
 | 
				
			||||||
 | 
					            application.gitSource.gitlabApp.appSecret = decrypt(application.gitSource.gitlabApp.appSecret) || null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (application?.secrets.length > 0) {
 | 
				
			||||||
 | 
					            application.secrets = application.secrets.map((s: any) => {
 | 
				
			||||||
 | 
					                s.value = decrypt(s.value) || null
 | 
				
			||||||
 | 
					                return s;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return application;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -451,6 +451,7 @@ export async function deployApplication(request: FastifyRequest<DeployApplicatio
 | 
				
			|||||||
                data: {
 | 
					                data: {
 | 
				
			||||||
                    id: buildId,
 | 
					                    id: buildId,
 | 
				
			||||||
                    applicationId: id,
 | 
					                    applicationId: id,
 | 
				
			||||||
 | 
					                    sourceBranch: branch,
 | 
				
			||||||
                    branch: application.branch,
 | 
					                    branch: application.branch,
 | 
				
			||||||
                    pullmergeRequestId,
 | 
					                    pullmergeRequestId,
 | 
				
			||||||
                    forceRebuild,
 | 
					                    forceRebuild,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -158,8 +158,11 @@ export async function getTeam(request: FastifyRequest<OnlyId>, reply: FastifyRep
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
        const team = await prisma.team.findUnique({ where: { id }, include: { permissions: true } });
 | 
					        const team = await prisma.team.findUnique({ where: { id }, include: { permissions: true } });
 | 
				
			||||||
        const invitations = await prisma.teamInvitation.findMany({ where: { teamId: team.id } });
 | 
					        const invitations = await prisma.teamInvitation.findMany({ where: { teamId: team.id } });
 | 
				
			||||||
 | 
					        const { teams } = await prisma.user.findUnique({ where: { id: userId }, include: { teams: true } })
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
 | 
					            currentTeam: teamId,
 | 
				
			||||||
            team,
 | 
					            team,
 | 
				
			||||||
 | 
					            teams,
 | 
				
			||||||
            permissions,
 | 
					            permissions,
 | 
				
			||||||
            invitations
 | 
					            invitations
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@ export async function listSources(request: FastifyRequest) {
 | 
				
			|||||||
    try {
 | 
					    try {
 | 
				
			||||||
        const teamId = request.user?.teamId;
 | 
					        const teamId = request.user?.teamId;
 | 
				
			||||||
        const sources = await prisma.gitSource.findMany({
 | 
					        const sources = await prisma.gitSource.findMany({
 | 
				
			||||||
            where: { teams: { some: { id: teamId === '0' ? undefined : teamId } } },
 | 
					            where: { teams: { some: { id: teamId === '0' ? undefined : teamId } }, githubApp: { gitSource: { forPublic: false } } },
 | 
				
			||||||
            include: { teams: true, githubApp: true, gitlabApp: true }
 | 
					            include: { teams: true, githubApp: true, gitlabApp: true }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,7 +146,7 @@ export async function gitHubEvents(request: FastifyRequest<GitHubEvents>): Promi
 | 
				
			|||||||
                    message: 'Queued. Thank you!'
 | 
					                    message: 'Queued. Thank you!'
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
            } else if (githubEvent === 'pull_request') {
 | 
					            } else if (githubEvent === 'pull_request') {
 | 
				
			||||||
                const pullmergeRequestId = body.number;
 | 
					                const pullmergeRequestId = body.number.toString();
 | 
				
			||||||
                const pullmergeRequestAction = body.action;
 | 
					                const pullmergeRequestAction = body.action;
 | 
				
			||||||
                const sourceBranch = body.pull_request.head.ref.includes('/') ? body.pull_request.head.ref.split('/')[2] : body.pull_request.head.ref;
 | 
					                const sourceBranch = body.pull_request.head.ref.includes('/') ? body.pull_request.head.ref.split('/')[2] : body.pull_request.head.ref;
 | 
				
			||||||
                if (!allowedActions.includes(pullmergeRequestAction)) {
 | 
					                if (!allowedActions.includes(pullmergeRequestAction)) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,7 +86,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<div class="w-full">
 | 
					<div class="w-full">
 | 
				
			||||||
	<div class="flex items-center">
 | 
						<div class="flex items-center">
 | 
				
			||||||
		<h1 class="title text-4xl">Hardware Details</h1>
 | 
							<h1 class="title lg:text-3xl">Hardware Details</h1>
 | 
				
			||||||
		<div class="flex space-x-4">
 | 
							<div class="flex space-x-4">
 | 
				
			||||||
			{#if $appSession.teamId === '0'}
 | 
								{#if $appSession.teamId === '0'}
 | 
				
			||||||
				<button on:click={manuallyCleanupStorage} class:loading={loading.cleanup} class="btn btn-sm"
 | 
									<button on:click={manuallyCleanupStorage} class:loading={loading.cleanup} class="btn btn-sm"
 | 
				
			||||||
@@ -101,42 +101,41 @@
 | 
				
			|||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<div class="divider" />
 | 
						<div class="divider" />
 | 
				
			||||||
	<div class="grid grid-flow-col gap-4 grid-rows-3 lg:grid-rows-1">
 | 
						<div class="grid grid-flow-col gap-4 grid-rows-3 justify-start lg:justify-center lg:grid-rows-1">
 | 
				
			||||||
		<div class="stats stats-vertical lg:stats-horizontal w-full mb-5 bg-transparent rounded">
 | 
							<div class="stats stats-vertical min-w-[16rem] mb-5 rounded bg-transparent">
 | 
				
			||||||
			<div class="font-bold flex lg:justify-center">Memory</div>
 | 
					 | 
				
			||||||
			<div class="stat">
 | 
								<div class="stat">
 | 
				
			||||||
				<div class="stat-title">Total</div>
 | 
									<div class="stat-title">Total Memory</div>
 | 
				
			||||||
				<div class="stat-value text-2xl">
 | 
									<div class="stat-value text-2xl">
 | 
				
			||||||
					{(usage?.memory.totalMemMb).toFixed(0)}<span class="text-sm">MB</span>
 | 
										{(usage?.memory.totalMemMb).toFixed(0)}<span class="text-sm">MB</span>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<div class="stat">
 | 
								<div class="stat">
 | 
				
			||||||
				<div class="stat-title">Used</div>
 | 
									<div class="stat-title">Used Memory</div>
 | 
				
			||||||
				<div class="stat-value text-2xl">
 | 
									<div class="stat-value text-2xl">
 | 
				
			||||||
					{(usage?.memory.usedMemMb).toFixed(0)}<span class="text-sm">MB</span>
 | 
										{(usage?.memory.usedMemMb).toFixed(0)}<span class="text-sm">MB</span>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<div class="stat">
 | 
								<div class="stat">
 | 
				
			||||||
				<div class="stat-title">Free</div>
 | 
									<div class="stat-title">Free Memory</div>
 | 
				
			||||||
				<div class="stat-value text-2xl">
 | 
									<div class="stat-value text-2xl">
 | 
				
			||||||
					{usage?.memory.freeMemPercentage}<span class="text-sm">%</span>
 | 
										{usage?.memory.freeMemPercentage}<span class="text-sm">%</span>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class="stats stats-vertical lg:stats-horizontal w-full mb-5 bg-transparent rounded">
 | 
							<div class="stats stats-vertical min-w-[20rem] mb-5 bg-transparent rounded">
 | 
				
			||||||
			<div class="font-bold flex lg:justify-center">CPU</div>
 | 
					
 | 
				
			||||||
			<div class="stat">
 | 
								<div class="stat">
 | 
				
			||||||
				<div class="stat-title">Total</div>
 | 
									<div class="stat-title">Total CPU</div>
 | 
				
			||||||
				<div class="stat-value text-2xl">
 | 
									<div class="stat-value text-2xl">
 | 
				
			||||||
					{usage?.cpu.count}
 | 
										{usage?.cpu.count}
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<div class="stat">
 | 
								<div class="stat">
 | 
				
			||||||
				<div class="stat-title">Usage</div>
 | 
									<div class="stat-title">CPU Usage</div>
 | 
				
			||||||
				<div class="stat-value text-2xl">
 | 
									<div class="stat-value text-2xl">
 | 
				
			||||||
					{usage?.cpu.usage}<span class="text-sm">%</span>
 | 
										{usage?.cpu.usage}<span class="text-sm">%</span>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
@@ -147,24 +146,23 @@
 | 
				
			|||||||
				<div class="stat-value text-2xl">{usage?.cpu.load}</div>
 | 
									<div class="stat-value text-2xl">{usage?.cpu.load}</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<div class="stats stats-vertical lg:stats-horizontal w-full mb-5 bg-transparent rounded">
 | 
							<div class="stats stats-vertical min-w-[16rem] mb-5 bg-transparent rounded">
 | 
				
			||||||
			<div class="font-bold flex lg:justify-center">Disk</div>
 | 
					 | 
				
			||||||
			<div class="stat">
 | 
								<div class="stat">
 | 
				
			||||||
				<div class="stat-title">Total</div>
 | 
									<div class="stat-title">Total Disk</div>
 | 
				
			||||||
				<div class="stat-value text-2xl">
 | 
									<div class="stat-value text-2xl">
 | 
				
			||||||
					{usage?.disk.totalGb}<span class="text-sm">GB</span>
 | 
										{usage?.disk.totalGb}<span class="text-sm">GB</span>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<div class="stat">
 | 
								<div class="stat">
 | 
				
			||||||
				<div class="stat-title">Used</div>
 | 
									<div class="stat-title">Used Disk</div>
 | 
				
			||||||
				<div class="stat-value text-2xl">
 | 
									<div class="stat-value text-2xl">
 | 
				
			||||||
					{usage?.disk.usedGb}<span class="text-sm">GB</span>
 | 
										{usage?.disk.usedGb}<span class="text-sm">GB</span>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			<div class="stat">
 | 
								<div class="stat">
 | 
				
			||||||
				<div class="stat-title">Free</div>
 | 
									<div class="stat-title">Free Disk</div>
 | 
				
			||||||
				<div class="stat-value text-2xl">
 | 
									<div class="stat-value text-2xl">
 | 
				
			||||||
					{usage?.disk.freePercentage}<span class="text-sm">%</span>
 | 
										{usage?.disk.freePercentage}<span class="text-sm">%</span>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<svg viewBox="0 0 128 128" class={isAbsolute ? 'absolute top-0 left-0 -m-8 h-16 w-16' : 'mx-auto w-10 h-10'}>
 | 
					<svg viewBox="0 0 128 128" class={isAbsolute ? 'absolute top-0 left-0 -m-5 h-12 w-12' : 'mx-auto w-10 h-10'}>
 | 
				
			||||||
	<path d="M124.8 52.1c-4.3-2.5-10-2.8-14.8-1.4-.6-5.2-4-9.7-8-12.9l-1.6-1.3-1.4 1.6c-2.7 3.1-3.5 8.3-3.1 12.3.3 2.9 1.2 5.9 3 8.3-1.4.8-2.9 1.9-4.3 2.4-2.8 1-5.9 2-8.9 2H79V49H66V24H51v12H26v13H13v14H1.8l-.2 1.5c-.5 6.4.3 12.6 3 18.5l1.1 2.2.1.2c7.9 13.4 21.7 19 36.8 19 29.2 0 53.3-13.1 64.3-40.6 7.4.4 15-1.8 18.6-8.9l.9-1.8-1.6-1zM28 39h10v11H28V39zm13.1 44.2c0 1.7-1.4 3.1-3.1 3.1-1.7 0-3.1-1.4-3.1-3.1 0-1.7 1.4-3.1 3.1-3.1 1.7.1 3.1 1.4 3.1 3.1zM28 52h10v11H28V52zm-13 0h11v11H15V52zm27.7 50.2c-15.8-.1-24.3-5.4-31.3-12.4 2.1.1 4.1.2 5.9.2 1.6 0 3.2 0 4.7-.1 3.9-.2 7.3-.7 10.1-1.5 2.3 5.3 6.5 10.2 14 13.8h-3.4zM51 63H40V52h11v11zm0-13H40V39h11v11zm13 13H53V52h11v11zm0-13H53V39h11v11zm0-13H53V26h11v11zm13 26H66V52h11v11zM38.8 81.2c-.2-.1-.5-.2-.8-.2-1.2 0-2.2 1-2.2 2.2 0 1.2 1 2.2 2.2 2.2s2.2-1 2.2-2.2c0-.3-.1-.6-.2-.8-.2.3-.4.5-.8.5-.5 0-.9-.4-.9-.9.1-.4.3-.7.5-.8z" fill="#019BC6"></path>
 | 
						<path d="M124.8 52.1c-4.3-2.5-10-2.8-14.8-1.4-.6-5.2-4-9.7-8-12.9l-1.6-1.3-1.4 1.6c-2.7 3.1-3.5 8.3-3.1 12.3.3 2.9 1.2 5.9 3 8.3-1.4.8-2.9 1.9-4.3 2.4-2.8 1-5.9 2-8.9 2H79V49H66V24H51v12H26v13H13v14H1.8l-.2 1.5c-.5 6.4.3 12.6 3 18.5l1.1 2.2.1.2c7.9 13.4 21.7 19 36.8 19 29.2 0 53.3-13.1 64.3-40.6 7.4.4 15-1.8 18.6-8.9l.9-1.8-1.6-1zM28 39h10v11H28V39zm13.1 44.2c0 1.7-1.4 3.1-3.1 3.1-1.7 0-3.1-1.4-3.1-3.1 0-1.7 1.4-3.1 3.1-3.1 1.7.1 3.1 1.4 3.1 3.1zM28 52h10v11H28V52zm-13 0h11v11H15V52zm27.7 50.2c-15.8-.1-24.3-5.4-31.3-12.4 2.1.1 4.1.2 5.9.2 1.6 0 3.2 0 4.7-.1 3.9-.2 7.3-.7 10.1-1.5 2.3 5.3 6.5 10.2 14 13.8h-3.4zM51 63H40V52h11v11zm0-13H40V39h11v11zm13 13H53V52h11v11zm0-13H53V39h11v11zm0-13H53V26h11v11zm13 26H66V52h11v11zM38.8 81.2c-.2-.1-.5-.2-.8-.2-1.2 0-2.2 1-2.2 2.2 0 1.2 1 2.2 2.2 2.2s2.2-1 2.2-2.2c0-.3-.1-.6-.2-.8-.2.3-.4.5-.8.5-.5 0-.9-.4-.9-.9.1-.4.3-.7.5-.8z" fill="#019BC6"></path>
 | 
				
			||||||
	</svg>
 | 
						</svg>
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<img
 | 
					<img
 | 
				
			||||||
	alt="ghost logo"
 | 
						alt="ghost logo"
 | 
				
			||||||
	class={isAbsolute ? 'w-12 absolute top-0 left-0 -m-3 -mt-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-12 h-12 absolute top-0 left-0 -m-3 -mt-5' : 'w-8 h-8 mx-auto'}
 | 
				
			||||||
	src="/ghost.png"
 | 
						src="/ghost.png"
 | 
				
			||||||
/>
 | 
					/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<svg
 | 
					<svg
 | 
				
			||||||
	class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 h-8 mx-auto'}
 | 
				
			||||||
	viewBox="0 0 81 84"
 | 
						viewBox="0 0 81 84"
 | 
				
			||||||
	fill="none"
 | 
						fill="none"
 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
						xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<svg
 | 
					<svg
 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
						xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
	class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 h-8 mx-auto'}
 | 
				
			||||||
	fill="none"
 | 
						fill="none"
 | 
				
			||||||
	viewBox="0 0 140 140"
 | 
						viewBox="0 0 140 140"
 | 
				
			||||||
	data-lt-extension-installed="true"
 | 
						data-lt-extension-installed="true"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<svg
 | 
					<svg
 | 
				
			||||||
	viewBox="0 0 127 74"
 | 
						viewBox="0 0 127 74"
 | 
				
			||||||
	class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 h-8mx-auto'}
 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
						xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
	><path
 | 
						><path
 | 
				
			||||||
		d="M.825 73.993l23.244-59.47A21.85 21.85 0 0144.42.625h14.014L35.19 60.096a21.85 21.85 0 01-20.352 13.897H.825z"
 | 
							d="M.825 73.993l23.244-59.47A21.85 21.85 0 0144.42.625h14.014L35.19 60.096a21.85 21.85 0 01-20.352 13.897H.825z"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<img
 | 
					<img
 | 
				
			||||||
	alt="minio logo"
 | 
						alt="minio logo"
 | 
				
			||||||
	class={isAbsolute ? 'w-7 absolute top-0 left-0 -m-3 -mt-5' : 'w-4  mx-auto'}
 | 
						class={isAbsolute ? 'w-7 h-12 absolute top-0 left-0 -m-3 -mt-5' : 'w-4 h-8 mx-auto'}
 | 
				
			||||||
	src="/minio.png"
 | 
						src="/minio.png"
 | 
				
			||||||
/>
 | 
					/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,6 @@
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
<img
 | 
					<img
 | 
				
			||||||
	alt="moodle logo"
 | 
						alt="moodle logo"
 | 
				
			||||||
	class={isAbsolute ? 'w-9 absolute top-0 left-0 -m-3 -mt-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-9 h-9 absolute top-0 left-0 -m-3 -mt-5' : 'w-8 h-8 mx-auto'}
 | 
				
			||||||
	src="/moodle.png"
 | 
						src="/moodle.png"
 | 
				
			||||||
/>
 | 
					/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<svg
 | 
					<svg
 | 
				
			||||||
	class={isAbsolute ? 'w-12 h-12 absolute top-0 left-0 -m-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-12 h-12 absolute top-0 left-0 -m-5' : 'w-8 h-8 mx-auto'}
 | 
				
			||||||
	viewBox="0 0 220 105"
 | 
						viewBox="0 0 220 105"
 | 
				
			||||||
>
 | 
					>
 | 
				
			||||||
	<g>
 | 
						<g>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<img
 | 
					<img
 | 
				
			||||||
	alt="nocodb logo"
 | 
						alt="nocodb logo"
 | 
				
			||||||
	class={isAbsolute ? 'w-10 absolute top-0 left-0 -m-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 h-8 mx-auto'}
 | 
				
			||||||
	src="/nocodb.png"
 | 
						src="/nocodb.png"
 | 
				
			||||||
/>
 | 
					/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@
 | 
				
			|||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
						xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
	viewBox="0 0 856.000000 856.000000"
 | 
						viewBox="0 0 856.000000 856.000000"
 | 
				
			||||||
	preserveAspectRatio="xMidYMid meet"
 | 
						preserveAspectRatio="xMidYMid meet"
 | 
				
			||||||
	class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 h-8 mx-auto'}
 | 
				
			||||||
>
 | 
					>
 | 
				
			||||||
	<metadata> Created by potrace 1.11, written by Peter Selinger 2001-2013 </metadata>
 | 
						<metadata> Created by potrace 1.11, written by Peter Selinger 2001-2013 </metadata>
 | 
				
			||||||
	<g
 | 
						<g
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<svg
 | 
					<svg
 | 
				
			||||||
	class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 h-8mx-auto'}
 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
						viewBox="0 0 128 128"
 | 
				
			||||||
>
 | 
					>
 | 
				
			||||||
	<path
 | 
						<path
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<svg
 | 
					<svg
 | 
				
			||||||
	class={isAbsolute ? 'w-10 absolute top-0 left-0 -m-5' : 'w-8 mx-auto'}
 | 
						class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 h-8mx-auto'}
 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
						xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
	xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
						xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
				
			||||||
	version="1.1"
 | 
						version="1.1"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
	export let isAbsolute = false;
 | 
						export let isAbsolute = false;
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<svg class={isAbsolute ? 'w-10  absolute top-0 left-0 -m-5' : 'w-8 mx-auto'} viewBox="0 0 128 128">
 | 
					<svg class={isAbsolute ? 'w-10 h-10 absolute top-0 left-0 -m-5' : 'w-8 h-8mx-auto'} viewBox="0 0 128 128">
 | 
				
			||||||
	<path
 | 
						<path
 | 
				
			||||||
		fill-rule="evenodd"
 | 
							fill-rule="evenodd"
 | 
				
			||||||
		clip-rule="evenodd"
 | 
							clip-rule="evenodd"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,11 +57,12 @@
 | 
				
			|||||||
					message: 'Secret added.',
 | 
										message: 'Secret added.',
 | 
				
			||||||
					type: 'success'
 | 
										type: 'success'
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			}
 | 
								} else {
 | 
				
			||||||
				addToast({
 | 
									addToast({
 | 
				
			||||||
				message: 'Secret updated.',
 | 
									message: 'Secret updated.',
 | 
				
			||||||
				type: 'success'
 | 
									type: 'success'
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			dispatch('refresh');
 | 
								dispatch('refresh');
 | 
				
			||||||
		} catch (error) {
 | 
							} catch (error) {
 | 
				
			||||||
			console.log(error);
 | 
								console.log(error);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,18 +25,38 @@
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
						export let team: any;
 | 
				
			||||||
 | 
						export let currentTeam: string;
 | 
				
			||||||
 | 
						export let teams: any;
 | 
				
			||||||
	import { page } from '$app/stores';
 | 
						import { page } from '$app/stores';
 | 
				
			||||||
	import { errorNotification, handlerNotFoundLoad } from '$lib/common';
 | 
						import { errorNotification, handlerNotFoundLoad } from '$lib/common';
 | 
				
			||||||
	import { appSession } from '$lib/store';
 | 
						import { appSession } from '$lib/store';
 | 
				
			||||||
	import { t } from '$lib/translations';
 | 
						import { t } from '$lib/translations';
 | 
				
			||||||
	import DeleteIcon from '$lib/components/DeleteIcon.svelte';
 | 
						import DeleteIcon from '$lib/components/DeleteIcon.svelte';
 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
						import { goto } from '$app/navigation';
 | 
				
			||||||
 | 
						import Cookies from 'js-cookie';
 | 
				
			||||||
	const { id } = $page.params;
 | 
						const { id } = $page.params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	async function deleteTeam() {
 | 
						async function deleteTeam() {
 | 
				
			||||||
		const sure = confirm('Are you sure you want to delete this team?');
 | 
							const sure = confirm('Are you sure you want to delete this team?');
 | 
				
			||||||
		if (sure) {
 | 
							if (sure) {
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				await del(`/iam/team/${id}`, { id });
 | 
									await del(`/iam/team/${id}`, { id });
 | 
				
			||||||
 | 
									if (currentTeam === id) {
 | 
				
			||||||
 | 
										const switchTeam = teams.find((team: any) => team.id !== id);
 | 
				
			||||||
 | 
										const payload = await get(`/user?teamId=${switchTeam.id}`);
 | 
				
			||||||
 | 
										if (payload.token) {
 | 
				
			||||||
 | 
											Cookies.set('token', payload.token, {
 | 
				
			||||||
 | 
												path: '/'
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
											$appSession.teamId = payload.teamId;
 | 
				
			||||||
 | 
											$appSession.userId = payload.userId;
 | 
				
			||||||
 | 
											$appSession.permission = payload.permission;
 | 
				
			||||||
 | 
											$appSession.isAdmin = payload.isAdmin;
 | 
				
			||||||
 | 
											return window.location.assign('/iam');
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				return await goto('/iam', { replaceState: true });
 | 
									return await goto('/iam', { replaceState: true });
 | 
				
			||||||
			} catch (error) {
 | 
								} catch (error) {
 | 
				
			||||||
				return errorNotification(error);
 | 
									return errorNotification(error);
 | 
				
			||||||
@@ -47,6 +67,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{#if id !== 'new'}
 | 
					{#if id !== 'new'}
 | 
				
			||||||
	<nav class="nav-side">
 | 
						<nav class="nav-side">
 | 
				
			||||||
 | 
							{#if team.id !== '0'}
 | 
				
			||||||
			<button
 | 
								<button
 | 
				
			||||||
				on:click={deleteTeam}
 | 
									on:click={deleteTeam}
 | 
				
			||||||
				type="submit"
 | 
									type="submit"
 | 
				
			||||||
@@ -57,6 +78,7 @@
 | 
				
			|||||||
					? 'Delete'
 | 
										? 'Delete'
 | 
				
			||||||
					: $t('destination.permission_denied_delete_destination')}><DeleteIcon /></button
 | 
										: $t('destination.permission_denied_delete_destination')}><DeleteIcon /></button
 | 
				
			||||||
			>
 | 
								>
 | 
				
			||||||
 | 
							{/if}
 | 
				
			||||||
	</nav>
 | 
						</nav>
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
<slot />
 | 
					<slot />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -76,13 +76,13 @@
 | 
				
			|||||||
<div class="flex space-x-1 p-6 font-bold">
 | 
					<div class="flex space-x-1 p-6 font-bold">
 | 
				
			||||||
	<div class="mr-4 text-2xl tracking-tight">{$t('index.dashboard')}</div>
 | 
						<div class="mr-4 text-2xl tracking-tight">{$t('index.dashboard')}</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
<div class="container lg:mx-auto lg:p-0 p-5">
 | 
					<div class="container lg:mx-auto lg:p-0 px-8 p-5">
 | 
				
			||||||
	{#if $appSession.teamId === '0'}
 | 
						{#if $appSession.teamId === '0'}
 | 
				
			||||||
		<Usage />
 | 
							<Usage />
 | 
				
			||||||
	{/if}
 | 
						{/if}
 | 
				
			||||||
	<h1 class="title text-4xl mt-10">Applications</h1>
 | 
						<h1 class="title lg:text-3xl mt-10">Applications</h1>
 | 
				
			||||||
	<div class="divider" />
 | 
						<div class="divider" />
 | 
				
			||||||
	<div class="grid grid-col gap-4 auto-cols-max grid-cols-1 lg:grid-cols-3 p-4">
 | 
						<div class="grid grid-col gap-8 auto-cols-max grid-cols-1 lg:grid-cols-3 p-4">
 | 
				
			||||||
		{#if applications.length > 0}
 | 
							{#if applications.length > 0}
 | 
				
			||||||
			{#each applications as application}
 | 
								{#each applications as application}
 | 
				
			||||||
				<a class="no-underline mb-5" href={`/applications/${application.id}`}>
 | 
									<a class="no-underline mb-5" href={`/applications/${application.id}`}>
 | 
				
			||||||
@@ -97,12 +97,12 @@
 | 
				
			|||||||
							{/if}
 | 
												{/if}
 | 
				
			||||||
						{/await}
 | 
											{/await}
 | 
				
			||||||
						<div class="w-full flex flex-row">
 | 
											<div class="w-full flex flex-row">
 | 
				
			||||||
							<ApplicationsIcons {application} isAbsolute={false} />
 | 
												<ApplicationsIcons {application} isAbsolute={true} />
 | 
				
			||||||
							<div class="w-full flex flex-col ml-5">
 | 
												<div class="w-full flex flex-col">
 | 
				
			||||||
								<h1 class="font-bold text-xl truncate">
 | 
													<h1 class="font-bold text-lg lg:text-sm truncate">
 | 
				
			||||||
									{application.name}
 | 
														{application.name}
 | 
				
			||||||
									{#if application.settings.isBot}
 | 
														{#if application.settings.isBot}
 | 
				
			||||||
										<span class="text-xs"> BOT</span>
 | 
															<span class="text-xs">BOT</span>
 | 
				
			||||||
									{/if}
 | 
														{/if}
 | 
				
			||||||
								</h1>
 | 
													</h1>
 | 
				
			||||||
								<div class="h-10">
 | 
													<div class="h-10">
 | 
				
			||||||
@@ -165,9 +165,9 @@
 | 
				
			|||||||
			<h1 class="">Nothing is configured yet.</h1>
 | 
								<h1 class="">Nothing is configured yet.</h1>
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<h1 class="title text-4xl mt-10">Services</h1>
 | 
						<h1 class="title lg:text-3xl mt-10">Services</h1>
 | 
				
			||||||
	<div class="divider" />
 | 
						<div class="divider" />
 | 
				
			||||||
	<div class="grid grid-col gap-4 auto-cols-max grid-cols-1 lg:grid-cols-3 p-4">
 | 
						<div class="grid grid-col gap-8 auto-cols-max grid-cols-1 lg:grid-cols-3 p-4">
 | 
				
			||||||
		{#if services.length > 0}
 | 
							{#if services.length > 0}
 | 
				
			||||||
			{#each services as service}
 | 
								{#each services as service}
 | 
				
			||||||
				<a class="no-underline mb-5" href={`/services/${service.id}`}>
 | 
									<a class="no-underline mb-5" href={`/services/${service.id}`}>
 | 
				
			||||||
@@ -182,9 +182,9 @@
 | 
				
			|||||||
							{/if}
 | 
												{/if}
 | 
				
			||||||
						{/await}
 | 
											{/await}
 | 
				
			||||||
						<div class="w-full flex flex-row">
 | 
											<div class="w-full flex flex-row">
 | 
				
			||||||
							<ServiceIcons type={service.type} isAbsolute={false} />
 | 
												<ServiceIcons type={service.type} isAbsolute={true} />
 | 
				
			||||||
							<div class="w-full flex flex-col ml-5">
 | 
												<div class="w-full flex flex-col">
 | 
				
			||||||
								<h1 class="font-bold text-xl truncate">{service.name}</h1>
 | 
													<h1 class="font-bold text-lg lg:text-sm truncate">{service.name}</h1>
 | 
				
			||||||
								<div class="h-10">
 | 
													<div class="h-10">
 | 
				
			||||||
									{#if service?.fqdn}
 | 
														{#if service?.fqdn}
 | 
				
			||||||
										<h2>{service?.fqdn.replace('https://', '').replace('http://', '')}</h2>
 | 
															<h2>{service?.fqdn.replace('https://', '').replace('http://', '')}</h2>
 | 
				
			||||||
@@ -223,9 +223,9 @@
 | 
				
			|||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<h1 class="title text-4xl mt-10">Databases</h1>
 | 
						<h1 class="title lg:text-3xl mt-10">Databases</h1>
 | 
				
			||||||
	<div class="divider" />
 | 
						<div class="divider" />
 | 
				
			||||||
	<div class="grid grid-col gap-4 auto-cols-max grid-cols-1 lg:grid-cols-3 p-4 mb-32">
 | 
						<div class="grid grid-col gap-8 auto-cols-max grid-cols-1 lg:grid-cols-3 p-4 mb-32">
 | 
				
			||||||
		{#if databases.length > 0}
 | 
							{#if databases.length > 0}
 | 
				
			||||||
			{#each databases as database}
 | 
								{#each databases as database}
 | 
				
			||||||
				<a class="no-underline mb-5" href={`/databases/${database.id}`}>
 | 
									<a class="no-underline mb-5" href={`/databases/${database.id}`}>
 | 
				
			||||||
@@ -239,14 +239,14 @@
 | 
				
			|||||||
								<span class="indicator-item badge bg-error badge-xs" />
 | 
													<span class="indicator-item badge bg-error badge-xs" />
 | 
				
			||||||
							{/if}
 | 
												{/if}
 | 
				
			||||||
						{/await}
 | 
											{/await}
 | 
				
			||||||
						<div class="w-full flex flex-row pt-2">
 | 
											<div class="w-full flex flex-row">
 | 
				
			||||||
							<DatabaseIcons type={database.type} isAbsolute={false} />
 | 
												<DatabaseIcons type={database.type} isAbsolute={true} />
 | 
				
			||||||
							<div class="w-full flex flex-col ml-5">
 | 
												<div class="w-full flex flex-col">
 | 
				
			||||||
								<div class="h-10">
 | 
													<div class="h-10">
 | 
				
			||||||
									<h1 class="font-bold text-xl truncate">{database.name}</h1>
 | 
														<h1 class="font-bold text-lg lg:text-sm truncate">{database.name}</h1>
 | 
				
			||||||
									<div class="h-10">
 | 
														<div class="h-10">
 | 
				
			||||||
										{#if database?.version}
 | 
															{#if database?.version}
 | 
				
			||||||
											<h2>{database?.version}</h2>
 | 
																<h2 class="text-xs">{database?.version}</h2>
 | 
				
			||||||
										{:else}
 | 
															{:else}
 | 
				
			||||||
											<h2 class="text-red-500">Not configured</h2>
 | 
																<h2 class="text-red-500">Not configured</h2>
 | 
				
			||||||
										{/if}
 | 
															{/if}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "coolify",
 | 
					  "name": "coolify",
 | 
				
			||||||
  "description": "An open-source & self-hostable Heroku / Netlify alternative.",
 | 
					  "description": "An open-source & self-hostable Heroku / Netlify alternative.",
 | 
				
			||||||
  "version": "3.8.3",
 | 
					  "version": "3.8.4",
 | 
				
			||||||
  "license": "Apache-2.0",
 | 
					  "license": "Apache-2.0",
 | 
				
			||||||
  "repository": "github:coollabsio/coolify",
 | 
					  "repository": "github:coollabsio/coolify",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user