remove trpc
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							@@ -1,13 +0,0 @@
 | 
				
			|||||||
.DS_Store
 | 
					 | 
				
			||||||
node_modules
 | 
					 | 
				
			||||||
/build
 | 
					 | 
				
			||||||
/.svelte-kit
 | 
					 | 
				
			||||||
/package
 | 
					 | 
				
			||||||
.env
 | 
					 | 
				
			||||||
.env.*
 | 
					 | 
				
			||||||
!.env.example
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Ignore files for PNPM, NPM and YARN
 | 
					 | 
				
			||||||
pnpm-lock.yaml
 | 
					 | 
				
			||||||
package-lock.json
 | 
					 | 
				
			||||||
yarn.lock
 | 
					 | 
				
			||||||
@@ -1,20 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
	root: true,
 | 
					 | 
				
			||||||
	parser: '@typescript-eslint/parser',
 | 
					 | 
				
			||||||
	extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
 | 
					 | 
				
			||||||
	plugins: ['svelte3', '@typescript-eslint'],
 | 
					 | 
				
			||||||
	ignorePatterns: ['*.cjs'],
 | 
					 | 
				
			||||||
	overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
 | 
					 | 
				
			||||||
	settings: {
 | 
					 | 
				
			||||||
		'svelte3/typescript': () => require('typescript')
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	parserOptions: {
 | 
					 | 
				
			||||||
		sourceType: 'module',
 | 
					 | 
				
			||||||
		ecmaVersion: 2020
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	env: {
 | 
					 | 
				
			||||||
		browser: true,
 | 
					 | 
				
			||||||
		es2017: true,
 | 
					 | 
				
			||||||
		node: true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										10
									
								
								apps/trpc-experimental/client/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								apps/trpc-experimental/client/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +0,0 @@
 | 
				
			|||||||
.DS_Store
 | 
					 | 
				
			||||||
node_modules
 | 
					 | 
				
			||||||
/build
 | 
					 | 
				
			||||||
/.svelte-kit
 | 
					 | 
				
			||||||
/package
 | 
					 | 
				
			||||||
.env
 | 
					 | 
				
			||||||
.env.*
 | 
					 | 
				
			||||||
!.env.example
 | 
					 | 
				
			||||||
vite.config.js.timestamp-*
 | 
					 | 
				
			||||||
vite.config.ts.timestamp-*
 | 
					 | 
				
			||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
engine-strict=true
 | 
					 | 
				
			||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
.DS_Store
 | 
					 | 
				
			||||||
node_modules
 | 
					 | 
				
			||||||
/build
 | 
					 | 
				
			||||||
/.svelte-kit
 | 
					 | 
				
			||||||
/package
 | 
					 | 
				
			||||||
.env
 | 
					 | 
				
			||||||
.env.*
 | 
					 | 
				
			||||||
!.env.example
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Ignore files for PNPM, NPM and YARN
 | 
					 | 
				
			||||||
pnpm-lock.yaml
 | 
					 | 
				
			||||||
package-lock.json
 | 
					 | 
				
			||||||
yarn.lock
 | 
					 | 
				
			||||||
@@ -1,9 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
	"useTabs": true,
 | 
					 | 
				
			||||||
	"singleQuote": true,
 | 
					 | 
				
			||||||
	"trailingComma": "none",
 | 
					 | 
				
			||||||
	"printWidth": 100,
 | 
					 | 
				
			||||||
	"plugins": ["prettier-plugin-svelte"],
 | 
					 | 
				
			||||||
	"pluginSearchDirs": ["."],
 | 
					 | 
				
			||||||
	"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
# SvelteKit Static site
 | 
					 | 
				
			||||||
@@ -1,54 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
	"name": "client",
 | 
					 | 
				
			||||||
	"description": "Coolify's SvelteKit UI",
 | 
					 | 
				
			||||||
	"license": "Apache-2.0",
 | 
					 | 
				
			||||||
	"private": true,
 | 
					 | 
				
			||||||
	"scripts": {
 | 
					 | 
				
			||||||
		"dev": "vite dev",
 | 
					 | 
				
			||||||
		"build": "vite build && cp -Pr build/ ../../build/public",
 | 
					 | 
				
			||||||
		"preview": "vite preview",
 | 
					 | 
				
			||||||
		"test": "playwright test",
 | 
					 | 
				
			||||||
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
 | 
					 | 
				
			||||||
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
 | 
					 | 
				
			||||||
		"lint": "prettier --plugin-search-dir . --check . && eslint .",
 | 
					 | 
				
			||||||
		"format": "prettier --plugin-search-dir . --write ."
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"devDependencies": {
 | 
					 | 
				
			||||||
		"@playwright/test": "1.28.1",
 | 
					 | 
				
			||||||
		"@sveltejs/adapter-static": "1.0.0-next.48",
 | 
					 | 
				
			||||||
		"@sveltejs/kit": "1.0.0-next.572",
 | 
					 | 
				
			||||||
		"@types/js-cookie": "3.0.2",
 | 
					 | 
				
			||||||
		"@typescript-eslint/eslint-plugin": "5.44.0",
 | 
					 | 
				
			||||||
		"@typescript-eslint/parser": "5.44.0",
 | 
					 | 
				
			||||||
		"autoprefixer": "10.4.13",
 | 
					 | 
				
			||||||
		"eslint": "8.28.0",
 | 
					 | 
				
			||||||
		"eslint-config-prettier": "8.5.0",
 | 
					 | 
				
			||||||
		"eslint-plugin-svelte3": "4.0.0",
 | 
					 | 
				
			||||||
		"postcss": "8.4.19",
 | 
					 | 
				
			||||||
		"postcss-load-config": "4.0.1",
 | 
					 | 
				
			||||||
		"prettier": "2.8.0",
 | 
					 | 
				
			||||||
		"prettier-plugin-svelte": "2.8.1",
 | 
					 | 
				
			||||||
		"svelte": "3.53.1",
 | 
					 | 
				
			||||||
		"svelte-check": "2.9.2",
 | 
					 | 
				
			||||||
		"svelte-preprocess": "^4.10.7",
 | 
					 | 
				
			||||||
		"tailwindcss": "3.2.4",
 | 
					 | 
				
			||||||
		"tslib": "2.4.1",
 | 
					 | 
				
			||||||
		"typescript": "4.9.3",
 | 
					 | 
				
			||||||
		"vite": "3.2.4"
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"type": "module",
 | 
					 | 
				
			||||||
	"dependencies": {
 | 
					 | 
				
			||||||
		"@trpc/client": "10.1.0",
 | 
					 | 
				
			||||||
		"@trpc/server": "10.1.0",
 | 
					 | 
				
			||||||
		"cuid": "2.1.8",
 | 
					 | 
				
			||||||
		"daisyui": "2.41.0",
 | 
					 | 
				
			||||||
		"dayjs": "1.11.6",
 | 
					 | 
				
			||||||
		"flowbite-svelte": "0.28.0",
 | 
					 | 
				
			||||||
		"js-cookie": "3.0.1",
 | 
					 | 
				
			||||||
		"js-yaml": "4.1.0",
 | 
					 | 
				
			||||||
		"p-limit": "4.0.0",
 | 
					 | 
				
			||||||
		"server": "workspace:*",
 | 
					 | 
				
			||||||
		"superjson": "1.11.0",
 | 
					 | 
				
			||||||
		"svelte-select": "4.4.7"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
import type { PlaywrightTestConfig } from '@playwright/test';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const config: PlaywrightTestConfig = {
 | 
					 | 
				
			||||||
	webServer: {
 | 
					 | 
				
			||||||
		command: 'npm run build && npm run preview',
 | 
					 | 
				
			||||||
		port: 4173
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default config;
 | 
					 | 
				
			||||||
							
								
								
									
										1793
									
								
								apps/trpc-experimental/client/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1793
									
								
								apps/trpc-experimental/client/pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,13 +0,0 @@
 | 
				
			|||||||
const tailwindcss = require('tailwindcss');
 | 
					 | 
				
			||||||
const autoprefixer = require('autoprefixer');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const config = {
 | 
					 | 
				
			||||||
	plugins: [
 | 
					 | 
				
			||||||
		//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
 | 
					 | 
				
			||||||
		tailwindcss(),
 | 
					 | 
				
			||||||
		//But others, like autoprefixer, need to run after,
 | 
					 | 
				
			||||||
		autoprefixer
 | 
					 | 
				
			||||||
	]
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = config;
 | 
					 | 
				
			||||||
							
								
								
									
										12
									
								
								apps/trpc-experimental/client/src/app.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								apps/trpc-experimental/client/src/app.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +0,0 @@
 | 
				
			|||||||
// See https://kit.svelte.dev/docs/types#app
 | 
					 | 
				
			||||||
// for information about these interfaces
 | 
					 | 
				
			||||||
// and what to do when importing types
 | 
					 | 
				
			||||||
declare namespace App {
 | 
					 | 
				
			||||||
	// interface Locals {}
 | 
					 | 
				
			||||||
	// interface PageData {}
 | 
					 | 
				
			||||||
	// interface Error {}
 | 
					 | 
				
			||||||
	// interface Platform {}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare const GITPOD_WORKSPACE_URL: string;
 | 
					 | 
				
			||||||
declare const CODESANDBOX_HOST: string;
 | 
					 | 
				
			||||||
@@ -1,12 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang="en">
 | 
					 | 
				
			||||||
	<head>
 | 
					 | 
				
			||||||
		<meta charset="utf-8" />
 | 
					 | 
				
			||||||
		<link rel="icon" href="%sveltekit.assets%/favicon.png" />
 | 
					 | 
				
			||||||
		<meta name="viewport" content="width=device-width" />
 | 
					 | 
				
			||||||
		%sveltekit.head%
 | 
					 | 
				
			||||||
	</head>
 | 
					 | 
				
			||||||
	<body>
 | 
					 | 
				
			||||||
		<div class="h-screen">%sveltekit.body%</div>
 | 
					 | 
				
			||||||
	</body>
 | 
					 | 
				
			||||||
</html>
 | 
					 | 
				
			||||||
@@ -1,284 +0,0 @@
 | 
				
			|||||||
/* Write your global styles here, in PostCSS syntax */
 | 
					 | 
				
			||||||
@tailwind base;
 | 
					 | 
				
			||||||
@tailwind components;
 | 
					 | 
				
			||||||
@tailwind utilities;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@font-face {
 | 
					 | 
				
			||||||
	font-family: 'Poppins';
 | 
					 | 
				
			||||||
	font-style: normal;
 | 
					 | 
				
			||||||
	font-weight: 400;
 | 
					 | 
				
			||||||
	src: local(''), url('/poppins-v19-latin-ext_latin_devanagari-regular.woff2') format('woff2'),
 | 
					 | 
				
			||||||
		url('/poppins-v19-latin-ext_latin_devanagari-regular.woff') format('woff');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@font-face {
 | 
					 | 
				
			||||||
	font-family: 'Poppins';
 | 
					 | 
				
			||||||
	font-style: normal;
 | 
					 | 
				
			||||||
	font-weight: 500;
 | 
					 | 
				
			||||||
	src: local(''), url('/poppins-v19-latin-ext_latin_devanagari-500.woff2') format('woff2'),
 | 
					 | 
				
			||||||
		url('/poppins-v19-latin-ext_latin_devanagari-500.woff') format('woff');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
button {
 | 
					 | 
				
			||||||
	@apply text-sm !important;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
html {
 | 
					 | 
				
			||||||
	@apply h-full min-h-full overflow-y-scroll;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
body {
 | 
					 | 
				
			||||||
	@apply min-h-screen overflow-x-hidden bg-coolblack text-sm text-white scrollbar-w-1 scrollbar-thumb-coollabs scrollbar-track-coolgray-200;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
input,
 | 
					 | 
				
			||||||
.input {
 | 
					 | 
				
			||||||
	@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-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 {
 | 
					 | 
				
			||||||
	@apply placeholder:text-stone-600;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#svelte .custom-select-wrapper .selectContainer input {
 | 
					 | 
				
			||||||
	@apply text-white;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#svelte .custom-select-wrapper .selectContainer {
 | 
					 | 
				
			||||||
	@apply h-12 rounded 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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#svelte .listContainer {
 | 
					 | 
				
			||||||
	@apply bg-coolgray-400 text-white scrollbar-w-2 scrollbar-thumb-green-500 scrollbar-track-coolgray-200;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#svelte .selectedItem {
 | 
					 | 
				
			||||||
	@apply pl-2;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#svelte .item.hover {
 | 
					 | 
				
			||||||
	@apply bg-coollabs text-white !important;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#svelte .item.active {
 | 
					 | 
				
			||||||
	@apply bg-coolgray-100 text-white;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
select {
 | 
					 | 
				
			||||||
	@apply h-12 w-96 rounded bg-coolgray-200 p-2 text-xs font-bold tracking-tight text-white placeholder-stone-600 outline-none transition duration-150 hover:bg-coolgray-500 focus:bg-coolgray-500 disabled:text-stone-600 md:text-sm;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.custom-select-wrapper {
 | 
					 | 
				
			||||||
	--background: rgb(32 32 32);
 | 
					 | 
				
			||||||
	--inputColor: white;
 | 
					 | 
				
			||||||
	--multiItemPadding: 0;
 | 
					 | 
				
			||||||
	--multiSelectPadding: 0 0.5rem 0 0.5rem;
 | 
					 | 
				
			||||||
	--border: none;
 | 
					 | 
				
			||||||
	--placeholderColor: rgb(87 83 78);
 | 
					 | 
				
			||||||
	--listBackground: rgb(32 32 32);
 | 
					 | 
				
			||||||
	--itemColor: white;
 | 
					 | 
				
			||||||
	--itemHoverBG: rgb(107 22 237);
 | 
					 | 
				
			||||||
	--multiItemBG: rgb(32 32 32);
 | 
					 | 
				
			||||||
	--multiClearHoverBG: transparent;
 | 
					 | 
				
			||||||
	--multiClearHoverFill: rgb(239 68 68);
 | 
					 | 
				
			||||||
	--multiItemActiveBG: transparent;
 | 
					 | 
				
			||||||
	--multiClearBG: transparent;
 | 
					 | 
				
			||||||
	--clearSelectFocusColor: white;
 | 
					 | 
				
			||||||
	--clearSelectHoverColor: rgb(239 68 68);
 | 
					 | 
				
			||||||
	--multiItemBorderRadius: 0.25rem;
 | 
					 | 
				
			||||||
	--listShadow: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
label {
 | 
					 | 
				
			||||||
	@apply inline-block;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.btn {
 | 
					 | 
				
			||||||
	@apply text-white text-base min-w-fit no-animation;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
a {
 | 
					 | 
				
			||||||
	@apply underline hover:text-white;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.content {
 | 
					 | 
				
			||||||
	@apply p-2 px-4;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.title {
 | 
					 | 
				
			||||||
	@apply text-lg lg:text-2xl font-bold;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.subtitle {
 | 
					 | 
				
			||||||
	@apply text-lg lg:text-xl font-bold text-indigo-300;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.label {
 | 
					 | 
				
			||||||
	@apply text-sm leading-6 font-semibold text-sky-500 dark:text-sky-400;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.card {
 | 
					 | 
				
			||||||
	@apply border bg-coolgray-100 border-coolgray-200 rounded p-2 space-y-2 sticky top-4 mb-2 items-center;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.icon-holder {
 | 
					 | 
				
			||||||
	overflow: hidden;
 | 
					 | 
				
			||||||
	height: 30px;
 | 
					 | 
				
			||||||
	border-radius: 5px;
 | 
					 | 
				
			||||||
	margin-right: 8px;
 | 
					 | 
				
			||||||
	background: linear-gradient(0deg, #999, #ddd);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.instance-status-running {
 | 
					 | 
				
			||||||
	box-shadow: 1px 4px 5px #3df721;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.instance-status-stopped {
 | 
					 | 
				
			||||||
	box-shadow: 1px 4px 5px rgb(110, 191, 225);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.instance-status-error {
 | 
					 | 
				
			||||||
	box-shadow: 1px 4px 5px #fb00ff;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.instance-status-degraded {
 | 
					 | 
				
			||||||
	box-shadow: 1px 4px 5px #f7b121;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.badge-status-healthy,
 | 
					 | 
				
			||||||
.badge-status-running {
 | 
					 | 
				
			||||||
	@apply text-green-500;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.badge-status-degraded {
 | 
					 | 
				
			||||||
	@apply text-green-500;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.badge-status-stopped {
 | 
					 | 
				
			||||||
	@apply text-sky-500;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.delete-button {
 | 
					 | 
				
			||||||
	@apply bg-red-600;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.delete-button:hover {
 | 
					 | 
				
			||||||
	@apply bg-red-500;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/* Interchange menu position */
 | 
					 | 
				
			||||||
.menu-left {
 | 
					 | 
				
			||||||
	display: flex;
 | 
					 | 
				
			||||||
	flex-direction: row;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.menu-left .menu-bar {
 | 
					 | 
				
			||||||
	display: flex;
 | 
					 | 
				
			||||||
	flex-direction: column;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.menu-left .menu-bar > * {
 | 
					 | 
				
			||||||
	display: flex;
 | 
					 | 
				
			||||||
	flex-direction: column;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.menu-top {
 | 
					 | 
				
			||||||
	display: flex;
 | 
					 | 
				
			||||||
	flex-direction: column;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.menu-top .menu-bar {
 | 
					 | 
				
			||||||
	display: flex;
 | 
					 | 
				
			||||||
	flex-direction: row;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.menu-top .menu-bar > * {
 | 
					 | 
				
			||||||
	display: flex;
 | 
					 | 
				
			||||||
	flex-direction: row;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.nav-main {
 | 
					 | 
				
			||||||
	@apply fixed top-0 left-0 min-h-screen w-16 min-w-[4rem] overflow-hidden border-r border-stone-800 bg-coolgray-200 scrollbar-w-1  scrollbar-thumb-coollabs scrollbar-track-coolgray-200 xl:overflow-visible;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.nav-side {
 | 
					 | 
				
			||||||
	@apply absolute right-0 top-0 z-50 m-5 flex flex-wrap items-center justify-end space-x-2 bg-coolblack/40 text-white;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.add-icon {
 | 
					 | 
				
			||||||
	@apply rounded p-1 transition duration-200;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.icons {
 | 
					 | 
				
			||||||
	@apply rounded p-2 transition duration-200 hover:bg-coolgray-500 disabled:bg-coolblack disabled:text-coolgray-500 !important;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.arrow-right-applications {
 | 
					 | 
				
			||||||
	@apply -ml-6 px-2 font-bold text-green-500;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.border-gradient {
 | 
					 | 
				
			||||||
	border-bottom: 2px solid transparent;
 | 
					 | 
				
			||||||
	-o-border-image: linear-gradient(
 | 
					 | 
				
			||||||
		0.25turn,
 | 
					 | 
				
			||||||
		rgba(255, 249, 34),
 | 
					 | 
				
			||||||
		rgba(255, 0, 128),
 | 
					 | 
				
			||||||
		rgba(56, 2, 155, 0)
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
	border-image: linear-gradient(
 | 
					 | 
				
			||||||
		0.25turn,
 | 
					 | 
				
			||||||
		rgba(255, 249, 34),
 | 
					 | 
				
			||||||
		rgba(255, 0, 128),
 | 
					 | 
				
			||||||
		rgba(56, 2, 155, 0)
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
	border-image-slice: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.border-gradient-full {
 | 
					 | 
				
			||||||
	border: 4px solid transparent;
 | 
					 | 
				
			||||||
	-o-border-image: linear-gradient(
 | 
					 | 
				
			||||||
		0.25turn,
 | 
					 | 
				
			||||||
		rgba(255, 249, 34),
 | 
					 | 
				
			||||||
		rgba(255, 0, 128),
 | 
					 | 
				
			||||||
		rgba(56, 2, 155, 0)
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
	border-image: linear-gradient(
 | 
					 | 
				
			||||||
		0.25turn,
 | 
					 | 
				
			||||||
		rgba(255, 249, 34),
 | 
					 | 
				
			||||||
		rgba(255, 0, 128),
 | 
					 | 
				
			||||||
		rgba(56, 2, 155, 0)
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
	border-image-slice: 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.box-selection {
 | 
					 | 
				
			||||||
	@apply min-w-[16rem]  justify-center rounded border-transparent bg-coolgray-200 p-6 hover:border-transparent hover:bg-coolgray-400;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.lds-heart {
 | 
					 | 
				
			||||||
	animation: lds-heart 1.2s infinite cubic-bezier(0.215, 0.61, 0.355, 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@keyframes lds-heart {
 | 
					 | 
				
			||||||
	0% {
 | 
					 | 
				
			||||||
		transform: scale(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	5% {
 | 
					 | 
				
			||||||
		transform: scale(1.2);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	39% {
 | 
					 | 
				
			||||||
		transform: scale(0.85);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	45% {
 | 
					 | 
				
			||||||
		transform: scale(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	60% {
 | 
					 | 
				
			||||||
		transform: scale(0.95);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	100% {
 | 
					 | 
				
			||||||
		transform: scale(0.9);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.sub-menu {
 | 
					 | 
				
			||||||
	@apply w-48 text-base font-bold hover:bg-coolgray-500 rounded p-2 hover:text-white text-stone-200 cursor-pointer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.sub-menu-active {
 | 
					 | 
				
			||||||
	@apply bg-coolgray-500  text-white;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.table tbody td,
 | 
					 | 
				
			||||||
.table tbody th,
 | 
					 | 
				
			||||||
.table thead th {
 | 
					 | 
				
			||||||
	background-color: transparent;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.table * {
 | 
					 | 
				
			||||||
	border: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.header {
 | 
					 | 
				
			||||||
	@apply flex flex-row  z-10 w-full py-5 px-5;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.burger {
 | 
					 | 
				
			||||||
	@apply block m-[2px] h-[3px] w-5 rounded;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.bg-coollabs-gradient {
 | 
					 | 
				
			||||||
	@apply bg-gradient-to-r from-purple-500 via-pink-500 to-red-500;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,210 +0,0 @@
 | 
				
			|||||||
import { dev } from '$app/environment';
 | 
					 | 
				
			||||||
import { addToast } from './store';
 | 
					 | 
				
			||||||
import Cookies from 'js-cookie';
 | 
					 | 
				
			||||||
export const asyncSleep = (delay: number) => new Promise((resolve) => setTimeout(resolve, delay));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function dashify(str: string, options?: any): string {
 | 
					 | 
				
			||||||
	if (typeof str !== 'string') return str;
 | 
					 | 
				
			||||||
	return str
 | 
					 | 
				
			||||||
		.trim()
 | 
					 | 
				
			||||||
		.replace(/\W/g, (m) => (/[À-ž]/.test(m) ? m : '-'))
 | 
					 | 
				
			||||||
		.replace(/^-+|-+$/g, '')
 | 
					 | 
				
			||||||
		.replace(/-{2,}/g, (m) => (options && options.condense ? '-' : m))
 | 
					 | 
				
			||||||
		.toLowerCase();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export function errorNotification(error: any | { message: string }): void {
 | 
					 | 
				
			||||||
	if (error instanceof Error) {
 | 
					 | 
				
			||||||
		console.error(error.message)
 | 
					 | 
				
			||||||
		addToast({
 | 
					 | 
				
			||||||
			message: error.message,
 | 
					 | 
				
			||||||
			type: 'error'
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		console.error(error)
 | 
					 | 
				
			||||||
		addToast({
 | 
					 | 
				
			||||||
			message: error,
 | 
					 | 
				
			||||||
			type: 'error'
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export function getRndInteger(min: number, max: number) {
 | 
					 | 
				
			||||||
	return Math.floor(Math.random() * (max - min + 1)) + min;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function getDomain(domain: string) {
 | 
					 | 
				
			||||||
	return domain?.replace('https://', '').replace('http://', '');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const notNodeDeployments = ['php', 'docker', 'rust', 'python', 'deno', 'laravel', 'heroku'];
 | 
					 | 
				
			||||||
export const staticDeployments = [
 | 
					 | 
				
			||||||
	'react',
 | 
					 | 
				
			||||||
	'vuejs',
 | 
					 | 
				
			||||||
	'static',
 | 
					 | 
				
			||||||
	'svelte',
 | 
					 | 
				
			||||||
	'gatsby',
 | 
					 | 
				
			||||||
	'php',
 | 
					 | 
				
			||||||
	'astro',
 | 
					 | 
				
			||||||
	'eleventy'
 | 
					 | 
				
			||||||
];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function getAPIUrl() {
 | 
					 | 
				
			||||||
	if (GITPOD_WORKSPACE_URL) {
 | 
					 | 
				
			||||||
		const { href } = new URL(GITPOD_WORKSPACE_URL);
 | 
					 | 
				
			||||||
		const newURL = href.replace('https://', 'https://3001-').replace(/\/$/, '');
 | 
					 | 
				
			||||||
		return newURL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (CODESANDBOX_HOST) {
 | 
					 | 
				
			||||||
		return `https://${CODESANDBOX_HOST.replace(/\$PORT/, '3001')}`;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return dev ? `http://${window.location.hostname}:3001` : 'http://localhost:3000';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export function getWebhookUrl(type: string) {
 | 
					 | 
				
			||||||
	if (GITPOD_WORKSPACE_URL) {
 | 
					 | 
				
			||||||
		const { href } = new URL(GITPOD_WORKSPACE_URL);
 | 
					 | 
				
			||||||
		const newURL = href.replace('https://', 'https://3001-').replace(/\/$/, '');
 | 
					 | 
				
			||||||
		if (type === 'github') {
 | 
					 | 
				
			||||||
			return `${newURL}/webhooks/github/events`;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (type === 'gitlab') {
 | 
					 | 
				
			||||||
			return `${newURL}/webhooks/gitlab/events`;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (CODESANDBOX_HOST) {
 | 
					 | 
				
			||||||
		const newURL = `https://${CODESANDBOX_HOST.replace(/\$PORT/, '3001')}`;
 | 
					 | 
				
			||||||
		if (type === 'github') {
 | 
					 | 
				
			||||||
			return `${newURL}/webhooks/github/events`;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (type === 'gitlab') {
 | 
					 | 
				
			||||||
			return `${newURL}/webhooks/gitlab/events`;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return `https://webhook.site/0e5beb2c-4e9b-40e2-a89e-32295e570c21/events`;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function send({
 | 
					 | 
				
			||||||
	method,
 | 
					 | 
				
			||||||
	path,
 | 
					 | 
				
			||||||
	data = null,
 | 
					 | 
				
			||||||
	headers,
 | 
					 | 
				
			||||||
	timeout = 120000
 | 
					 | 
				
			||||||
}: {
 | 
					 | 
				
			||||||
	method: string;
 | 
					 | 
				
			||||||
	path: string;
 | 
					 | 
				
			||||||
	data?: any;
 | 
					 | 
				
			||||||
	headers?: any;
 | 
					 | 
				
			||||||
	timeout?: number;
 | 
					 | 
				
			||||||
}): Promise<Record<string, unknown>> {
 | 
					 | 
				
			||||||
	const token = Cookies.get('token');
 | 
					 | 
				
			||||||
	const controller = new AbortController();
 | 
					 | 
				
			||||||
	const id = setTimeout(() => controller.abort(), timeout);
 | 
					 | 
				
			||||||
	const opts: any = { method, headers: {}, body: null, signal: controller.signal };
 | 
					 | 
				
			||||||
	if (data && Object.keys(data).length > 0) {
 | 
					 | 
				
			||||||
		const parsedData = data;
 | 
					 | 
				
			||||||
		for (const [key, value] of Object.entries(data)) {
 | 
					 | 
				
			||||||
			if (value === '') {
 | 
					 | 
				
			||||||
				parsedData[key] = null;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (parsedData) {
 | 
					 | 
				
			||||||
			opts.headers['Content-Type'] = 'application/json';
 | 
					 | 
				
			||||||
			opts.body = JSON.stringify(parsedData);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (headers) {
 | 
					 | 
				
			||||||
		opts.headers = {
 | 
					 | 
				
			||||||
			...opts.headers,
 | 
					 | 
				
			||||||
			...headers
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (token && !path.startsWith('https://')) {
 | 
					 | 
				
			||||||
		opts.headers = {
 | 
					 | 
				
			||||||
			...opts.headers,
 | 
					 | 
				
			||||||
			Authorization: `Bearer ${token}`
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (!path.startsWith('https://')) {
 | 
					 | 
				
			||||||
		path = `/api/v1${path}`;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (dev && !path.startsWith('https://')) {
 | 
					 | 
				
			||||||
		path = `${getAPIUrl()}${path}`;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (method === 'POST' && data && !opts.body) {
 | 
					 | 
				
			||||||
		opts.body = data;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	const response = await fetch(`${path}`, opts);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	clearTimeout(id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const contentType = response.headers.get('content-type');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let responseData = {};
 | 
					 | 
				
			||||||
	if (contentType) {
 | 
					 | 
				
			||||||
		if (contentType?.indexOf('application/json') !== -1) {
 | 
					 | 
				
			||||||
			responseData = await response.json();
 | 
					 | 
				
			||||||
		} else if (contentType?.indexOf('text/plain') !== -1) {
 | 
					 | 
				
			||||||
			responseData = await response.text();
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return {};
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return {};
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (!response.ok) {
 | 
					 | 
				
			||||||
		if (
 | 
					 | 
				
			||||||
			response.status === 401 &&
 | 
					 | 
				
			||||||
			!path.startsWith('https://api.github') &&
 | 
					 | 
				
			||||||
			!path.includes('/v4/')
 | 
					 | 
				
			||||||
		) {
 | 
					 | 
				
			||||||
			Cookies.remove('token');
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		throw responseData;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return responseData;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function get(path: string, headers?: Record<string, unknown>): Promise<Record<string, any>> {
 | 
					 | 
				
			||||||
	return send({ method: 'GET', path, headers });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function del(
 | 
					 | 
				
			||||||
	path: string,
 | 
					 | 
				
			||||||
	data: Record<string, unknown>,
 | 
					 | 
				
			||||||
	headers?: Record<string, unknown>
 | 
					 | 
				
			||||||
): Promise<Record<string, any>> {
 | 
					 | 
				
			||||||
	return send({ method: 'DELETE', path, data, headers });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function post(
 | 
					 | 
				
			||||||
	path: string,
 | 
					 | 
				
			||||||
	data: Record<string, unknown> | FormData,
 | 
					 | 
				
			||||||
	headers?: Record<string, unknown>
 | 
					 | 
				
			||||||
): Promise<Record<string, any>> {
 | 
					 | 
				
			||||||
	return send({ method: 'POST', path, data, headers });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function put(
 | 
					 | 
				
			||||||
	path: string,
 | 
					 | 
				
			||||||
	data: Record<string, unknown>,
 | 
					 | 
				
			||||||
	headers?: Record<string, unknown>
 | 
					 | 
				
			||||||
): Promise<Record<string, any>> {
 | 
					 | 
				
			||||||
	return send({ method: 'PUT', path, data, headers });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export function changeQueryParams(buildId: string) {
 | 
					 | 
				
			||||||
	const queryParams = new URLSearchParams(window.location.search);
 | 
					 | 
				
			||||||
	queryParams.set('buildId', buildId);
 | 
					 | 
				
			||||||
	// @ts-ignore
 | 
					 | 
				
			||||||
	return history.pushState(null, null, '?' + queryParams.toString());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const dateOptions: any = {
 | 
					 | 
				
			||||||
	year: 'numeric',
 | 
					 | 
				
			||||||
	month: 'short',
 | 
					 | 
				
			||||||
	day: '2-digit',
 | 
					 | 
				
			||||||
	hour: 'numeric',
 | 
					 | 
				
			||||||
	minute: 'numeric',
 | 
					 | 
				
			||||||
	second: 'numeric',
 | 
					 | 
				
			||||||
	hour12: false
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
<span class="badge bg-coollabs-gradient rounded text-white font-normal"> BETA </span>
 | 
					 | 
				
			||||||
@@ -1,156 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { browser } from '$app/environment';
 | 
					 | 
				
			||||||
	import { addToast } from '$lib/store';
 | 
					 | 
				
			||||||
	let showPassword = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let value: string;
 | 
					 | 
				
			||||||
	export let disabled = false;
 | 
					 | 
				
			||||||
	export let isPasswordField = false;
 | 
					 | 
				
			||||||
	export let readonly = false;
 | 
					 | 
				
			||||||
	export let textarea = false;
 | 
					 | 
				
			||||||
	export let required = false;
 | 
					 | 
				
			||||||
	export let pattern: string | null | undefined = null;
 | 
					 | 
				
			||||||
	export let id: string;
 | 
					 | 
				
			||||||
	export let name: string;
 | 
					 | 
				
			||||||
	export let placeholder = '';
 | 
					 | 
				
			||||||
	export let inputStyle = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let disabledClass = 'input input-primary bg-coolback disabled:bg-coolblack w-full';
 | 
					 | 
				
			||||||
	let isHttps = browser && window.location.protocol === 'https:';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function copyToClipboard() {
 | 
					 | 
				
			||||||
		if (isHttps && navigator.clipboard) {
 | 
					 | 
				
			||||||
			navigator.clipboard.writeText(value);
 | 
					 | 
				
			||||||
			addToast({
 | 
					 | 
				
			||||||
				message: 'Copied to clipboard.',
 | 
					 | 
				
			||||||
				type: 'success'
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="relative">
 | 
					 | 
				
			||||||
	{#if !isPasswordField || showPassword}
 | 
					 | 
				
			||||||
		{#if textarea}
 | 
					 | 
				
			||||||
			<textarea
 | 
					 | 
				
			||||||
				style={inputStyle}
 | 
					 | 
				
			||||||
				rows="5"
 | 
					 | 
				
			||||||
				class={disabledClass}
 | 
					 | 
				
			||||||
				class:pr-10={true}
 | 
					 | 
				
			||||||
				class:pr-20={value && isHttps}
 | 
					 | 
				
			||||||
				class:border={required && !value}
 | 
					 | 
				
			||||||
				class:border-red-500={required && !value}
 | 
					 | 
				
			||||||
				{placeholder}
 | 
					 | 
				
			||||||
				type="text"
 | 
					 | 
				
			||||||
				{id}
 | 
					 | 
				
			||||||
				{pattern}
 | 
					 | 
				
			||||||
				{required}
 | 
					 | 
				
			||||||
				{readonly}
 | 
					 | 
				
			||||||
				{disabled}
 | 
					 | 
				
			||||||
				{name}>{value}</textarea
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
		{:else}
 | 
					 | 
				
			||||||
			<input
 | 
					 | 
				
			||||||
				style={inputStyle}
 | 
					 | 
				
			||||||
				class={disabledClass}
 | 
					 | 
				
			||||||
				type="text"
 | 
					 | 
				
			||||||
				class:pr-10={true}
 | 
					 | 
				
			||||||
				class:pr-20={value && isHttps}
 | 
					 | 
				
			||||||
				class:border={required && !value}
 | 
					 | 
				
			||||||
				class:border-red-500={required && !value}
 | 
					 | 
				
			||||||
				{id}
 | 
					 | 
				
			||||||
				{name}
 | 
					 | 
				
			||||||
				{required}
 | 
					 | 
				
			||||||
				{pattern}
 | 
					 | 
				
			||||||
				{readonly}
 | 
					 | 
				
			||||||
				bind:value
 | 
					 | 
				
			||||||
				{disabled}
 | 
					 | 
				
			||||||
				{placeholder}
 | 
					 | 
				
			||||||
			/>
 | 
					 | 
				
			||||||
		{/if}
 | 
					 | 
				
			||||||
	{:else}
 | 
					 | 
				
			||||||
		<input
 | 
					 | 
				
			||||||
			style={inputStyle}
 | 
					 | 
				
			||||||
			class={disabledClass}
 | 
					 | 
				
			||||||
			class:pr-10={true}
 | 
					 | 
				
			||||||
			class:pr-20={value && isHttps}
 | 
					 | 
				
			||||||
			class:border={required && !value}
 | 
					 | 
				
			||||||
			class:border-red-500={required && !value}
 | 
					 | 
				
			||||||
			type="password"
 | 
					 | 
				
			||||||
			{id}
 | 
					 | 
				
			||||||
			{name}
 | 
					 | 
				
			||||||
			{readonly}
 | 
					 | 
				
			||||||
			{pattern}
 | 
					 | 
				
			||||||
			{required}
 | 
					 | 
				
			||||||
			bind:value
 | 
					 | 
				
			||||||
			{disabled}
 | 
					 | 
				
			||||||
			{placeholder}
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	<div class="absolute top-0 right-0 flex justify-center items-center h-full cursor-pointer text-stone-600 hover:text-white mr-3">
 | 
					 | 
				
			||||||
		<div class="flex space-x-2">
 | 
					 | 
				
			||||||
			{#if isPasswordField}
 | 
					 | 
				
			||||||
				<!-- svelte-ignore a11y-click-events-have-key-events -->
 | 
					 | 
				
			||||||
				<div on:click={() => (showPassword = !showPassword)}>
 | 
					 | 
				
			||||||
					{#if showPassword}
 | 
					 | 
				
			||||||
						<svg
 | 
					 | 
				
			||||||
							xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
							class="h-6 w-6"
 | 
					 | 
				
			||||||
							fill="none"
 | 
					 | 
				
			||||||
							viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
							stroke="currentColor"
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							<path
 | 
					 | 
				
			||||||
								stroke-linecap="round"
 | 
					 | 
				
			||||||
								stroke-linejoin="round"
 | 
					 | 
				
			||||||
								stroke-width="2"
 | 
					 | 
				
			||||||
								d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
 | 
					 | 
				
			||||||
							/>
 | 
					 | 
				
			||||||
						</svg>
 | 
					 | 
				
			||||||
					{:else}
 | 
					 | 
				
			||||||
						<svg
 | 
					 | 
				
			||||||
							xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
							class="h-6 w-6"
 | 
					 | 
				
			||||||
							fill="none"
 | 
					 | 
				
			||||||
							viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
							stroke="currentColor"
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							<path
 | 
					 | 
				
			||||||
								stroke-linecap="round"
 | 
					 | 
				
			||||||
								stroke-linejoin="round"
 | 
					 | 
				
			||||||
								stroke-width="2"
 | 
					 | 
				
			||||||
								d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
 | 
					 | 
				
			||||||
							/>
 | 
					 | 
				
			||||||
							<path
 | 
					 | 
				
			||||||
								stroke-linecap="round"
 | 
					 | 
				
			||||||
								stroke-linejoin="round"
 | 
					 | 
				
			||||||
								stroke-width="2"
 | 
					 | 
				
			||||||
								d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
 | 
					 | 
				
			||||||
							/>
 | 
					 | 
				
			||||||
						</svg>
 | 
					 | 
				
			||||||
					{/if}
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
			{/if}
 | 
					 | 
				
			||||||
			{#if value && isHttps}
 | 
					 | 
				
			||||||
				<!-- svelte-ignore a11y-click-events-have-key-events -->
 | 
					 | 
				
			||||||
				<div on:click={copyToClipboard}>
 | 
					 | 
				
			||||||
					<svg
 | 
					 | 
				
			||||||
						xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
						class="h-6 w-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" />
 | 
					 | 
				
			||||||
						<rect x="8" y="8" width="12" height="12" rx="2" />
 | 
					 | 
				
			||||||
						<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" />
 | 
					 | 
				
			||||||
					</svg>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
			{/if}
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,44 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import ExternalLink from './ExternalLink.svelte';
 | 
					 | 
				
			||||||
	import Tooltip from './Tooltip.svelte';
 | 
					 | 
				
			||||||
	export let url = 'https://docs.coollabs.io';
 | 
					 | 
				
			||||||
	export let text: any = '';
 | 
					 | 
				
			||||||
	export let isExternal = false;
 | 
					 | 
				
			||||||
	let id =
 | 
					 | 
				
			||||||
		'cool-' +
 | 
					 | 
				
			||||||
		url
 | 
					 | 
				
			||||||
			.split('')
 | 
					 | 
				
			||||||
			.map((c) => c.charCodeAt(0).toString(16).padStart(2, '0'))
 | 
					 | 
				
			||||||
			.join('')
 | 
					 | 
				
			||||||
			.slice(-16);
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<a
 | 
					 | 
				
			||||||
	{id}
 | 
					 | 
				
			||||||
	href={url}
 | 
					 | 
				
			||||||
	target="_blank noreferrer"
 | 
					 | 
				
			||||||
	class="flex no-underline inline-block cursor-pointer"
 | 
					 | 
				
			||||||
	class:icons={!text}
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<svg
 | 
					 | 
				
			||||||
		xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
		fill="none"
 | 
					 | 
				
			||||||
		viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
		stroke-width="1.5"
 | 
					 | 
				
			||||||
		stroke="currentColor"
 | 
					 | 
				
			||||||
		class="w-6 h-6"
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			stroke-linecap="round"
 | 
					 | 
				
			||||||
			stroke-linejoin="round"
 | 
					 | 
				
			||||||
			d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	{text}
 | 
					 | 
				
			||||||
	{#if isExternal}
 | 
					 | 
				
			||||||
		<ExternalLink />
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
</a>
 | 
					 | 
				
			||||||
{#if !text}
 | 
					 | 
				
			||||||
	<Tooltip triggeredBy={`#${id}`}>See details in the documentation</Tooltip>
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
@@ -1,38 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	// import { onMount } from 'svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// import Tooltip from './Tooltip.svelte';
 | 
					 | 
				
			||||||
	export let explanation = '';
 | 
					 | 
				
			||||||
	export let position = 'dropdown-right';
 | 
					 | 
				
			||||||
	// let id: any;
 | 
					 | 
				
			||||||
	// let self: any;
 | 
					 | 
				
			||||||
	// onMount(() => {
 | 
					 | 
				
			||||||
	// 	id = `info-${self.offsetLeft}-${self.offsetTop}`;
 | 
					 | 
				
			||||||
	// });
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class={`dropdown dropdown-end ${position}`}>
 | 
					 | 
				
			||||||
	<!-- svelte-ignore a11y-label-has-associated-control -->
 | 
					 | 
				
			||||||
	<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
 | 
					 | 
				
			||||||
	<label tabindex="0" class="btn btn-circle btn-ghost btn-xs text-sky-500">
 | 
					 | 
				
			||||||
		<svg
 | 
					 | 
				
			||||||
			xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
			fill="none"
 | 
					 | 
				
			||||||
			viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
			class="w-4 h-4 stroke-current"
 | 
					 | 
				
			||||||
			><path
 | 
					 | 
				
			||||||
				stroke-linecap="round"
 | 
					 | 
				
			||||||
				stroke-linejoin="round"
 | 
					 | 
				
			||||||
				stroke-width="2"
 | 
					 | 
				
			||||||
				d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
 | 
					 | 
				
			||||||
			/></svg
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	</label>
 | 
					 | 
				
			||||||
	<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
 | 
					 | 
				
			||||||
	<div tabindex="0" class="card compact dropdown-content shadow bg-coolgray-400 rounded w-64">
 | 
					 | 
				
			||||||
		<div class="card-body">
 | 
					 | 
				
			||||||
			<!-- <h2 class="card-title">You needed more info?</h2>  -->
 | 
					 | 
				
			||||||
			<p class="text-xs font-normal">{@html explanation}</p>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
<svg
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	fill="currentColor"
 | 
					 | 
				
			||||||
	viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
	stroke-width="3"
 | 
					 | 
				
			||||||
	stroke="currentColor"
 | 
					 | 
				
			||||||
	class="w-3 h-3 text-white"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path stroke-linecap="round" stroke-linejoin="round" d="M4.5 19.5l15-15m0 0H8.25m11.25 0v11.25" />
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 261 B  | 
@@ -1,87 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import Beta from './Beta.svelte';
 | 
					 | 
				
			||||||
	import Explaner from './Explainer.svelte';
 | 
					 | 
				
			||||||
	import Tooltip from './Tooltip.svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let id: any;
 | 
					 | 
				
			||||||
	export let customClass: any = null;
 | 
					 | 
				
			||||||
	export let setting: any;
 | 
					 | 
				
			||||||
	export let title: any;
 | 
					 | 
				
			||||||
	export let isBeta: any = false;
 | 
					 | 
				
			||||||
	export let description: any = null;
 | 
					 | 
				
			||||||
	export let isCenter = true;
 | 
					 | 
				
			||||||
	export let disabled = false;
 | 
					 | 
				
			||||||
	export let dataTooltip: any = null;
 | 
					 | 
				
			||||||
	export let loading = false;
 | 
					 | 
				
			||||||
	let triggeredBy = `#${id}`;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="flex items-center py-4 pr-8">
 | 
					 | 
				
			||||||
	<div class="flex w-96 flex-col">
 | 
					 | 
				
			||||||
		<!-- svelte-ignore a11y-label-has-associated-control -->
 | 
					 | 
				
			||||||
		<label>
 | 
					 | 
				
			||||||
			{title}
 | 
					 | 
				
			||||||
			{#if isBeta}
 | 
					 | 
				
			||||||
				<Beta />
 | 
					 | 
				
			||||||
			{/if}
 | 
					 | 
				
			||||||
			{#if description && description !== ''}
 | 
					 | 
				
			||||||
				<Explaner explanation={description} />
 | 
					 | 
				
			||||||
			{/if}
 | 
					 | 
				
			||||||
		</label>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class:text-center={isCenter} class={`flex justify-center ${customClass}`}>
 | 
					 | 
				
			||||||
	<!-- svelte-ignore a11y-click-events-have-key-events -->
 | 
					 | 
				
			||||||
	<div
 | 
					 | 
				
			||||||
		on:click
 | 
					 | 
				
			||||||
		aria-pressed="false"
 | 
					 | 
				
			||||||
		class="relative mx-20 inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out"
 | 
					 | 
				
			||||||
		class:opacity-50={disabled || loading}
 | 
					 | 
				
			||||||
		class:bg-green-600={!loading && setting}
 | 
					 | 
				
			||||||
		class:bg-stone-700={!loading && !setting}
 | 
					 | 
				
			||||||
		class:bg-yellow-500={loading}
 | 
					 | 
				
			||||||
		{id}
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<span class="sr-only">Use setting</span>
 | 
					 | 
				
			||||||
		<span
 | 
					 | 
				
			||||||
			class="pointer-events-none relative inline-block h-5 w-5 transform rounded-full bg-white shadow transition duration-200 ease-in-out"
 | 
					 | 
				
			||||||
			class:translate-x-5={setting}
 | 
					 | 
				
			||||||
			class:translate-x-0={!setting}
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<span
 | 
					 | 
				
			||||||
				class=" absolute inset-0 flex h-full w-full items-center justify-center transition-opacity duration-200 ease-in"
 | 
					 | 
				
			||||||
				class:opacity-0={setting}
 | 
					 | 
				
			||||||
				class:opacity-100={!setting}
 | 
					 | 
				
			||||||
				class:animate-spin={loading}
 | 
					 | 
				
			||||||
				aria-hidden="true"
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				<svg class="h-3 w-3 bg-white text-red-600" fill="none" viewBox="0 0 12 12">
 | 
					 | 
				
			||||||
					<path
 | 
					 | 
				
			||||||
						d="M4 8l2-2m0 0l2-2M6 6L4 4m2 2l2 2"
 | 
					 | 
				
			||||||
						stroke="currentColor"
 | 
					 | 
				
			||||||
						stroke-width="2"
 | 
					 | 
				
			||||||
						stroke-linecap="round"
 | 
					 | 
				
			||||||
						stroke-linejoin="round"
 | 
					 | 
				
			||||||
					/>
 | 
					 | 
				
			||||||
				</svg>
 | 
					 | 
				
			||||||
			</span>
 | 
					 | 
				
			||||||
			<span
 | 
					 | 
				
			||||||
				class="absolute inset-0 flex h-full w-full items-center justify-center transition-opacity duration-100 ease-out"
 | 
					 | 
				
			||||||
				aria-hidden="true"
 | 
					 | 
				
			||||||
				class:opacity-100={setting}
 | 
					 | 
				
			||||||
				class:opacity-0={!setting}
 | 
					 | 
				
			||||||
				class:animate-spin={loading}
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				<svg class="h-3 w-3 bg-white text-green-600" fill="currentColor" viewBox="0 0 12 12">
 | 
					 | 
				
			||||||
					<path
 | 
					 | 
				
			||||||
						d="M3.707 5.293a1 1 0 00-1.414 1.414l1.414-1.414zM5 8l-.707.707a1 1 0 001.414 0L5 8zm4.707-3.293a1 1 0 00-1.414-1.414l1.414 1.414zm-7.414 2l2 2 1.414-1.414-2-2-1.414 1.414zm3.414 2l4-4-1.414-1.414-4 4 1.414 1.414z"
 | 
					 | 
				
			||||||
					/>
 | 
					 | 
				
			||||||
				</svg>
 | 
					 | 
				
			||||||
			</span>
 | 
					 | 
				
			||||||
		</span>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if dataTooltip}
 | 
					 | 
				
			||||||
	<Tooltip {triggeredBy} placement="top">{dataTooltip}</Tooltip>
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
@@ -1,6 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let text: string;
 | 
					 | 
				
			||||||
	export let customClass = 'max-w-[24rem]';
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="p-2 text-xs text-stone-400 {customClass}">{@html text}</div>
 | 
					 | 
				
			||||||
@@ -1,64 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
	import { createEventDispatcher } from 'svelte';
 | 
					 | 
				
			||||||
	const dispatch = createEventDispatcher();
 | 
					 | 
				
			||||||
	export let type = 'info';
 | 
					 | 
				
			||||||
	function success() {
 | 
					 | 
				
			||||||
		if (type === 'success') {
 | 
					 | 
				
			||||||
			return 'bg-dark lg:bg-primary';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
 | 
					 | 
				
			||||||
<div
 | 
					 | 
				
			||||||
	on:click={() => dispatch('click')}
 | 
					 | 
				
			||||||
	on:mouseover={() => dispatch('pause')}
 | 
					 | 
				
			||||||
	on:focus={() => dispatch('pause')}
 | 
					 | 
				
			||||||
	on:mouseout={() => dispatch('resume')}
 | 
					 | 
				
			||||||
	on:blur={() => dispatch('resume')}
 | 
					 | 
				
			||||||
	class={` flex flex-row justify-center alert shadow-lg text-white hover:scale-105 transition-all duration-100 cursor-pointer rounded ${success()}`}
 | 
					 | 
				
			||||||
	class:alert-error={type === 'error'}
 | 
					 | 
				
			||||||
	class:alert-info={type === 'info'}
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	{#if type === 'success'}
 | 
					 | 
				
			||||||
		<svg
 | 
					 | 
				
			||||||
			xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
			class="stroke-current flex-shrink-0 h-6 w-6"
 | 
					 | 
				
			||||||
			fill="none"
 | 
					 | 
				
			||||||
			viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
			><path
 | 
					 | 
				
			||||||
				stroke-linecap="round"
 | 
					 | 
				
			||||||
				stroke-linejoin="round"
 | 
					 | 
				
			||||||
				stroke-width="2"
 | 
					 | 
				
			||||||
				d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
 | 
					 | 
				
			||||||
			/></svg
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	{:else if type === 'error'}
 | 
					 | 
				
			||||||
		<svg
 | 
					 | 
				
			||||||
			xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
			class="stroke-current flex-shrink-0 h-6 w-6"
 | 
					 | 
				
			||||||
			fill="none"
 | 
					 | 
				
			||||||
			viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
			><path
 | 
					 | 
				
			||||||
				stroke-linecap="round"
 | 
					 | 
				
			||||||
				stroke-linejoin="round"
 | 
					 | 
				
			||||||
				stroke-width="2"
 | 
					 | 
				
			||||||
				d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
 | 
					 | 
				
			||||||
			/></svg
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	{:else if type === 'info'}
 | 
					 | 
				
			||||||
		<svg
 | 
					 | 
				
			||||||
			xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
			fill="none"
 | 
					 | 
				
			||||||
			viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
			class="stroke-current flex-shrink-0 w-6 h-6"
 | 
					 | 
				
			||||||
			><path
 | 
					 | 
				
			||||||
				stroke-linecap="round"
 | 
					 | 
				
			||||||
				stroke-linejoin="round"
 | 
					 | 
				
			||||||
				stroke-width="2"
 | 
					 | 
				
			||||||
				d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
 | 
					 | 
				
			||||||
			/></svg
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
	<slot />
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,25 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import Toast from './Toast.svelte';
 | 
					 | 
				
			||||||
	import { dismissToast, pauseToast, resumeToast, toasts } from '$lib/store';
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if $toasts.length > 0}
 | 
					 | 
				
			||||||
	<section>
 | 
					 | 
				
			||||||
		<article class="toast toast-top toast-center rounded-none w-2/3 lg:w-[20rem]" role="alert">
 | 
					 | 
				
			||||||
			{#each $toasts as toast (toast.id)}
 | 
					 | 
				
			||||||
				<Toast
 | 
					 | 
				
			||||||
					type={toast.type}
 | 
					 | 
				
			||||||
					on:resume={() => resumeToast(toast.id)}
 | 
					 | 
				
			||||||
					on:pause={() => pauseToast(toast.id)}
 | 
					 | 
				
			||||||
					on:click={() => dismissToast(toast.id)}>{@html toast.message}</Toast
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			{/each}
 | 
					 | 
				
			||||||
		</article>
 | 
					 | 
				
			||||||
	</section>
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style lang="postcss">
 | 
					 | 
				
			||||||
	section {
 | 
					 | 
				
			||||||
		@apply fixed top-0 left-0 right-0 w-full flex flex-col mt-4 justify-center z-[1000];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { Tooltip } from 'flowbite-svelte';
 | 
					 | 
				
			||||||
	export let placement = 'bottom';
 | 
					 | 
				
			||||||
	export let color = 'bg-coollabs';
 | 
					 | 
				
			||||||
	export let triggeredBy = '#tooltip-default';
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<Tooltip {triggeredBy} {placement} arrow={false} defaultClass={color + ' font-thin text-xs text-left border-none p-2'} style="custom"
 | 
					 | 
				
			||||||
	><slot /></Tooltip
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
@@ -1,206 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { dev } from '$app/environment';
 | 
					 | 
				
			||||||
	import {
 | 
					 | 
				
			||||||
		addToast,
 | 
					 | 
				
			||||||
		appSession,
 | 
					 | 
				
			||||||
		features,
 | 
					 | 
				
			||||||
		updateLoading,
 | 
					 | 
				
			||||||
		isUpdateAvailable,
 | 
					 | 
				
			||||||
		latestVersion
 | 
					 | 
				
			||||||
	} from '$lib/store';
 | 
					 | 
				
			||||||
	import { asyncSleep, errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	import { onMount } from 'svelte';
 | 
					 | 
				
			||||||
	import Tooltip from './Tooltip.svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let updateStatus: any = {
 | 
					 | 
				
			||||||
		found: false,
 | 
					 | 
				
			||||||
		loading: false,
 | 
					 | 
				
			||||||
		success: null
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	async function update() {
 | 
					 | 
				
			||||||
		updateStatus.loading = true;
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			if (dev) {
 | 
					 | 
				
			||||||
				localStorage.setItem('lastVersion', $appSession.version);
 | 
					 | 
				
			||||||
				await asyncSleep(1000);
 | 
					 | 
				
			||||||
				updateStatus.loading = false;
 | 
					 | 
				
			||||||
				return window.location.reload();
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				localStorage.setItem('lastVersion', $appSession.version);
 | 
					 | 
				
			||||||
				// await post(`/update`, { type: 'update', latestVersion: $latestVersion });
 | 
					 | 
				
			||||||
				addToast({
 | 
					 | 
				
			||||||
					message: 'Update completed.<br><br>Waiting for the new version to start...',
 | 
					 | 
				
			||||||
					type: 'success'
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				let reachable = false;
 | 
					 | 
				
			||||||
				let tries = 0;
 | 
					 | 
				
			||||||
				do {
 | 
					 | 
				
			||||||
					await asyncSleep(4000);
 | 
					 | 
				
			||||||
					try {
 | 
					 | 
				
			||||||
						// await get(`/undead`);
 | 
					 | 
				
			||||||
						reachable = true;
 | 
					 | 
				
			||||||
					} catch (error) {
 | 
					 | 
				
			||||||
						reachable = false;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					if (reachable) break;
 | 
					 | 
				
			||||||
					tries++;
 | 
					 | 
				
			||||||
				} while (!reachable || tries < 120);
 | 
					 | 
				
			||||||
				addToast({
 | 
					 | 
				
			||||||
					message: 'New version reachable. Reloading...',
 | 
					 | 
				
			||||||
					type: 'success'
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
				updateStatus.loading = false;
 | 
					 | 
				
			||||||
				updateStatus.success = true;
 | 
					 | 
				
			||||||
				await asyncSleep(3000);
 | 
					 | 
				
			||||||
				return window.location.reload();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			updateStatus.success = false;
 | 
					 | 
				
			||||||
			updateStatus.loading = false;
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	onMount(async () => {
 | 
					 | 
				
			||||||
		if ($appSession.userId) {
 | 
					 | 
				
			||||||
			const overrideVersion = $features.latestVersion;
 | 
					 | 
				
			||||||
			if ($appSession.teamId === '0') {
 | 
					 | 
				
			||||||
				if ($updateLoading === true) return;
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					$updateLoading = true;
 | 
					 | 
				
			||||||
					// const data = await get(`/update`);
 | 
					 | 
				
			||||||
					if (overrideVersion || data?.isUpdateAvailable) {
 | 
					 | 
				
			||||||
						$latestVersion = overrideVersion || data.latestVersion;
 | 
					 | 
				
			||||||
						if (overrideVersion) {
 | 
					 | 
				
			||||||
							$isUpdateAvailable = true;
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							$isUpdateAvailable = data.isUpdateAvailable;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} catch (error) {
 | 
					 | 
				
			||||||
					return errorNotification(error);
 | 
					 | 
				
			||||||
				} finally {
 | 
					 | 
				
			||||||
					$updateLoading = false;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="py-0 lg:py-2">
 | 
					 | 
				
			||||||
	{#if $appSession.teamId === '0'}
 | 
					 | 
				
			||||||
		{#if $isUpdateAvailable}
 | 
					 | 
				
			||||||
			<button
 | 
					 | 
				
			||||||
				id="update"
 | 
					 | 
				
			||||||
				disabled={updateStatus.success === false}
 | 
					 | 
				
			||||||
				on:click={update}
 | 
					 | 
				
			||||||
				class="icons bg-coollabs-gradient text-white duration-75 hover:scale-105 w-full"
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				{#if updateStatus.loading}
 | 
					 | 
				
			||||||
					<svg
 | 
					 | 
				
			||||||
						xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
						class="lds-heart h-8 w-8 mx-auto"
 | 
					 | 
				
			||||||
						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" />
 | 
					 | 
				
			||||||
						<path
 | 
					 | 
				
			||||||
							d="M19.5 13.572l-7.5 7.428l-7.5 -7.428m0 0a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572"
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
					</svg>
 | 
					 | 
				
			||||||
				{:else if updateStatus.success === null}
 | 
					 | 
				
			||||||
					<div class="flex items-center justify-center space-x-2">
 | 
					 | 
				
			||||||
						<svg
 | 
					 | 
				
			||||||
							xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
							class="h-8 w-8"
 | 
					 | 
				
			||||||
							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" />
 | 
					 | 
				
			||||||
							<line x1="12" y1="8" x2="8" y2="12" />
 | 
					 | 
				
			||||||
							<line x1="12" y1="8" x2="12" y2="16" />
 | 
					 | 
				
			||||||
							<line x1="16" y1="12" x2="12" y2="8" />
 | 
					 | 
				
			||||||
						</svg>
 | 
					 | 
				
			||||||
						<span class="flex lg:hidden">Update available</span>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				{:else if updateStatus.success}
 | 
					 | 
				
			||||||
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" class="h-8 w-8"
 | 
					 | 
				
			||||||
						><path
 | 
					 | 
				
			||||||
							fill="#DD2E44"
 | 
					 | 
				
			||||||
							d="M11.626 7.488c-.112.112-.197.247-.268.395l-.008-.008L.134 33.141l.011.011c-.208.403.14 1.223.853 1.937.713.713 1.533 1.061 1.936.853l.01.01L28.21 24.735l-.008-.009c.147-.07.282-.155.395-.269 1.562-1.562-.971-6.627-5.656-11.313-4.687-4.686-9.752-7.218-11.315-5.656z"
 | 
					 | 
				
			||||||
						/><path
 | 
					 | 
				
			||||||
							fill="#EA596E"
 | 
					 | 
				
			||||||
							d="M13 12L.416 32.506l-.282.635.011.011c-.208.403.14 1.223.853 1.937.232.232.473.408.709.557L17 17l-4-5z"
 | 
					 | 
				
			||||||
						/><path
 | 
					 | 
				
			||||||
							fill="#A0041E"
 | 
					 | 
				
			||||||
							d="M23.012 13.066c4.67 4.672 7.263 9.652 5.789 11.124-1.473 1.474-6.453-1.118-11.126-5.788-4.671-4.672-7.263-9.654-5.79-11.127 1.474-1.473 6.454 1.119 11.127 5.791z"
 | 
					 | 
				
			||||||
						/><path
 | 
					 | 
				
			||||||
							fill="#AA8DD8"
 | 
					 | 
				
			||||||
							d="M18.59 13.609c-.199.161-.459.245-.734.215-.868-.094-1.598-.396-2.109-.873-.541-.505-.808-1.183-.735-1.862.128-1.192 1.324-2.286 3.363-2.066.793.085 1.147-.17 1.159-.292.014-.121-.277-.446-1.07-.532-.868-.094-1.598-.396-2.11-.873-.541-.505-.809-1.183-.735-1.862.13-1.192 1.325-2.286 3.362-2.065.578.062.883-.057 1.012-.134.103-.063.144-.123.148-.158.012-.121-.275-.446-1.07-.532-.549-.06-.947-.552-.886-1.102.059-.549.55-.946 1.101-.886 2.037.219 2.973 1.542 2.844 2.735-.13 1.194-1.325 2.286-3.364 2.067-.578-.063-.88.057-1.01.134-.103.062-.145.123-.149.157-.013.122.276.446 1.071.532 2.037.22 2.973 1.542 2.844 2.735-.129 1.192-1.324 2.286-3.362 2.065-.578-.062-.882.058-1.012.134-.104.064-.144.124-.148.158-.013.121.276.446 1.07.532.548.06.947.553.886 1.102-.028.274-.167.511-.366.671z"
 | 
					 | 
				
			||||||
						/><path
 | 
					 | 
				
			||||||
							fill="#77B255"
 | 
					 | 
				
			||||||
							d="M30.661 22.857c1.973-.557 3.334.323 3.658 1.478.324 1.154-.378 2.615-2.35 3.17-.77.216-1.001.584-.97.701.034.118.425.312 1.193.095 1.972-.555 3.333.325 3.657 1.479.326 1.155-.378 2.614-2.351 3.17-.769.216-1.001.585-.967.702.033.117.423.311 1.192.095.53-.149 1.084.16 1.233.691.148.532-.161 1.084-.693 1.234-1.971.555-3.333-.323-3.659-1.479-.324-1.154.379-2.613 2.353-3.169.77-.217 1.001-.584.967-.702-.032-.117-.422-.312-1.19-.096-1.974.556-3.334-.322-3.659-1.479-.325-1.154.378-2.613 2.351-3.17.768-.215.999-.585.967-.701-.034-.118-.423-.312-1.192-.096-.532.15-1.083-.16-1.233-.691-.149-.53.161-1.082.693-1.232z"
 | 
					 | 
				
			||||||
						/><path
 | 
					 | 
				
			||||||
							fill="#AA8DD8"
 | 
					 | 
				
			||||||
							d="M23.001 20.16c-.294 0-.584-.129-.782-.375-.345-.432-.274-1.061.156-1.406.218-.175 5.418-4.259 12.767-3.208.547.078.927.584.849 1.131-.078.546-.58.93-1.132.848-6.493-.922-11.187 2.754-11.233 2.791-.186.148-.406.219-.625.219z"
 | 
					 | 
				
			||||||
						/><path
 | 
					 | 
				
			||||||
							fill="#77B255"
 | 
					 | 
				
			||||||
							d="M5.754 16c-.095 0-.192-.014-.288-.042-.529-.159-.829-.716-.67-1.245 1.133-3.773 2.16-9.794.898-11.364-.141-.178-.354-.353-.842-.316-.938.072-.849 2.051-.848 2.071.042.551-.372 1.031-.922 1.072-.559.034-1.031-.372-1.072-.923-.103-1.379.326-4.035 2.692-4.214 1.056-.08 1.933.287 2.552 1.057 2.371 2.951-.036 11.506-.542 13.192-.13.433-.528.712-.958.712z"
 | 
					 | 
				
			||||||
						/><circle fill="#5C913B" cx="25.5" cy="9.5" r="1.5" /><circle
 | 
					 | 
				
			||||||
							fill="#9266CC"
 | 
					 | 
				
			||||||
							cx="2"
 | 
					 | 
				
			||||||
							cy="18"
 | 
					 | 
				
			||||||
							r="2"
 | 
					 | 
				
			||||||
						/><circle fill="#5C913B" cx="32.5" cy="19.5" r="1.5" /><circle
 | 
					 | 
				
			||||||
							fill="#5C913B"
 | 
					 | 
				
			||||||
							cx="23.5"
 | 
					 | 
				
			||||||
							cy="31.5"
 | 
					 | 
				
			||||||
							r="1.5"
 | 
					 | 
				
			||||||
						/><circle fill="#FFCC4D" cx="28" cy="4" r="2" /><circle
 | 
					 | 
				
			||||||
							fill="#FFCC4D"
 | 
					 | 
				
			||||||
							cx="32.5"
 | 
					 | 
				
			||||||
							cy="8.5"
 | 
					 | 
				
			||||||
							r="1.5"
 | 
					 | 
				
			||||||
						/><circle fill="#FFCC4D" cx="29.5" cy="12.5" r="1.5" /><circle
 | 
					 | 
				
			||||||
							fill="#FFCC4D"
 | 
					 | 
				
			||||||
							cx="7.5"
 | 
					 | 
				
			||||||
							cy="23.5"
 | 
					 | 
				
			||||||
							r="1.5"
 | 
					 | 
				
			||||||
						/></svg
 | 
					 | 
				
			||||||
					>
 | 
					 | 
				
			||||||
				{:else}
 | 
					 | 
				
			||||||
					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" class="h-9 w-8"
 | 
					 | 
				
			||||||
						><path
 | 
					 | 
				
			||||||
							fill="#FFCC4D"
 | 
					 | 
				
			||||||
							d="M36 18c0 9.941-8.059 18-18 18S0 27.941 0 18 8.059 0 18 0s18 8.059 18 18"
 | 
					 | 
				
			||||||
						/><path
 | 
					 | 
				
			||||||
							fill="#664500"
 | 
					 | 
				
			||||||
							d="M22 27c0 2.763-1.791 3-4 3-2.21 0-4-.237-4-3 0-2.761 1.79-6 4-6 2.209 0 4 3.239 4 6zm8-12c-.124 0-.25-.023-.371-.072-5.229-2.091-7.372-5.241-7.461-5.374-.307-.46-.183-1.081.277-1.387.459-.306 1.077-.184 1.385.274.019.027 1.93 2.785 6.541 4.629.513.206.763.787.558 1.3-.157.392-.533.63-.929.63zM6 15c-.397 0-.772-.238-.929-.629-.205-.513.044-1.095.557-1.3 4.612-1.844 6.523-4.602 6.542-4.629.308-.456.929-.577 1.387-.27.457.308.581.925.275 1.383-.089.133-2.232 3.283-7.46 5.374C6.25 14.977 6.124 15 6 15z"
 | 
					 | 
				
			||||||
						/><path fill="#5DADEC" d="M24 16h4v19l-4-.046V16zM8 35l4-.046V16H8v19z" /><path
 | 
					 | 
				
			||||||
							fill="#664500"
 | 
					 | 
				
			||||||
							d="M14.999 18c-.15 0-.303-.034-.446-.105-3.512-1.756-7.07-.018-7.105 0-.495.249-1.095.046-1.342-.447-.247-.494-.047-1.095.447-1.342.182-.09 4.498-2.197 8.895 0 .494.247.694.848.447 1.342-.176.35-.529.552-.896.552zm14 0c-.15 0-.303-.034-.446-.105-3.513-1.756-7.07-.018-7.105 0-.494.248-1.094.047-1.342-.447-.247-.494-.047-1.095.447-1.342.182-.09 4.501-2.196 8.895 0 .494.247.694.848.447 1.342-.176.35-.529.552-.896.552z"
 | 
					 | 
				
			||||||
						/><ellipse fill="#5DADEC" cx="18" cy="34" rx="18" ry="2" /><ellipse
 | 
					 | 
				
			||||||
							fill="#E75A70"
 | 
					 | 
				
			||||||
							cx="18"
 | 
					 | 
				
			||||||
							cy="27"
 | 
					 | 
				
			||||||
							rx="3"
 | 
					 | 
				
			||||||
							ry="2"
 | 
					 | 
				
			||||||
						/></svg
 | 
					 | 
				
			||||||
					>
 | 
					 | 
				
			||||||
				{/if}
 | 
					 | 
				
			||||||
			</button>
 | 
					 | 
				
			||||||
			<Tooltip triggeredBy="#update" placement="right" color="bg-coolgray-200 text-white"
 | 
					 | 
				
			||||||
				>New Version Available!</Tooltip
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
		{/if}
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,17 +0,0 @@
 | 
				
			|||||||
<svg
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	class="h-6 w-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" />
 | 
					 | 
				
			||||||
	<line x1="4" y1="7" x2="20" y2="7" />
 | 
					 | 
				
			||||||
	<line x1="10" y1="11" x2="10" y2="17" />
 | 
					 | 
				
			||||||
	<line x1="14" y1="11" x2="14" y2="17" />
 | 
					 | 
				
			||||||
	<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
 | 
					 | 
				
			||||||
	<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 486 B  | 
@@ -1,10 +0,0 @@
 | 
				
			|||||||
<svg
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	fill="currentColor"
 | 
					 | 
				
			||||||
	viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
	stroke-width="3"
 | 
					 | 
				
			||||||
	stroke="currentColor"
 | 
					 | 
				
			||||||
	class="w-3 h-3  text-white"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path stroke-linecap="round" stroke-linejoin="round" d="M4.5 19.5l15-15m0 0H8.25m11.25 0v11.25" />
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 262 B  | 
@@ -1,47 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import * as Icons from '$lib/components/icons/applications';
 | 
					 | 
				
			||||||
	export let application: any;
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if application.buildPack?.toLowerCase() === 'rust'}
 | 
					 | 
				
			||||||
	<Icons.Rust {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'node'}
 | 
					 | 
				
			||||||
	<Icons.Nodejs {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'react'}
 | 
					 | 
				
			||||||
	<Icons.React {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'svelte'}
 | 
					 | 
				
			||||||
	<Icons.Svelte {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'vuejs'}
 | 
					 | 
				
			||||||
	<Icons.Vuejs {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'php'}
 | 
					 | 
				
			||||||
	<Icons.Php {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'python'}
 | 
					 | 
				
			||||||
	<Icons.Python {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'static'}
 | 
					 | 
				
			||||||
	<Icons.Static {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'nestjs'}
 | 
					 | 
				
			||||||
	<Icons.Nestjs {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'nuxtjs'}
 | 
					 | 
				
			||||||
	<Icons.Nuxtjs {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'nextjs'}
 | 
					 | 
				
			||||||
	<Icons.Nextjs {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'gatsby'}
 | 
					 | 
				
			||||||
	<Icons.Gatsby {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'docker'}
 | 
					 | 
				
			||||||
	<Icons.Docker {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'astro'}
 | 
					 | 
				
			||||||
	<Icons.Astro {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'eleventy'}
 | 
					 | 
				
			||||||
	<Icons.Eleventy {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'deno'}
 | 
					 | 
				
			||||||
	<Icons.Deno {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'laravel'}
 | 
					 | 
				
			||||||
	<Icons.Laravel {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'heroku'}
 | 
					 | 
				
			||||||
	<Icons.Heroku {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.buildPack?.toLowerCase() === 'compose'}
 | 
					 | 
				
			||||||
	<Icons.Compose {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if application.simpleDockerfile}
 | 
					 | 
				
			||||||
	<Icons.Docker {isAbsolute} />
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
@@ -1,25 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-6 h-14 w-14' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	viewBox="0 0 256 256"
 | 
					 | 
				
			||||||
	fill="none"
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		id="a"
 | 
					 | 
				
			||||||
		fill="#302649"
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		id="flame"
 | 
					 | 
				
			||||||
		fill="#EF661E"
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,9 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<img
 | 
					 | 
				
			||||||
	alt="docker compose logo"
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'w-16 h-16 absolute top-0 left-0 -m-8' : 'w-8 h-8 mx-auto'}
 | 
					 | 
				
			||||||
	src="/icons/compose.png"
 | 
					 | 
				
			||||||
/>
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -1,9 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<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>
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-8 h-16 w-16' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path fill="transparent" d="M18 0h92v128H18z" /><path
 | 
					 | 
				
			||||||
		d="M55.3 36.3h.4c1.1 0 1.5.9 1.5 2.3v41.8c0 1.8-.4 3-1.6 3l-4.8-.1c-1.2 0-1.6-1-1.6-3V45.5l-2.1.5c-1 0-1.5-.8-1.5-2.2v-3c0-1.2.4-2 1.4-2.2l8.3-2.2zm16 36.1l.1 3 .6 1.3.6.6.8.1h2.2c1 0 1.7.8 1.7 2v1.9c0 1.2-.6 2-1.8 2h-3.2l-2.3-.1c-.7-.2-1.4-.5-2.2-1a5.7 5.7 0 01-2-1.9c-.4-.8-.8-1.9-1-3.2-.4-1.4-.5-3-.5-4.8v-16h-1.5c-1.1 0-1.6-1-1.6-2.4v-1.7c0-1.4.5-2.3 1.6-2.3h1.5v-.1l.6-12.3c0-1.5.5-2.5 1.6-2.5h3.1c1.2 0 1.6 1 1.6 2.5v12.3h3.6c1.1 0 1.6 1 1.6 2.4V54c0 1.4-.5 2.3-1.6 2.3h-3.6v16.2zm9.4 15.7c0-2 .3-3.2 1.5-3.2.2 0 .4 0 1.4.4l1.1.3.2-.1.4-.7c.3-.6.4-1.6.4-3l-.6-3.3L79 52.7v-.9c0-1.2.3-2 1.2-2H84c.5 0 1 .3 1.3.6.3.4.5.9.6 1.6l3.4 18 2.6-17.8c.1-.8.3-1.3.6-1.7.3-.4.8-.6 1.3-.6h2.6c1 0 1.4.8 1.4 2l-.1.8L92 82.2c-.5 2.5-1 4.4-1.5 5.7a6.6 6.6 0 01-2 3c-.9.6-1.9.9-3.1.9h-.3c-2 0-3.3-.6-4.1-1.7-.3-.4-.4-1-.4-2zM31.3 38.8l8.2-2.1h.5c1 0 1.4.8 1.4 2.2v41.9c0 1.8-.4 2.9-1.6 2.9h-4.7c-1.2 0-1.6-1.1-1.6-3v-35l-2 .6c-1.2 0-1.6-.9-1.6-2.2v-3c0-1.2.4-2 1.4-2.3z"
 | 
					 | 
				
			||||||
		fill="#FFF"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-4 h-10 w-10' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		fill="#64328B"
 | 
					 | 
				
			||||||
		d="M64,0C28.7,0,0,28.7,0,64v0c0,35.3,28.7,64,64,64s64-28.7,64-64v0C128,28.7,99.3,0,64,0z M13.2,64L64,114.8 C35.9,114.8,13.2,92.1,13.2,64z M75.4,113.5l-60.9-61C19.7,30,39.9,13.2,64,13.2c16.6,0,31.3,7.9,40.5,20.2l-7.5,7.2 C89.7,30.2,77.7,23.5,64,23.5c-17.6,0-32.5,11.2-38.1,26.8C33.1,57,75.4,98.8,78.1,102c12.7-4.7,22.3-15.5,25.4-28.9H81.9v-9.4 l33,0.2C114.8,88.2,98,108.4,75.4,113.5z"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,15 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-4 h-10 w-10' : 'mx-auto w-8 h-8 '}
 | 
					 | 
				
			||||||
	viewBox="0 0 72 80"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
		fill="#430098"
 | 
					 | 
				
			||||||
		d="M64.8,0 L7.2,0 C3.224,0 0,3.224 0,7.2 L0,72.8 C0,76.776 3.224,80 7.2,80 L64.8,80 C68.776,80 72,76.776 72,72.8 L72,7.2 C72,3.224 68.776,0 64.8,0 Z M18,68 L18,52 L27,60 L18,68 Z M46,68 L46,44.11 C45.961,42.243 45.062,40 41,40 C32.866,40 23.742,44.091 23.651,44.132 L18,46.692 L18,12 L26,12 L26,34.711 C29.994,33.411 35.577,32 41,32 C45.945,32 48.905,33.944 50.517,35.575 C53.958,39.055 54.005,43.488 54.0002258,44 L54.0002258,68 L46,68 Z M48,25 L40,25 C43.144,20.875 45.118,16.534 46,12 L54,12 C53.46,16.544 51.618,20.9 48,25 Z"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-4 h-10 w-10' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	viewBox="0 0 50 52"
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	><title>Logomark</title><path
 | 
					 | 
				
			||||||
		d="M49.626 11.564a.809.809 0 0 1 .028.209v10.972a.8.8 0 0 1-.402.694l-9.209 5.302V39.25c0 .286-.152.55-.4.694L20.42 51.01c-.044.025-.092.041-.14.058-.018.006-.035.017-.054.022a.805.805 0 0 1-.41 0c-.022-.006-.042-.018-.063-.026-.044-.016-.09-.03-.132-.054L.402 39.944A.801.801 0 0 1 0 39.25V6.334c0-.072.01-.142.028-.21.006-.023.02-.044.028-.067.015-.042.029-.085.051-.124.015-.026.037-.047.055-.071.023-.032.044-.065.071-.093.023-.023.053-.04.079-.06.029-.024.055-.05.088-.069h.001l9.61-5.533a.802.802 0 0 1 .8 0l9.61 5.533h.002c.032.02.059.045.088.068.026.02.055.038.078.06.028.029.048.062.072.094.017.024.04.045.054.071.023.04.036.082.052.124.008.023.022.044.028.068a.809.809 0 0 1 .028.209v20.559l8.008-4.611v-10.51c0-.07.01-.141.028-.208.007-.024.02-.045.028-.068.016-.042.03-.085.052-.124.015-.026.037-.047.054-.071.024-.032.044-.065.072-.093.023-.023.052-.04.078-.06.03-.024.056-.05.088-.069h.001l9.611-5.533a.801.801 0 0 1 .8 0l9.61 5.533c.034.02.06.045.09.068.025.02.054.038.077.06.028.029.048.062.072.094.018.024.04.045.054.071.023.039.036.082.052.124.009.023.022.044.028.068zm-1.574 10.718v-9.124l-3.363 1.936-4.646 2.675v9.124l8.01-4.611zm-9.61 16.505v-9.13l-4.57 2.61-13.05 7.448v9.216l17.62-10.144zM1.602 7.719v31.068L19.22 48.93v-9.214l-9.204-5.209-.003-.002-.004-.002c-.031-.018-.057-.044-.086-.066-.025-.02-.054-.036-.076-.058l-.002-.003c-.026-.025-.044-.056-.066-.084-.02-.027-.044-.05-.06-.078l-.001-.003c-.018-.03-.029-.066-.042-.1-.013-.03-.03-.058-.038-.09v-.001c-.01-.038-.012-.078-.016-.117-.004-.03-.012-.06-.012-.09v-.002-21.481L4.965 9.654 1.602 7.72zm8.81-5.994L2.405 6.334l8.005 4.609 8.006-4.61-8.006-4.608zm4.164 28.764l4.645-2.674V7.719l-3.363 1.936-4.646 2.675v20.096l3.364-1.937zM39.243 7.164l-8.006 4.609 8.006 4.609 8.005-4.61-8.005-4.608zm-.801 10.605l-4.646-2.675-3.363-1.936v9.124l4.645 2.674 3.364 1.937v-9.124zM20.02 38.33l11.743-6.704 5.87-3.35-8-4.606-9.211 5.303-8.395 4.833 7.993 4.524z"
 | 
					 | 
				
			||||||
		fill="#FF2D20"
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
	/></svg
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -1,14 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute
 | 
					 | 
				
			||||||
		? 'absolute top-0 left-0 -m-4 h-10 w-10 fill-current text-blue-500'
 | 
					 | 
				
			||||||
		: 'mx-auto w-8 h-8 fill-current text-blue-500'}
 | 
					 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		d="M64 0C28.7 0 0 28.7 0 64s28.7 64 64 64c11.2 0 21.7-2.9 30.8-7.9L48.4 55.3v36.6h-6.8V41.8h6.8l50.5 75.8C116.4 106.2 128 86.5 128 64c0-35.3-28.7-64-64-64zm22.1 84.6l-7.5-11.3V41.8h7.5v42.8z"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,18 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-4 h-10 w-10 text-green-500' : 'mx-auto w-8 h-8 text-green-500'}
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	aria-hidden="true"
 | 
					 | 
				
			||||||
	focusable="false"
 | 
					 | 
				
			||||||
	data-prefix="fab"
 | 
					 | 
				
			||||||
	data-icon="node-js"
 | 
					 | 
				
			||||||
	role="img"
 | 
					 | 
				
			||||||
	viewBox="0 0 448 512"
 | 
					 | 
				
			||||||
	><path
 | 
					 | 
				
			||||||
		fill="currentColor"
 | 
					 | 
				
			||||||
		d="M224 508c-6.7 0-13.5-1.8-19.4-5.2l-61.7-36.5c-9.2-5.2-4.7-7-1.7-8 12.3-4.3 14.8-5.2 27.9-12.7 1.4-.8 3.2-.5 4.6.4l47.4 28.1c1.7 1 4.1 1 5.7 0l184.7-106.6c1.7-1 2.8-3 2.8-5V149.3c0-2.1-1.1-4-2.9-5.1L226.8 37.7c-1.7-1-4-1-5.7 0L36.6 144.3c-1.8 1-2.9 3-2.9 5.1v213.1c0 2 1.1 4 2.9 4.9l50.6 29.2c27.5 13.7 44.3-2.4 44.3-18.7V167.5c0-3 2.4-5.3 5.4-5.3h23.4c2.9 0 5.4 2.3 5.4 5.3V378c0 36.6-20 57.6-54.7 57.6-10.7 0-19.1 0-42.5-11.6l-48.4-27.9C8.1 389.2.7 376.3.7 362.4V149.3c0-13.8 7.4-26.8 19.4-33.7L204.6 9c11.7-6.6 27.2-6.6 38.8 0l184.7 106.7c12 6.9 19.4 19.8 19.4 33.7v213.1c0 13.8-7.4 26.7-19.4 33.7L243.4 502.8c-5.9 3.4-12.6 5.2-19.4 5.2zm149.1-210.1c0-39.9-27-50.5-83.7-58-57.4-7.6-63.2-11.5-63.2-24.9 0-11.1 4.9-25.9 47.4-25.9 37.9 0 51.9 8.2 57.7 33.8.5 2.4 2.7 4.2 5.2 4.2h24c1.5 0 2.9-.6 3.9-1.7s1.5-2.6 1.4-4.1c-3.7-44.1-33-64.6-92.2-64.6-52.7 0-84.1 22.2-84.1 59.5 0 40.4 31.3 51.6 81.8 56.6 60.5 5.9 65.2 14.8 65.2 26.7 0 20.6-16.6 29.4-55.5 29.4-48.9 0-59.6-12.3-63.2-36.6-.4-2.6-2.6-4.5-5.3-4.5h-23.9c-3 0-5.3 2.4-5.3 5.3 0 31.1 16.9 68.2 97.8 68.2 58.4-.1 92-23.2 92-63.4z"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,24 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-4 h-10 w-10' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	viewBox="0 0 400 400"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<g fill-rule="nonzero" transform="translate(0 50)" fill="none">
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M227.92099 83.45116l-13.6889 24.10141-46.8148-82.44693L23.7037 278.17052h97.3037c0 13.31084 10.61252 24.10142 23.70371 24.10142H23.70371c-8.46771 0-16.29145-4.59601-20.5246-12.05272-4.23315-7.4567-4.23272-16.64312.00114-24.0994L146.89383 13.05492c4.23415-7.45738 12.0596-12.05138 20.5284-12.05138 8.46878 0 16.29423 4.594 20.52839 12.05138l39.97037 70.39623z"
 | 
					 | 
				
			||||||
			fill="#00C58E"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M331.6642 266.11981l-90.05432-158.56724-13.6889-24.10141-13.68888 24.10141-90.04445 158.56724c-4.23385 7.45629-4.23428 16.64271-.00113 24.09941 4.23314 7.4567 12.05689 12.05272 20.5246 12.05272h166.4c8.46946 0 16.29644-4.591 20.532-12.04837 4.23555-7.45736 4.23606-16.64592.00132-24.10376h.01976zM144.7111 278.17052L227.921 131.65399l83.19012 146.51653h-166.4z"
 | 
					 | 
				
			||||||
			fill="#FFF"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M396.04938 290.22123c-4.23344 7.45557-12.05656 12.0507-20.52345 12.0507H311.1111c13.0912 0 23.7037-10.79057 23.7037-24.10141h40.66173L260.09877 74.98553l-18.4889 32.56704L227.921 83.45116l11.65432-20.51634c4.23416-7.45738 12.0596-12.05138 20.5284-12.05138 8.46879 0 16.29423 4.594 20.52839 12.05138l115.41728 203.185c4.23426 7.457 4.23426 16.6444 0 24.1014z"
 | 
					 | 
				
			||||||
			fill="#108775"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
	</g>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,15 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
					 | 
				
			||||||
	class={isAbsolute
 | 
					 | 
				
			||||||
		? 'absolute top-0 left-0 -m-6 h-14 w-14 text-white'
 | 
					 | 
				
			||||||
		: 'mx-auto w-8 h-8 text-white'}
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		fill="#6181B6"
 | 
					 | 
				
			||||||
		d="M64 33.039c-33.74 0-61.094 13.862-61.094 30.961s27.354 30.961 61.094 30.961 61.094-13.862 61.094-30.961-27.354-30.961-61.094-30.961zm-15.897 36.993c-1.458 1.364-3.077 1.927-4.86 2.507-1.783.581-4.052.461-6.811.461h-6.253l-1.733 10h-7.301l6.515-34h14.04c4.224 0 7.305 1.215 9.242 3.432 1.937 2.217 2.519 5.364 1.747 9.337-.319 1.637-.856 3.159-1.614 4.515-.759 1.357-1.75 2.624-2.972 3.748zm21.311 2.968l2.881-14.42c.328-1.688.208-2.942-.361-3.555-.57-.614-1.782-1.025-3.635-1.025h-5.79l-3.731 19h-7.244l6.515-33h7.244l-1.732 9h6.453c4.061 0 6.861.815 8.402 2.231s2.003 3.356 1.387 6.528l-3.031 15.241h-7.358zm40.259-11.178c-.318 1.637-.856 3.133-1.613 4.488-.758 1.357-1.748 2.598-2.971 3.722-1.458 1.364-3.078 1.927-4.86 2.507-1.782.581-4.053.461-6.812.461h-6.253l-1.732 10h-7.301l6.514-34h14.041c4.224 0 7.305 1.215 9.241 3.432 1.935 2.217 2.518 5.418 1.746 9.39zM95.919 54h-5.001l-2.727 14h4.442c2.942 0 5.136-.29 6.576-1.4 1.442-1.108 2.413-2.828 2.918-5.421.484-2.491.264-4.434-.66-5.458-.925-1.024-2.774-1.721-5.548-1.721zM38.934 54h-5.002l-2.727 14h4.441c2.943 0 5.136-.29 6.577-1.4 1.441-1.108 2.413-2.828 2.917-5.421.484-2.491.264-4.434-.66-5.458s-2.772-1.721-5.546-1.721z"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,57 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-6 h-14 w-14' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<linearGradient
 | 
					 | 
				
			||||||
		id="a"
 | 
					 | 
				
			||||||
		gradientUnits="userSpaceOnUse"
 | 
					 | 
				
			||||||
		x1="70.252"
 | 
					 | 
				
			||||||
		y1="1237.476"
 | 
					 | 
				
			||||||
		x2="170.659"
 | 
					 | 
				
			||||||
		y2="1151.089"
 | 
					 | 
				
			||||||
		gradientTransform="matrix(.563 0 0 -.568 -29.215 707.817)"
 | 
					 | 
				
			||||||
		><stop offset="0" stop-color="#5A9FD4" /><stop
 | 
					 | 
				
			||||||
			offset="1"
 | 
					 | 
				
			||||||
			stop-color="#306998"
 | 
					 | 
				
			||||||
		/></linearGradient
 | 
					 | 
				
			||||||
	><path
 | 
					 | 
				
			||||||
		fill="url(#a)"
 | 
					 | 
				
			||||||
		d="M63.391 1.988c-4.222.02-8.252.379-11.8 1.007-10.45 1.846-12.346 5.71-12.346 12.837v9.411h24.693v3.137h-33.961c-7.176 0-13.46 4.313-15.426 12.521-2.268 9.405-2.368 15.275 0 25.096 1.755 7.311 5.947 12.519 13.124 12.519h8.491v-11.282c0-8.151 7.051-15.34 15.426-15.34h24.665c6.866 0 12.346-5.654 12.346-12.548v-23.513c0-6.693-5.646-11.72-12.346-12.837-4.244-.706-8.645-1.027-12.866-1.008zm-13.354 7.569c2.55 0 4.634 2.117 4.634 4.721 0 2.593-2.083 4.69-4.634 4.69-2.56 0-4.633-2.097-4.633-4.69-.001-2.604 2.073-4.721 4.633-4.721z"
 | 
					 | 
				
			||||||
	/><linearGradient
 | 
					 | 
				
			||||||
		id="b"
 | 
					 | 
				
			||||||
		gradientUnits="userSpaceOnUse"
 | 
					 | 
				
			||||||
		x1="209.474"
 | 
					 | 
				
			||||||
		y1="1098.811"
 | 
					 | 
				
			||||||
		x2="173.62"
 | 
					 | 
				
			||||||
		y2="1149.537"
 | 
					 | 
				
			||||||
		gradientTransform="matrix(.563 0 0 -.568 -29.215 707.817)"
 | 
					 | 
				
			||||||
		><stop offset="0" stop-color="#FFD43B" /><stop
 | 
					 | 
				
			||||||
			offset="1"
 | 
					 | 
				
			||||||
			stop-color="#FFE873"
 | 
					 | 
				
			||||||
		/></linearGradient
 | 
					 | 
				
			||||||
	><path
 | 
					 | 
				
			||||||
		fill="url(#b)"
 | 
					 | 
				
			||||||
		d="M91.682 28.38v10.966c0 8.5-7.208 15.655-15.426 15.655h-24.665c-6.756 0-12.346 5.783-12.346 12.549v23.515c0 6.691 5.818 10.628 12.346 12.547 7.816 2.297 15.312 2.713 24.665 0 6.216-1.801 12.346-5.423 12.346-12.547v-9.412h-24.664v-3.138h37.012c7.176 0 9.852-5.005 12.348-12.519 2.578-7.735 2.467-15.174 0-25.096-1.774-7.145-5.161-12.521-12.348-12.521h-9.268zm-13.873 59.547c2.561 0 4.634 2.097 4.634 4.692 0 2.602-2.074 4.719-4.634 4.719-2.55 0-4.633-2.117-4.633-4.719 0-2.595 2.083-4.692 4.633-4.692z"
 | 
					 | 
				
			||||||
	/><radialGradient
 | 
					 | 
				
			||||||
		id="c"
 | 
					 | 
				
			||||||
		cx="1825.678"
 | 
					 | 
				
			||||||
		cy="444.45"
 | 
					 | 
				
			||||||
		r="26.743"
 | 
					 | 
				
			||||||
		gradientTransform="matrix(0 -.24 -1.055 0 532.979 557.576)"
 | 
					 | 
				
			||||||
		gradientUnits="userSpaceOnUse"
 | 
					 | 
				
			||||||
		><stop offset="0" stop-color="#B8B8B8" stop-opacity=".498" /><stop
 | 
					 | 
				
			||||||
			offset="1"
 | 
					 | 
				
			||||||
			stop-color="#7F7F7F"
 | 
					 | 
				
			||||||
			stop-opacity="0"
 | 
					 | 
				
			||||||
		/></radialGradient
 | 
					 | 
				
			||||||
	><path
 | 
					 | 
				
			||||||
		opacity=".444"
 | 
					 | 
				
			||||||
		fill="url(#c)"
 | 
					 | 
				
			||||||
		enable-background="new"
 | 
					 | 
				
			||||||
		d="M97.309 119.597c0 3.543-14.816 6.416-33.091 6.416-18.276 0-33.092-2.873-33.092-6.416 0-3.544 14.815-6.417 33.092-6.417 18.275 0 33.091 2.872 33.091 6.417z"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,16 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute
 | 
					 | 
				
			||||||
		? 'absolute top-0 left-0 -m-4 h-10 w-10 text-blue-500'
 | 
					 | 
				
			||||||
		: 'mx-auto w-8 h-8 text-blue-500'}
 | 
					 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<g fill="#61DAFB"
 | 
					 | 
				
			||||||
		><circle cx="64" cy="64" r="11.4" /><path
 | 
					 | 
				
			||||||
			d="M107.3 45.2c-2.2-.8-4.5-1.6-6.9-2.3.6-2.4 1.1-4.8 1.5-7.1 2.1-13.2-.2-22.5-6.6-26.1-1.9-1.1-4-1.6-6.4-1.6-7 0-15.9 5.2-24.9 13.9-9-8.7-17.9-13.9-24.9-13.9-2.4 0-4.5.5-6.4 1.6-6.4 3.7-8.7 13-6.6 26.1.4 2.3.9 4.7 1.5 7.1-2.4.7-4.7 1.4-6.9 2.3-12.5 4.8-19.3 11.4-19.3 18.8s6.9 14 19.3 18.8c2.2.8 4.5 1.6 6.9 2.3-.6 2.4-1.1 4.8-1.5 7.1-2.1 13.2.2 22.5 6.6 26.1 1.9 1.1 4 1.6 6.4 1.6 7.1 0 16-5.2 24.9-13.9 9 8.7 17.9 13.9 24.9 13.9 2.4 0 4.5-.5 6.4-1.6 6.4-3.7 8.7-13 6.6-26.1-.4-2.3-.9-4.7-1.5-7.1 2.4-.7 4.7-1.4 6.9-2.3 12.5-4.8 19.3-11.4 19.3-18.8s-6.8-14-19.3-18.8zm-14.8-30.5c4.1 2.4 5.5 9.8 3.8 20.3-.3 2.1-.8 4.3-1.4 6.6-5.2-1.2-10.7-2-16.5-2.5-3.4-4.8-6.9-9.1-10.4-13 7.4-7.3 14.9-12.3 21-12.3 1.3 0 2.5.3 3.5.9zm-11.2 59.3c-1.8 3.2-3.9 6.4-6.1 9.6-3.7.3-7.4.4-11.2.4-3.9 0-7.6-.1-11.2-.4-2.2-3.2-4.2-6.4-6-9.6-1.9-3.3-3.7-6.7-5.3-10 1.6-3.3 3.4-6.7 5.3-10 1.8-3.2 3.9-6.4 6.1-9.6 3.7-.3 7.4-.4 11.2-.4 3.9 0 7.6.1 11.2.4 2.2 3.2 4.2 6.4 6 9.6 1.9 3.3 3.7 6.7 5.3 10-1.7 3.3-3.4 6.6-5.3 10zm8.3-3.3c1.5 3.5 2.7 6.9 3.8 10.3-3.4.8-7 1.4-10.8 1.9 1.2-1.9 2.5-3.9 3.6-6 1.2-2.1 2.3-4.2 3.4-6.2zm-25.6 27.1c-2.4-2.6-4.7-5.4-6.9-8.3 2.3.1 4.6.2 6.9.2 2.3 0 4.6-.1 6.9-.2-2.2 2.9-4.5 5.7-6.9 8.3zm-18.6-15c-3.8-.5-7.4-1.1-10.8-1.9 1.1-3.3 2.3-6.8 3.8-10.3 1.1 2 2.2 4.1 3.4 6.1 1.2 2.2 2.4 4.1 3.6 6.1zm-7-25.5c-1.5-3.5-2.7-6.9-3.8-10.3 3.4-.8 7-1.4 10.8-1.9-1.2 1.9-2.5 3.9-3.6 6-1.2 2.1-2.3 4.2-3.4 6.2zm25.6-27.1c2.4 2.6 4.7 5.4 6.9 8.3-2.3-.1-4.6-.2-6.9-.2-2.3 0-4.6.1-6.9.2 2.2-2.9 4.5-5.7 6.9-8.3zm22.2 21l-3.6-6c3.8.5 7.4 1.1 10.8 1.9-1.1 3.3-2.3 6.8-3.8 10.3-1.1-2.1-2.2-4.2-3.4-6.2zm-54.5-16.2c-1.7-10.5-.3-17.9 3.8-20.3 1-.6 2.2-.9 3.5-.9 6 0 13.5 4.9 21 12.3-3.5 3.8-7 8.2-10.4 13-5.8.5-11.3 1.4-16.5 2.5-.6-2.3-1-4.5-1.4-6.6zm-24.7 29c0-4.7 5.7-9.7 15.7-13.4 2-.8 4.2-1.5 6.4-2.1 1.6 5 3.6 10.3 6 15.6-2.4 5.3-4.5 10.5-6 15.5-13.8-4-22.1-10-22.1-15.6zm28.5 49.3c-4.1-2.4-5.5-9.8-3.8-20.3.3-2.1.8-4.3 1.4-6.6 5.2 1.2 10.7 2 16.5 2.5 3.4 4.8 6.9 9.1 10.4 13-7.4 7.3-14.9 12.3-21 12.3-1.3 0-2.5-.3-3.5-.9zm60.8-20.3c1.7 10.5.3 17.9-3.8 20.3-1 .6-2.2.9-3.5.9-6 0-13.5-4.9-21-12.3 3.5-3.8 7-8.2 10.4-13 5.8-.5 11.3-1.4 16.5-2.5.6 2.3 1 4.5 1.4 6.6zm9-15.6c-2 .8-4.2 1.5-6.4 2.1-1.6-5-3.6-10.3-6-15.6 2.4-5.3 4.5-10.5 6-15.5 13.8 4 22.1 10 22.1 15.6 0 4.7-5.8 9.7-15.7 13.4z"
 | 
					 | 
				
			||||||
		/></g
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -1,34 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute
 | 
					 | 
				
			||||||
		? 'absolute top-0 left-0 -m-4 h-10 w-10 text-white'
 | 
					 | 
				
			||||||
		: 'mx-auto w-8 h-8 text-white'}
 | 
					 | 
				
			||||||
	viewBox="0 0 32 32"
 | 
					 | 
				
			||||||
	fill="none"
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	><g clip-path="url(#HTML5_Clip0_4)"
 | 
					 | 
				
			||||||
		><path
 | 
					 | 
				
			||||||
			d="M30.216 0L27.6454 28.7967L16.0907 32L4.56783 28.8012L2 0H30.216Z"
 | 
					 | 
				
			||||||
			fill="#E44D26"
 | 
					 | 
				
			||||||
		/><path
 | 
					 | 
				
			||||||
			d="M16.108 29.5515L25.4447 26.963L27.6415 2.35497H16.108V29.5515Z"
 | 
					 | 
				
			||||||
			fill="#F16529"
 | 
					 | 
				
			||||||
		/><path
 | 
					 | 
				
			||||||
			d="M11.1109 9.4197H16.108V5.88731H7.25053L7.33509 6.83499L8.20327 16.5692H16.108V13.0369H11.4338L11.1109 9.4197Z"
 | 
					 | 
				
			||||||
			fill="#EBEBEB"
 | 
					 | 
				
			||||||
		/><path
 | 
					 | 
				
			||||||
			d="M11.907 18.3354H8.36111L8.856 23.8818L16.0917 25.8904L16.108 25.8859V22.2108L16.0925 22.2149L12.1585 21.1527L11.907 18.3354Z"
 | 
					 | 
				
			||||||
			fill="#EBEBEB"
 | 
					 | 
				
			||||||
		/><path
 | 
					 | 
				
			||||||
			d="M16.0958 16.5692H20.4455L20.0354 21.1504L16.0958 22.2138V25.8887L23.3373 23.8817L23.3904 23.285L24.2205 13.9855L24.3067 13.0369H16.0958V16.5692Z"
 | 
					 | 
				
			||||||
			fill="white"
 | 
					 | 
				
			||||||
		/><path
 | 
					 | 
				
			||||||
			d="M16.0958 9.41105V9.41969H24.6281L24.6989 8.62572L24.8599 6.83499L24.9444 5.88731H16.0958V9.41105Z"
 | 
					 | 
				
			||||||
			fill="white"
 | 
					 | 
				
			||||||
		/></g
 | 
					 | 
				
			||||||
	><defs><clipPath id="HTML5_Clip0_4"><rect width="32" height="32" fill="white" /></clipPath></defs
 | 
					 | 
				
			||||||
	></svg
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
@@ -1,25 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-4 h-10 w-10' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	version="1.1"
 | 
					 | 
				
			||||||
	id="Layer_1"
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
					 | 
				
			||||||
	x="0px"
 | 
					 | 
				
			||||||
	y="0px"
 | 
					 | 
				
			||||||
	viewBox="0 0 98.1 118"
 | 
					 | 
				
			||||||
	style="enable-background:new 0 0 98.1 118;"
 | 
					 | 
				
			||||||
	xml:space="preserve"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		fill="#FF3E00"
 | 
					 | 
				
			||||||
		d="M91.8,15.6C80.9-0.1,59.2-4.7,43.6,5.2L16.1,22.8C8.6,27.5,3.4,35.2,1.9,43.9c-1.3,7.3-0.2,14.8,3.3,21.3  c-2.4,3.6-4,7.6-4.7,11.8c-1.6,8.9,0.5,18.1,5.7,25.4c11,15.7,32.6,20.3,48.2,10.4l27.5-17.5c7.5-4.7,12.7-12.4,14.2-21.1  c1.3-7.3,0.2-14.8-3.3-21.3c2.4-3.6,4-7.6,4.7-11.8C99.2,32.1,97.1,22.9,91.8,15.6"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		fill="#FFFFFF"
 | 
					 | 
				
			||||||
		d="M40.9,103.9c-8.9,2.3-18.2-1.2-23.4-8.7c-3.2-4.4-4.4-9.9-3.5-15.3c0.2-0.9,0.4-1.7,0.6-2.6l0.5-1.6l1.4,1  c3.3,2.4,6.9,4.2,10.8,5.4l1,0.3l-0.1,1c-0.1,1.4,0.3,2.9,1.1,4.1c1.6,2.3,4.4,3.4,7.1,2.7c0.6-0.2,1.2-0.4,1.7-0.7L65.5,72  c1.4-0.9,2.3-2.2,2.6-3.8c0.3-1.6-0.1-3.3-1-4.6c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7l-10.5,6.7  c-1.7,1.1-3.6,1.9-5.6,2.4c-8.9,2.3-18.2-1.2-23.4-8.7c-3.1-4.4-4.4-9.9-3.4-15.3c0.9-5.2,4.1-9.9,8.6-12.7l27.5-17.5  c1.7-1.1,3.6-1.9,5.6-2.5c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.2,0.9-0.4,1.7-0.7,2.6l-0.5,1.6l-1.4-1  c-3.3-2.4-6.9-4.2-10.8-5.4l-1-0.3l0.1-1c0.1-1.4-0.3-2.9-1.1-4.1c-1.6-2.3-4.4-3.3-7.1-2.6c-0.6,0.2-1.2,0.4-1.7,0.7L32.4,46.1  c-1.4,0.9-2.3,2.2-2.6,3.8s0.1,3.3,1,4.6c1.6,2.3,4.4,3.3,7.1,2.6c0.6-0.2,1.2-0.4,1.7-0.7l10.5-6.7c1.7-1.1,3.6-1.9,5.6-2.5  c8.9-2.3,18.2,1.2,23.4,8.7c3.2,4.4,4.4,9.9,3.5,15.3c-0.9,5.2-4.1,9.9-8.6,12.7l-27.5,17.5C44.8,102.5,42.9,103.3,40.9,103.9"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,21 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = true;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute
 | 
					 | 
				
			||||||
		? 'absolute top-0 left-0 -m-4 h-10 w-10 text-green-500'
 | 
					 | 
				
			||||||
		: 'mx-auto w-8 h-8 text-green-500'}
 | 
					 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		d="m-2.3125e-8 8.9337 49.854 0.1586 14.167 24.47 14.432-24.47 49.547-0.1577-63.834 110.14zm126.98 0.6374-24.36 0.0207-38.476 66.052-38.453-66.052-24.749-0.0194 63.211 107.89zm-25.149-0.008-22.745 0.16758l-15.053 24.647-14.817-24.647-22.794-0.1679 37.731 64.476zM25.997 9.3929l23.002 0.0087M25.997 9.3929l23.002 0.0087"
 | 
					 | 
				
			||||||
		fill="none"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		d="m25.997 9.3929 23.002 0.0087l15.036 24.958 14.983-24.956 22.982-0.0057-37.85 65.655z"
 | 
					 | 
				
			||||||
		fill="#35495e"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		d="m0.91068 9.5686 25.066-0.1711 38.151 65.658 37.852-65.654 25.11 0.0263-62.966 108.06z"
 | 
					 | 
				
			||||||
		fill="#41b883"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,20 +0,0 @@
 | 
				
			|||||||
//@ts-nocheck
 | 
					 | 
				
			||||||
export { default as Rust } from './Rust.svelte';
 | 
					 | 
				
			||||||
export { default as Nodejs } from './Nodejs.svelte';
 | 
					 | 
				
			||||||
export { default as React } from './React.svelte';
 | 
					 | 
				
			||||||
export { default as Svelte } from './Svelte.svelte';
 | 
					 | 
				
			||||||
export { default as Vuejs } from './Vuejs.svelte';
 | 
					 | 
				
			||||||
export { default as Php } from './PHP.svelte';
 | 
					 | 
				
			||||||
export { default as Python } from './Python.svelte';
 | 
					 | 
				
			||||||
export { default as Static } from './Static.svelte';
 | 
					 | 
				
			||||||
export { default as Nestjs } from './Nestjs.svelte';
 | 
					 | 
				
			||||||
export { default as Nuxtjs } from './Nuxtjs.svelte';
 | 
					 | 
				
			||||||
export { default as Nextjs } from './Nextjs.svelte';
 | 
					 | 
				
			||||||
export { default as Gatsby } from './Gatsby.svelte';
 | 
					 | 
				
			||||||
export { default as Docker } from './Docker.svelte';
 | 
					 | 
				
			||||||
export { default as Astro } from './Astro.svelte';
 | 
					 | 
				
			||||||
export { default as Eleventy } from './Eleventy.svelte';
 | 
					 | 
				
			||||||
export { default as Deno } from './Deno.svelte';
 | 
					 | 
				
			||||||
export { default as Laravel } from './Laravel.svelte';
 | 
					 | 
				
			||||||
export { default as Heroku } from './Heroku.svelte';
 | 
					 | 
				
			||||||
export { default as Compose } from './Compose.svelte';
 | 
					 | 
				
			||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-5 h-10 w-10' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	viewBox="0 0 9 8"
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	><path d="m0 7h1v1h-1z" fill="#f00" /><path
 | 
					 | 
				
			||||||
		d="m0 0h1v7h-1zm2 0h1v8h-1zm2 0h1v8h-1zm2 0h1v8h-1zm2 3.25h1v1.5h-1z"
 | 
					 | 
				
			||||||
		fill="#fc0"
 | 
					 | 
				
			||||||
	/></svg
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
@@ -1,18 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute
 | 
					 | 
				
			||||||
		? 'absolute top-0 left-0 -m-5 h-10 w-10 fill-current text-red-500'
 | 
					 | 
				
			||||||
		: 'mx-auto w-8 h-8 text-red-500'}
 | 
					 | 
				
			||||||
	id="CouchDB"
 | 
					 | 
				
			||||||
	fill="currentColor"
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
					 | 
				
			||||||
	><g id="original"
 | 
					 | 
				
			||||||
		><path
 | 
					 | 
				
			||||||
			d="M101.4,77.2c0,5-2.7,7.5-7.6,7.7H33.9c-4.9,0-7.6-2.5-7.6-7.7,0-5,2.7-7.5,7.6-7.7H94.1C99,69.7,101.4,72.2,101.4,77.2ZM94.1,88.7H33.9c-4.9,0-7.6,2.4-7.6,7.7,0,5,2.7,7.4,7.6,7.7H94.1c4.9,0,7.6-2.5,7.6-7.7C101.4,91.1,99,88.7,94.1,88.7Zm18.6-42.1h0c-4.9,0-7.6,2.5-7.6,7.4V96.1c0,5,2.7,7.5,7.6,7.7h0c7.4-.2,11.3-7.7,11.3-22.9V62C124,51.8,120.1,46.8,112.7,46.6Zm-97.4,0h0C7.9,46.8,4,51.8,4,62V80.9c0,15.2,3.9,22.7,11.3,22.9h0c4.9,0,7.6-2.4,7.6-7.7V54.3C22.7,49.3,20.2,46.8,15.3,46.6Zm97.4-3.8c0-12.7-6.6-18.7-18.6-18.9H33.9c-12.2.2-18.6,6.5-18.6,18.9h0c7.4,0,11.3,4,11.3,11.5s3.9,11.4,11.3,11.4H90.4c7.3,0,11.3-3.9,11.3-11.4-.3-7.7,3.9-11.2,11-11.5Z"
 | 
					 | 
				
			||||||
		/></g
 | 
					 | 
				
			||||||
	></svg
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
@@ -1,21 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import * as Icons from '$lib/components/icons/databases';
 | 
					 | 
				
			||||||
	export let type: any;
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if type === 'mysql'}
 | 
					 | 
				
			||||||
	<Icons.MySQL {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if type === 'postgresql'}
 | 
					 | 
				
			||||||
	<Icons.PostgreSQL {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if type === 'mongodb'}
 | 
					 | 
				
			||||||
	<Icons.MongoDB {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if type === 'mariadb'}
 | 
					 | 
				
			||||||
	<Icons.MariaDB {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if type === 'redis'}
 | 
					 | 
				
			||||||
	<Icons.Redis {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if type === 'couchdb'}
 | 
					 | 
				
			||||||
	<Icons.CouchDB {isAbsolute} />
 | 
					 | 
				
			||||||
{:else if type === 'edgedb'}
 | 
					 | 
				
			||||||
	<Icons.EdgeDB {isAbsolute} />
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-8 h-16 w-16' : 'mx-auto w-12 h-12'}
 | 
					 | 
				
			||||||
	width="88"
 | 
					 | 
				
			||||||
	fill="#1F8AED"
 | 
					 | 
				
			||||||
	height="101"
 | 
					 | 
				
			||||||
	viewBox="0 -15 88 101"
 | 
					 | 
				
			||||||
	><path
 | 
					 | 
				
			||||||
		class="pageNav_logoBar__2v4ah"
 | 
					 | 
				
			||||||
		style="transform-origin:center 35.5px"
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		d="M55.1436 71H58.1436V0H55.1436V71Z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		d="M74.5362 35.3047C74.5362 41.3776 72.1013 42.4662 69.3799 42.4662H63.5935V28.1432H69.3799C72.1013 28.1432 74.5362 29.2318 74.5362 35.3047V35.3047ZM71.5862 35.3047C71.5862 31.0651 70.2971 30.8646 68.4352 30.8646H66.6305V39.7448H68.4352C70.2971 39.7448 71.5862 39.5443 71.5862 35.3047V35.3047ZM40.9348 42.4662V28.1432H50.0442V30.8646H43.9713V33.7865H48.5546V36.4792H43.9713V39.7448H50.0442V42.4662H40.9348ZM80.6092 36.1068V39.7448H83.13C84.7055 39.7448 85.1066 38.7135 85.1066 37.9401C85.1066 37.3385 84.8201 36.1068 82.6717 36.1068H80.6092ZM80.6092 30.8646V33.5859H82.6717C83.8462 33.5859 84.5337 33.0703 84.5337 32.2109C84.5337 31.3516 83.8462 30.8646 82.6717 30.8646H80.6092ZM77.5732 28.1432H83.4169C86.482 28.1432 87.3987 30.2917 87.3987 31.8385C87.3987 33.2708 86.482 34.3021 85.8518 34.5885C87.6851 35.4766 88.0002 37.2813 88.0002 38.1979C88.0002 39.401 87.3987 42.4662 83.4169 42.4662H77.5732V28.1432ZM23.4899 35.3047C23.4899 41.3776 21.055 42.4662 18.3337 42.4662H12.5472V28.1432H18.3337C21.055 28.1432 23.4899 29.2318 23.4899 35.3047V35.3047ZM32.4272 39.8594C33.974 39.8594 34.7761 39.3438 35.0626 39V37.4245H32.599V34.9609H37.4975V40.6615C37.0678 41.3203 34.7188 42.6094 32.5704 42.6094C29.047 42.6094 26.0678 41.2344 26.0678 35.1615C26.0678 29.0885 29.0756 28 31.797 28C36.0652 28 37.1251 30.2344 37.4688 32.2109L34.948 32.7839C34.8048 31.8672 34.0027 30.7214 32.1694 30.7214C30.3074 30.7214 29.0183 30.9219 29.0183 35.1615C29.0183 39.401 30.3647 39.8594 32.4272 39.8594V39.8594ZM20.539 35.3047C20.539 31.0651 19.2499 30.8646 17.3879 30.8646H15.5833V39.7448H17.3879C19.2499 39.7448 20.539 39.5443 20.539 35.3047V35.3047ZM0 42.4662V28.1432H9.10938V30.8646H3.03646V33.7865H7.61979V36.4792H3.03646V39.7448H9.10938V42.4662H0Z"
 | 
					 | 
				
			||||||
	/></svg
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
@@ -1,17 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	id="Layer_1"
 | 
					 | 
				
			||||||
	data-name="Layer 1"
 | 
					 | 
				
			||||||
	viewBox="0 0 309.88 252.72"
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-5 h-12 w-12 ' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		fill="#fff"
 | 
					 | 
				
			||||||
		d="M316,10.05a4.2,4.2,0,0,0-2.84-1c-2.84,0-6.5,1.92-8.46,3l-.79.4a26.81,26.81,0,0,1-10.57,2.66c-3.76.12-7,.34-11.22.77-25,2.58-36.15,21.74-46.89,40.27-5.84,10.08-11.88,20.5-20.16,28.57a55.71,55.71,0,0,1-5.46,4.63c-8.57,6.39-19.33,10.9-27.74,14.12-8.07,3.08-16.86,5.85-25.37,8.53-7.78,2.45-15.14,4.76-21.9,7.28-3.05,1.13-5.64,2-7.93,2.76-6.15,2-10.6,3.53-17.08,8-2.53,1.73-5.07,3.6-6.8,5a71.26,71.26,0,0,0-13.54,14.27A84.81,84.81,0,0,1,77.88,163c-1.36,1.34-3.8,2-7.43,2-4.27,0-9.43-.88-14.91-1.81s-11.46-2-16.46-2c-4.07,0-7.17.66-9.5,2,0,0-3.9,2.28-5.56,5.23l1.62.73a33.56,33.56,0,0,1,6.93,5,33.68,33.68,0,0,0,7.19,5.12A6.37,6.37,0,0,1,42,180.72c-.69,1-1.69,2.29-2.74,3.67-5.77,7.55-9.13,12.32-7.2,14.92a6,6,0,0,0,3,.68c12.59,0,19.34-3.27,27.9-7.41,2.47-1.2,5-2.44,8-3.7,5-2.17,10.38-5.63,16.08-9.29,7.55-4.85,15.36-9.87,22.92-12.3a62.3,62.3,0,0,1,19.23-2.7c8,0,16.42,1.07,24.54,2.11,6.06.78,12.32,1.58,18.47,2,2.39.14,4.6.21,6.76.21a78.48,78.48,0,0,0,8.61-.45l.68-.24c4.32-2.65,6.34-8.34,8.29-13.84,1.26-3.54,2.32-6.72,4-8.74a2.06,2.06,0,0,1,.33-.27.4.4,0,0,1,.49.08.25.25,0,0,1,0,.16c-1,21.51-9.67,35.16-18.42,47.3L177,199.14s8.18,0,12.84-1.8c17-5.08,29.84-16.28,39.18-34.14a144.39,144.39,0,0,0,6.16-14.09c.16-.4,1.64-1.14,1.49.93,0,.61-.08,1.29-.13,2h0c0,.42-.06.85-.08,1.28-.25,3-1,9.34-1,9.34l5.25-2.81c12.66-8,22.42-24.14,29.82-49.25,3.09-10.46,5.34-20.85,7.33-30,2.38-11,4.43-20.43,6.78-24.09,3.69-5.74,9.32-9.62,14.77-13.39.75-.51,1.49-1,2.22-1.54,6.86-4.81,13.67-10.36,15.16-20.71l0-.23C317.93,12.92,317,11,316,10.05Z"
 | 
					 | 
				
			||||||
		transform="translate(-7.45 -9.1)"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,90 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	viewBox="0 0 128 128"
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-4 h-10 w-10' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#439934"
 | 
					 | 
				
			||||||
		d="M88.038 42.812c1.605 4.643 2.761 9.383 3.141 14.296.472 6.095.256 12.147-1.029 18.142-.035.165-.109.32-.164.48-.403.001-.814-.049-1.208.012-3.329.523-6.655 1.065-9.981 1.604-3.438.557-6.881 1.092-10.313 1.687-1.216.21-2.721-.041-3.212 1.641-.014.046-.154.054-.235.08l.166-10.051-.169-24.252 1.602-.275c2.62-.429 5.24-.864 7.862-1.281 3.129-.497 6.261-.98 9.392-1.465 1.381-.215 2.764-.412 4.148-.618z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#45A538"
 | 
					 | 
				
			||||||
		d="M61.729 110.054c-1.69-1.453-3.439-2.842-5.059-4.37-8.717-8.222-15.093-17.899-18.233-29.566-.865-3.211-1.442-6.474-1.627-9.792-.13-2.322-.318-4.665-.154-6.975.437-6.144 1.325-12.229 3.127-18.147l.099-.138c.175.233.427.439.516.702 1.759 5.18 3.505 10.364 5.242 15.551 5.458 16.3 10.909 32.604 16.376 48.9.107.318.384.579.583.866l-.87 2.969z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#46A037"
 | 
					 | 
				
			||||||
		d="M88.038 42.812c-1.384.206-2.768.403-4.149.616-3.131.485-6.263.968-9.392 1.465-2.622.417-5.242.852-7.862 1.281l-1.602.275-.012-1.045c-.053-.859-.144-1.717-.154-2.576-.069-5.478-.112-10.956-.18-16.434-.042-3.429-.105-6.857-.175-10.285-.043-2.13-.089-4.261-.185-6.388-.052-1.143-.236-2.28-.311-3.423-.042-.657.016-1.319.029-1.979.817 1.583 1.616 3.178 2.456 4.749 1.327 2.484 3.441 4.314 5.344 6.311 7.523 7.892 12.864 17.068 16.193 27.433z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#409433"
 | 
					 | 
				
			||||||
		d="M65.036 80.753c.081-.026.222-.034.235-.08.491-1.682 1.996-1.431 3.212-1.641 3.432-.594 6.875-1.13 10.313-1.687 3.326-.539 6.652-1.081 9.981-1.604.394-.062.805-.011 1.208-.012-.622 2.22-1.112 4.488-1.901 6.647-.896 2.449-1.98 4.839-3.131 7.182a49.142 49.142 0 01-6.353 9.763c-1.919 2.308-4.058 4.441-6.202 6.548-1.185 1.165-2.582 2.114-3.882 3.161l-.337-.23-1.214-1.038-1.256-2.753a41.402 41.402 0 01-1.394-9.838l.023-.561.171-2.426c.057-.828.133-1.655.168-2.485.129-2.982.241-5.964.359-8.946z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#4FAA41"
 | 
					 | 
				
			||||||
		d="M65.036 80.753c-.118 2.982-.23 5.964-.357 8.947-.035.83-.111 1.657-.168 2.485l-.765.289c-1.699-5.002-3.399-9.951-5.062-14.913-2.75-8.209-5.467-16.431-8.213-24.642a4498.887 4498.887 0 00-6.7-19.867c-.105-.31-.407-.552-.617-.826l4.896-9.002c.168.292.39.565.496.879a6167.476 6167.476 0 016.768 20.118c2.916 8.73 5.814 17.467 8.728 26.198.116.349.308.671.491 1.062l.67-.78-.167 10.052z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#4AA73C"
 | 
					 | 
				
			||||||
		d="M43.155 32.227c.21.274.511.516.617.826a4498.887 4498.887 0 016.7 19.867c2.746 8.211 5.463 16.433 8.213 24.642 1.662 4.961 3.362 9.911 5.062 14.913l.765-.289-.171 2.426-.155.559c-.266 2.656-.49 5.318-.814 7.968-.163 1.328-.509 2.632-.772 3.947-.198-.287-.476-.548-.583-.866-5.467-16.297-10.918-32.6-16.376-48.9a3888.972 3888.972 0 00-5.242-15.551c-.089-.263-.34-.469-.516-.702l3.272-8.84z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#57AE47"
 | 
					 | 
				
			||||||
		d="M65.202 70.702l-.67.78c-.183-.391-.375-.714-.491-1.062-2.913-8.731-5.812-17.468-8.728-26.198a6167.476 6167.476 0 00-6.768-20.118c-.105-.314-.327-.588-.496-.879l6.055-7.965c.191.255.463.482.562.769 1.681 4.921 3.347 9.848 5.003 14.778 1.547 4.604 3.071 9.215 4.636 13.813.105.308.47.526.714.786l.012 1.045c.058 8.082.115 16.167.171 24.251z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#60B24F"
 | 
					 | 
				
			||||||
		d="M65.021 45.404c-.244-.26-.609-.478-.714-.786-1.565-4.598-3.089-9.209-4.636-13.813-1.656-4.93-3.322-9.856-5.003-14.778-.099-.287-.371-.514-.562-.769 1.969-1.928 3.877-3.925 5.925-5.764 1.821-1.634 3.285-3.386 3.352-5.968.003-.107.059-.214.145-.514l.519 1.306c-.013.661-.072 1.322-.029 1.979.075 1.143.259 2.28.311 3.423.096 2.127.142 4.258.185 6.388.069 3.428.132 6.856.175 10.285.067 5.478.111 10.956.18 16.434.008.861.098 1.718.152 2.577z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#A9AA88"
 | 
					 | 
				
			||||||
		d="M62.598 107.085c.263-1.315.609-2.62.772-3.947.325-2.649.548-5.312.814-7.968l.066-.01.066.011a41.402 41.402 0 001.394 9.838c-.176.232-.425.439-.518.701-.727 2.05-1.412 4.116-2.143 6.166-.1.28-.378.498-.574.744l-.747-2.566.87-2.969z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#B6B598"
 | 
					 | 
				
			||||||
		d="M62.476 112.621c.196-.246.475-.464.574-.744.731-2.05 1.417-4.115 2.143-6.166.093-.262.341-.469.518-.701l1.255 2.754c-.248.352-.59.669-.728 1.061l-2.404 7.059c-.099.283-.437.483-.663.722l-.695-3.985z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#C2C1A7"
 | 
					 | 
				
			||||||
		d="M63.171 116.605c.227-.238.564-.439.663-.722l2.404-7.059c.137-.391.48-.709.728-1.061l1.215 1.037c-.587.58-.913 1.25-.717 2.097l-.369 1.208c-.168.207-.411.387-.494.624-.839 2.403-1.64 4.819-2.485 7.222-.107.305-.404.544-.614.812-.109-1.387-.22-2.771-.331-4.158z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#CECDB7"
 | 
					 | 
				
			||||||
		d="M63.503 120.763c.209-.269.506-.508.614-.812.845-2.402 1.646-4.818 2.485-7.222.083-.236.325-.417.494-.624l-.509 5.545c-.136.157-.333.294-.398.477-.575 1.614-1.117 3.24-1.694 4.854-.119.333-.347.627-.525.938-.158-.207-.441-.407-.454-.623-.051-.841-.016-1.688-.013-2.533z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#DBDAC7"
 | 
					 | 
				
			||||||
		d="M63.969 123.919c.178-.312.406-.606.525-.938.578-1.613 1.119-3.239 1.694-4.854.065-.183.263-.319.398-.477l.012 3.64-1.218 3.124-1.411-.495z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#EBE9DC"
 | 
					 | 
				
			||||||
		d="M65.38 124.415l1.218-3.124.251 3.696-1.469-.572z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#CECDB7"
 | 
					 | 
				
			||||||
		d="M67.464 110.898c-.196-.847.129-1.518.717-2.097l.337.23-1.054 1.867z"
 | 
					 | 
				
			||||||
	/><path
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		clip-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#4FAA41"
 | 
					 | 
				
			||||||
		d="M64.316 95.172l-.066-.011-.066.01.155-.559-.023.56z"
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,17 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-5 h-10 w-10' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	width="64"
 | 
					 | 
				
			||||||
	height="64"
 | 
					 | 
				
			||||||
	viewBox="0 0 25.6 25.6"
 | 
					 | 
				
			||||||
	><path
 | 
					 | 
				
			||||||
		d="M179.076 94.886c-3.568-.1-6.336.268-8.656 1.25-.668.27-1.74.27-1.828 1.116.357.355.4.936.713 1.428.535.893 1.473 2.096 2.32 2.72l2.855 2.053c1.74 1.07 3.703 1.695 5.398 2.766.982.625 1.963 1.428 2.945 2.098.5.357.803.938 1.428 1.16v-.135c-.312-.4-.402-.98-.713-1.428l-1.34-1.293c-1.293-1.74-2.9-3.258-4.64-4.506-1.428-.982-4.55-2.32-5.13-3.97l-.088-.1c.98-.1 2.14-.447 3.078-.715 1.518-.4 2.9-.312 4.46-.713l2.143-.625v-.4c-.803-.803-1.383-1.874-2.23-2.632-2.275-1.963-4.775-3.882-7.363-5.488-1.383-.892-3.168-1.473-4.64-2.23-.537-.268-1.428-.402-1.74-.848-.805-.98-1.25-2.275-1.83-3.436l-3.658-7.763c-.803-1.74-1.295-3.48-2.275-5.086-4.596-7.585-9.594-12.18-17.268-16.687-1.65-.937-3.613-1.34-5.7-1.83l-3.346-.18c-.715-.312-1.428-1.16-2.053-1.562-2.543-1.606-9.102-5.086-10.977-.5-1.205 2.9 1.785 5.755 2.8 7.228.76 1.026 1.74 2.186 2.277 3.346.3.758.4 1.562.713 2.365.713 1.963 1.383 4.15 2.32 5.98.5.937 1.025 1.92 1.65 2.767.357.5.982.714 1.115 1.517-.625.893-.668 2.23-1.025 3.347-1.607 5.042-.982 11.288 1.293 15 .715 1.115 2.4 3.57 4.686 2.632 2.008-.803 1.56-3.346 2.14-5.577.135-.535.045-.892.312-1.25v.1l1.83 3.703c1.383 2.186 3.793 4.462 5.8 5.98 1.07.803 1.918 2.187 3.256 2.677v-.135h-.088c-.268-.4-.67-.58-1.027-.892-.803-.803-1.695-1.785-2.32-2.677-1.873-2.498-3.523-5.265-4.996-8.12-.715-1.383-1.34-2.9-1.918-4.283-.27-.536-.27-1.34-.715-1.606-.67.98-1.65 1.83-2.143 3.034-.848 1.918-.936 4.283-1.248 6.737-.18.045-.1 0-.18.1-1.426-.356-1.918-1.83-2.453-3.078-1.338-3.168-1.562-8.254-.402-11.913.312-.937 1.652-3.882 1.117-4.774-.27-.848-1.16-1.338-1.652-2.008-.58-.848-1.203-1.918-1.605-2.855-1.07-2.5-1.605-5.265-2.766-7.764-.537-1.16-1.473-2.365-2.232-3.435-.848-1.205-1.783-2.053-2.453-3.48-.223-.5-.535-1.294-.178-1.83.088-.357.268-.5.623-.58.58-.5 2.232.134 2.812.4 1.65.67 3.033 1.294 4.416 2.23.625.446 1.295 1.294 2.098 1.518h.938c1.428.312 3.033.1 4.37.5 2.365.76 4.506 1.874 6.426 3.08 5.844 3.703 10.664 8.968 13.92 15.26.535 1.026.758 1.963 1.25 3.034.938 2.187 2.098 4.417 3.033 6.56.938 2.097 1.83 4.24 3.168 5.98.67.937 3.346 1.427 4.55 1.918.893.4 2.275.76 3.08 1.25 1.516.937 3.033 2.008 4.46 3.034.713.534 2.945 1.65 3.078 2.54zm-45.5-38.772a7.09 7.09 0 0 0-1.828.223v.1h.088c.357.714.982 1.205 1.428 1.83l1.027 2.142.088-.1c.625-.446.938-1.16.938-2.23-.268-.312-.312-.625-.535-.937-.268-.446-.848-.67-1.206-1.026z"
 | 
					 | 
				
			||||||
		transform="matrix(.390229 0 0 .38781 -46.300037 -16.856717)"
 | 
					 | 
				
			||||||
		fill-rule="evenodd"
 | 
					 | 
				
			||||||
		fill="#00678c"
 | 
					 | 
				
			||||||
	/></svg
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
@@ -1,56 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-5 h-10 w-10' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	viewBox="0 0 432.071 445.383"
 | 
					 | 
				
			||||||
	xml:space="preserve"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	<g id="orginal" style="fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;" />
 | 
					 | 
				
			||||||
	<g
 | 
					 | 
				
			||||||
		id="Layer_x0020_3"
 | 
					 | 
				
			||||||
		style="fill-rule:nonzero;clip-rule:nonzero;fill:none;stroke:#FFFFFF;stroke-width:12.4651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;"
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			style="fill:#000000;stroke:#000000;stroke-width:37.3953;stroke-linecap:butt;stroke-linejoin:miter;"
 | 
					 | 
				
			||||||
			d="M323.205,324.227c2.833-23.601,1.984-27.062,19.563-23.239l4.463,0.392c13.517,0.615,31.199-2.174,41.587-7c22.362-10.376,35.622-27.7,13.572-23.148c-50.297,10.376-53.755-6.655-53.755-6.655c53.111-78.803,75.313-178.836,56.149-203.322    C352.514-5.534,262.036,26.049,260.522,26.869l-0.482,0.089c-9.938-2.062-21.06-3.294-33.554-3.496c-22.761-0.374-40.032,5.967-53.133,15.904c0,0-161.408-66.498-153.899,83.628c1.597,31.936,45.777,241.655,98.47,178.31    c19.259-23.163,37.871-42.748,37.871-42.748c9.242,6.14,20.307,9.272,31.912,8.147l0.897-0.765c-0.281,2.876-0.157,5.689,0.359,9.019c-13.572,15.167-9.584,17.83-36.723,23.416c-27.457,5.659-11.326,15.734-0.797,18.367c12.768,3.193,42.305,7.716,62.268-20.224    l-0.795,3.188c5.325,4.26,4.965,30.619,5.72,49.452c0.756,18.834,2.017,36.409,5.856,46.771c3.839,10.36,8.369,37.05,44.036,29.406c29.809-6.388,52.6-15.582,54.677-101.107"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			style="fill:#336791;stroke:none;"
 | 
					 | 
				
			||||||
			d="M402.395,271.23c-50.302,10.376-53.76-6.655-53.76-6.655c53.111-78.808,75.313-178.843,56.153-203.326c-52.27-66.785-142.752-35.2-144.262-34.38l-0.486,0.087c-9.938-2.063-21.06-3.292-33.56-3.496c-22.761-0.373-40.026,5.967-53.127,15.902    c0,0-161.411-66.495-153.904,83.63c1.597,31.938,45.776,241.657,98.471,178.312c19.26-23.163,37.869-42.748,37.869-42.748c9.243,6.14,20.308,9.272,31.908,8.147l0.901-0.765c-0.28,2.876-0.152,5.689,0.361,9.019c-13.575,15.167-9.586,17.83-36.723,23.416    c-27.459,5.659-11.328,15.734-0.796,18.367c12.768,3.193,42.307,7.716,62.266-20.224l-0.796,3.188c5.319,4.26,9.054,27.711,8.428,48.969c-0.626,21.259-1.044,35.854,3.147,47.254c4.191,11.4,8.368,37.05,44.042,29.406c29.809-6.388,45.256-22.942,47.405-50.555    c1.525-19.631,4.976-16.729,5.194-34.28l2.768-8.309c3.192-26.611,0.507-35.196,18.872-31.203l4.463,0.392c13.517,0.615,31.208-2.174,41.591-7c22.358-10.376,35.618-27.7,13.573-23.148z"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M215.866,286.484c-1.385,49.516,0.348,99.377,5.193,111.495c4.848,12.118,15.223,35.688,50.9,28.045c29.806-6.39,40.651-18.756,45.357-46.051c3.466-20.082,10.148-75.854,11.005-87.281"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M173.104,38.256c0,0-161.521-66.016-154.012,84.109c1.597,31.938,45.779,241.664,98.473,178.316c19.256-23.166,36.671-41.335,36.671-41.335"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M260.349,26.207c-5.591,1.753,89.848-34.889,144.087,34.417c19.159,24.484-3.043,124.519-56.153,203.329"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			style="stroke-linejoin:bevel;"
 | 
					 | 
				
			||||||
			d="M348.282,263.953c0,0,3.461,17.036,53.764,6.653c22.04-4.552,8.776,12.774-13.577,23.155c-18.345,8.514-59.474,10.696-60.146-1.069c-1.729-30.355,21.647-21.133,19.96-28.739c-1.525-6.85-11.979-13.573-18.894-30.338    c-6.037-14.633-82.796-126.849,21.287-110.183c3.813-0.789-27.146-99.002-124.553-100.599c-97.385-1.597-94.19,119.762-94.19,119.762"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M188.604,274.334c-13.577,15.166-9.584,17.829-36.723,23.417c-27.459,5.66-11.326,15.733-0.797,18.365c12.768,3.195,42.307,7.718,62.266-20.229c6.078-8.509-0.036-22.086-8.385-25.547c-4.034-1.671-9.428-3.765-16.361,3.994z"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M187.715,274.069c-1.368-8.917,2.93-19.528,7.536-31.942c6.922-18.626,22.893-37.255,10.117-96.339c-9.523-44.029-73.396-9.163-73.436-3.193c-0.039,5.968,2.889,30.26-1.067,58.548c-5.162,36.913,23.488,68.132,56.479,64.938"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			style="fill:#FFFFFF;stroke-width:4.155;stroke-linecap:butt;stroke-linejoin:miter;"
 | 
					 | 
				
			||||||
			d="M172.517,141.7c-0.288,2.039,3.733,7.48,8.976,8.207c5.234,0.73,9.714-3.522,9.998-5.559c0.284-2.039-3.732-4.285-8.977-5.015c-5.237-0.731-9.719,0.333-9.996,2.367z"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			style="fill:#FFFFFF;stroke-width:2.0775;stroke-linecap:butt;stroke-linejoin:miter;"
 | 
					 | 
				
			||||||
			d="M331.941,137.543c0.284,2.039-3.732,7.48-8.976,8.207c-5.238,0.73-9.718-3.522-10.005-5.559c-0.277-2.039,3.74-4.285,8.979-5.015c5.239-0.73,9.718,0.333,10.002,2.368z"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M350.676,123.432c0.863,15.994-3.445,26.888-3.988,43.914c-0.804,24.748,11.799,53.074-7.191,81.435"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<path style="stroke-width:3;" d="M0,60.232" />
 | 
					 | 
				
			||||||
	</g>
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,34 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
	class={isAbsolute ? 'absolute top-0 left-0 -m-5 h-10 w-10' : 'mx-auto w-8 h-8'}
 | 
					 | 
				
			||||||
	viewBox="0 0 32 32"
 | 
					 | 
				
			||||||
	xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
	xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
					 | 
				
			||||||
	><defs
 | 
					 | 
				
			||||||
		><path
 | 
					 | 
				
			||||||
			id="a"
 | 
					 | 
				
			||||||
			d="m45.536 38.764c-2.013 1.05-12.44 5.337-14.66 6.494s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276c-1-.478-1.524-.88-1.524-1.26v-3.813s14.447-3.145 16.78-3.982 3.14-.867 5.126-.14 13.853 2.868 15.814 3.587v3.76c0 .377-.452.8-1.477 1.324z"
 | 
					 | 
				
			||||||
		/><path
 | 
					 | 
				
			||||||
			id="b"
 | 
					 | 
				
			||||||
			d="m45.536 28.733c-2.013 1.05-12.44 5.337-14.66 6.494s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276-2.04-1.613-.077-2.382l15.332-5.935c2.332-.837 3.14-.867 5.126-.14s12.35 4.853 14.312 5.57 2.037 1.31.024 2.36z"
 | 
					 | 
				
			||||||
		/></defs
 | 
					 | 
				
			||||||
	><g transform="matrix(.848327 0 0 .848327 -7.883573 -9.449691)"
 | 
					 | 
				
			||||||
		><use fill="#a41e11" xlink:href="#a" /><path
 | 
					 | 
				
			||||||
			d="m45.536 34.95c-2.013 1.05-12.44 5.337-14.66 6.494s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276-2.04-1.613-.077-2.382l15.332-5.936c2.332-.836 3.14-.867 5.126-.14s12.35 4.852 14.31 5.582 2.037 1.31.024 2.36z"
 | 
					 | 
				
			||||||
			fill="#d82c20"
 | 
					 | 
				
			||||||
		/><use fill="#a41e11" xlink:href="#a" y="-6.218" /><use fill="#d82c20" xlink:href="#b" /><path
 | 
					 | 
				
			||||||
			d="m45.536 26.098c-2.013 1.05-12.44 5.337-14.66 6.495s-3.453 1.146-5.207.308-12.85-5.32-14.85-6.276c-1-.478-1.524-.88-1.524-1.26v-3.815s14.447-3.145 16.78-3.982 3.14-.867 5.126-.14 13.853 2.868 15.814 3.587v3.76c0 .377-.452.8-1.477 1.324z"
 | 
					 | 
				
			||||||
			fill="#a41e11"
 | 
					 | 
				
			||||||
		/><use fill="#d82c20" xlink:href="#b" y="-6.449" /><g fill="#fff"
 | 
					 | 
				
			||||||
			><path
 | 
					 | 
				
			||||||
				d="m29.096 20.712-1.182-1.965-3.774-.34 2.816-1.016-.845-1.56 2.636 1.03 2.486-.814-.672 1.612 2.534.95-3.268.34zm-6.296 3.912 8.74-1.342-2.64 3.872z"
 | 
					 | 
				
			||||||
			/><ellipse cx="20.444" cy="21.402" rx="4.672" ry="1.811" /></g
 | 
					 | 
				
			||||||
		><path d="m42.132 21.138-5.17 2.042-.004-4.087z" fill="#7a0c00" /><path
 | 
					 | 
				
			||||||
			d="m36.963 23.18-.56.22-5.166-2.042 5.723-2.264z"
 | 
					 | 
				
			||||||
			fill="#ad2115"
 | 
					 | 
				
			||||||
		/></g
 | 
					 | 
				
			||||||
	></svg
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
@@ -1,11 +0,0 @@
 | 
				
			|||||||
//@ts-nocheck
 | 
					 | 
				
			||||||
export { default as Clickhouse } from './Clickhouse.svelte';
 | 
					 | 
				
			||||||
export { default as CouchDB } from './CouchDB.svelte';
 | 
					 | 
				
			||||||
export { default as MariaDB } from './MariaDB.svelte';
 | 
					 | 
				
			||||||
export { default as MongoDB } from './MongoDB.svelte';
 | 
					 | 
				
			||||||
export { default as MySQL } from './MySQL.svelte';
 | 
					 | 
				
			||||||
export { default as PostgreSQL } from './PostgreSQL.svelte';
 | 
					 | 
				
			||||||
export { default as Redis } from './Redis.svelte';
 | 
					 | 
				
			||||||
export { default as EdgeDB } from './EdgeDB.svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
  export let isAbsolute=false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
<svg
 | 
					 | 
				
			||||||
  xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
  class={isAbsolute ? 'absolute top-0 left-0 -m-2 h-12 w-12 text-sky-500' : 'mx-auto w-8 h-8 text-sky-500'}
 | 
					 | 
				
			||||||
  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" />
 | 
					 | 
				
			||||||
  <path
 | 
					 | 
				
			||||||
    d="M22 12.54c-1.804 -.345 -2.701 -1.08 -3.523 -2.94c-.487 .696 -1.102 1.568 -.92 2.4c.028 .238 -.32 1.002 -.557 1h-14c0 5.208 3.164 7 6.196 7c4.124 .022 7.828 -1.376 9.854 -5c1.146 -.101 2.296 -1.505 2.95 -2.46z"
 | 
					 | 
				
			||||||
  />
 | 
					 | 
				
			||||||
  <path d="M5 10h3v3h-3z" />
 | 
					 | 
				
			||||||
  <path d="M8 10h3v3h-3z" />
 | 
					 | 
				
			||||||
  <path d="M11 10h3v3h-3z" />
 | 
					 | 
				
			||||||
  <path d="M8 7h3v3h-3z" />
 | 
					 | 
				
			||||||
  <path d="M11 7h3v3h-3z" />
 | 
					 | 
				
			||||||
  <path d="M11 4h3v3h-3z" />
 | 
					 | 
				
			||||||
  <path d="M4.571 18c1.5 0 2.047 -.074 2.958 -.78" />
 | 
					 | 
				
			||||||
  <line x1="10" y1="16" x2="10" y2="16.01" />
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
@@ -1,16 +0,0 @@
 | 
				
			|||||||
<svg
 | 
					 | 
				
			||||||
  xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
  class="absolute top-0 left-9 -m-2 h-6 w-6 text-sky-500 rotate-45"
 | 
					 | 
				
			||||||
  viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
  stroke-width="3"
 | 
					 | 
				
			||||||
  stroke="currentColor"
 | 
					 | 
				
			||||||
  fill="none"
 | 
					 | 
				
			||||||
  stroke-linecap="round"
 | 
					 | 
				
			||||||
  stroke-linejoin="round"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
  <line x1="12" y1="18" x2="12.01" y2="18" />
 | 
					 | 
				
			||||||
  <path d="M9.172 15.172a4 4 0 0 1 5.656 0" />
 | 
					 | 
				
			||||||
  <path d="M6.343 12.343a8 8 0 0 1 11.314 0" />
 | 
					 | 
				
			||||||
  <path d="M3.515 9.515c4.686 -4.687 12.284 -4.687 17 0" />
 | 
					 | 
				
			||||||
</svg>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 505 B  | 
@@ -1,2 +0,0 @@
 | 
				
			|||||||
export { default as LocalDocker } from './LocalDocker.svelte';
 | 
					 | 
				
			||||||
export { default as RemoteDocker } from './RemoteDocker.svelte';
 | 
					 | 
				
			||||||
@@ -1,6 +0,0 @@
 | 
				
			|||||||
export { default as RemoteLink } from './RemoteLink.svelte';
 | 
					 | 
				
			||||||
export { default as Delete } from './Delete.svelte';
 | 
					 | 
				
			||||||
export * as Applications from './applications';
 | 
					 | 
				
			||||||
export * as Sources from './sources';
 | 
					 | 
				
			||||||
export * as Destinations from './destinations';
 | 
					 | 
				
			||||||
export * as Databases from './databases';
 | 
					 | 
				
			||||||
@@ -1,62 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let type: string;
 | 
					 | 
				
			||||||
	export let isAbsolute = false;
 | 
					 | 
				
			||||||
	let fallback = '/icons/default.png';
 | 
					 | 
				
			||||||
	const handleError = (ev: { target: { src: string } }) => (ev.target.src = fallback);
 | 
					 | 
				
			||||||
	let extension = 'png';
 | 
					 | 
				
			||||||
	let svgs = [
 | 
					 | 
				
			||||||
		'mattermost',
 | 
					 | 
				
			||||||
		'repman',
 | 
					 | 
				
			||||||
		'directus',
 | 
					 | 
				
			||||||
		'pocketbase',
 | 
					 | 
				
			||||||
		'gitea',
 | 
					 | 
				
			||||||
		'languagetool',
 | 
					 | 
				
			||||||
		'meilisearch',
 | 
					 | 
				
			||||||
		'n8n',
 | 
					 | 
				
			||||||
		'glitchtip',
 | 
					 | 
				
			||||||
		'searxng',
 | 
					 | 
				
			||||||
		'umami',
 | 
					 | 
				
			||||||
		'uptimekuma',
 | 
					 | 
				
			||||||
		'vaultwarden',
 | 
					 | 
				
			||||||
		'weblate',
 | 
					 | 
				
			||||||
		'wordpress'
 | 
					 | 
				
			||||||
	];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const name: any =
 | 
					 | 
				
			||||||
		type &&
 | 
					 | 
				
			||||||
		(type[0].toUpperCase() + type.substring(1).toLowerCase())
 | 
					 | 
				
			||||||
			.replaceAll('.', '')
 | 
					 | 
				
			||||||
			.replaceAll(' ', '')
 | 
					 | 
				
			||||||
			.split('-')[0]
 | 
					 | 
				
			||||||
			.toLowerCase();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (svgs.includes(name)) {
 | 
					 | 
				
			||||||
		extension = 'svg';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function generateClass() {
 | 
					 | 
				
			||||||
		switch (name) {
 | 
					 | 
				
			||||||
			case 'n8n':
 | 
					 | 
				
			||||||
				if (isAbsolute) {
 | 
					 | 
				
			||||||
					return 'w-12 h-12 absolute -m-9 -mt-12';
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return 'w-12 h-12 -mt-3';
 | 
					 | 
				
			||||||
			case 'weblate':
 | 
					 | 
				
			||||||
				if (isAbsolute) {
 | 
					 | 
				
			||||||
					return 'w-12 h-12 absolute -m-9 -mt-12';
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return 'w-12 h-12 -mt-3';
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				return isAbsolute ? 'w-10 h-10 absolute -m-4 -mt-9 left-0' : 'w-10 h-10';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if name}
 | 
					 | 
				
			||||||
	<img
 | 
					 | 
				
			||||||
		class={generateClass()}
 | 
					 | 
				
			||||||
		src={`/icons/${name}.${extension}`}
 | 
					 | 
				
			||||||
		on:error={handleError}
 | 
					 | 
				
			||||||
		alt={`Icon of ${name}`}
 | 
					 | 
				
			||||||
	/>
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
@@ -1,15 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
	export let small = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg viewBox="0 0 128 128" class={small ? 'h-6 w-6' : 'h-10 w-10'}>
 | 
					 | 
				
			||||||
	<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>
 | 
					 | 
				
			||||||
@@ -1,25 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
	export let small = false;
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svg viewBox="0 0 128 128" class={small ? 'h-6 w-6' : 'h-10 w-10'}>
 | 
					 | 
				
			||||||
	<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>
 | 
					 | 
				
			||||||
@@ -1,2 +0,0 @@
 | 
				
			|||||||
export { default as GitHub } from './Github.svelte';
 | 
					 | 
				
			||||||
export { default as GitLab } from './Gitlab.svelte';
 | 
					 | 
				
			||||||
@@ -1,7 +0,0 @@
 | 
				
			|||||||
import dayjs from 'dayjs';
 | 
					 | 
				
			||||||
import utc from 'dayjs/plugin/utc.js';
 | 
					 | 
				
			||||||
import relativeTime from 'dayjs/plugin/relativeTime.js';
 | 
					 | 
				
			||||||
dayjs.extend(utc);
 | 
					 | 
				
			||||||
dayjs.extend(relativeTime);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export { dayjs as day };
 | 
					 | 
				
			||||||
@@ -1,183 +0,0 @@
 | 
				
			|||||||
import { writable, readable, type Writable } from 'svelte/store';
 | 
					 | 
				
			||||||
import superjson from 'superjson';
 | 
					 | 
				
			||||||
import type { AppRouter } from 'server/src/trpc';
 | 
					 | 
				
			||||||
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
 | 
					 | 
				
			||||||
import { browser, dev } from '$app/environment';
 | 
					 | 
				
			||||||
import Cookies from 'js-cookie';
 | 
					 | 
				
			||||||
import cuid from 'cuid';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const serverBaseUrl = dev ? `http://${browser && window.location.hostname}:2022` : '';
 | 
					 | 
				
			||||||
export let token: string = Cookies.get('token') || '';
 | 
					 | 
				
			||||||
export const trpc = createTRPCProxyClient<AppRouter>({
 | 
					 | 
				
			||||||
	transformer: superjson,
 | 
					 | 
				
			||||||
	links: [
 | 
					 | 
				
			||||||
		httpBatchLink({
 | 
					 | 
				
			||||||
			url: `${serverBaseUrl}/trpc`,
 | 
					 | 
				
			||||||
			headers() {
 | 
					 | 
				
			||||||
				return {
 | 
					 | 
				
			||||||
					Authorization: token
 | 
					 | 
				
			||||||
				};
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	]
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
export const disabledButton: Writable<boolean> = writable(false);
 | 
					 | 
				
			||||||
export const location: Writable<null | string> = writable(null)
 | 
					 | 
				
			||||||
interface AppSession {
 | 
					 | 
				
			||||||
	isRegistrationEnabled: boolean;
 | 
					 | 
				
			||||||
	token?: string;
 | 
					 | 
				
			||||||
	ipv4: string | null;
 | 
					 | 
				
			||||||
	ipv6: string | null;
 | 
					 | 
				
			||||||
	version: string | null;
 | 
					 | 
				
			||||||
	userId: string | null;
 | 
					 | 
				
			||||||
	teamId: string | null;
 | 
					 | 
				
			||||||
	permission: string;
 | 
					 | 
				
			||||||
	isAdmin: boolean;
 | 
					 | 
				
			||||||
	whiteLabeled: boolean;
 | 
					 | 
				
			||||||
	whiteLabeledDetails: {
 | 
					 | 
				
			||||||
		icon: string | null;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	tokens: {
 | 
					 | 
				
			||||||
		github: string | null;
 | 
					 | 
				
			||||||
		gitlab: string | null;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	pendingInvitations: Array<any>;
 | 
					 | 
				
			||||||
	isARM: boolean
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const appSession: Writable<AppSession> = writable({
 | 
					 | 
				
			||||||
	isRegistrationEnabled: false,
 | 
					 | 
				
			||||||
	ipv4: null,
 | 
					 | 
				
			||||||
	ipv6: null,
 | 
					 | 
				
			||||||
	version: null,
 | 
					 | 
				
			||||||
	userId: null,
 | 
					 | 
				
			||||||
	teamId: null,
 | 
					 | 
				
			||||||
	permission: 'read',
 | 
					 | 
				
			||||||
	isAdmin: false,
 | 
					 | 
				
			||||||
	whiteLabeled: false,
 | 
					 | 
				
			||||||
	whiteLabeledDetails: {
 | 
					 | 
				
			||||||
		icon: null
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	tokens: {
 | 
					 | 
				
			||||||
		github: null,
 | 
					 | 
				
			||||||
		gitlab: null
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	pendingInvitations: [],
 | 
					 | 
				
			||||||
	isARM: false
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface AddToast {
 | 
					 | 
				
			||||||
	type?: 'info' | 'success' | 'error';
 | 
					 | 
				
			||||||
	message: string;
 | 
					 | 
				
			||||||
	timeout?: number | undefined;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export const toasts: any = writable([]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const dismissToast = (id: string) => {
 | 
					 | 
				
			||||||
	toasts.update((all: any) => all.filter((t: any) => t.id !== id));
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
export const pauseToast = (id: string) => {
 | 
					 | 
				
			||||||
	toasts.update((all: any) => {
 | 
					 | 
				
			||||||
		const index = all.findIndex((t: any) => t.id === id);
 | 
					 | 
				
			||||||
		if (index > -1) clearTimeout(all[index].timeoutInterval);
 | 
					 | 
				
			||||||
		return all;
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
export const resumeToast = (id: string) => {
 | 
					 | 
				
			||||||
	toasts.update((all: any) => {
 | 
					 | 
				
			||||||
		const index = all.findIndex((t: any) => t.id === id);
 | 
					 | 
				
			||||||
		if (index > -1) {
 | 
					 | 
				
			||||||
			all[index].timeoutInterval = setTimeout(() => {
 | 
					 | 
				
			||||||
				dismissToast(id);
 | 
					 | 
				
			||||||
			}, all[index].timeout);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return all;
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const addToast = (toast: AddToast) => {
 | 
					 | 
				
			||||||
	const id = cuid();
 | 
					 | 
				
			||||||
	const defaults = {
 | 
					 | 
				
			||||||
		id,
 | 
					 | 
				
			||||||
		type: 'info',
 | 
					 | 
				
			||||||
		timeout: 2000
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	let t: any = { ...defaults, ...toast };
 | 
					 | 
				
			||||||
	if (t.timeout) t.timeoutInterval = setTimeout(() => dismissToast(id), t.timeout);
 | 
					 | 
				
			||||||
	toasts.update((all: any) => [t, ...all]);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const features = readable({
 | 
					 | 
				
			||||||
	beta: browser && window.localStorage.getItem('beta') === 'true',
 | 
					 | 
				
			||||||
	latestVersion: browser && window.localStorage.getItem('latestVersion')
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const updateLoading: Writable<boolean> = writable(false);
 | 
					 | 
				
			||||||
export const isUpdateAvailable: Writable<boolean> = writable(false);
 | 
					 | 
				
			||||||
export const latestVersion: Writable<string> = writable('latest');
 | 
					 | 
				
			||||||
export const loginEmail: Writable<string | undefined> = writable();
 | 
					 | 
				
			||||||
export const search: any = writable('');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const isDeploymentEnabled: Writable<boolean> = writable(false);
 | 
					 | 
				
			||||||
export const status: Writable<any> = writable({
 | 
					 | 
				
			||||||
	application: {
 | 
					 | 
				
			||||||
		statuses: [],
 | 
					 | 
				
			||||||
		overallStatus: 'stopped',
 | 
					 | 
				
			||||||
		loading: false,
 | 
					 | 
				
			||||||
		restarting: false,
 | 
					 | 
				
			||||||
		initialLoading: true
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	service: {
 | 
					 | 
				
			||||||
		statuses: [],
 | 
					 | 
				
			||||||
		overallStatus: 'stopped',
 | 
					 | 
				
			||||||
		loading: false,
 | 
					 | 
				
			||||||
		startup: {},
 | 
					 | 
				
			||||||
		initialLoading: true
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	database: {
 | 
					 | 
				
			||||||
		isRunning: false,
 | 
					 | 
				
			||||||
		isExited: false,
 | 
					 | 
				
			||||||
		loading: false,
 | 
					 | 
				
			||||||
		initialLoading: true,
 | 
					 | 
				
			||||||
		isPublic: false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function checkIfDeploymentEnabledApplications(isAdmin: boolean, application: any) {
 | 
					 | 
				
			||||||
	return !!(
 | 
					 | 
				
			||||||
		(isAdmin && application.buildPack === 'compose') ||
 | 
					 | 
				
			||||||
		((application.fqdn || application.settings.isBot) &&
 | 
					 | 
				
			||||||
			((application.gitSource && application.repository && application.buildPack) ||
 | 
					 | 
				
			||||||
				application.simpleDockerfile) &&
 | 
					 | 
				
			||||||
			application.destinationDocker)
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export const setLocation = (resource: any, settings?: any) => {
 | 
					 | 
				
			||||||
	if (resource.settings.isBot && resource.exposePort) {
 | 
					 | 
				
			||||||
		disabledButton.set(false);
 | 
					 | 
				
			||||||
		return location.set(`http://${dev ? 'localhost' : settings.ipv4}:${resource.exposePort}`);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (GITPOD_WORKSPACE_URL && resource.exposePort) {
 | 
					 | 
				
			||||||
		const { href } = new URL(GITPOD_WORKSPACE_URL);
 | 
					 | 
				
			||||||
		const newURL = href.replace('https://', `https://${resource.exposePort}-`).replace(/\/$/, '');
 | 
					 | 
				
			||||||
		return location.set(newURL);
 | 
					 | 
				
			||||||
	} else if (CODESANDBOX_HOST) {
 | 
					 | 
				
			||||||
		const newURL = `https://${CODESANDBOX_HOST.replace(/\$PORT/, resource.exposePort)}`;
 | 
					 | 
				
			||||||
		return location.set(newURL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (resource.fqdn) {
 | 
					 | 
				
			||||||
		return location.set(resource.fqdn);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		location.set(null);
 | 
					 | 
				
			||||||
		disabledButton.set(false);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
export const selectedBuildId: any = writable(null)
 | 
					 | 
				
			||||||
export function checkIfDeploymentEnabledServices( service: any) {
 | 
					 | 
				
			||||||
    return (
 | 
					 | 
				
			||||||
        service.fqdn &&
 | 
					 | 
				
			||||||
        service.destinationDocker &&
 | 
					 | 
				
			||||||
        service.version &&
 | 
					 | 
				
			||||||
        service.type
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
<script>
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="mx-auto flex h-screen flex-col items-center justify-center px-4">
 | 
					 | 
				
			||||||
	<div class="text-3xl font-bold pb-4">Ooops, are you lost?</div>
 | 
					 | 
				
			||||||
	<a href="/" class="btn btn-sm bg-coollabs">Go back</a>
 | 
					 | 
				
			||||||
	{#if $page.error.message !== 'Not Found'}
 | 
					 | 
				
			||||||
		<div class="py-10 text-xs font-bold">
 | 
					 | 
				
			||||||
			<pre class="w-full whitespace-pre-wrap break-words text-left text-xs tracking-tighter">{$page
 | 
					 | 
				
			||||||
					.error.message}</pre>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,417 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let data: LayoutData;
 | 
					 | 
				
			||||||
	import type { LayoutData } from './$types';
 | 
					 | 
				
			||||||
	export const ssr = false;
 | 
					 | 
				
			||||||
	import '../app.postcss';
 | 
					 | 
				
			||||||
	import { appSession } from '$lib/store';
 | 
					 | 
				
			||||||
	import Tooltip from '$lib/components/Tooltip.svelte';
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	// import UpdateAvailable from '$lib/components/UpdateAvailable.svelte';
 | 
					 | 
				
			||||||
	import Cookies from 'js-cookie';
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	import Toasts from '$lib/components/Toasts.svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let sidedrawerToggler: HTMLInputElement;
 | 
					 | 
				
			||||||
	if (data.settings.success) {
 | 
					 | 
				
			||||||
		$appSession = {
 | 
					 | 
				
			||||||
			...$appSession,
 | 
					 | 
				
			||||||
			...data.settings.data
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const closeDrawer = () => (sidedrawerToggler.checked = false);
 | 
					 | 
				
			||||||
	async function logout() {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			Cookies.remove('token');
 | 
					 | 
				
			||||||
			return window.location.replace('/login');
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<svelte:head>
 | 
					 | 
				
			||||||
	{#if !$appSession.whiteLabeled}
 | 
					 | 
				
			||||||
		<title>Coolify</title>
 | 
					 | 
				
			||||||
		<link rel="icon" href="/favicon.png" />
 | 
					 | 
				
			||||||
	{:else if $appSession.whiteLabeledDetails.icon}
 | 
					 | 
				
			||||||
		<title>Coolify</title>
 | 
					 | 
				
			||||||
		<link rel="icon" href={$appSession.whiteLabeledDetails.icon} />
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
</svelte:head>
 | 
					 | 
				
			||||||
<Toasts />
 | 
					 | 
				
			||||||
<div class="drawer">
 | 
					 | 
				
			||||||
	<input id="main-drawer" type="checkbox" class="drawer-toggle" bind:this={sidedrawerToggler} />
 | 
					 | 
				
			||||||
	<div class="drawer-content">
 | 
					 | 
				
			||||||
		{#if $appSession.userId}
 | 
					 | 
				
			||||||
			<Tooltip triggeredBy="#iam" placement="right" color="bg-iam">IAM</Tooltip>
 | 
					 | 
				
			||||||
			<Tooltip triggeredBy="#settings" placement="right" color="bg-settings text-black"
 | 
					 | 
				
			||||||
				>Settings</Tooltip
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
			<Tooltip triggeredBy="#documentation" placement="right" color="bg-info">Documentation</Tooltip
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
			<Tooltip triggeredBy="#logout" placement="right" color="bg-red-600">Logout</Tooltip>
 | 
					 | 
				
			||||||
			<nav class="nav-main hidden lg:block z-20">
 | 
					 | 
				
			||||||
				<div class="flex h-screen w-full flex-col items-center transition-all duration-100">
 | 
					 | 
				
			||||||
					{#if !$appSession.whiteLabeled}
 | 
					 | 
				
			||||||
						<div class="mb-2 mt-4 h-10 w-10">
 | 
					 | 
				
			||||||
							<img src="/favicon.png" alt="coolLabs logo" />
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
					{:else if $appSession.whiteLabeledDetails.icon}
 | 
					 | 
				
			||||||
						<div class="mb-2 mt-4 h-10 w-10">
 | 
					 | 
				
			||||||
							<img src={$appSession.whiteLabeledDetails.icon} alt="White labeled logo" />
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
					{/if}
 | 
					 | 
				
			||||||
					<div class="flex flex-col space-y-2 py-2" class:mt-2={$appSession.whiteLabeled}>
 | 
					 | 
				
			||||||
						<a
 | 
					 | 
				
			||||||
							id="dashboard"
 | 
					 | 
				
			||||||
							href="/"
 | 
					 | 
				
			||||||
							class="icons hover:text-pink-500"
 | 
					 | 
				
			||||||
							class:text-pink-500={$page.url.pathname === '/'}
 | 
					 | 
				
			||||||
							class:bg-coolgray-500={$page.url.pathname === '/'}
 | 
					 | 
				
			||||||
							class:bg-coolgray-200={!($page.url.pathname === '/')}
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							<svg
 | 
					 | 
				
			||||||
								xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
								class="h-9 w-9"
 | 
					 | 
				
			||||||
								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" />
 | 
					 | 
				
			||||||
								<path
 | 
					 | 
				
			||||||
									d="M19 8.71l-5.333 -4.148a2.666 2.666 0 0 0 -3.274 0l-5.334 4.148a2.665 2.665 0 0 0 -1.029 2.105v7.2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-7.2c0 -.823 -.38 -1.6 -1.03 -2.105"
 | 
					 | 
				
			||||||
								/>
 | 
					 | 
				
			||||||
								<path d="M16 15c-2.21 1.333 -5.792 1.333 -8 0" />
 | 
					 | 
				
			||||||
							</svg>
 | 
					 | 
				
			||||||
						</a>
 | 
					 | 
				
			||||||
						{#if $appSession.teamId === '0'}
 | 
					 | 
				
			||||||
							<a
 | 
					 | 
				
			||||||
								id="servers"
 | 
					 | 
				
			||||||
								href="/servers"
 | 
					 | 
				
			||||||
								class="icons hover:text-sky-500"
 | 
					 | 
				
			||||||
								class:text-sky-500={$page.url.pathname === '/servers'}
 | 
					 | 
				
			||||||
								class:bg-coolgray-500={$page.url.pathname === '/servers'}
 | 
					 | 
				
			||||||
								class:bg-coolgray-200={!($page.url.pathname === '/servers')}
 | 
					 | 
				
			||||||
							>
 | 
					 | 
				
			||||||
								<svg
 | 
					 | 
				
			||||||
									xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
									class="w-8 h-8 mx-auto"
 | 
					 | 
				
			||||||
									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" />
 | 
					 | 
				
			||||||
									<rect x="3" y="4" width="18" height="8" rx="3" />
 | 
					 | 
				
			||||||
									<rect x="3" y="12" width="18" height="8" rx="3" />
 | 
					 | 
				
			||||||
									<line x1="7" y1="8" x2="7" y2="8.01" />
 | 
					 | 
				
			||||||
									<line x1="7" y1="16" x2="7" y2="16.01" />
 | 
					 | 
				
			||||||
								</svg>
 | 
					 | 
				
			||||||
							</a>
 | 
					 | 
				
			||||||
						{/if}
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
					<Tooltip triggeredBy="#dashboard" placement="right">Dashboard</Tooltip>
 | 
					 | 
				
			||||||
					<Tooltip triggeredBy="#servers" placement="right">Servers</Tooltip>
 | 
					 | 
				
			||||||
					<div class="flex-1" />
 | 
					 | 
				
			||||||
					<div class="lg:block hidden">
 | 
					 | 
				
			||||||
						<!-- <UpdateAvailable /> -->
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
					<div class="flex flex-col space-y-2 py-2">
 | 
					 | 
				
			||||||
						<a
 | 
					 | 
				
			||||||
							id="iam"
 | 
					 | 
				
			||||||
							href={$appSession.pendingInvitations.length > 0 ? '/iam/pending' : '/iam'}
 | 
					 | 
				
			||||||
							class="icons hover:text-iam indicator"
 | 
					 | 
				
			||||||
							class:text-iam={$page.url.pathname.startsWith('/iam')}
 | 
					 | 
				
			||||||
							class:bg-coolgray-500={$page.url.pathname.startsWith('/iam')}
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							{#if $appSession.pendingInvitations.length > 0}
 | 
					 | 
				
			||||||
								<span class="indicator-item rounded-full badge badge-primary mr-2"
 | 
					 | 
				
			||||||
									>{$appSession.pendingInvitations.length}</span
 | 
					 | 
				
			||||||
								>
 | 
					 | 
				
			||||||
							{/if}<svg
 | 
					 | 
				
			||||||
								xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
								viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
								class="h-9 w-9"
 | 
					 | 
				
			||||||
								stroke-width="1.5"
 | 
					 | 
				
			||||||
								stroke="currentColor"
 | 
					 | 
				
			||||||
								fill="none"
 | 
					 | 
				
			||||||
								stroke-linecap="round"
 | 
					 | 
				
			||||||
								stroke-linejoin="round"
 | 
					 | 
				
			||||||
							>
 | 
					 | 
				
			||||||
								<path stroke="none" d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
								<circle cx="9" cy="7" r="4" />
 | 
					 | 
				
			||||||
								<path d="M3 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2" />
 | 
					 | 
				
			||||||
								<path d="M16 3.13a4 4 0 0 1 0 7.75" />
 | 
					 | 
				
			||||||
								<path d="M21 21v-2a4 4 0 0 0 -3 -3.85" />
 | 
					 | 
				
			||||||
							</svg>
 | 
					 | 
				
			||||||
						</a>
 | 
					 | 
				
			||||||
						<a
 | 
					 | 
				
			||||||
							id="settings"
 | 
					 | 
				
			||||||
							href={$appSession.teamId === '0' ? '/settings/coolify' : '/settings/docker'}
 | 
					 | 
				
			||||||
							class="icons hover:text-settings"
 | 
					 | 
				
			||||||
							class:text-settings={$page.url.pathname.startsWith('/settings')}
 | 
					 | 
				
			||||||
							class:bg-coolgray-500={$page.url.pathname.startsWith('/settings')}
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							<svg
 | 
					 | 
				
			||||||
								xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
								viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
								class="h-9 w-9"
 | 
					 | 
				
			||||||
								stroke-width="1.5"
 | 
					 | 
				
			||||||
								stroke="currentColor"
 | 
					 | 
				
			||||||
								fill="none"
 | 
					 | 
				
			||||||
								stroke-linecap="round"
 | 
					 | 
				
			||||||
								stroke-linejoin="round"
 | 
					 | 
				
			||||||
							>
 | 
					 | 
				
			||||||
								<path stroke="none" d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
								<path
 | 
					 | 
				
			||||||
									d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z"
 | 
					 | 
				
			||||||
								/>
 | 
					 | 
				
			||||||
								<circle cx="12" cy="12" r="3" />
 | 
					 | 
				
			||||||
							</svg>
 | 
					 | 
				
			||||||
						</a>
 | 
					 | 
				
			||||||
						<a
 | 
					 | 
				
			||||||
							id="documentation"
 | 
					 | 
				
			||||||
							href="https://docs.coollabs.io/coolify/"
 | 
					 | 
				
			||||||
							target="_blank"
 | 
					 | 
				
			||||||
							rel="noopener noreferrer"
 | 
					 | 
				
			||||||
							class="icons hover:text-info"
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							<svg
 | 
					 | 
				
			||||||
								xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
								fill="none"
 | 
					 | 
				
			||||||
								viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
								stroke-width="1.5"
 | 
					 | 
				
			||||||
								stroke="currentColor"
 | 
					 | 
				
			||||||
								class="w-9 h-9"
 | 
					 | 
				
			||||||
							>
 | 
					 | 
				
			||||||
								<path
 | 
					 | 
				
			||||||
									stroke-linecap="round"
 | 
					 | 
				
			||||||
									stroke-linejoin="round"
 | 
					 | 
				
			||||||
									d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25"
 | 
					 | 
				
			||||||
								/>
 | 
					 | 
				
			||||||
							</svg>
 | 
					 | 
				
			||||||
						</a>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						<!-- svelte-ignore a11y-click-events-have-key-events -->
 | 
					 | 
				
			||||||
						<div
 | 
					 | 
				
			||||||
							id="logout"
 | 
					 | 
				
			||||||
							class="icons bg-coolgray-200 hover:text-error cursor-pointer"
 | 
					 | 
				
			||||||
							on:click={logout}
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							<svg
 | 
					 | 
				
			||||||
								xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
								class="ml-1 h-8 w-8"
 | 
					 | 
				
			||||||
								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" />
 | 
					 | 
				
			||||||
								<path
 | 
					 | 
				
			||||||
									d="M14 8v-2a2 2 0 0 0 -2 -2h-7a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2 -2v-2"
 | 
					 | 
				
			||||||
								/>
 | 
					 | 
				
			||||||
								<path d="M7 12h14l-3 -3m0 6l3 -3" />
 | 
					 | 
				
			||||||
							</svg>
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
						<!-- <div class="lg:block">
 | 
					 | 
				
			||||||
							<LocalePicker/>
 | 
					 | 
				
			||||||
						</div> -->
 | 
					 | 
				
			||||||
						<div
 | 
					 | 
				
			||||||
							class="w-full text-center font-bold text-stone-400 hover:bg-coolgray-200 hover:text-white"
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							<a
 | 
					 | 
				
			||||||
								class="text-[10px] no-underline"
 | 
					 | 
				
			||||||
								href={`https://github.com/coollabsio/coolify/releases/tag/v${$appSession.version}`}
 | 
					 | 
				
			||||||
								target="_blank noreferrer">v{$appSession.version}</a
 | 
					 | 
				
			||||||
							>
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
			</nav>
 | 
					 | 
				
			||||||
			{#if $appSession.whiteLabeled}
 | 
					 | 
				
			||||||
				<span class="fixed bottom-0 left-[50px] z-50 m-2 px-4 text-xs text-stone-700"
 | 
					 | 
				
			||||||
					>Powered by <a href="https://coolify.io" target="_blank noreferrer">Coolify</a></span
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			{/if}
 | 
					 | 
				
			||||||
		{/if}
 | 
					 | 
				
			||||||
		<div
 | 
					 | 
				
			||||||
			class="navbar lg:hidden space-x-2 flex flex-row justify-between bg-coollabs"
 | 
					 | 
				
			||||||
			class:hidden={!$appSession.userId}
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<div>
 | 
					 | 
				
			||||||
				<label for="main-drawer" class="drawer-button btn btn-square btn-ghost flex-col">
 | 
					 | 
				
			||||||
					<span class="burger bg-white" />
 | 
					 | 
				
			||||||
					<span class="burger bg-white" />
 | 
					 | 
				
			||||||
					<span class="burger bg-white" />
 | 
					 | 
				
			||||||
				</label>
 | 
					 | 
				
			||||||
				<div class="prose flex flex-row justify-between space-x-1 w-full items-center pr-3">
 | 
					 | 
				
			||||||
					{#if !$appSession.whiteLabeled}
 | 
					 | 
				
			||||||
						<h3 class="mb-0 text-white">Coolify</h3>
 | 
					 | 
				
			||||||
					{/if}
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
			<!-- <LocalePicker /> -->
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<main>
 | 
					 | 
				
			||||||
			<div class={$appSession.userId ? 'lg:pl-16' : null}>
 | 
					 | 
				
			||||||
				<slot />
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		</main>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
	<div class="drawer-side">
 | 
					 | 
				
			||||||
		<label for="main-drawer" class="drawer-overlay w-full" />
 | 
					 | 
				
			||||||
		<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"
 | 
					 | 
				
			||||||
					href="/"
 | 
					 | 
				
			||||||
					class:bg-pink-500={$page.url.pathname === '/'}
 | 
					 | 
				
			||||||
					on:click={closeDrawer}
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
					<svg
 | 
					 | 
				
			||||||
						xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
						class="h-8 w-8"
 | 
					 | 
				
			||||||
						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" />
 | 
					 | 
				
			||||||
						<path
 | 
					 | 
				
			||||||
							d="M19 8.71l-5.333 -4.148a2.666 2.666 0 0 0 -3.274 0l-5.334 4.148a2.665 2.665 0 0 0 -1.029 2.105v7.2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-7.2c0 -.823 -.38 -1.6 -1.03 -2.105"
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
						<path d="M16 15c-2.21 1.333 -5.792 1.333 -8 0" />
 | 
					 | 
				
			||||||
					</svg>
 | 
					 | 
				
			||||||
					Dashboard
 | 
					 | 
				
			||||||
				</a>
 | 
					 | 
				
			||||||
			</li>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			<li>
 | 
					 | 
				
			||||||
				<a
 | 
					 | 
				
			||||||
					id="servers"
 | 
					 | 
				
			||||||
					class="no-underline icons hover:text-white hover:bg-sky-500"
 | 
					 | 
				
			||||||
					href="/servers"
 | 
					 | 
				
			||||||
					class:bg-sky-500={$page.url.pathname.startsWith('/servers')}
 | 
					 | 
				
			||||||
					on:click={closeDrawer}
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
					<svg
 | 
					 | 
				
			||||||
						xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
						class="w-8 h-8"
 | 
					 | 
				
			||||||
						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" />
 | 
					 | 
				
			||||||
						<rect x="3" y="4" width="18" height="8" rx="3" />
 | 
					 | 
				
			||||||
						<rect x="3" y="12" width="18" height="8" rx="3" />
 | 
					 | 
				
			||||||
						<line x1="7" y1="8" x2="7" y2="8.01" />
 | 
					 | 
				
			||||||
						<line x1="7" y1="16" x2="7" y2="16.01" />
 | 
					 | 
				
			||||||
					</svg>
 | 
					 | 
				
			||||||
					Servers
 | 
					 | 
				
			||||||
				</a>
 | 
					 | 
				
			||||||
			</li>
 | 
					 | 
				
			||||||
			<li>
 | 
					 | 
				
			||||||
				<a
 | 
					 | 
				
			||||||
					class="no-underline icons hover:text-white hover:bg-iam"
 | 
					 | 
				
			||||||
					href="/iam"
 | 
					 | 
				
			||||||
					class:bg-iam={$page.url.pathname.startsWith('/iam')}
 | 
					 | 
				
			||||||
					on:click={closeDrawer}
 | 
					 | 
				
			||||||
					><svg
 | 
					 | 
				
			||||||
						xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
						viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
						class="h-8 w-8"
 | 
					 | 
				
			||||||
						stroke-width="1.5"
 | 
					 | 
				
			||||||
						stroke="currentColor"
 | 
					 | 
				
			||||||
						fill="none"
 | 
					 | 
				
			||||||
						stroke-linecap="round"
 | 
					 | 
				
			||||||
						stroke-linejoin="round"
 | 
					 | 
				
			||||||
					>
 | 
					 | 
				
			||||||
						<path stroke="none" d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
						<circle cx="9" cy="7" r="4" />
 | 
					 | 
				
			||||||
						<path d="M3 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2" />
 | 
					 | 
				
			||||||
						<path d="M16 3.13a4 4 0 0 1 0 7.75" />
 | 
					 | 
				
			||||||
						<path d="M21 21v-2a4 4 0 0 0 -3 -3.85" />
 | 
					 | 
				
			||||||
					</svg>
 | 
					 | 
				
			||||||
					IAM {#if $appSession.pendingInvitations.length > 0}
 | 
					 | 
				
			||||||
						<span class="indicator-item rounded-full badge badge-primary"
 | 
					 | 
				
			||||||
							>{$appSession.pendingInvitations.length}</span
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
					{/if}
 | 
					 | 
				
			||||||
				</a>
 | 
					 | 
				
			||||||
			</li>
 | 
					 | 
				
			||||||
			<li>
 | 
					 | 
				
			||||||
				<a
 | 
					 | 
				
			||||||
					class="no-underline icons hover:text-black hover:bg-settings"
 | 
					 | 
				
			||||||
					href={$appSession.teamId === '0' ? '/settings/coolify' : '/settings/ssh'}
 | 
					 | 
				
			||||||
					class:bg-settings={$page.url.pathname.startsWith('/settings')}
 | 
					 | 
				
			||||||
					class:text-black={$page.url.pathname.startsWith('/settings')}
 | 
					 | 
				
			||||||
					on:click={closeDrawer}
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
					<svg
 | 
					 | 
				
			||||||
						xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
						viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
						class="h-8 w-8"
 | 
					 | 
				
			||||||
						stroke-width="1.5"
 | 
					 | 
				
			||||||
						stroke="currentColor"
 | 
					 | 
				
			||||||
						fill="none"
 | 
					 | 
				
			||||||
						stroke-linecap="round"
 | 
					 | 
				
			||||||
						stroke-linejoin="round"
 | 
					 | 
				
			||||||
					>
 | 
					 | 
				
			||||||
						<path stroke="none" d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
						<path
 | 
					 | 
				
			||||||
							d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z"
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
						<circle cx="12" cy="12" r="3" />
 | 
					 | 
				
			||||||
					</svg>
 | 
					 | 
				
			||||||
					Settings
 | 
					 | 
				
			||||||
				</a>
 | 
					 | 
				
			||||||
			</li>
 | 
					 | 
				
			||||||
			<li class="flex-1 bg-transparent" />
 | 
					 | 
				
			||||||
			<div class="block lg:hidden">
 | 
					 | 
				
			||||||
				<!-- <UpdateAvailable /> -->
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
			<li>
 | 
					 | 
				
			||||||
				<!-- svelte-ignore a11y-click-events-have-key-events -->
 | 
					 | 
				
			||||||
				<div class="no-underline icons hover:bg-error" on:click={logout}>
 | 
					 | 
				
			||||||
					<svg
 | 
					 | 
				
			||||||
						xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
						class="ml-1 h-8 w-8"
 | 
					 | 
				
			||||||
						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" />
 | 
					 | 
				
			||||||
						<path
 | 
					 | 
				
			||||||
							d="M14 8v-2a2 2 0 0 0 -2 -2h-7a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2 -2v-2"
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
						<path d="M7 12h14l-3 -3m0 6l3 -3" />
 | 
					 | 
				
			||||||
					</svg>
 | 
					 | 
				
			||||||
					<div class="-ml-1">Logout</div>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
			</li>
 | 
					 | 
				
			||||||
			<li class="w-full">
 | 
					 | 
				
			||||||
				<a
 | 
					 | 
				
			||||||
					class="text-xs hover:bg-coolgray-200 no-underline hover:text-white text-right"
 | 
					 | 
				
			||||||
					href={`https://github.com/coollabsio/coolify/releases/tag/v${$appSession.version}`}
 | 
					 | 
				
			||||||
					target="_blank noreferrer">v{$appSession.version}</a
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			</li>
 | 
					 | 
				
			||||||
		</ul>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,43 +0,0 @@
 | 
				
			|||||||
import { error } from '@sveltejs/kit';
 | 
					 | 
				
			||||||
import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
import type { LayoutLoad } from './$types';
 | 
					 | 
				
			||||||
import { redirect } from '@sveltejs/kit';
 | 
					 | 
				
			||||||
import Cookies from 'js-cookie';
 | 
					 | 
				
			||||||
export const ssr = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const load: LayoutLoad = async ({ url }) => {
 | 
					 | 
				
			||||||
	const { pathname } = new URL(url);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	try {
 | 
					 | 
				
			||||||
		if (pathname === '/login' || pathname === '/register') {
 | 
					 | 
				
			||||||
			const baseSettings = await trpc.settings.getBaseSettings.query();
 | 
					 | 
				
			||||||
			return {
 | 
					 | 
				
			||||||
				settings: {
 | 
					 | 
				
			||||||
					...baseSettings
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			};
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		const settings = await trpc.settings.getInstanceSettings.query();
 | 
					 | 
				
			||||||
		if (settings.data.token) {
 | 
					 | 
				
			||||||
			Cookies.set('token', settings.data.token);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			settings: {
 | 
					 | 
				
			||||||
				...settings
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	} catch (err) {
 | 
					 | 
				
			||||||
		if (err?.data?.httpStatus == 401) {
 | 
					 | 
				
			||||||
			throw redirect(307, '/login');
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (err instanceof Error) {
 | 
					 | 
				
			||||||
			throw error(500, {
 | 
					 | 
				
			||||||
				message: 'An unexpected error occurred, please try again later.' + '<br><br>' + err.message
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		throw error(500, {
 | 
					 | 
				
			||||||
			message: 'An unexpected error occurred, please try again later.'
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,13 +0,0 @@
 | 
				
			|||||||
import { error } from '@sveltejs/kit';
 | 
					 | 
				
			||||||
import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
export const ssr = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const load = async () => {
 | 
					 | 
				
			||||||
	try {
 | 
					 | 
				
			||||||
		return await trpc.dashboard.resources.query();
 | 
					 | 
				
			||||||
	} catch (err) {
 | 
					 | 
				
			||||||
		throw error(500, {
 | 
					 | 
				
			||||||
			message: 'An unexpected error occurred, please try again later.'
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@@ -1,114 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	import { status, trpc } from '$lib/store';
 | 
					 | 
				
			||||||
	import { onDestroy, onMount } from 'svelte';
 | 
					 | 
				
			||||||
	import type { LayoutData } from './$types';
 | 
					 | 
				
			||||||
	import * as Buttons from './components/Buttons';
 | 
					 | 
				
			||||||
	import * as States from './components/States';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	import Menu from './components/Menu.svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let data: LayoutData;
 | 
					 | 
				
			||||||
	const id = $page.params.id;
 | 
					 | 
				
			||||||
	const application = data.application.data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	$: isConfigurationView = $page.url.pathname.startsWith(`/applications/${id}/configuration/`);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let stopping = false;
 | 
					 | 
				
			||||||
	let statusInterval: NodeJS.Timeout;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	onMount(async () => {
 | 
					 | 
				
			||||||
		await getStatus();
 | 
					 | 
				
			||||||
		statusInterval = setInterval(async () => {
 | 
					 | 
				
			||||||
			await getStatus();
 | 
					 | 
				
			||||||
		}, 2000);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	onDestroy(() => {
 | 
					 | 
				
			||||||
		$status.application.initialLoading = true;
 | 
					 | 
				
			||||||
		$status.application.loading = false;
 | 
					 | 
				
			||||||
		$status.application.statuses = [];
 | 
					 | 
				
			||||||
		$status.application.overallStatus = 'stopped';
 | 
					 | 
				
			||||||
		clearInterval(statusInterval);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	async function getStatus() {
 | 
					 | 
				
			||||||
		if (($status.application.loading && stopping) || $status.application.restarting === true)
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		$status.application.loading = true;
 | 
					 | 
				
			||||||
		$status.application.statuses = await trpc.applications.status.query({ id });
 | 
					 | 
				
			||||||
		let numberOfApplications = 0;
 | 
					 | 
				
			||||||
		if (application.dockerComposeConfiguration) {
 | 
					 | 
				
			||||||
			numberOfApplications =
 | 
					 | 
				
			||||||
				application.buildPack === 'compose'
 | 
					 | 
				
			||||||
					? Object.entries(JSON.parse(application.dockerComposeConfiguration)).length
 | 
					 | 
				
			||||||
					: 1;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			numberOfApplications = 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if ($status.application.statuses.length === 0) {
 | 
					 | 
				
			||||||
			$status.application.overallStatus = 'stopped';
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			for (const oneStatus of $status.application.statuses) {
 | 
					 | 
				
			||||||
				if (oneStatus.status.isExited || oneStatus.status.isRestarting) {
 | 
					 | 
				
			||||||
					$status.application.overallStatus = 'degraded';
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (oneStatus.status.isRunning) {
 | 
					 | 
				
			||||||
					$status.application.overallStatus = 'healthy';
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (
 | 
					 | 
				
			||||||
					!oneStatus.status.isExited &&
 | 
					 | 
				
			||||||
					!oneStatus.status.isRestarting &&
 | 
					 | 
				
			||||||
					!oneStatus.status.isRunning
 | 
					 | 
				
			||||||
				) {
 | 
					 | 
				
			||||||
					$status.application.overallStatus = 'stopped';
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		$status.application.loading = false;
 | 
					 | 
				
			||||||
		$status.application.initialLoading = false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<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 items-start">
 | 
					 | 
				
			||||||
		<div class="title lg:pb-10">
 | 
					 | 
				
			||||||
			<div class="flex justify-center items-center space-x-2">
 | 
					 | 
				
			||||||
				<div>Configurations</div>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		{#if isConfigurationView}
 | 
					 | 
				
			||||||
			<Buttons.Delete {id} name={application.name} />
 | 
					 | 
				
			||||||
		{/if}
 | 
					 | 
				
			||||||
	</nav>
 | 
					 | 
				
			||||||
	<div
 | 
					 | 
				
			||||||
		class="pt-4 flex flex-row items-start justify-center lg:justify-end space-x-2 order-1 lg:order-2"
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		{#if $status.application.initialLoading}
 | 
					 | 
				
			||||||
			<States.Loading />
 | 
					 | 
				
			||||||
		{:else if $status.application.overallStatus === 'degraded'}
 | 
					 | 
				
			||||||
			<States.Degraded
 | 
					 | 
				
			||||||
				{id}
 | 
					 | 
				
			||||||
				on:stopping={() => (stopping = true)}
 | 
					 | 
				
			||||||
				on:stopped={() => (stopping = false)}
 | 
					 | 
				
			||||||
			/>
 | 
					 | 
				
			||||||
		{:else if $status.application.overallStatus === 'healthy'}
 | 
					 | 
				
			||||||
			<States.Healthy {id} isComposeBuildPack={application.buildPack === 'compose'} />
 | 
					 | 
				
			||||||
		{:else if $status.application.overallStatus === 'stopped'}
 | 
					 | 
				
			||||||
			<States.Stopped {id} />
 | 
					 | 
				
			||||||
		{/if}
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div
 | 
					 | 
				
			||||||
	class="mx-auto max-w-screen-2xl px-0 lg:px-10 grid grid-cols-1"
 | 
					 | 
				
			||||||
	class:lg:grid-cols-4={!isConfigurationView}
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	{#if !isConfigurationView}
 | 
					 | 
				
			||||||
		<nav class="header flex flex-col lg:pt-0 ">
 | 
					 | 
				
			||||||
			<Menu {application} />
 | 
					 | 
				
			||||||
		</nav>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
	<div class="pt-0 col-span-0 lg:col-span-3 pb-24">
 | 
					 | 
				
			||||||
		<slot />
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,56 +0,0 @@
 | 
				
			|||||||
import { error } from '@sveltejs/kit';
 | 
					 | 
				
			||||||
import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
import type { LayoutLoad } from './$types';
 | 
					 | 
				
			||||||
import { redirect } from '@sveltejs/kit';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function checkConfiguration(application: any): string | null {
 | 
					 | 
				
			||||||
	let configurationPhase = null;
 | 
					 | 
				
			||||||
	if (!application.gitSourceId && !application.simpleDockerfile) {
 | 
					 | 
				
			||||||
		return (configurationPhase = 'source');
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (application.simpleDockerfile) {
 | 
					 | 
				
			||||||
		if (!application.destinationDockerId) {
 | 
					 | 
				
			||||||
			configurationPhase = 'destination';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return configurationPhase;
 | 
					 | 
				
			||||||
	} else if (!application.repository && !application.branch) {
 | 
					 | 
				
			||||||
		configurationPhase = 'repository';
 | 
					 | 
				
			||||||
	} else if (!application.destinationDockerId) {
 | 
					 | 
				
			||||||
		configurationPhase = 'destination';
 | 
					 | 
				
			||||||
	} else if (!application.buildPack) {
 | 
					 | 
				
			||||||
		configurationPhase = 'buildpack';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return configurationPhase;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const load: LayoutLoad = async ({ params, url }) => {
 | 
					 | 
				
			||||||
	const { pathname } = new URL(url);
 | 
					 | 
				
			||||||
	const { id } = params;
 | 
					 | 
				
			||||||
	try {
 | 
					 | 
				
			||||||
		const application = await trpc.applications.getApplicationById.query({ id });
 | 
					 | 
				
			||||||
		if (!application) {
 | 
					 | 
				
			||||||
			throw redirect(307, '/applications');
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		const configurationPhase = checkConfiguration(application);
 | 
					 | 
				
			||||||
		console.log({ configurationPhase });
 | 
					 | 
				
			||||||
		// if (
 | 
					 | 
				
			||||||
		// 	configurationPhase &&
 | 
					 | 
				
			||||||
		// 	pathname !== `/applications/${params.id}/configuration/${configurationPhase}`
 | 
					 | 
				
			||||||
		// ) {
 | 
					 | 
				
			||||||
		// 	throw redirect(302, `/applications/${params.id}/configuration/${configurationPhase}`);
 | 
					 | 
				
			||||||
		// }
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			application
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	} catch (err) {
 | 
					 | 
				
			||||||
		if (err instanceof Error) {
 | 
					 | 
				
			||||||
			throw error(500, {
 | 
					 | 
				
			||||||
				message: 'An unexpected error occurred, please try again later.' + '<br><br>' + err.message
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		throw error(500, {
 | 
					 | 
				
			||||||
			message: 'An unexpected error occurred, please try again later.'
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,204 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import type { PageData } from '../build/$types';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let data: PageData;
 | 
					 | 
				
			||||||
	console.log(data);
 | 
					 | 
				
			||||||
	let builds = data.builds;
 | 
					 | 
				
			||||||
	const application = data.application.data;
 | 
					 | 
				
			||||||
	const buildCount = data.buildCount;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	import { addToast, selectedBuildId, trpc } from '$lib/store';
 | 
					 | 
				
			||||||
	import BuildLog from './BuildLog.svelte';
 | 
					 | 
				
			||||||
	import { changeQueryParams, dateOptions, errorNotification, asyncSleep } from '$lib/common';
 | 
					 | 
				
			||||||
	import Tooltip from '$lib/components/Tooltip.svelte';
 | 
					 | 
				
			||||||
	import { day } from '$lib/dayjs';
 | 
					 | 
				
			||||||
	import { onDestroy, onMount } from 'svelte';
 | 
					 | 
				
			||||||
	const { id } = $page.params;
 | 
					 | 
				
			||||||
	let debug = application.settings.debug;
 | 
					 | 
				
			||||||
	let loadBuildLogsInterval: any = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let skip = 0;
 | 
					 | 
				
			||||||
	let noMoreBuilds = buildCount < 5 || buildCount <= skip;
 | 
					 | 
				
			||||||
	let preselectedBuildId = $page.url.searchParams.get('buildId');
 | 
					 | 
				
			||||||
	if (preselectedBuildId) $selectedBuildId = preselectedBuildId;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	onMount(async () => {
 | 
					 | 
				
			||||||
		getBuildLogs();
 | 
					 | 
				
			||||||
		loadBuildLogsInterval = setInterval(() => {
 | 
					 | 
				
			||||||
			getBuildLogs();
 | 
					 | 
				
			||||||
		}, 2000);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	onDestroy(() => {
 | 
					 | 
				
			||||||
		clearInterval(loadBuildLogsInterval);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	async function getBuildLogs() {
 | 
					 | 
				
			||||||
		const response = await trpc.applications.getBuilds.query({ id, skip });
 | 
					 | 
				
			||||||
		builds = response.builds;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	async function loadMoreBuilds() {
 | 
					 | 
				
			||||||
		if (buildCount >= skip) {
 | 
					 | 
				
			||||||
			skip = skip + 5;
 | 
					 | 
				
			||||||
			noMoreBuilds = buildCount <= skip;
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				const data = await trpc.applications.getBuilds.query({ id, skip });
 | 
					 | 
				
			||||||
				builds = data.builds;
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			} catch (error) {
 | 
					 | 
				
			||||||
				return errorNotification(error);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			noMoreBuilds = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	function loadBuild(build: any) {
 | 
					 | 
				
			||||||
		$selectedBuildId = build;
 | 
					 | 
				
			||||||
		return changeQueryParams($selectedBuildId);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function resetQueue() {
 | 
					 | 
				
			||||||
		const sure = confirm(
 | 
					 | 
				
			||||||
			'It will reset all build queues for all applications. If something is queued, it will be canceled automatically. Are you sure? '
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
		if (sure) {
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				await trpc.applications.resetQueue.mutate();
 | 
					 | 
				
			||||||
				addToast({
 | 
					 | 
				
			||||||
					message: 'Queue reset done.',
 | 
					 | 
				
			||||||
					type: 'success'
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
				await asyncSleep(500);
 | 
					 | 
				
			||||||
				return window.location.reload();
 | 
					 | 
				
			||||||
			} catch (error) {
 | 
					 | 
				
			||||||
				return errorNotification(error);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	function generateBadgeColors(status: string) {
 | 
					 | 
				
			||||||
		if (status === 'failed') {
 | 
					 | 
				
			||||||
			return 'text-red-500';
 | 
					 | 
				
			||||||
		} else if (status === 'running') {
 | 
					 | 
				
			||||||
			return 'text-yellow-300';
 | 
					 | 
				
			||||||
		} else if (status === 'success') {
 | 
					 | 
				
			||||||
			return 'text-green-500';
 | 
					 | 
				
			||||||
		} else if (status === 'canceled') {
 | 
					 | 
				
			||||||
			return 'text-orange-500';
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return 'text-white';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function changeSettings(name: any) {
 | 
					 | 
				
			||||||
		if (name === 'debug') {
 | 
					 | 
				
			||||||
			debug = !debug;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			trpc.applications.saveSettings.mutate({
 | 
					 | 
				
			||||||
				id,
 | 
					 | 
				
			||||||
				debug
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
			return addToast({
 | 
					 | 
				
			||||||
				message: 'Settings saved.',
 | 
					 | 
				
			||||||
				type: 'success'
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			if (name === 'debug') {
 | 
					 | 
				
			||||||
				debug = !debug;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="mx-auto w-full lg:px-0 px-1">
 | 
					 | 
				
			||||||
	<div class="flex lg:flex-row flex-col border-b border-coolgray-500 mb-6 space-x-2">
 | 
					 | 
				
			||||||
		<div class="flex flex-row">
 | 
					 | 
				
			||||||
			<div class="title font-bold pb-3 pr-3">Build Logs</div>
 | 
					 | 
				
			||||||
			<button class="btn btn-sm bg-error" on:click={resetQueue}>Reset Build Queue</button>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<div class=" flex-1" />
 | 
					 | 
				
			||||||
		<div class="form-control">
 | 
					 | 
				
			||||||
			<label class="label cursor-pointer">
 | 
					 | 
				
			||||||
				<span class="label-text text-white pr-4 font-bold">Enable Debug Logs</span>
 | 
					 | 
				
			||||||
				<input
 | 
					 | 
				
			||||||
					type="checkbox"
 | 
					 | 
				
			||||||
					checked={debug}
 | 
					 | 
				
			||||||
					class="checkbox checkbox-success"
 | 
					 | 
				
			||||||
					on:click={() => changeSettings('debug')}
 | 
					 | 
				
			||||||
				/>
 | 
					 | 
				
			||||||
			</label>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="justify-start space-x-5 flex flex-col-reverse lg:flex-row">
 | 
					 | 
				
			||||||
	<div class="flex-1 md:w-96">
 | 
					 | 
				
			||||||
		{#if $selectedBuildId}
 | 
					 | 
				
			||||||
			{#key $selectedBuildId}
 | 
					 | 
				
			||||||
				<svelte:component this={BuildLog} />
 | 
					 | 
				
			||||||
			{/key}
 | 
					 | 
				
			||||||
		{:else if buildCount === 0}
 | 
					 | 
				
			||||||
			Not build logs found.
 | 
					 | 
				
			||||||
		{:else}
 | 
					 | 
				
			||||||
			Select a build to see the logs.
 | 
					 | 
				
			||||||
		{/if}
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
	<div class="mb-4 min-w-[16rem] space-y-2 md:mb-0 ">
 | 
					 | 
				
			||||||
		<div class="top-4 md:sticky">
 | 
					 | 
				
			||||||
			<div class="flex space-x-2 pb-2">
 | 
					 | 
				
			||||||
				<button
 | 
					 | 
				
			||||||
					disabled={noMoreBuilds}
 | 
					 | 
				
			||||||
					class:btn-primary={!noMoreBuilds}
 | 
					 | 
				
			||||||
					class=" btn btn-sm w-full"
 | 
					 | 
				
			||||||
					on:click={loadMoreBuilds}>Load more</button
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
			{#each builds as build, index (build.id)}
 | 
					 | 
				
			||||||
				<!-- svelte-ignore a11y-click-events-have-key-events -->
 | 
					 | 
				
			||||||
				<div
 | 
					 | 
				
			||||||
					id={`building-${build.id}`}
 | 
					 | 
				
			||||||
					on:click={() => loadBuild(build.id)}
 | 
					 | 
				
			||||||
					class:rounded-tr={index === 0}
 | 
					 | 
				
			||||||
					class:rounded-br={index === builds.length - 1}
 | 
					 | 
				
			||||||
					class="flex cursor-pointer items-center justify-center py-4 no-underline transition-all duration-150 hover:bg-coolgray-300 hover:shadow-xl"
 | 
					 | 
				
			||||||
					class:bg-coolgray-200={$selectedBuildId === build.id}
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
					<div class="flex-col px-2 text-center">
 | 
					 | 
				
			||||||
						<div class="text-sm font-bold truncate">
 | 
					 | 
				
			||||||
							{build.branch || application.branch}
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
						<div class="text-xs">
 | 
					 | 
				
			||||||
							{build.type}
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
						<div
 | 
					 | 
				
			||||||
							class={`badge badge-sm text-xs uppercase rounded bg-coolgray-300 border-none font-bold ${generateBadgeColors(
 | 
					 | 
				
			||||||
								build.status
 | 
					 | 
				
			||||||
							)}`}
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							{build.status}
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					<div class="w-32 text-center text-xs">
 | 
					 | 
				
			||||||
						{#if build.status === 'running'}
 | 
					 | 
				
			||||||
							<div>
 | 
					 | 
				
			||||||
								<span class="font-bold text-xl">{build.elapsed}s</span>
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
						{:else if build.status !== 'queued'}
 | 
					 | 
				
			||||||
							<div>{day(build.updatedAt).utc().fromNow()}</div>
 | 
					 | 
				
			||||||
							<div>
 | 
					 | 
				
			||||||
								Finished in
 | 
					 | 
				
			||||||
								<span class="font-bold"
 | 
					 | 
				
			||||||
									>{day(build.updatedAt).utc().diff(day(build.createdAt)) / 1000}s</span
 | 
					 | 
				
			||||||
								>
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
						{/if}
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
				<Tooltip triggeredBy={`#building-${build.id}`}
 | 
					 | 
				
			||||||
					>{new Intl.DateTimeFormat('default', dateOptions).format(new Date(build.createdAt)) +
 | 
					 | 
				
			||||||
						`\n`}</Tooltip
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			{/each}
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,16 +0,0 @@
 | 
				
			|||||||
import { error } from '@sveltejs/kit';
 | 
					 | 
				
			||||||
import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
import type { PageLoad } from './$types';
 | 
					 | 
				
			||||||
export const ssr = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const load: PageLoad = async ({ params }) => {
 | 
					 | 
				
			||||||
	try {
 | 
					 | 
				
			||||||
		const { id } = params;
 | 
					 | 
				
			||||||
		const data = await trpc.applications.getBuilds.query({ id, skip: 0 });
 | 
					 | 
				
			||||||
		return data;
 | 
					 | 
				
			||||||
	} catch (err) {
 | 
					 | 
				
			||||||
		throw error(500, {
 | 
					 | 
				
			||||||
			message: 'An unexpected error occurred, please try again later.'
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@@ -1,215 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { onDestroy, onMount } from 'svelte';
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	import Tooltip from '$lib/components/Tooltip.svelte';
 | 
					 | 
				
			||||||
	import { day } from '$lib/dayjs';
 | 
					 | 
				
			||||||
	import { selectedBuildId, trpc } from '$lib/store';
 | 
					 | 
				
			||||||
	import { dev } from '$app/environment';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let logs: any = [];
 | 
					 | 
				
			||||||
	let currentStatus: any;
 | 
					 | 
				
			||||||
	let streamInterval: any;
 | 
					 | 
				
			||||||
	let followingLogs: any;
 | 
					 | 
				
			||||||
	let followingInterval: any;
 | 
					 | 
				
			||||||
	let logsEl: any;
 | 
					 | 
				
			||||||
	let fromDb = false;
 | 
					 | 
				
			||||||
	let cancelInprogress = false;
 | 
					 | 
				
			||||||
	let position = 0;
 | 
					 | 
				
			||||||
	let loading = true;
 | 
					 | 
				
			||||||
	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() {
 | 
					 | 
				
			||||||
		followingLogs = !followingLogs;
 | 
					 | 
				
			||||||
		if (followingLogs) {
 | 
					 | 
				
			||||||
			followingInterval = setInterval(() => {
 | 
					 | 
				
			||||||
				logsEl.scrollTop = logsEl.scrollHeight;
 | 
					 | 
				
			||||||
				window.scrollTo(0, document.body.scrollHeight);
 | 
					 | 
				
			||||||
			}, 100);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			window.clearInterval(followingInterval);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function streamLogs(sequence = 0) {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			loading = true;
 | 
					 | 
				
			||||||
			let {
 | 
					 | 
				
			||||||
				logs: responseLogs,
 | 
					 | 
				
			||||||
				status,
 | 
					 | 
				
			||||||
				fromDb: from
 | 
					 | 
				
			||||||
			} = await trpc.applications.getBuildLogs.query({ id, buildId: $selectedBuildId, sequence });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			currentStatus = status;
 | 
					 | 
				
			||||||
			logs = logs.concat(
 | 
					 | 
				
			||||||
				responseLogs.map((log: any) => ({ ...log, line: cleanAnsiCodes(log.line) }))
 | 
					 | 
				
			||||||
			);
 | 
					 | 
				
			||||||
			fromDb = from;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			streamInterval = setInterval(async () => {
 | 
					 | 
				
			||||||
				const nextSequence = logs[logs.length - 1]?.time || 0;
 | 
					 | 
				
			||||||
				if (status !== 'running' && status !== 'queued') {
 | 
					 | 
				
			||||||
					loading = false;
 | 
					 | 
				
			||||||
					try {
 | 
					 | 
				
			||||||
						const data = await trpc.applications.getBuildLogs.query({
 | 
					 | 
				
			||||||
							id,
 | 
					 | 
				
			||||||
							buildId: $selectedBuildId,
 | 
					 | 
				
			||||||
							sequence: nextSequence
 | 
					 | 
				
			||||||
						});
 | 
					 | 
				
			||||||
						status = data.status;
 | 
					 | 
				
			||||||
						currentStatus = status;
 | 
					 | 
				
			||||||
						fromDb = data.fromDb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						logs = logs.concat(
 | 
					 | 
				
			||||||
							data.logs.map((log: any) => ({ ...log, line: cleanAnsiCodes(log.line) }))
 | 
					 | 
				
			||||||
						);
 | 
					 | 
				
			||||||
						loading = false;
 | 
					 | 
				
			||||||
					} catch (error) {
 | 
					 | 
				
			||||||
						return errorNotification(error);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					clearInterval(streamInterval);
 | 
					 | 
				
			||||||
					return;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					const data = await trpc.applications.getBuildLogs.query({
 | 
					 | 
				
			||||||
						id,
 | 
					 | 
				
			||||||
						buildId: $selectedBuildId,
 | 
					 | 
				
			||||||
						sequence: nextSequence
 | 
					 | 
				
			||||||
					});
 | 
					 | 
				
			||||||
					status = data.status;
 | 
					 | 
				
			||||||
					currentStatus = status;
 | 
					 | 
				
			||||||
					fromDb = data.fromDb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					logs = logs.concat(
 | 
					 | 
				
			||||||
						data.logs.map((log: any) => ({ ...log, line: cleanAnsiCodes(log.line) }))
 | 
					 | 
				
			||||||
					);
 | 
					 | 
				
			||||||
					loading = false;
 | 
					 | 
				
			||||||
				} catch (error) {
 | 
					 | 
				
			||||||
					return errorNotification(error);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}, 1000);
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function cancelBuild() {
 | 
					 | 
				
			||||||
		if (cancelInprogress) return;
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			cancelInprogress = true;
 | 
					 | 
				
			||||||
			await trpc.applications.cancelBuild.mutate({
 | 
					 | 
				
			||||||
				buildId: $selectedBuildId,
 | 
					 | 
				
			||||||
				applicationId: id
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	onDestroy(() => {
 | 
					 | 
				
			||||||
		clearInterval(streamInterval);
 | 
					 | 
				
			||||||
		clearInterval(followingInterval);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	onMount(async () => {
 | 
					 | 
				
			||||||
		window.scrollTo(0, 0);
 | 
					 | 
				
			||||||
		await streamLogs();
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="flex justify-start top-0 pb-2 space-x-2">
 | 
					 | 
				
			||||||
	<button
 | 
					 | 
				
			||||||
		on:click={followBuild}
 | 
					 | 
				
			||||||
		class="btn btn-sm bg-coollabs"
 | 
					 | 
				
			||||||
		disabled={currentStatus !== 'running'}
 | 
					 | 
				
			||||||
		class:bg-coolgray-300={followingLogs || currentStatus !== 'running'}
 | 
					 | 
				
			||||||
		class:text-applications={followingLogs}
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<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"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<path stroke="none" d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
			<circle cx="12" cy="12" r="9" />
 | 
					 | 
				
			||||||
			<line x1="8" y1="12" x2="12" y2="16" />
 | 
					 | 
				
			||||||
			<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>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	<button
 | 
					 | 
				
			||||||
		on:click={cancelBuild}
 | 
					 | 
				
			||||||
		class:animation-spin={cancelInprogress}
 | 
					 | 
				
			||||||
		class="btn btn-sm"
 | 
					 | 
				
			||||||
		disabled={currentStatus !== 'running'}
 | 
					 | 
				
			||||||
		class:bg-coolgray-300={cancelInprogress || currentStatus !== 'running'}
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<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"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<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>
 | 
					 | 
				
			||||||
	{#if currentStatus === 'running'}
 | 
					 | 
				
			||||||
		<button id="streaming" class="btn btn-sm bg-transparent border-none loading" />
 | 
					 | 
				
			||||||
		<Tooltip triggeredBy="#streaming">Streaming logs</Tooltip>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
{#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"
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		Queued and waiting for execution.
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
{:else if logs.length > 0}
 | 
					 | 
				
			||||||
	<div
 | 
					 | 
				
			||||||
		bind:this={logsEl}
 | 
					 | 
				
			||||||
		on:scroll={detect}
 | 
					 | 
				
			||||||
		class="font-mono w-full bg-coolgray-100 border border-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 whitespace-pre"
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		{#each logs as log}
 | 
					 | 
				
			||||||
			{#if fromDb}
 | 
					 | 
				
			||||||
				{log.line + '\n'}
 | 
					 | 
				
			||||||
			{:else}
 | 
					 | 
				
			||||||
				[{day.unix(log.time).format('HH:mm:ss.SSS')}] {log.line + '\n'}
 | 
					 | 
				
			||||||
			{/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"
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		{loading
 | 
					 | 
				
			||||||
			? 'Loading logs...'
 | 
					 | 
				
			||||||
			: dev
 | 
					 | 
				
			||||||
			? 'In development, logs are shown in the console.'
 | 
					 | 
				
			||||||
			: 'No logs found yet.'}
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
@@ -1,29 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	import { appSession, trpc } from '$lib/store';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let id: string;
 | 
					 | 
				
			||||||
	export let name: string;
 | 
					 | 
				
			||||||
	export let force: boolean = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	async function handleSubmit() {
 | 
					 | 
				
			||||||
		const sure = confirm(`Are you sure you want to delete ${name}?`);
 | 
					 | 
				
			||||||
		if (sure) {
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				await trpc.applications.delete.mutate({ id, force });
 | 
					 | 
				
			||||||
				return await goto('/');
 | 
					 | 
				
			||||||
			} catch (error) {
 | 
					 | 
				
			||||||
				return errorNotification(error);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<button
 | 
					 | 
				
			||||||
	on:click={handleSubmit}
 | 
					 | 
				
			||||||
	disabled={!$appSession.isAdmin}
 | 
					 | 
				
			||||||
	class="btn btn-sm btn-error hover:bg-red-700 text-sm w-64"
 | 
					 | 
				
			||||||
>
 | 
					 | 
				
			||||||
	{force ? 'Force' : ''} Delete Application
 | 
					 | 
				
			||||||
</button>
 | 
					 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	export let id: string;
 | 
					 | 
				
			||||||
	import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
	async function handleSubmit() {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			await trpc.applications.deploy.mutate({
 | 
					 | 
				
			||||||
				id
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<button class="btn btn-sm gap-2" on:click={handleSubmit}>
 | 
					 | 
				
			||||||
	<svg
 | 
					 | 
				
			||||||
		xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
		class="w-6 h-6 text-pink-500"
 | 
					 | 
				
			||||||
		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" />
 | 
					 | 
				
			||||||
		<path d="M7 4v16l13 -8z" />
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	Deploy
 | 
					 | 
				
			||||||
</button>
 | 
					 | 
				
			||||||
@@ -1,34 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	export let id: string;
 | 
					 | 
				
			||||||
	import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
	async function handleSubmit() {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			await trpc.applications.forceRedeploy.mutate({
 | 
					 | 
				
			||||||
				id
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<button class="btn btn-sm gap-2" on:click={handleSubmit}>
 | 
					 | 
				
			||||||
	<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" />
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M16.3 5h.7a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h5l-2.82 -2.82m0 5.64l2.82 -2.82"
 | 
					 | 
				
			||||||
			transform="rotate(-45 12 12)"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	Force re-Deploy
 | 
					 | 
				
			||||||
</button>
 | 
					 | 
				
			||||||
@@ -1,21 +0,0 @@
 | 
				
			|||||||
<button class="btn btn-ghost btn-sm gap-2">
 | 
					 | 
				
			||||||
	<svg
 | 
					 | 
				
			||||||
		xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
		class="h-6 w-6 animate-spin duration-500 ease-in-out"
 | 
					 | 
				
			||||||
		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" />
 | 
					 | 
				
			||||||
		<path d="M9 4.55a8 8 0 0 1 6 14.9m0 -4.45v5h5" />
 | 
					 | 
				
			||||||
		<line x1="5.63" y1="7.16" x2="5.63" y2="7.17" />
 | 
					 | 
				
			||||||
		<line x1="4.06" y1="11" x2="4.06" y2="11.01" />
 | 
					 | 
				
			||||||
		<line x1="4.63" y1="15.1" x2="4.63" y2="15.11" />
 | 
					 | 
				
			||||||
		<line x1="7.16" y1="18.37" x2="7.16" y2="18.38" />
 | 
					 | 
				
			||||||
		<line x1="11" y1="19.94" x2="11" y2="19.95" />
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	Loading...
 | 
					 | 
				
			||||||
</button>
 | 
					 | 
				
			||||||
@@ -1,30 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	export let id: string;
 | 
					 | 
				
			||||||
	import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	async function handleSubmit() {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			return await trpc.applications.restart.mutate({ id });
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<button on:click={handleSubmit} class="btn btn-sm gap-2">
 | 
					 | 
				
			||||||
	<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" />
 | 
					 | 
				
			||||||
		<path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" />
 | 
					 | 
				
			||||||
		<path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" />
 | 
					 | 
				
			||||||
	</svg> Restart
 | 
					 | 
				
			||||||
</button>
 | 
					 | 
				
			||||||
@@ -1,37 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { createEventDispatcher } from 'svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let id: string;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const dispatch = createEventDispatcher();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	async function handleSubmit() {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			dispatch('stopping');
 | 
					 | 
				
			||||||
			await trpc.applications.stop.mutate({ id });
 | 
					 | 
				
			||||||
			dispatch('stopped');
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<button on:click={handleSubmit} class="btn btn-sm gap-2">
 | 
					 | 
				
			||||||
	<svg
 | 
					 | 
				
			||||||
		xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
		class="w-6 h-6 text-error"
 | 
					 | 
				
			||||||
		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" />
 | 
					 | 
				
			||||||
		<rect x="6" y="5" width="4" height="14" rx="1" />
 | 
					 | 
				
			||||||
		<rect x="14" y="5" width="4" height="14" rx="1" />
 | 
					 | 
				
			||||||
	</svg> Stop
 | 
					 | 
				
			||||||
</button>
 | 
					 | 
				
			||||||
@@ -1,6 +0,0 @@
 | 
				
			|||||||
export { default as Delete } from './Delete.svelte';
 | 
					 | 
				
			||||||
export { default as Stop } from './Stop.svelte';
 | 
					 | 
				
			||||||
export { default as Restart } from './Restart.svelte';
 | 
					 | 
				
			||||||
export { default as Deploy } from './Deploy.svelte';
 | 
					 | 
				
			||||||
export { default as ForceDeploy } from './ForceDeploy.svelte';
 | 
					 | 
				
			||||||
export { default as Loading } from './Loading.svelte';
 | 
					 | 
				
			||||||
@@ -1,278 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let application: any;
 | 
					 | 
				
			||||||
	import { status } from '$lib/store';
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	import * as Icons from '$lib/components/icons';
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<ul class="menu border bg-coolgray-100 border-coolgray-200 rounded p-2 space-y-2 sticky top-4">
 | 
					 | 
				
			||||||
	<li class="menu-title">
 | 
					 | 
				
			||||||
		<span>General</span>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
	{#if application.gitSource?.htmlUrl && application.repository && application.branch}
 | 
					 | 
				
			||||||
		<li>
 | 
					 | 
				
			||||||
			<a
 | 
					 | 
				
			||||||
				id="git"
 | 
					 | 
				
			||||||
				href="{application.gitSource.htmlUrl}/{application.repository}/tree/{application.branch}"
 | 
					 | 
				
			||||||
				target="_blank noreferrer"
 | 
					 | 
				
			||||||
				class="no-underline"
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				{#if application.gitSource?.type === 'gitlab'}
 | 
					 | 
				
			||||||
					<Icons.Sources.GitHub small={true} />
 | 
					 | 
				
			||||||
				{:else if application.gitSource?.type === 'github'}
 | 
					 | 
				
			||||||
					<Icons.Sources.GitLab small={true} />
 | 
					 | 
				
			||||||
				{/if}
 | 
					 | 
				
			||||||
				Open on Git <Icons.RemoteLink />
 | 
					 | 
				
			||||||
			</a>
 | 
					 | 
				
			||||||
		</li>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	<li class="rounded" class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}`}>
 | 
					 | 
				
			||||||
		<a href={`/applications/${$page.params.id}`} class="no-underline w-full"
 | 
					 | 
				
			||||||
			><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" />
 | 
					 | 
				
			||||||
				<path
 | 
					 | 
				
			||||||
					d="M7 10h3v-3l-3.5 -3.5a6 6 0 0 1 8 8l6 6a2 2 0 0 1 -3 3l-6 -6a6 6 0 0 1 -8 -8l3.5 3.5"
 | 
					 | 
				
			||||||
				/>
 | 
					 | 
				
			||||||
			</svg>Configuration</a
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
	<li
 | 
					 | 
				
			||||||
		class="rounded"
 | 
					 | 
				
			||||||
		class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/secrets`}
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<a href={`/applications/${$page.params.id}/secrets`} class="no-underline w-full"
 | 
					 | 
				
			||||||
			><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" />
 | 
					 | 
				
			||||||
				<path
 | 
					 | 
				
			||||||
					d="M12 3a12 12 0 0 0 8.5 3a12 12 0 0 1 -8.5 15a12 12 0 0 1 -8.5 -15a12 12 0 0 0 8.5 -3"
 | 
					 | 
				
			||||||
				/>
 | 
					 | 
				
			||||||
				<circle cx="12" cy="11" r="1" />
 | 
					 | 
				
			||||||
				<line x1="12" y1="12" x2="12" y2="14.5" />
 | 
					 | 
				
			||||||
			</svg>Secrets</a
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
	<li
 | 
					 | 
				
			||||||
		class="rounded"
 | 
					 | 
				
			||||||
		class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/storages`}
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<a href={`/applications/${$page.params.id}/storages`} class="no-underline w-full"
 | 
					 | 
				
			||||||
			><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" />
 | 
					 | 
				
			||||||
				<ellipse cx="12" cy="6" rx="8" ry="3" />
 | 
					 | 
				
			||||||
				<path d="M4 6v6a8 3 0 0 0 16 0v-6" />
 | 
					 | 
				
			||||||
				<path d="M4 12v6a8 3 0 0 0 16 0v-6" />
 | 
					 | 
				
			||||||
			</svg>Persistent Volumes</a
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
	{#if !application.simpleDockerfile}
 | 
					 | 
				
			||||||
		<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"
 | 
					 | 
				
			||||||
				><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" />
 | 
					 | 
				
			||||||
					<polyline points="13 3 13 10 19 10 11 21 11 14 5 14 13 3" />
 | 
					 | 
				
			||||||
				</svg>Features</a
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
		</li>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	<li class="menu-title">
 | 
					 | 
				
			||||||
		<span>Logs</span>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
	<li
 | 
					 | 
				
			||||||
		class:text-stone-600={$status.application.overallStatus === 'stopped'}
 | 
					 | 
				
			||||||
		class="rounded"
 | 
					 | 
				
			||||||
		class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/logs`}
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<a
 | 
					 | 
				
			||||||
			href={$status.application.overallStatus !== 'stopped'
 | 
					 | 
				
			||||||
				? `/applications/${$page.params.id}/logs`
 | 
					 | 
				
			||||||
				: ''}
 | 
					 | 
				
			||||||
			class="no-underline w-full"
 | 
					 | 
				
			||||||
			><svg
 | 
					 | 
				
			||||||
				xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
				class="h-6 w-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" />
 | 
					 | 
				
			||||||
				<path d="M3 19a9 9 0 0 1 9 0a9 9 0 0 1 9 0" />
 | 
					 | 
				
			||||||
				<path d="M3 6a9 9 0 0 1 9 0a9 9 0 0 1 9 0" />
 | 
					 | 
				
			||||||
				<line x1="3" y1="6" x2="3" y2="19" />
 | 
					 | 
				
			||||||
				<line x1="12" y1="6" x2="12" y2="19" />
 | 
					 | 
				
			||||||
				<line x1="21" y1="6" x2="21" y2="19" />
 | 
					 | 
				
			||||||
			</svg>Application</a
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
	<li
 | 
					 | 
				
			||||||
		class="rounded"
 | 
					 | 
				
			||||||
		class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/builds`}
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<a href={`/applications/${$page.params.id}/builds`} class="no-underline w-full"
 | 
					 | 
				
			||||||
			><svg
 | 
					 | 
				
			||||||
				xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
				class="h-6 w-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="19" cy="13" r="2" />
 | 
					 | 
				
			||||||
				<circle cx="4" cy="17" r="2" />
 | 
					 | 
				
			||||||
				<circle cx="13" cy="17" r="2" />
 | 
					 | 
				
			||||||
				<line x1="13" y1="19" x2="4" y2="19" />
 | 
					 | 
				
			||||||
				<line x1="4" y1="15" x2="13" y2="15" />
 | 
					 | 
				
			||||||
				<path d="M8 12v-5h2a3 3 0 0 1 3 3v5" />
 | 
					 | 
				
			||||||
				<path d="M5 15v-2a1 1 0 0 1 1 -1h7" />
 | 
					 | 
				
			||||||
				<path d="M19 11v-7l-6 7" />
 | 
					 | 
				
			||||||
			</svg>Build</a
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
	<li class="menu-title">
 | 
					 | 
				
			||||||
		<span>Advanced</span>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
	{#if application.gitSourceId}
 | 
					 | 
				
			||||||
		<li
 | 
					 | 
				
			||||||
			class="rounded"
 | 
					 | 
				
			||||||
			class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/revert`}
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<a href={`/applications/${$page.params.id}/revert`} class="no-underline w-full">
 | 
					 | 
				
			||||||
				<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" />
 | 
					 | 
				
			||||||
					<path d="M20 5v14l-12 -7z" />
 | 
					 | 
				
			||||||
					<line x1="4" y1="5" x2="4" y2="19" />
 | 
					 | 
				
			||||||
				</svg>
 | 
					 | 
				
			||||||
				Revert</a
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
		</li>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
	<li
 | 
					 | 
				
			||||||
		class="rounded"
 | 
					 | 
				
			||||||
		class:text-stone-600={$status.application.overallStatus !== 'healthy'}
 | 
					 | 
				
			||||||
		class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/usage`}
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<a
 | 
					 | 
				
			||||||
			href={$status.application.overallStatus === 'healthy'
 | 
					 | 
				
			||||||
				? `/applications/${$page.params.id}/usage`
 | 
					 | 
				
			||||||
				: ''}
 | 
					 | 
				
			||||||
			class="no-underline w-full"
 | 
					 | 
				
			||||||
			><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" />
 | 
					 | 
				
			||||||
				<path d="M3 12h4l3 8l4 -16l3 8h4" />
 | 
					 | 
				
			||||||
			</svg>Monitoring</a
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
	{#if !application.settings.isBot && application.gitSourceId}
 | 
					 | 
				
			||||||
		<li
 | 
					 | 
				
			||||||
			class="rounded"
 | 
					 | 
				
			||||||
			class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/previews`}
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<a href={`/applications/${$page.params.id}/previews`} class="no-underline w-full"
 | 
					 | 
				
			||||||
				><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="7" cy="18" r="2" />
 | 
					 | 
				
			||||||
					<circle cx="7" cy="6" r="2" />
 | 
					 | 
				
			||||||
					<circle cx="17" cy="12" r="2" />
 | 
					 | 
				
			||||||
					<line x1="7" y1="8" x2="7" y2="16" />
 | 
					 | 
				
			||||||
					<path d="M7 8a4 4 0 0 0 4 4h4" />
 | 
					 | 
				
			||||||
				</svg>Preview Deployments</a
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
		</li>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
	<li
 | 
					 | 
				
			||||||
		class="rounded"
 | 
					 | 
				
			||||||
		class:bg-coollabs={$page.url.pathname === `/applications/${$page.params.id}/danger`}
 | 
					 | 
				
			||||||
	>
 | 
					 | 
				
			||||||
		<a href={`/applications/${$page.params.id}/danger`} class="no-underline w-full"
 | 
					 | 
				
			||||||
			><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" />
 | 
					 | 
				
			||||||
				<path d="M12 9v2m0 4v.01" />
 | 
					 | 
				
			||||||
				<path
 | 
					 | 
				
			||||||
					d="M5 19h14a2 2 0 0 0 1.84 -2.75l-7.1 -12.25a2 2 0 0 0 -3.5 0l-7.1 12.25a2 2 0 0 0 1.75 2.75"
 | 
					 | 
				
			||||||
				/>
 | 
					 | 
				
			||||||
			</svg>Danger Zone</a
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	</li>
 | 
					 | 
				
			||||||
</ul>
 | 
					 | 
				
			||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let id: string;
 | 
					 | 
				
			||||||
	import * as Buttons from '../Buttons';
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<a href={`/applications/${id}/logs`} class="btn btn-sm text-sm gap-2">
 | 
					 | 
				
			||||||
	<svg
 | 
					 | 
				
			||||||
		xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
		class="w-6 h-6 text-red-500"
 | 
					 | 
				
			||||||
		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" />
 | 
					 | 
				
			||||||
		<path
 | 
					 | 
				
			||||||
			d="M8.7 3h6.6c.3 0 .5 .1 .7 .3l4.7 4.7c.2 .2 .3 .4 .3 .7v6.6c0 .3 -.1 .5 -.3 .7l-4.7 4.7c-.2 .2 -.4 .3 -.7 .3h-6.6c-.3 0 -.5 -.1 -.7 -.3l-4.7 -4.7c-.2 -.2 -.3 -.4 -.3 -.7v-6.6c0 -.3 .1 -.5 .3 -.7l4.7 -4.7c.2 -.2 .4 -.3 .7 -.3z"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<line x1="12" y1="8" x2="12" y2="12" />
 | 
					 | 
				
			||||||
		<line x1="12" y1="16" x2="12.01" y2="16" />
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	Application Error (check logs)
 | 
					 | 
				
			||||||
</a>
 | 
					 | 
				
			||||||
<Buttons.Stop {id} />
 | 
					 | 
				
			||||||
@@ -1,11 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let id: string;
 | 
					 | 
				
			||||||
	export let isComposeBuildPack: boolean = false;
 | 
					 | 
				
			||||||
	import * as Buttons from '../Buttons';
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if !isComposeBuildPack}
 | 
					 | 
				
			||||||
	<Buttons.Restart {id} />
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
<Buttons.ForceDeploy {id} />
 | 
					 | 
				
			||||||
<Buttons.Stop {id} />
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import * as Buttons from '../Buttons';
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<Buttons.Loading />
 | 
					 | 
				
			||||||
@@ -1,6 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	export let id: string;
 | 
					 | 
				
			||||||
	import * as Buttons from '../Buttons';
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<Buttons.Deploy {id} />
 | 
					 | 
				
			||||||
@@ -1,4 +0,0 @@
 | 
				
			|||||||
export { default as Loading } from './Loading.svelte';
 | 
					 | 
				
			||||||
export { default as Degraded } from './Degraded.svelte';
 | 
					 | 
				
			||||||
export { default as Healthy } from './Healthy.svelte';
 | 
					 | 
				
			||||||
export { default as Stopped } from './Stopped.svelte';
 | 
					 | 
				
			||||||
@@ -1,60 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import type { PageData } from './$types';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let data: PageData;
 | 
					 | 
				
			||||||
	let application: any = data.application.data;
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	import { appSession, status, trpc } from '$lib/store';
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
					 | 
				
			||||||
	const { id } = $page.params;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let forceDelete = false;
 | 
					 | 
				
			||||||
	async function deleteApplication(name: string, force: boolean) {
 | 
					 | 
				
			||||||
		const sure = confirm('Are you sure you want to delete this application?');
 | 
					 | 
				
			||||||
		if (sure) {
 | 
					 | 
				
			||||||
			$status.application.initialLoading = true;
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				await trpc.applications.deleteApplication.mutate({ id, force });
 | 
					 | 
				
			||||||
				return await goto('/');
 | 
					 | 
				
			||||||
			} catch (error) {
 | 
					 | 
				
			||||||
				if (error.message.startsWith(`Command failed: SSH_AUTH_SOCK=/tmp/coolify-ssh-agent.pid`)) {
 | 
					 | 
				
			||||||
					forceDelete = true;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return errorNotification(error);
 | 
					 | 
				
			||||||
			} finally {
 | 
					 | 
				
			||||||
				$status.application.initialLoading = false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<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">Danger Zone</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{#if forceDelete}
 | 
					 | 
				
			||||||
		<button
 | 
					 | 
				
			||||||
			id="forcedelete"
 | 
					 | 
				
			||||||
			on:click={() => deleteApplication(application.name, true)}
 | 
					 | 
				
			||||||
			type="submit"
 | 
					 | 
				
			||||||
			disabled={!$appSession.isAdmin}
 | 
					 | 
				
			||||||
			class:bg-red-600={$appSession.isAdmin}
 | 
					 | 
				
			||||||
			class:hover:bg-red-500={$appSession.isAdmin}
 | 
					 | 
				
			||||||
			class="btn btn-lg btn-error hover:bg-red-700 text-sm w-64"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			Force Delete Application
 | 
					 | 
				
			||||||
		</button>
 | 
					 | 
				
			||||||
	{:else}
 | 
					 | 
				
			||||||
		<button
 | 
					 | 
				
			||||||
			id="delete"
 | 
					 | 
				
			||||||
			on:click={() => deleteApplication(application.name, false)}
 | 
					 | 
				
			||||||
			type="submit"
 | 
					 | 
				
			||||||
			disabled={!$appSession.isAdmin}
 | 
					 | 
				
			||||||
			class="btn btn-lg btn-error hover:bg-red-700 text-sm w-64"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			Delete Application
 | 
					 | 
				
			||||||
		</button>
 | 
					 | 
				
			||||||
	{/if}
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,118 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import type { PageParentData } from './$types';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let data: PageParentData;
 | 
					 | 
				
			||||||
	const application = data.application.data;
 | 
					 | 
				
			||||||
	const settings = data.settings.data;
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	const { id } = $page.params;
 | 
					 | 
				
			||||||
	import {
 | 
					 | 
				
			||||||
		addToast,
 | 
					 | 
				
			||||||
		appSession,
 | 
					 | 
				
			||||||
		checkIfDeploymentEnabledApplications,
 | 
					 | 
				
			||||||
		setLocation,
 | 
					 | 
				
			||||||
		status,
 | 
					 | 
				
			||||||
		isDeploymentEnabled,
 | 
					 | 
				
			||||||
		trpc
 | 
					 | 
				
			||||||
	} from '$lib/store';
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	import Setting from '$lib/components/Setting.svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	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 === '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 trpc.applications.saveSettings.mutate({
 | 
					 | 
				
			||||||
				id,
 | 
					 | 
				
			||||||
				previews,
 | 
					 | 
				
			||||||
				dualCerts,
 | 
					 | 
				
			||||||
				isBot,
 | 
					 | 
				
			||||||
				autodeploy,
 | 
					 | 
				
			||||||
				isDBBranching
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return addToast({
 | 
					 | 
				
			||||||
				message: 'Settings saved',
 | 
					 | 
				
			||||||
				type: 'success'
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			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="Enable Automatic Deployment"
 | 
					 | 
				
			||||||
						description="Enable automatic deployment through webhooks."
 | 
					 | 
				
			||||||
					/>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
				{#if !application.settings.isBot && !application.simpleDockerfile}
 | 
					 | 
				
			||||||
					<div class="grid grid-cols-2 items-center">
 | 
					 | 
				
			||||||
						<Setting
 | 
					 | 
				
			||||||
							id="previews"
 | 
					 | 
				
			||||||
							isCenter={false}
 | 
					 | 
				
			||||||
							bind:setting={previews}
 | 
					 | 
				
			||||||
							on:click={() => changeSettings('previews')}
 | 
					 | 
				
			||||||
							title="Enable MR/PR Previews"
 | 
					 | 
				
			||||||
							description="Enable preview deployments from pull or merge requests."
 | 
					 | 
				
			||||||
						/>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				{/if}
 | 
					 | 
				
			||||||
			{:else}
 | 
					 | 
				
			||||||
				No features available for this application
 | 
					 | 
				
			||||||
			{/if}
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,176 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
	import { onMount, onDestroy } from 'svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let application: any = {};
 | 
					 | 
				
			||||||
	let logsLoading = false;
 | 
					 | 
				
			||||||
	let loadLogsInterval: any = null;
 | 
					 | 
				
			||||||
	let logs: any = [];
 | 
					 | 
				
			||||||
	let lastLog: any = null;
 | 
					 | 
				
			||||||
	let followingInterval: any;
 | 
					 | 
				
			||||||
	let followingLogs: any;
 | 
					 | 
				
			||||||
	let logsEl: any;
 | 
					 | 
				
			||||||
	let position = 0;
 | 
					 | 
				
			||||||
	let services: any = [];
 | 
					 | 
				
			||||||
	let selectedService: any = null;
 | 
					 | 
				
			||||||
	let noContainer = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const { id } = $page.params;
 | 
					 | 
				
			||||||
	onMount(async () => {
 | 
					 | 
				
			||||||
		const { data } = await trpc.applications.getApplicationById.query({ id });
 | 
					 | 
				
			||||||
		application = data;
 | 
					 | 
				
			||||||
		if (application.dockerComposeFile && application.buildPack === 'compose') {
 | 
					 | 
				
			||||||
			services = normalizeDockerServices(JSON.parse(data.dockerComposeFile).services);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			services = [
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					name: ''
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			];
 | 
					 | 
				
			||||||
			await selectService('');
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	onDestroy(() => {
 | 
					 | 
				
			||||||
		clearInterval(loadLogsInterval);
 | 
					 | 
				
			||||||
		clearInterval(followingInterval);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	function normalizeDockerServices(services: any[]) {
 | 
					 | 
				
			||||||
		const tempdockerComposeServices = [];
 | 
					 | 
				
			||||||
		for (const [name, data] of Object.entries(services)) {
 | 
					 | 
				
			||||||
			tempdockerComposeServices.push({
 | 
					 | 
				
			||||||
				name,
 | 
					 | 
				
			||||||
				data
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return tempdockerComposeServices;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function loadLogs() {
 | 
					 | 
				
			||||||
		if (logsLoading) return;
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			const newLogs = await trpc.applications.loadLogs.query({
 | 
					 | 
				
			||||||
				id,
 | 
					 | 
				
			||||||
				containerId: selectedService,
 | 
					 | 
				
			||||||
				since: Number(lastLog?.split(' ')[0]) || 0
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (newLogs.noContainer) {
 | 
					 | 
				
			||||||
				noContainer = true;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				noContainer = false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (newLogs?.logs && newLogs.logs[newLogs.logs.length - 1] !== logs[logs.length - 1]) {
 | 
					 | 
				
			||||||
				logs = logs.concat(newLogs.logs);
 | 
					 | 
				
			||||||
				lastLog = newLogs.logs[newLogs.logs.length - 1];
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	function detect() {
 | 
					 | 
				
			||||||
		if (position < logsEl.scrollTop) {
 | 
					 | 
				
			||||||
			position = logsEl.scrollTop;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if (followingLogs) {
 | 
					 | 
				
			||||||
				clearInterval(followingInterval);
 | 
					 | 
				
			||||||
				followingLogs = false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			position = logsEl.scrollTop;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function followBuild() {
 | 
					 | 
				
			||||||
		followingLogs = !followingLogs;
 | 
					 | 
				
			||||||
		if (followingLogs) {
 | 
					 | 
				
			||||||
			followingInterval = setInterval(() => {
 | 
					 | 
				
			||||||
				logsEl.scrollTop = logsEl.scrollHeight;
 | 
					 | 
				
			||||||
				window.scrollTo(0, document.body.scrollHeight);
 | 
					 | 
				
			||||||
			}, 1000);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			clearInterval(followingInterval);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function selectService(service: any, init: boolean = false) {
 | 
					 | 
				
			||||||
		if (loadLogsInterval) clearInterval(loadLogsInterval);
 | 
					 | 
				
			||||||
		if (followingInterval) clearInterval(followingInterval);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		logs = [];
 | 
					 | 
				
			||||||
		lastLog = null;
 | 
					 | 
				
			||||||
		followingLogs = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		selectedService = `${application.id}${service.name ? `-${service.name}` : ''}`;
 | 
					 | 
				
			||||||
		loadLogs();
 | 
					 | 
				
			||||||
		loadLogsInterval = setInterval(() => {
 | 
					 | 
				
			||||||
			loadLogs();
 | 
					 | 
				
			||||||
		}, 1000);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<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">Application Logs</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<div class="flex gap-2 lg:gap-8 pb-4">
 | 
					 | 
				
			||||||
	{#each services as service}
 | 
					 | 
				
			||||||
		<button
 | 
					 | 
				
			||||||
			on:click={() => selectService(service, true)}
 | 
					 | 
				
			||||||
			class:bg-primary={selectedService ===
 | 
					 | 
				
			||||||
				`${application.id}${service.name ? `-${service.name}` : ''}`}
 | 
					 | 
				
			||||||
			class:bg-coolgray-200={selectedService !==
 | 
					 | 
				
			||||||
				`${application.id}${service.name ? `-${service.name}` : ''}`}
 | 
					 | 
				
			||||||
			class="w-full rounded p-5 hover:bg-primary font-bold"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			{application.id}{service.name ? `-${service.name}` : ''}</button
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
	{/each}
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if selectedService}
 | 
					 | 
				
			||||||
	<div class="flex flex-row justify-center space-x-2">
 | 
					 | 
				
			||||||
		{#if logs.length === 0}
 | 
					 | 
				
			||||||
			{#if noContainer}
 | 
					 | 
				
			||||||
				<div class="text-xl font-bold tracking-tighter">Container not found / exited.</div>
 | 
					 | 
				
			||||||
			{/if}
 | 
					 | 
				
			||||||
		{:else}
 | 
					 | 
				
			||||||
			<div class="relative w-full">
 | 
					 | 
				
			||||||
				<div class="flex justify-start sticky space-x-2 pb-2">
 | 
					 | 
				
			||||||
					<button on:click={followBuild} class="btn btn-sm " class:bg-coollabs={followingLogs}>
 | 
					 | 
				
			||||||
						<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"
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
							<path stroke="none" d="M0 0h24v24H0z" fill="none" />
 | 
					 | 
				
			||||||
							<circle cx="12" cy="12" r="9" />
 | 
					 | 
				
			||||||
							<line x1="8" y1="12" x2="12" y2="16" />
 | 
					 | 
				
			||||||
							<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>
 | 
					 | 
				
			||||||
					{#if loadLogsInterval}
 | 
					 | 
				
			||||||
						<button id="streaming" class="btn btn-sm bg-transparent border-none loading"
 | 
					 | 
				
			||||||
							>Streaming logs</button
 | 
					 | 
				
			||||||
						>
 | 
					 | 
				
			||||||
					{/if}
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
				<div
 | 
					 | 
				
			||||||
					bind:this={logsEl}
 | 
					 | 
				
			||||||
					on:scroll={detect}
 | 
					 | 
				
			||||||
					class="font-mono w-full bg-coolgray-100 border border-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}
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		{/if}
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
@@ -1,323 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import type { PageData } from './$types';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let data: PageData;
 | 
					 | 
				
			||||||
	let application: any = data.application.data;
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	import { goto } from '$app/navigation';
 | 
					 | 
				
			||||||
	import { asyncSleep, errorNotification, getRndInteger } from '$lib/common';
 | 
					 | 
				
			||||||
	import { onDestroy, onMount } from 'svelte';
 | 
					 | 
				
			||||||
	import { addToast, appSession, trpc } from '$lib/store';
 | 
					 | 
				
			||||||
	import Tooltip from '$lib/components/Tooltip.svelte';
 | 
					 | 
				
			||||||
	import * as Icons from '$lib/components/icons';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const { id } = $page.params;
 | 
					 | 
				
			||||||
	let loadBuildingStatusInterval: any = null;
 | 
					 | 
				
			||||||
	let loading = {
 | 
					 | 
				
			||||||
		init: true,
 | 
					 | 
				
			||||||
		restart: false,
 | 
					 | 
				
			||||||
		removing: false
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	let numberOfGetStatus = 0;
 | 
					 | 
				
			||||||
	let status: any = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	async function removeApplication(preview: any) {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			loading.removing = true;
 | 
					 | 
				
			||||||
			await trpc.applications.stopPreview.mutate({
 | 
					 | 
				
			||||||
				id,
 | 
					 | 
				
			||||||
				pullmergeRequestId: preview.pullmergeRequestId
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
			return window.location.reload();
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function redeploy(preview: any) {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			const { buildId } = await trpc.applications.deploy.mutate({
 | 
					 | 
				
			||||||
				id,
 | 
					 | 
				
			||||||
				pullmergeRequestId: preview.pullmergeRequestId,
 | 
					 | 
				
			||||||
				branch: preview.sourceBranch
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			addToast({
 | 
					 | 
				
			||||||
				message: 'Deployment queued.',
 | 
					 | 
				
			||||||
				type: 'success'
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
			if ($page.url.pathname.startsWith(`/applications/${id}/logs/build`)) {
 | 
					 | 
				
			||||||
				return window.location.assign(`/applications/${id}/logs/build?buildId=${buildId}`);
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				return await goto(`/applications/${id}/logs/build?buildId=${buildId}`, {
 | 
					 | 
				
			||||||
					replaceState: true
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function loadPreviewsFromDocker() {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			const { data } = await trpc.applications.loadPreviews.mutate({ id });
 | 
					 | 
				
			||||||
			application.previewApplication = data.previews;
 | 
					 | 
				
			||||||
			addToast({
 | 
					 | 
				
			||||||
				message: 'Previews loaded.',
 | 
					 | 
				
			||||||
				type: 'success'
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function getStatus(resources: any) {
 | 
					 | 
				
			||||||
		const { applicationId, pullmergeRequestId, id } = resources;
 | 
					 | 
				
			||||||
		if (status[id]) return status[id];
 | 
					 | 
				
			||||||
		while (numberOfGetStatus > 1) {
 | 
					 | 
				
			||||||
			await asyncSleep(getRndInteger(100, 200));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			numberOfGetStatus++;
 | 
					 | 
				
			||||||
			let isRunning = false;
 | 
					 | 
				
			||||||
			let isBuilding = false;
 | 
					 | 
				
			||||||
			const { data } = await trpc.applications.getPreviewStatus.query({
 | 
					 | 
				
			||||||
				id: applicationId,
 | 
					 | 
				
			||||||
				pullmergeRequestId
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			isRunning = data.isRunning;
 | 
					 | 
				
			||||||
			isBuilding = data.isBuilding;
 | 
					 | 
				
			||||||
			if (isBuilding) {
 | 
					 | 
				
			||||||
				status[id] = 'building';
 | 
					 | 
				
			||||||
				return 'building';
 | 
					 | 
				
			||||||
			} else if (isRunning) {
 | 
					 | 
				
			||||||
				status[id] = 'running';
 | 
					 | 
				
			||||||
				return 'running';
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				status[id] = 'stopped';
 | 
					 | 
				
			||||||
				return 'stopped';
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			status[id] = 'error';
 | 
					 | 
				
			||||||
			return 'error';
 | 
					 | 
				
			||||||
		} finally {
 | 
					 | 
				
			||||||
			numberOfGetStatus--;
 | 
					 | 
				
			||||||
			status = status;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function restartPreview(preview: any) {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			loading.restart = true;
 | 
					 | 
				
			||||||
			const { pullmergeRequestId } = preview;
 | 
					 | 
				
			||||||
			await trpc.applications.restartPreview.mutate({ id, pullmergeRequestId });
 | 
					 | 
				
			||||||
			addToast({
 | 
					 | 
				
			||||||
				type: 'success',
 | 
					 | 
				
			||||||
				message: 'Restart successful.'
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		} finally {
 | 
					 | 
				
			||||||
			await getStatus(preview);
 | 
					 | 
				
			||||||
			loading.restart = false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	onDestroy(() => {
 | 
					 | 
				
			||||||
		clearInterval(loadBuildingStatusInterval);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
	onMount(async () => {
 | 
					 | 
				
			||||||
		loadBuildingStatusInterval = setInterval(() => {
 | 
					 | 
				
			||||||
			application.previewApplication.forEach(async (preview: any) => {
 | 
					 | 
				
			||||||
				const { applicationId, pullmergeRequestId } = preview;
 | 
					 | 
				
			||||||
				if (status[preview.id] === 'building') {
 | 
					 | 
				
			||||||
					const { data } = await trpc.applications.getPreviewStatus.query({
 | 
					 | 
				
			||||||
						id: applicationId,
 | 
					 | 
				
			||||||
						pullmergeRequestId
 | 
					 | 
				
			||||||
					});
 | 
					 | 
				
			||||||
					if (data.isBuilding) {
 | 
					 | 
				
			||||||
						status[preview.id] = 'building';
 | 
					 | 
				
			||||||
					} else if (data.isRunning) {
 | 
					 | 
				
			||||||
						status[preview.id] = 'running';
 | 
					 | 
				
			||||||
						return 'running';
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						status[preview.id] = 'stopped';
 | 
					 | 
				
			||||||
						return 'stopped';
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}, 2000);
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			loading.init = true;
 | 
					 | 
				
			||||||
			loading.restart = true;
 | 
					 | 
				
			||||||
		} catch (error) {
 | 
					 | 
				
			||||||
			return errorNotification(error);
 | 
					 | 
				
			||||||
		} finally {
 | 
					 | 
				
			||||||
			loading.init = false;
 | 
					 | 
				
			||||||
			loading.restart = false;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
</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">Preview Deployments</div>
 | 
					 | 
				
			||||||
			<div class="text-center">
 | 
					 | 
				
			||||||
				<button class="btn btn-sm bg-coollabs" on:click={loadPreviewsFromDocker}
 | 
					 | 
				
			||||||
					>Load Previews</button
 | 
					 | 
				
			||||||
				>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{#if loading.init}
 | 
					 | 
				
			||||||
	<div class="px-6 pt-4">
 | 
					 | 
				
			||||||
		<div class="flex justify-center py-4 text-center text-xl font-bold">Loading...</div>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
{:else if application.previewApplication.length > 0}
 | 
					 | 
				
			||||||
	<div class="grid grid-col gap-4 auto-cols-max grid-cols-1 md:grid-cols-2 lg:grid-cols-2 px-6">
 | 
					 | 
				
			||||||
		{#each application.previewApplication as preview}
 | 
					 | 
				
			||||||
			<div class="no-underline mb-5 w-full">
 | 
					 | 
				
			||||||
				<div class="w-full rounded p-5 bg-coolgray-200 indicator">
 | 
					 | 
				
			||||||
					{#await getStatus(preview)}
 | 
					 | 
				
			||||||
						<span class="indicator-item badge bg-yellow-500 badge-sm" />
 | 
					 | 
				
			||||||
					{:then}
 | 
					 | 
				
			||||||
						{#if status[preview.id] === 'running'}
 | 
					 | 
				
			||||||
							<span class="indicator-item badge bg-success badge-sm" />
 | 
					 | 
				
			||||||
						{:else}
 | 
					 | 
				
			||||||
							<span class="indicator-item badge bg-error badge-sm" />
 | 
					 | 
				
			||||||
						{/if}
 | 
					 | 
				
			||||||
					{/await}
 | 
					 | 
				
			||||||
					<div class="w-full flex flex-row">
 | 
					 | 
				
			||||||
						<div class="w-full flex flex-col">
 | 
					 | 
				
			||||||
							<h1 class="font-bold text-lg lg:text-xl truncate">
 | 
					 | 
				
			||||||
								PR #{preview.pullmergeRequestId}
 | 
					 | 
				
			||||||
								{#if status[preview.id] === 'building'}
 | 
					 | 
				
			||||||
									<span
 | 
					 | 
				
			||||||
										class="badge badge-sm text-xs uppercase rounded bg-coolgray-300 text-green-500 border-none font-bold"
 | 
					 | 
				
			||||||
									>
 | 
					 | 
				
			||||||
										BUILDING
 | 
					 | 
				
			||||||
									</span>
 | 
					 | 
				
			||||||
								{/if}
 | 
					 | 
				
			||||||
							</h1>
 | 
					 | 
				
			||||||
							<div class="h-10 text-xs">
 | 
					 | 
				
			||||||
								<h2>{preview.customDomain.replace('https://', '').replace('http://', '')}</h2>
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							<div class="flex justify-end items-end space-x-2 h-10">
 | 
					 | 
				
			||||||
								{#if preview.customDomain}
 | 
					 | 
				
			||||||
									<a
 | 
					 | 
				
			||||||
										id="openpreview"
 | 
					 | 
				
			||||||
										href={preview.customDomain}
 | 
					 | 
				
			||||||
										target="_blank noreferrer"
 | 
					 | 
				
			||||||
										class="icons"
 | 
					 | 
				
			||||||
									>
 | 
					 | 
				
			||||||
										<svg
 | 
					 | 
				
			||||||
											xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
											class="h-6 w-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" />
 | 
					 | 
				
			||||||
											<path d="M11 7h-5a2 2 0 0 0 -2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2 -2v-5" />
 | 
					 | 
				
			||||||
											<line x1="10" y1="14" x2="20" y2="4" />
 | 
					 | 
				
			||||||
											<polyline points="15 4 20 4 20 9" />
 | 
					 | 
				
			||||||
										</svg>
 | 
					 | 
				
			||||||
									</a>
 | 
					 | 
				
			||||||
								{/if}
 | 
					 | 
				
			||||||
								<Tooltip triggeredBy="#openpreview">Open Preview</Tooltip>
 | 
					 | 
				
			||||||
								{#if loading.restart}
 | 
					 | 
				
			||||||
									<button
 | 
					 | 
				
			||||||
										class="icons flex animate-spin items-center space-x-2 bg-transparent text-sm duration-500 ease-in-out hover:bg-transparent"
 | 
					 | 
				
			||||||
									>
 | 
					 | 
				
			||||||
										<svg
 | 
					 | 
				
			||||||
											xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
											class="h-6 w-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" />
 | 
					 | 
				
			||||||
											<path d="M9 4.55a8 8 0 0 1 6 14.9m0 -4.45v5h5" />
 | 
					 | 
				
			||||||
											<line x1="5.63" y1="7.16" x2="5.63" y2="7.17" />
 | 
					 | 
				
			||||||
											<line x1="4.06" y1="11" x2="4.06" y2="11.01" />
 | 
					 | 
				
			||||||
											<line x1="4.63" y1="15.1" x2="4.63" y2="15.11" />
 | 
					 | 
				
			||||||
											<line x1="7.16" y1="18.37" x2="7.16" y2="18.38" />
 | 
					 | 
				
			||||||
											<line x1="11" y1="19.94" x2="11" y2="19.95" />
 | 
					 | 
				
			||||||
										</svg>
 | 
					 | 
				
			||||||
									</button>
 | 
					 | 
				
			||||||
								{:else}
 | 
					 | 
				
			||||||
									<button
 | 
					 | 
				
			||||||
										id="restart"
 | 
					 | 
				
			||||||
										disabled={!$appSession.isAdmin}
 | 
					 | 
				
			||||||
										on:click={() => restartPreview(preview)}
 | 
					 | 
				
			||||||
										type="submit"
 | 
					 | 
				
			||||||
										class="icons bg-transparent text-sm flex items-center space-x-2"
 | 
					 | 
				
			||||||
									>
 | 
					 | 
				
			||||||
										<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" />
 | 
					 | 
				
			||||||
											<path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" />
 | 
					 | 
				
			||||||
											<path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" />
 | 
					 | 
				
			||||||
										</svg>
 | 
					 | 
				
			||||||
									</button>
 | 
					 | 
				
			||||||
								{/if}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
								<Tooltip triggeredBy="#restart">Restart (useful to change secrets)</Tooltip>
 | 
					 | 
				
			||||||
								<button
 | 
					 | 
				
			||||||
									id="forceredeploypreview"
 | 
					 | 
				
			||||||
									class="icons"
 | 
					 | 
				
			||||||
									disabled={!$appSession.isAdmin}
 | 
					 | 
				
			||||||
									on:click={() => redeploy(preview)}
 | 
					 | 
				
			||||||
								>
 | 
					 | 
				
			||||||
									<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" />
 | 
					 | 
				
			||||||
										<path
 | 
					 | 
				
			||||||
											d="M16.3 5h.7a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h5l-2.82 -2.82m0 5.64l2.82 -2.82"
 | 
					 | 
				
			||||||
											transform="rotate(-45 12 12)"
 | 
					 | 
				
			||||||
										/>
 | 
					 | 
				
			||||||
									</svg></button
 | 
					 | 
				
			||||||
								>
 | 
					 | 
				
			||||||
								<Tooltip triggeredBy="#forceredeploypreview">Force redeploy (without cache)</Tooltip
 | 
					 | 
				
			||||||
								>
 | 
					 | 
				
			||||||
								<button
 | 
					 | 
				
			||||||
									id="deletepreview"
 | 
					 | 
				
			||||||
									class="icons"
 | 
					 | 
				
			||||||
									class:hover:text-error={!loading.removing}
 | 
					 | 
				
			||||||
									disabled={loading.removing || !$appSession.isAdmin}
 | 
					 | 
				
			||||||
									on:click={() => removeApplication(preview)}
 | 
					 | 
				
			||||||
									><Icons.Delete />
 | 
					 | 
				
			||||||
								</button>
 | 
					 | 
				
			||||||
								<Tooltip triggeredBy="#deletepreview">Delete Preview</Tooltip>
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				</div>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		{/each}
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
{:else}
 | 
					 | 
				
			||||||
	No previews found.
 | 
					 | 
				
			||||||
{/if}
 | 
					 | 
				
			||||||
@@ -1,151 +0,0 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					 | 
				
			||||||
	import type { PageData } from './$types';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	export let data: PageData;
 | 
					 | 
				
			||||||
	let application: any = data.application.data;
 | 
					 | 
				
			||||||
	let imagesAvailables: any = data.imagesAvailables;
 | 
					 | 
				
			||||||
	let runningImage: any = data.runningImage;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	import { page } from '$app/stores';
 | 
					 | 
				
			||||||
	import { status, addToast, trpc } from '$lib/store';
 | 
					 | 
				
			||||||
	import { errorNotification } from '$lib/common';
 | 
					 | 
				
			||||||
	import Explainer from '$lib/components/Explainer.svelte';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const { id } = $page.params;
 | 
					 | 
				
			||||||
	let remoteImage: any = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	async function revertToLocal(image: any) {
 | 
					 | 
				
			||||||
		const sure = confirm(`Are you sure you want to revert to ${image.tag} ?`);
 | 
					 | 
				
			||||||
		if (sure) {
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				$status.application.initialLoading = true;
 | 
					 | 
				
			||||||
				$status.application.loading = true;
 | 
					 | 
				
			||||||
				const imageId = `${image.repository}:${image.tag}`;
 | 
					 | 
				
			||||||
				await trpc.applications.restart.mutate({ id, imageId });
 | 
					 | 
				
			||||||
				// await post(`/applications/${id}/restart`, { imageId });
 | 
					 | 
				
			||||||
				addToast({
 | 
					 | 
				
			||||||
					type: 'success',
 | 
					 | 
				
			||||||
					message: 'Revert successful.'
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
			} catch (error) {
 | 
					 | 
				
			||||||
				return errorNotification(error);
 | 
					 | 
				
			||||||
			} finally {
 | 
					 | 
				
			||||||
				$status.application.initialLoading = false;
 | 
					 | 
				
			||||||
				$status.application.loading = false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	async function revertToRemote() {
 | 
					 | 
				
			||||||
		const sure = confirm(`Are you sure you want to revert to ${remoteImage} ?`);
 | 
					 | 
				
			||||||
		if (sure) {
 | 
					 | 
				
			||||||
			try {
 | 
					 | 
				
			||||||
				$status.application.initialLoading = true;
 | 
					 | 
				
			||||||
				$status.application.loading = true;
 | 
					 | 
				
			||||||
				$status.application.restarting = true;
 | 
					 | 
				
			||||||
				await trpc.applications.restart.mutate({ id, imageId: remoteImage });
 | 
					 | 
				
			||||||
				addToast({
 | 
					 | 
				
			||||||
					type: 'success',
 | 
					 | 
				
			||||||
					message: 'Revert successful.'
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
			} catch (error) {
 | 
					 | 
				
			||||||
				return errorNotification(error);
 | 
					 | 
				
			||||||
			} finally {
 | 
					 | 
				
			||||||
				$status.application.initialLoading = false;
 | 
					 | 
				
			||||||
				$status.application.loading = false;
 | 
					 | 
				
			||||||
				$status.application.restarting = false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
</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">
 | 
					 | 
				
			||||||
				Revert <Explainer
 | 
					 | 
				
			||||||
					position="dropdown-bottom"
 | 
					 | 
				
			||||||
					explanation="You can revert application to a previously built image. Currently only locally stored images
 | 
					 | 
				
			||||||
				supported."
 | 
					 | 
				
			||||||
				/>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<div class="pb-4 text-xs">
 | 
					 | 
				
			||||||
			If you do not want the next commit to overwrite the reverted application, temporary disable <span
 | 
					 | 
				
			||||||
				class="text-yellow-400 font-bold">Automatic Deployment</span
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
			feature <a href={`/applications/${id}/features`}>here</a>.
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		{#if imagesAvailables.length > 0}
 | 
					 | 
				
			||||||
			<div class="text-xl font-bold pb-3">Local Images</div>
 | 
					 | 
				
			||||||
			<div
 | 
					 | 
				
			||||||
				class="px-4 lg:pb-10 pb-6 flex flex-wrap items-center justify-center lg:justify-start gap-8"
 | 
					 | 
				
			||||||
			>
 | 
					 | 
				
			||||||
				{#each imagesAvailables as image}
 | 
					 | 
				
			||||||
					<div class="gap-2 py-4 m-2">
 | 
					 | 
				
			||||||
						<div class="flex flex-col justify-center items-center">
 | 
					 | 
				
			||||||
							<div class="text-xl font-bold">
 | 
					 | 
				
			||||||
								{image.tag}
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
							<div>
 | 
					 | 
				
			||||||
								<a
 | 
					 | 
				
			||||||
									class="flex no-underline text-xs my-4"
 | 
					 | 
				
			||||||
									href="{application.gitSource.htmlUrl}/{application.repository}/commit/{image.tag}"
 | 
					 | 
				
			||||||
									target="_blank noreferrer"
 | 
					 | 
				
			||||||
								>
 | 
					 | 
				
			||||||
									<button class="btn btn-sm">
 | 
					 | 
				
			||||||
										Check Commit
 | 
					 | 
				
			||||||
										<svg
 | 
					 | 
				
			||||||
											xmlns="http://www.w3.org/2000/svg"
 | 
					 | 
				
			||||||
											fill="currentColor"
 | 
					 | 
				
			||||||
											viewBox="0 0 24 24"
 | 
					 | 
				
			||||||
											stroke-width="3"
 | 
					 | 
				
			||||||
											stroke="currentColor"
 | 
					 | 
				
			||||||
											class="w-3 h-3 text-white ml-2"
 | 
					 | 
				
			||||||
										>
 | 
					 | 
				
			||||||
											<path
 | 
					 | 
				
			||||||
												stroke-linecap="round"
 | 
					 | 
				
			||||||
												stroke-linejoin="round"
 | 
					 | 
				
			||||||
												d="M4.5 19.5l15-15m0 0H8.25m11.25 0v11.25"
 | 
					 | 
				
			||||||
											/>
 | 
					 | 
				
			||||||
										</svg>
 | 
					 | 
				
			||||||
									</button></a
 | 
					 | 
				
			||||||
								>
 | 
					 | 
				
			||||||
								{#if image.repository + ':' + image.tag !== runningImage}
 | 
					 | 
				
			||||||
									<button
 | 
					 | 
				
			||||||
										class="btn btn-sm btn-primary w-full"
 | 
					 | 
				
			||||||
										on:click={() => revertToLocal(image)}>Revert Now</button
 | 
					 | 
				
			||||||
									>
 | 
					 | 
				
			||||||
								{:else}
 | 
					 | 
				
			||||||
									<button
 | 
					 | 
				
			||||||
										class="btn btn-sm btn-primary w-full btn-disabled bg-transparent underline"
 | 
					 | 
				
			||||||
										>Currently Used</button
 | 
					 | 
				
			||||||
									>
 | 
					 | 
				
			||||||
								{/if}
 | 
					 | 
				
			||||||
							</div>
 | 
					 | 
				
			||||||
						</div>
 | 
					 | 
				
			||||||
					</div>
 | 
					 | 
				
			||||||
				{/each}
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		{:else}
 | 
					 | 
				
			||||||
			<div class="flex flex-col pb-10">
 | 
					 | 
				
			||||||
				<div class="text-xl font-bold">No Local images available</div>
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		{/if}
 | 
					 | 
				
			||||||
		<div class="text-xl font-bold pb-3">
 | 
					 | 
				
			||||||
			Remote Images (Docker Registry) <Explainer
 | 
					 | 
				
			||||||
				position="dropdown-bottom"
 | 
					 | 
				
			||||||
				explanation="If the image is not available or you are unauthorized to access it, you will not be able to revert to it."
 | 
					 | 
				
			||||||
			/>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<form on:submit|preventDefault={revertToRemote}>
 | 
					 | 
				
			||||||
			<input
 | 
					 | 
				
			||||||
				id="dockerImage"
 | 
					 | 
				
			||||||
				name="dockerImage"
 | 
					 | 
				
			||||||
				required
 | 
					 | 
				
			||||||
				placeholder="coollabsio/coolify:0.0.1"
 | 
					 | 
				
			||||||
				bind:value={remoteImage}
 | 
					 | 
				
			||||||
			/>
 | 
					 | 
				
			||||||
			<button class="btn btn-sm btn-primary" type="submit">Revert Now</button>
 | 
					 | 
				
			||||||
		</form>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1,16 +0,0 @@
 | 
				
			|||||||
import { error } from '@sveltejs/kit';
 | 
					 | 
				
			||||||
import { trpc } from '$lib/store';
 | 
					 | 
				
			||||||
import type { PageLoad } from './$types';
 | 
					 | 
				
			||||||
export const ssr = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const load: PageLoad = async ({ params }) => {
 | 
					 | 
				
			||||||
	try {
 | 
					 | 
				
			||||||
		const { id } = params;
 | 
					 | 
				
			||||||
		const { data } = await trpc.applications.getLocalImages.query({ id });
 | 
					 | 
				
			||||||
		return data;
 | 
					 | 
				
			||||||
	} catch (err) {
 | 
					 | 
				
			||||||
		throw error(500, {
 | 
					 | 
				
			||||||
			message: 'An unexpected error occurred, please try again later.'
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user