diff --git a/.tool-versions b/.tool-versions index 8505c76c..f4132be9 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -bun 1.1.42 -nodejs 22.12.0 +bun 1.2.2 +nodejs 22.14.0 diff --git a/bun.lockb b/bun.lockb index e3297d31..356de890 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 01b944a0..38177352 100644 --- a/package.json +++ b/package.json @@ -12,27 +12,27 @@ "lint": "eslint ." }, "devDependencies": { - "@nomimono/nomimono-css": "^0.4.25", - "@sveltejs/adapter-cloudflare": "^4.9.0", - "@sveltejs/adapter-node": "^5.2.11", - "@sveltejs/kit": "=2.11.1", - "@typescript-eslint/eslint-plugin": "^8.18.0", - "@typescript-eslint/parser": "^8.18.0", + "@nomimono/nomimono-css": "^0.6.0", + "@sveltejs/adapter-cloudflare": "^5.0.2", + "@sveltejs/adapter-node": "^5.2.12", + "@sveltejs/kit": "=2.17.1", + "@typescript-eslint/eslint-plugin": "^8.24.0", + "@typescript-eslint/parser": "^8.24.0", "clipboard": "^2.0.11", "dayjs": "^1.11.13", - "eslint": "^9.17.0", + "eslint": "^9.20.1", "eslint-plugin-svelte": "^2.46.1", "global": "^4.4.0", "gravatar-url": "^4.0.1", - "highcharts": "^11.4.8", + "highcharts": "=11.4.8", "js-cookie": "^3.0.5", - "sass": "^1.83.0", - "svelte": "^4.2.19", - "svelte-check": "^4.1.1", + "sass": "^1.84.0", + "svelte": "^5.19.10", + "svelte-check": "^4.1.4", "svelte-eslint-parser": "^0.43.0", "svelte-preprocess": "^6.0.3", - "sweetalert2": "^11.14.5", - "typescript": "~5.7.2", + "sweetalert2": "^11.16.0", + "typescript": "~5.7.3", "valid-url": "^1.0.9" }, "type": "module" diff --git a/src/global.d.ts b/src/global.d.ts deleted file mode 100644 index 92ebb190..00000000 --- a/src/global.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare module 'svelte/elements' { - export interface SvelteWindowAttributes { - 'on:sidebar:toggle'?: () => void - } -} - -export {} diff --git a/src/lib/components/Chart.svelte b/src/lib/components/Chart.svelte index dfe82cad..5a9d5896 100644 --- a/src/lib/components/Chart.svelte +++ b/src/lib/components/Chart.svelte @@ -4,23 +4,27 @@ import * as hc from '$lib/hc' import { browser } from '$app/environment' - /** @type {string} */ - export let title - - /** @type {string} */ - export let unit - /** @typedef {Object} Series */ /** @property {string} prefix */ /** @property {Array} lines */ /** @property {string?} dashStyle */ /** @property {string?} color */ - /** @type {Series[]} */ - export let series - - /** @type {'line' | 'spline'} */ - export let type = 'line' + /** + * @typedef {Object} Props + * @property {string} title + * @property {string} unit + * @property {Series[]} series + * @property {'line' | 'spline'} [type] + */ + + /** @type {Props} */ + const { + title, + unit, + series, + type = 'line' + } = $props() /** @type {HTMLDivElement} */ let el @@ -53,13 +57,6 @@ } }) - $: { - if (series?.length === 0) clear() - series?.forEach((s) => { - update(s.prefix, s.lines, s.dashStyle, s.color) - }) - chart?.redraw() - } function update (name, lines, dashStyle, color) { if (!browser || !chart) return @@ -108,6 +105,14 @@ } return v } + + $effect(() => { + if (series?.length === 0) clear() + series?.forEach((s) => { + update(s.prefix, s.lines, s.dashStyle, s.color) + }) + chart?.redraw() + })
diff --git a/src/lib/components/DeploymentStatusIcon.svelte b/src/lib/components/DeploymentStatusIcon.svelte index feed8b6a..901c00eb 100644 --- a/src/lib/components/DeploymentStatusIcon.svelte +++ b/src/lib/components/DeploymentStatusIcon.svelte @@ -2,17 +2,21 @@ import { browser } from '$app/environment' import { onDestroy } from 'svelte' - /** @type {Api.DeploymentAction} */ - export let action - - /** @type {Api.DeploymentStatus} */ - export let status - - /** @type {string} */ - export let url + /** + * @typedef {Object} Props + * @property {Api.DeploymentAction} action + * @property {Api.DeploymentStatus} status + * @property {string} url + * @property {Api.DeploymentType} type + */ - /** @type {Api.DeploymentType} */ - export let type + /** @type {Props} */ + const { + action, + status, + url, + type + } = $props() const statusIconClass = { pending: 'fa-solid fa-spinner-third fa-spin', @@ -22,21 +26,10 @@ } /** @type {Api.PodStatus | null} */ - let podStatus + let podStatus = $state(null) /** @type {string} */ - let iconClass - - $: { - status - url - action - browser && fetchPodStatus() - } - $: { - podStatus - iconClass = getIconClass() - } + let iconClass = $state('') /** * @returns {string} @@ -93,6 +86,16 @@ destroyed = true fetchPodStatusTimeout && clearTimeout(fetchPodStatusTimeout) }) + $effect(() => { + status + url + action + browser && fetchPodStatus() + }) + $effect(() => { + podStatus + iconClass = getIconClass() + }) diff --git a/src/lib/components/ErrorRow.svelte b/src/lib/components/ErrorRow.svelte index 321292d7..a7ef4d2b 100644 --- a/src/lib/components/ErrorRow.svelte +++ b/src/lib/components/ErrorRow.svelte @@ -1,16 +1,24 @@ {#if error} - - {#if error.forbidden} - You don't have permission to view data - {:else if error.message} - {error.message} - {:else} - {error} - {/if} - + + + {#if error.forbidden} + You don't have permission to view data + {:else if error.message} + {error.message} + {:else} + {error} + {/if} + + {/if} diff --git a/src/lib/components/LoadingRow.svelte b/src/lib/components/LoadingRow.svelte index c1d9e5aa..762fc1e2 100644 --- a/src/lib/components/LoadingRow.svelte +++ b/src/lib/components/LoadingRow.svelte @@ -1,5 +1,11 @@ diff --git a/src/lib/components/NoDataRow.svelte b/src/lib/components/NoDataRow.svelte index c6b15d5f..d66c9248 100644 --- a/src/lib/components/NoDataRow.svelte +++ b/src/lib/components/NoDataRow.svelte @@ -1,10 +1,18 @@ {#if !list?.length} - - No data - + + + No data + + {/if} diff --git a/src/lib/components/Secret.svelte b/src/lib/components/Secret.svelte index 2d1c1888..8a577add 100644 --- a/src/lib/components/Secret.svelte +++ b/src/lib/components/Secret.svelte @@ -1,8 +1,14 @@ -
+
{#if isHidden} {:else} diff --git a/src/lib/components/StatusIcon.svelte b/src/lib/components/StatusIcon.svelte index d5b1c1f3..c8dd6146 100644 --- a/src/lib/components/StatusIcon.svelte +++ b/src/lib/components/StatusIcon.svelte @@ -1,6 +1,12 @@ diff --git a/src/routes/(auth)/(project)/+layout.svelte b/src/routes/(auth)/(project)/+layout.svelte index be519e83..e15becd8 100644 --- a/src/routes/(auth)/(project)/+layout.svelte +++ b/src/routes/(auth)/(project)/+layout.svelte @@ -2,7 +2,7 @@ import Cookie from 'js-cookie' import { onMount } from 'svelte' - export let data + const { data, children } = $props() const project = data.project @@ -11,4 +11,4 @@ }) - +{@render children?.()} diff --git a/src/routes/(auth)/(project)/+page.svelte b/src/routes/(auth)/(project)/+page.svelte index 3b37f811..9302fe80 100644 --- a/src/routes/(auth)/(project)/+page.svelte +++ b/src/routes/(auth)/(project)/+page.svelte @@ -2,22 +2,11 @@ import { onMount } from 'svelte' import api from '$lib/api' - export let data + const { data } = $props() - $: projectInfo = data.projectInfo - $: usage = data.usage - $: price = data.price const unitGiB = 1024 * 1024 * 1024 - $: billing = { - price: formatNumber(price.price), - cpu: formatNumber(usage.cpuUsage), - memory: formatNumber(usage.memory / unitGiB), - egress: formatNumber(usage.egress / unitGiB), - disk: formatNumber(usage.disk / unitGiB), - replica: formatNumber(usage.replica) - } onMount(() => { const interval = setInterval(() => { @@ -32,6 +21,17 @@ if (Number.isNaN(v)) return '?' return v?.toLocaleString(undefined, { maximumFractionDigits: 2 }) ?? '?' } + const projectInfo = $derived(data.projectInfo) + const usage = $derived(data.usage) + const price = $derived(data.price) + const billing = $derived({ + price: formatNumber(price.price), + cpu: formatNumber(usage.cpuUsage), + memory: formatNumber(usage.memory / unitGiB), + egress: formatNumber(usage.egress / unitGiB), + disk: formatNumber(usage.disk / unitGiB), + replica: formatNumber(usage.replica) + })
Dashboard
diff --git a/src/routes/(auth)/(project)/deployment/(detail)/+layout.svelte b/src/routes/(auth)/(project)/deployment/(detail)/+layout.svelte index c3643b9a..e312dcf9 100644 --- a/src/routes/(auth)/(project)/deployment/(detail)/+layout.svelte +++ b/src/routes/(auth)/(project)/deployment/(detail)/+layout.svelte @@ -3,10 +3,10 @@ import { onMount } from 'svelte' import api from '$lib/api' - export let data + const { data, children } = $props() - $: project = data.project - $: deployment = data.deployment + const project = $derived(data.project) + const deployment = $derived(data.deployment) let lastReload = Date.now() @@ -31,7 +31,7 @@
-
api.invalidate('deployment.get')} /> +
api.invalidate('deployment.get')} /> - + {@render children?.()}
diff --git a/src/routes/(auth)/(project)/deployment/(detail)/detail/+page.svelte b/src/routes/(auth)/(project)/deployment/(detail)/detail/+page.svelte index 09d5ea53..0e470f25 100644 --- a/src/routes/(auth)/(project)/deployment/(detail)/detail/+page.svelte +++ b/src/routes/(auth)/(project)/deployment/(detail)/detail/+page.svelte @@ -8,13 +8,13 @@ import Secret from '$lib/components/Secret.svelte' import NoDataRow from '$lib/components/NoDataRow.svelte' - export let data + const { data } = $props() - $: deployment = data.deployment - $: location = data.location + const deployment = $derived(data.deployment) + const location = $derived(data.location) - $: hasExternalTCPAddress = ['TCPService'].includes(deployment.type) - $: hasInternalTCPAddress = ['WebService', 'TCPService', 'InternalTCPService'].includes(deployment.type) + const hasExternalTCPAddress = $derived(['TCPService'].includes(deployment.type)) + const hasInternalTCPAddress = $derived(['WebService', 'TCPService', 'InternalTCPService'].includes(deployment.type)) onMount(() => { const copyList = new ClipboardJS('.copy') @@ -46,172 +46,174 @@
Deployment details
- {#if deployment.type === 'WebService'} - {#if !deployment.internal} + + {#if deployment.type === 'WebService'} + {#if !deployment.internal} + + + + + {/if} + + + + + {/if} + {#if hasExternalTCPAddress} + + + + + {/if} + {#if hasInternalTCPAddress} - + {/if} - + - {/if} - {#if hasExternalTCPAddress} - - - - - {/if} - {#if hasInternalTCPAddress} - + - {/if} - - - - - - - - - - - - - {#if deployment.type === 'WebService'} - - - - - {:else if deployment.type === 'TCPService'} - - + + - {/if} - {#if location.features.disk} + {#if deployment.type === 'WebService'} + + + + + {:else if deployment.type === 'TCPService'} + + + + + {/if} + {#if location.features.disk} + + + + + {/if} + {#if deployment.minReplicas > 0} - + - {/if} - {#if deployment.minReplicas > 0} - - - - - {/if} - {#if deployment.type === 'CronJob'} + {/if} + {#if deployment.type === 'CronJob'} + + + + + {/if} - - + + - {/if} - - - - - - - - - - - - - {#if location.features.workloadIdentity} - - + + - {/if} - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + {#if location.features.workloadIdentity} + + + + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
URL + + {`https://${deployment.url}`} + + + + +
Internal URL + http://{deployment.internalUrl} + + + +
Address{deployment.address}:{deployment.nodePort}
URLInternal Address - - {`https://${deployment.url}`} - - + {deployment.internalAddress}:{deployment.port} +
Internal URLType - http://{deployment.internalUrl} - - - + {format.deploymentType(deployment.type)} + {#if deployment.internal} + (Internal) + {/if}
Address{deployment.address}:{deployment.nodePort}
Internal AddressLocation - {deployment.internalAddress}:{deployment.port} - + {deployment.location} +
Type - {format.deploymentType(deployment.type)} - {#if deployment.internal} - (Internal) - {/if} -
Location - {deployment.location} - - - -
Image - {deployment.image} - - - -
Port{deployment.port}{deployment.protocol ? `:${deployment.protocol}` : ''}
Port{deployment.port}:{deployment.nodePort}Image + {deployment.image} + + + +
Port{deployment.port}{deployment.protocol ? `:${deployment.protocol}` : ''}
Port{deployment.port}:{deployment.nodePort}
Disk + {#if deployment.disk} + {deployment.disk.name} + (mount: {deployment.disk.mountPath || '-'}, sub: {deployment.disk.subPath || '-'}) + {:else} + - + {/if} +
DiskReplicas - {#if deployment.disk} - {deployment.disk.name} - (mount: {deployment.disk.mountPath || '-'}, sub: {deployment.disk.subPath || '-'}) + {#if deployment.minReplicas > 0} + {#if deployment.minReplicas === deployment.maxReplicas} + {deployment.minReplicas} + {:else} + {deployment.minReplicas} - {deployment.maxReplicas} + {/if} {:else} - {/if}
Replicas - {#if deployment.minReplicas > 0} - {#if deployment.minReplicas === deployment.maxReplicas} - {deployment.minReplicas} - {:else} - {deployment.minReplicas} - {deployment.maxReplicas} - {/if} - {:else} - - - {/if} -
Schedule{deployment.schedule}
Schedule{deployment.schedule}Command{deployment.command.join(' ') || '-'}
Command{deployment.command.join(' ') || '-'}
Args{deployment.args.join(' ') || '-'}
Pull Secret{deployment.pullSecret || '-'}
Workload Identity{deployment.workloadIdentity || '-'}Args{deployment.args.join(' ') || '-'}
CPU limited{format.cpuLimited(deployment.resources.limits.cpu)}
Memory allocated{format.memory(deployment.resources.requests.memory)}
Sidecars{deployment.sidecars?.length || 0}
Deployed At{format.datetime(deployment.createdAt)}
Deployed By{deployment.createdBy}
Allocated Price{deployment.allocatedPrice.toLocaleString(undefined, { maximumFractionDigits: 2 })} THB/month/replica
Pull Secret{deployment.pullSecret || '-'}
Workload Identity{deployment.workloadIdentity || '-'}
CPU limited{format.cpuLimited(deployment.resources.limits.cpu)}
Memory allocated{format.memory(deployment.resources.requests.memory)}
Sidecars{deployment.sidecars?.length || 0}
Deployed At{format.datetime(deployment.createdAt)}
Deployed By{deployment.createdBy}
Allocated Price{deployment.allocatedPrice.toLocaleString(undefined, { maximumFractionDigits: 2 })} THB/month/replica
- +
diff --git a/src/routes/(auth)/(project)/deployment/(detail)/events/+page.svelte b/src/routes/(auth)/(project)/deployment/(detail)/events/+page.svelte index e326908c..a8ea7849 100644 --- a/src/routes/(auth)/(project)/deployment/(detail)/events/+page.svelte +++ b/src/routes/(auth)/(project)/deployment/(detail)/events/+page.svelte @@ -3,11 +3,11 @@ import * as format from '$lib/format' import NoDataRow from '$lib/components/NoDataRow.svelte' - export let data + const { data } = $props() - $: deployment = data.deployment + const deployment = $derived(data.deployment) - let events = [] + let events = $state([]) onMount(() => { reloadEvents() diff --git a/src/routes/(auth)/(project)/deployment/(detail)/logs/+page.svelte b/src/routes/(auth)/(project)/deployment/(detail)/logs/+page.svelte index f5065fe7..fec953b2 100644 --- a/src/routes/(auth)/(project)/deployment/(detail)/logs/+page.svelte +++ b/src/routes/(auth)/(project)/deployment/(detail)/logs/+page.svelte @@ -1,12 +1,12 @@
Deployments
diff --git a/src/routes/(auth)/(project)/deployment/_components/Header.svelte b/src/routes/(auth)/(project)/deployment/_components/Header.svelte index 38f9faed..bec78f19 100644 --- a/src/routes/(auth)/(project)/deployment/_components/Header.svelte +++ b/src/routes/(auth)/(project)/deployment/_components/Header.svelte @@ -1,18 +1,22 @@
Disks
@@ -46,7 +46,7 @@ {it.location} {format.datetime(it.createdAt)} - +
diff --git a/src/routes/(auth)/(project)/disk/create/+page.svelte b/src/routes/(auth)/(project)/disk/create/+page.svelte index 6dede681..696b82e9 100644 --- a/src/routes/(auth)/(project)/disk/create/+page.svelte +++ b/src/routes/(auth)/(project)/disk/create/+page.svelte @@ -3,7 +3,7 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() const { locations, location, @@ -11,16 +11,22 @@ disk } = data - $: project = data.project + const project = $derived(data.project) - const form = { + const form = $state({ location: location || '', name: name || '', size: disk?.size || 1 - } + }) + + let saving = $state(false) + + /** + * @param {Event} e + */ + async function save (e) { + e.preventDefault() - let saving = false - async function save () { if (saving) { return } @@ -78,7 +84,7 @@
-
+
diff --git a/src/routes/(auth)/(project)/domain/+page.svelte b/src/routes/(auth)/(project)/domain/+page.svelte index 5a05070c..bc5f6cfa 100644 --- a/src/routes/(auth)/(project)/domain/+page.svelte +++ b/src/routes/(auth)/(project)/domain/+page.svelte @@ -5,11 +5,11 @@ import api from '$lib/api' import ErrorRow from '$lib/components/ErrorRow.svelte' - export let data + const { data } = $props() - $: project = data.project - $: domains = data.domains - $: error = data.error + const project = $derived(data.project) + const domains = $derived(data.domains) + const error = $derived(data.error) function deleteDomain (domain) { modal.confirm({ @@ -79,7 +79,7 @@ - diff --git a/src/routes/(auth)/(project)/domain/create/+page.svelte b/src/routes/(auth)/(project)/domain/create/+page.svelte index a2f11257..7d36a4c8 100644 --- a/src/routes/(auth)/(project)/domain/create/+page.svelte +++ b/src/routes/(auth)/(project)/domain/create/+page.svelte @@ -3,22 +3,28 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() const { project, locations, projectInfo } = data - const form = { + const form = $state({ domain: '', location: '', cdn: false, wildcard: false - } + }) + + let saving = $state(false) + + /** + * @param {Event} e + */ + async function save (e) { + e.preventDefault() - let saving = false - async function save () { if (saving) { return } @@ -61,7 +67,7 @@

- +
diff --git a/src/routes/(auth)/(project)/domain/detail/+page.svelte b/src/routes/(auth)/(project)/domain/detail/+page.svelte index ac9c9eb8..5b4173b0 100644 --- a/src/routes/(auth)/(project)/domain/detail/+page.svelte +++ b/src/routes/(auth)/(project)/domain/detail/+page.svelte @@ -7,10 +7,10 @@ import api from '$lib/api' import Swal from 'sweetalert2' - export let data + const { data } = $props() - $: project = data.project - $: domain = data.domain + const project = $derived(data.project) + const domain = $derived(data.domain) onMount(() => { const copyList = new ClipboardJS('.copy') @@ -42,7 +42,7 @@ setTimeout(f, 3000) } - let purging = false + let purging = $state(false) async function purgeCache () { if (domain.wildcard) { return // not supported @@ -403,7 +403,7 @@
Purge everything

Remove all cached resources

-
@@ -413,7 +413,7 @@
Purge prefix

Remove cached resources at prefix path

-
@@ -423,7 +423,7 @@
Purge file

Remove cached resources at exact path

- @@ -435,13 +435,13 @@ {#if !domain.cdn}
- +
{/if}
-
diff --git a/src/routes/(auth)/(project)/dropbox/+page.svelte b/src/routes/(auth)/(project)/dropbox/+page.svelte index e51b8baa..55127c84 100644 --- a/src/routes/(auth)/(project)/dropbox/+page.svelte +++ b/src/routes/(auth)/(project)/dropbox/+page.svelte @@ -1,15 +1,20 @@
Emails
diff --git a/src/routes/(auth)/(project)/pull-secret/+page.svelte b/src/routes/(auth)/(project)/pull-secret/+page.svelte index b6a58dc9..af13592b 100644 --- a/src/routes/(auth)/(project)/pull-secret/+page.svelte +++ b/src/routes/(auth)/(project)/pull-secret/+page.svelte @@ -4,11 +4,11 @@ import * as format from '$lib/format' import ErrorRow from '$lib/components/ErrorRow.svelte' - export let data + const { data } = $props() - $: project = data.project - $: pullSecrets = data.pullSecrets - $: error = data.error + const project = $derived(data.project) + const pullSecrets = $derived(data.pullSecrets) + const error = $derived(data.error)
Pull Secrets
diff --git a/src/routes/(auth)/(project)/pull-secret/create/+page.svelte b/src/routes/(auth)/(project)/pull-secret/create/+page.svelte index 8326805a..0a099057 100644 --- a/src/routes/(auth)/(project)/pull-secret/create/+page.svelte +++ b/src/routes/(auth)/(project)/pull-secret/create/+page.svelte @@ -4,21 +4,27 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() - $: project = data.project + const project = $derived(data.project) const locations = data.locations - const form = { + const form = $state({ name: '', location: '', server: 'https://index.docker.io/v2/', username: '', password: '' - } + }) + + let saving = $state(false) + + /** + * @param {Event} e + */ + async function save (e) { + e.preventDefault() - let saving = false - async function save () { if (saving) { return } @@ -71,7 +77,7 @@
- +
diff --git a/src/routes/(auth)/(project)/pull-secret/detail/+page.svelte b/src/routes/(auth)/(project)/pull-secret/detail/+page.svelte index 60a64978..73c622e5 100644 --- a/src/routes/(auth)/(project)/pull-secret/detail/+page.svelte +++ b/src/routes/(auth)/(project)/pull-secret/detail/+page.svelte @@ -5,12 +5,12 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() - $: project = data.project - $: location = data.location - $: name = data.name - $: pullSecret = data.pullSecret + const project = $derived(data.project) + const location = $derived(data.location) + const name = $derived(data.name) + const pullSecret = $derived(data.pullSecret) onMount(() => { const copyList = new ClipboardJS('.copy') @@ -99,7 +99,7 @@
- +
diff --git a/src/routes/(auth)/(project)/registry/+page.svelte b/src/routes/(auth)/(project)/registry/+page.svelte index 4f7e6fe5..679fb6c2 100644 --- a/src/routes/(auth)/(project)/registry/+page.svelte +++ b/src/routes/(auth)/(project)/registry/+page.svelte @@ -2,11 +2,11 @@ import ErrorRow from '$lib/components/ErrorRow.svelte' import NoDataRow from '$lib/components/NoDataRow.svelte' - export let data + const { data } = $props() - $: project = data.project - $: repositories = data.repositories - $: error = data.error + const project = $derived(data.project) + const repositories = $derived(data.repositories) + const error = $derived(data.error)
Registry (Alpha)
diff --git a/src/routes/(auth)/(project)/registry/detail/+page.svelte b/src/routes/(auth)/(project)/registry/detail/+page.svelte index 33d53a6e..7d3e2958 100644 --- a/src/routes/(auth)/(project)/registry/detail/+page.svelte +++ b/src/routes/(auth)/(project)/registry/detail/+page.svelte @@ -5,12 +5,12 @@ import ErrorRow from '$lib/components/ErrorRow.svelte' import NoDataRow from '$lib/components/NoDataRow.svelte' - export let data + const { data } = $props() - $: project = data.project - $: repository = data.repository - $: tags = data.tags - $: error = data.error + const project = $derived(data.project) + const repository = $derived(data.repository) + const tags = $derived(data.tags) + const error = $derived(data.error) onMount(() => { const copyList = new ClipboardJS('.copy') diff --git a/src/routes/(auth)/(project)/role/+page.svelte b/src/routes/(auth)/(project)/role/+page.svelte index 838568a7..c48c6480 100644 --- a/src/routes/(auth)/(project)/role/+page.svelte +++ b/src/routes/(auth)/(project)/role/+page.svelte @@ -3,11 +3,11 @@ import * as format from '$lib/format' import ErrorRow from '$lib/components/ErrorRow.svelte' - export let data + const { data } = $props() - $: project = data.project - $: roles = data.roles - $: error = data.error + const project = $derived(data.project) + const roles = $derived(data.roles) + const error = $derived(data.error) /** * @param {string} sid @@ -56,7 +56,7 @@ {it.createdBy} {#if roleCanUpdate(it.role)} -
+
diff --git a/src/routes/(auth)/(project)/role/bind/+page.svelte b/src/routes/(auth)/(project)/role/bind/+page.svelte index 7a1a9433..65407c2f 100644 --- a/src/routes/(auth)/(project)/role/bind/+page.svelte +++ b/src/routes/(auth)/(project)/role/bind/+page.svelte @@ -4,19 +4,19 @@ import api from '$lib/api' import NoDataRow from '$lib/components/NoDataRow.svelte' - export let data + const { data } = $props() const { roles, email, selected } = data - $: project = data.project + const project = $derived(data.project) - const form = { + const form = $state({ email, roles: selected - } + }) function addRole (role) { if (!role || form.roles.includes(role)) { @@ -35,9 +35,14 @@ e.target.value = '' } - let saving = false + let saving = $state(false) + + /** + * @param {Event} e + */ + async function save (e) { + e.preventDefault() - async function save () { if (saving) { return } @@ -79,7 +84,7 @@
- +
@@ -87,7 +92,7 @@
- {#each roles as it} {#if !form.roles.includes(it.role)} @@ -112,7 +117,7 @@ {it}
removeRole(it)} on:keypress={() => removeRole(it)}> + onclick={() => removeRole(it)} onkeypress={() => removeRole(it)}>
diff --git a/src/routes/(auth)/(project)/role/create/+page.svelte b/src/routes/(auth)/(project)/role/create/+page.svelte index 43b4abe8..d521c455 100644 --- a/src/routes/(auth)/(project)/role/create/+page.svelte +++ b/src/routes/(auth)/(project)/role/create/+page.svelte @@ -4,19 +4,19 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() const { role, permissions } = data - $: project = data.project + const project = $derived(data.project) - const form = { + const form = $state({ role: role?.role ?? '', name: role?.name ?? '', permissions: role?.permissions ?? [] - } + }) function deleteItem () { if (!role) return @@ -57,8 +57,14 @@ form.permissions = form.permissions.filter((x) => x !== permission) } - let saving = false - async function save () { + let saving = $state(false) + + /** + * @param {Event} e + */ + async function save (e) { + e.preventDefault() + if (saving) { return } @@ -113,7 +119,7 @@
- +
@@ -137,7 +143,7 @@
- {#each permissions.filter((x) => !form.permissions.includes(x)) as it} @@ -160,7 +166,7 @@ {it}
removePermission(it)} on:keypress={() => removePermission(it)}> + onclick={() => removePermission(it)} onkeypress={() => removePermission(it)}>
@@ -180,7 +186,7 @@ {#if role}Update{:else}Create{/if} {#if role} - + {/if}
diff --git a/src/routes/(auth)/(project)/role/users/+page.svelte b/src/routes/(auth)/(project)/role/users/+page.svelte index 56c897f5..de6c5562 100644 --- a/src/routes/(auth)/(project)/role/users/+page.svelte +++ b/src/routes/(auth)/(project)/role/users/+page.svelte @@ -4,11 +4,11 @@ import api from '$lib/api' import ErrorRow from '$lib/components/ErrorRow.svelte' - export let data + const { data } = $props() - $: project = data.project - $: users = data.users - $: error = data.error + const project = $derived(data.project) + const users = $derived(data.users) + const error = $derived(data.error) /** * @param {string} email @@ -63,12 +63,12 @@ {/each} -
+
- diff --git a/src/routes/(auth)/(project)/route/+page.svelte b/src/routes/(auth)/(project)/route/+page.svelte index f0820058..673e0664 100644 --- a/src/routes/(auth)/(project)/route/+page.svelte +++ b/src/routes/(auth)/(project)/route/+page.svelte @@ -4,11 +4,11 @@ import api from '$lib/api' import ErrorRow from '$lib/components/ErrorRow.svelte' - export let data + const { data } = $props() - $: project = data.project - $: routes = data.routes - $: error = data.error + const project = $derived(data.project) + const routes = $derived(data.routes) + const error = $derived(data.error) /** * @param {Api.Route} route @@ -76,7 +76,7 @@ - diff --git a/src/routes/(auth)/(project)/route/create/+page.svelte b/src/routes/(auth)/(project)/route/create/+page.svelte index 4d5cd7c1..e9243149 100644 --- a/src/routes/(auth)/(project)/route/create/+page.svelte +++ b/src/routes/(auth)/(project)/route/create/+page.svelte @@ -3,12 +3,12 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() - $: project = data.project - $: locations = data.locations + const project = $derived(data.project) + const locations = $derived(data.locations) - const form = { + const form = $state({ domain: '', subdomain: '', path: '', @@ -23,19 +23,19 @@ } // TODO: add forwardAuth } - } + }) - $: targetPlaceholder = { + const targetPlaceholder = $derived({ 'redirect://': 'https://example.com', 'ipfs://': 'QmUVTKsrYJpaxUT7dr9FpKq6AoKHhEM7eG1ZHGL56haKLG', 'ipns://': 'k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nhoew' - }[form.targetPrefix] || '' + }[form.targetPrefix] || '') /** @type {Api.Domain[]} */ - let domains = [] - let deployments = [] + let domains = $state([]) + let deployments = $state([]) - $: selectedDomain = domains.find((x) => x.domain === form.domain) + const selectedDomain = $derived(domains.find((x) => x.domain === form.domain)) async function fetchDomains () { domains = [] @@ -54,7 +54,7 @@ async function fetchDeployments () { deployments = [] - form.target = '' + form.targetValue = '' const resp = await api.invoke('deployment.list', { project }, fetch) if (!resp.ok) { @@ -73,8 +73,14 @@ fetchDeployments() } - let saving = false - async function save () { + let saving = $state(false) + + /** + * @param {Event} e + */ + async function save (e) { + e.preventDefault() + if (saving) { return } @@ -132,11 +138,11 @@

-
+
- {#each locations as it} @@ -178,7 +184,7 @@
- form.targetValue = ''} required> diff --git a/src/routes/(auth)/(project)/service-account/+page.svelte b/src/routes/(auth)/(project)/service-account/+page.svelte index 575f2ce9..7160c28b 100644 --- a/src/routes/(auth)/(project)/service-account/+page.svelte +++ b/src/routes/(auth)/(project)/service-account/+page.svelte @@ -3,11 +3,11 @@ import * as format from '$lib/format' import ErrorRow from '$lib/components/ErrorRow.svelte' - export let data + const { data } = $props() - $: project = data.project - $: serviceAccounts = data.serviceAccounts - $: error = data.error + const project = $derived(data.project) + const serviceAccounts = $derived(data.serviceAccounts) + const error = $derived(data.error)
Service Accounts
@@ -42,7 +42,7 @@ {it.name} {format.datetime(it.createdAt)} - +
diff --git a/src/routes/(auth)/(project)/service-account/create/+page.svelte b/src/routes/(auth)/(project)/service-account/create/+page.svelte index a037292d..4d4c709d 100644 --- a/src/routes/(auth)/(project)/service-account/create/+page.svelte +++ b/src/routes/(auth)/(project)/service-account/create/+page.svelte @@ -3,20 +3,25 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() const { id, serviceAccount } = data - $: project = data.project + const project = $derived(data.project) - let sid = serviceAccount?.sid - let name = serviceAccount?.name - let desc = serviceAccount?.description - let saving = false + let sid = $state(serviceAccount?.sid) + let name = $state(serviceAccount?.name) + let desc = $state(serviceAccount?.description) + let saving = $state(false) + + /** + * @param {Event} e + */ + async function save (e) { + e.preventDefault() - async function save () { if (saving) { return } @@ -77,7 +82,7 @@
- + {#if id}
diff --git a/src/routes/(auth)/(project)/service-account/detail/+page.svelte b/src/routes/(auth)/(project)/service-account/detail/+page.svelte index abb05f19..5f43a63c 100644 --- a/src/routes/(auth)/(project)/service-account/detail/+page.svelte +++ b/src/routes/(auth)/(project)/service-account/detail/+page.svelte @@ -4,11 +4,11 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() - $: project = data.project - $: id = data.id - $: serviceAccount = data.serviceAccount + const project = $derived(data.project) + const id = $derived(data.id) + const serviceAccount = $derived(data.serviceAccount) function deleteItem () { modal.confirm({ @@ -25,7 +25,7 @@ }) } - let loadingCreateKey = false + let loadingCreateKey = $state(false) async function createKey () { if (loadingCreateKey) { @@ -122,14 +122,14 @@ {#each (serviceAccount.keys ?? []) as key}
-
{/each}
- @@ -139,7 +139,7 @@
-
diff --git a/src/routes/(auth)/(project)/workload-identity/+page.svelte b/src/routes/(auth)/(project)/workload-identity/+page.svelte index a74dd6ec..a961aeaf 100644 --- a/src/routes/(auth)/(project)/workload-identity/+page.svelte +++ b/src/routes/(auth)/(project)/workload-identity/+page.svelte @@ -4,11 +4,11 @@ import * as format from '$lib/format' import ErrorRow from '$lib/components/ErrorRow.svelte' - export let data + const { data } = $props() - $: project = data.project - $: workloadIdentities = data.workloadIdentities - $: error = data.error + const project = $derived(data.project) + const workloadIdentities = $derived(data.workloadIdentities) + const error = $derived(data.error)
Workload Identities
diff --git a/src/routes/(auth)/(project)/workload-identity/create/+page.svelte b/src/routes/(auth)/(project)/workload-identity/create/+page.svelte index a518109b..ee9b4263 100644 --- a/src/routes/(auth)/(project)/workload-identity/create/+page.svelte +++ b/src/routes/(auth)/(project)/workload-identity/create/+page.svelte @@ -3,20 +3,26 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() const locations = data.locations - $: project = data.project + const project = $derived(data.project) - const form = { + const form = $state({ name: '', location: '', gsa: '' - } + }) + + let saving = $state(false) + + /** + * @param {Event} e + */ + async function save (e) { + e.preventDefault() - let saving = false - async function save () { if (saving) { return } @@ -57,7 +63,7 @@

- +
diff --git a/src/routes/(auth)/(project)/workload-identity/detail/+page.svelte b/src/routes/(auth)/(project)/workload-identity/detail/+page.svelte index 48c5d0a9..488d4fd0 100644 --- a/src/routes/(auth)/(project)/workload-identity/detail/+page.svelte +++ b/src/routes/(auth)/(project)/workload-identity/detail/+page.svelte @@ -6,11 +6,11 @@ import * as modal from '$lib/modal' import api from '$lib/api' - export let data + const { data } = $props() - $: workloadIdentity = data.workloadIdentity - $: project = data.project - $: projectInfo = data.projectInfo + const workloadIdentity = $derived(data.workloadIdentity) + const project = $derived(data.project) + const projectInfo = $derived(data.projectInfo) onMount(() => { const copyList = new ClipboardJS('.copy') @@ -95,7 +95,7 @@
- +
diff --git a/src/routes/(auth)/+layout.svelte b/src/routes/(auth)/+layout.svelte index 7ea2d93a..503f3a88 100644 --- a/src/routes/(auth)/+layout.svelte +++ b/src/routes/(auth)/+layout.svelte @@ -7,16 +7,19 @@ import Sidebar from './Sidebar.svelte' import ModalSelectProject from './ModalSelectProject.svelte' - export let data + const { data, children } = $props() - $: profile = data.profile - $: projects = data.projects ?? [] + const profile = $derived(data.profile) + const projects = $derived(data.projects ?? []) - let showSidebar = false - $: $page, showSidebar = false + let showSidebar = $state(false) + $effect(() => { + $page + showSidebar = false + }) - /** @type {ModalSelectProject} */ - let projectModal + /** @type {?ModalSelectProject} */ + let projectModal = $state(null) onMount(() => { api.setOnUnauth(() => { @@ -29,23 +32,20 @@ } - showSidebar = !showSidebar} /> -
+ projectModal?.open} />
- + {@render children?.()}
diff --git a/src/routes/(auth)/ModalSelectProject.svelte b/src/routes/(auth)/ModalSelectProject.svelte index 2179f1a8..5e7b3bef 100644 --- a/src/routes/(auth)/ModalSelectProject.svelte +++ b/src/routes/(auth)/ModalSelectProject.svelte @@ -2,11 +2,16 @@ import { page } from '$app/stores' import { goto } from '$app/navigation' - /** @type {Api.Project[]} */ - export let projects + /** + * @typedef {Object} Props + * @property {Api.Project[]} projects + */ + + /** @type {Props} */ + const { projects } = $props() - $: project = $page.url.searchParams.get('project') - let isActive = false + const project = $derived($page.url.searchParams.get('project')) + let isActive = $state(false) /** * @param {string} sid @@ -34,9 +39,9 @@ } -