mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge pull request #2988 from appwrite/feat-deployment-retention-ui
feat: add deployment retention settings
This commit is contained in:
@@ -336,6 +336,7 @@ export enum Submit {
|
||||
FunctionUpdateScopes = 'submit_function_key_update_scopes',
|
||||
FunctionUpdateRuntime = 'submit_function_update_runtime',
|
||||
FunctionUpdateBuildCommand = 'submit_function_update_build_command',
|
||||
FunctionUpdateDeploymentRetention = 'submit_function_update_deployment_retention',
|
||||
FunctionConnectRepo = 'submit_function_connect_repo',
|
||||
FunctionDisconnectRepo = 'submit_function_disconnect_repo',
|
||||
FunctionRedeploy = 'submit_function_redeploy',
|
||||
@@ -458,6 +459,7 @@ export enum Submit {
|
||||
SiteUpdateScopes = 'submit_site_key_update_scopes',
|
||||
SiteUpdateBuildSettings = 'submit_site_update_build_settings',
|
||||
SiteUpdateResourceLimits = 'submit_site_update_resource_limits',
|
||||
SiteUpdateDeploymentRetention = 'submit_site_update_deployment_retention',
|
||||
SiteUpdateSinglePageApplication = 'submit_site_update_single_page_application',
|
||||
SiteConnectRepo = 'submit_site_connect_repo',
|
||||
SiteRedeploy = 'submit_site_redeploy',
|
||||
|
||||
+2
@@ -19,6 +19,7 @@
|
||||
import UpdateRepository from './updateRepository.svelte';
|
||||
import UpdateBuildCommand from './updateBuildCommand.svelte';
|
||||
import UpdateResourceLimits from './updateResourceLimits.svelte';
|
||||
import UpdateDeploymentRetention from './updateDeploymentRetention.svelte';
|
||||
import { isCloud } from '$lib/system';
|
||||
import UpdateVariables from '$routes/(console)/project-[region]-[project]/updateVariables.svelte';
|
||||
import { page } from '$app/state';
|
||||
@@ -108,6 +109,7 @@
|
||||
project={data.project}
|
||||
analyticsSource="function_settings" />
|
||||
<UpdateBuildCommand func={data.function} />
|
||||
<UpdateDeploymentRetention func={data.function} />
|
||||
|
||||
<UpdatePermissions />
|
||||
{#if isCloud}
|
||||
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { page } from '$app/state';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { CardGrid } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Button, Form, InputSelect, InputSwitch } from '$lib/elements/forms';
|
||||
import { isValueOfStringEnum } from '$lib/helpers/types';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Runtime, type Models, type Scopes } from '@appwrite.io/console';
|
||||
|
||||
let { func }: { func: Models.Function } = $props();
|
||||
|
||||
const MAX_DEPLOYMENT_RETENTION = 36500;
|
||||
const DEPLOYMENT_RETENTION_OPTIONS = [
|
||||
{ value: 7, label: '1 Week' },
|
||||
{ value: 30, label: '1 Month' },
|
||||
{ value: 90, label: '3 Months' },
|
||||
{ value: 180, label: '6 Months' },
|
||||
{ value: 365, label: '1 Year' },
|
||||
{ value: 730, label: '2 Years' },
|
||||
{ value: 1825, label: '5 Years' },
|
||||
{ value: 3650, label: '10 Years' }
|
||||
];
|
||||
const getInitialDeploymentRetention = () => func.deploymentRetention;
|
||||
const getRetentionOptions = (retention: number) => {
|
||||
const hasCurrentOption = DEPLOYMENT_RETENTION_OPTIONS.some(
|
||||
(option) => option.value === retention
|
||||
);
|
||||
|
||||
if (retention < 1 || retention > MAX_DEPLOYMENT_RETENTION || hasCurrentOption) {
|
||||
return DEPLOYMENT_RETENTION_OPTIONS;
|
||||
}
|
||||
|
||||
return [{ value: retention, label: `${retention} days` }, ...DEPLOYMENT_RETENTION_OPTIONS];
|
||||
};
|
||||
|
||||
let unlimitedRetention = $state(getInitialDeploymentRetention() === 0);
|
||||
let retentionDays = $state(
|
||||
getInitialDeploymentRetention() > 0 ? getInitialDeploymentRetention() : 30
|
||||
);
|
||||
const retentionOptions = $derived(getRetentionOptions(retentionDays));
|
||||
const deploymentRetention = $derived(unlimitedRetention ? 0 : retentionDays);
|
||||
let isUnchanged = $derived(func.deploymentRetention === deploymentRetention);
|
||||
let isInvalid = $derived(
|
||||
!unlimitedRetention &&
|
||||
(retentionDays === null ||
|
||||
retentionDays < 1 ||
|
||||
retentionDays > MAX_DEPLOYMENT_RETENTION)
|
||||
);
|
||||
|
||||
async function update() {
|
||||
try {
|
||||
if (!isValueOfStringEnum(Runtime, func.runtime)) {
|
||||
throw new Error(`Invalid runtime: ${func.runtime}`);
|
||||
}
|
||||
|
||||
await sdk.forProject(page.params.region, page.params.project).functions.update({
|
||||
functionId: func.$id,
|
||||
name: func.name,
|
||||
runtime: func.runtime,
|
||||
execute: func.execute || undefined,
|
||||
events: func.events || undefined,
|
||||
schedule: func.schedule || undefined,
|
||||
timeout: func.timeout || undefined,
|
||||
enabled: func.enabled || undefined,
|
||||
logging: func.logging || undefined,
|
||||
entrypoint: func.entrypoint || undefined,
|
||||
commands: func.commands || undefined,
|
||||
scopes: (func.scopes as Scopes[]) || undefined,
|
||||
installationId: func.installationId || undefined,
|
||||
providerRepositoryId: func.providerRepositoryId || undefined,
|
||||
providerBranch: func.providerBranch || undefined,
|
||||
providerSilentMode: func.providerSilentMode || undefined,
|
||||
providerRootDirectory: func.providerRootDirectory || undefined,
|
||||
buildSpecification: func.buildSpecification || undefined,
|
||||
runtimeSpecification: func.runtimeSpecification || undefined,
|
||||
deploymentRetention
|
||||
});
|
||||
|
||||
await invalidate(Dependencies.FUNCTION);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: 'Deployment retention has been updated'
|
||||
});
|
||||
trackEvent(Submit.FunctionUpdateDeploymentRetention);
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
});
|
||||
trackError(error, Submit.FunctionUpdateDeploymentRetention);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Form onSubmit={update}>
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">Deployment retention</svelte:fragment>
|
||||
Keep active deployments and choose when inactive deployments are deleted.
|
||||
<svelte:fragment slot="aside">
|
||||
<InputSwitch
|
||||
id="deployment-retention-unlimited"
|
||||
label="Keep deployments forever"
|
||||
bind:value={unlimitedRetention} />
|
||||
|
||||
{#if !unlimitedRetention}
|
||||
<InputSelect
|
||||
id="deployment-retention"
|
||||
label="Keep for"
|
||||
placeholder="1 Month"
|
||||
options={retentionOptions}
|
||||
required
|
||||
bind:value={retentionDays} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
<Button disabled={isUnchanged || isInvalid} submit>Update</Button>
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
</Form>
|
||||
+2
@@ -16,6 +16,7 @@
|
||||
import UpdateResourceLimits from './updateResourceLimits.svelte';
|
||||
import UpdateVariables from '$routes/(console)/project-[region]-[project]/updateVariables.svelte';
|
||||
import UpdateLogging from './updateLogging.svelte';
|
||||
import UpdateDeploymentRetention from './updateDeploymentRetention.svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -81,6 +82,7 @@
|
||||
{#if isCloud}
|
||||
<UpdateResourceLimits site={data.site} specs={data.specificationsList} />
|
||||
{/if}
|
||||
<UpdateDeploymentRetention site={data.site} />
|
||||
<UpdateTimeout site={data.site} />
|
||||
<UpdateLogging site={data.site} />
|
||||
<DangerZone site={data.site} />
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { page } from '$app/state';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { CardGrid } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Button, Form, InputSelect, InputSwitch } from '$lib/elements/forms';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Adapter, BuildRuntime, Framework, type Models } from '@appwrite.io/console';
|
||||
|
||||
let { site }: { site: Models.Site } = $props();
|
||||
|
||||
const MAX_DEPLOYMENT_RETENTION = 36500;
|
||||
const DEPLOYMENT_RETENTION_OPTIONS = [
|
||||
{ value: 7, label: '1 Week' },
|
||||
{ value: 30, label: '1 Month' },
|
||||
{ value: 90, label: '3 Months' },
|
||||
{ value: 180, label: '6 Months' },
|
||||
{ value: 365, label: '1 Year' },
|
||||
{ value: 730, label: '2 Years' },
|
||||
{ value: 1825, label: '5 Years' },
|
||||
{ value: 3650, label: '10 Years' }
|
||||
];
|
||||
const getInitialDeploymentRetention = () => site.deploymentRetention;
|
||||
const getRetentionOptions = (retention: number) => {
|
||||
const hasCurrentOption = DEPLOYMENT_RETENTION_OPTIONS.some(
|
||||
(option) => option.value === retention
|
||||
);
|
||||
|
||||
if (retention < 1 || retention > MAX_DEPLOYMENT_RETENTION || hasCurrentOption) {
|
||||
return DEPLOYMENT_RETENTION_OPTIONS;
|
||||
}
|
||||
|
||||
return [{ value: retention, label: `${retention} days` }, ...DEPLOYMENT_RETENTION_OPTIONS];
|
||||
};
|
||||
|
||||
let unlimitedRetention = $state(getInitialDeploymentRetention() === 0);
|
||||
let retentionDays = $state(
|
||||
getInitialDeploymentRetention() > 0 ? getInitialDeploymentRetention() : 30
|
||||
);
|
||||
const retentionOptions = $derived(getRetentionOptions(retentionDays));
|
||||
const deploymentRetention = $derived(unlimitedRetention ? 0 : retentionDays);
|
||||
let isUnchanged = $derived(site.deploymentRetention === deploymentRetention);
|
||||
let isInvalid = $derived(
|
||||
!unlimitedRetention &&
|
||||
(retentionDays === null ||
|
||||
retentionDays < 1 ||
|
||||
retentionDays > MAX_DEPLOYMENT_RETENTION)
|
||||
);
|
||||
|
||||
async function update() {
|
||||
try {
|
||||
await sdk.forProject(page.params.region, page.params.project).sites.update({
|
||||
siteId: site.$id,
|
||||
name: site.name,
|
||||
framework: site.framework as Framework,
|
||||
enabled: site.enabled || undefined,
|
||||
logging: site.logging || undefined,
|
||||
timeout: site.timeout || undefined,
|
||||
installCommand: site.installCommand || undefined,
|
||||
buildCommand: site.buildCommand || undefined,
|
||||
outputDirectory: site.outputDirectory || undefined,
|
||||
buildRuntime: (site.buildRuntime as BuildRuntime) || undefined,
|
||||
adapter: site.adapter as Adapter,
|
||||
fallbackFile: site.fallbackFile || undefined,
|
||||
installationId: site.installationId || undefined,
|
||||
providerRepositoryId: site.providerRepositoryId || undefined,
|
||||
providerBranch: site.providerBranch || undefined,
|
||||
providerSilentMode: site.providerSilentMode || undefined,
|
||||
providerRootDirectory: site.providerRootDirectory || undefined,
|
||||
buildSpecification: site.buildSpecification || undefined,
|
||||
runtimeSpecification: site.runtimeSpecification || undefined,
|
||||
deploymentRetention
|
||||
});
|
||||
|
||||
await invalidate(Dependencies.SITE);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: 'Deployment retention has been updated'
|
||||
});
|
||||
trackEvent(Submit.SiteUpdateDeploymentRetention);
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
});
|
||||
trackError(error, Submit.SiteUpdateDeploymentRetention);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Form onSubmit={update}>
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">Deployment retention</svelte:fragment>
|
||||
Keep active deployments and choose when inactive deployments are deleted.
|
||||
<svelte:fragment slot="aside">
|
||||
<InputSwitch
|
||||
id="deployment-retention-unlimited"
|
||||
label="Keep deployments forever"
|
||||
bind:value={unlimitedRetention} />
|
||||
|
||||
{#if !unlimitedRetention}
|
||||
<InputSelect
|
||||
id="deployment-retention"
|
||||
label="Keep for"
|
||||
placeholder="1 Month"
|
||||
options={retentionOptions}
|
||||
required
|
||||
bind:value={retentionDays} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
<Button disabled={isUnchanged || isInvalid} submit>Update</Button>
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
</Form>
|
||||
Reference in New Issue
Block a user