commit
2c7c5a3dc3
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": {
|
||||||
|
Loading…
Reference in New Issue
Block a user