mirror of
https://github.com/appwrite/console.git
synced 2026-04-07 19:17:46 +00:00
feat: creation flow fixes
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Button, InputSelect, InputText } from '$lib/elements/forms';
|
||||
import { Fieldset, Layout, Selector, Skeleton } from '@appwrite.io/pink-svelte';
|
||||
import SelectRootModal from '../../../routes/(console)/project-[project]/sites/(components)/selectRootModal.svelte';
|
||||
import SelectRootModal from './selectRootModal.svelte';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { sortBranches } from '$lib/stores/vcs';
|
||||
|
||||
|
||||
+30
-1
@@ -1,8 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { CustomId } from '$lib/components';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { InputSelect, InputText } from '$lib/elements/forms';
|
||||
import Link from '$lib/elements/link.svelte';
|
||||
import { upgradeURL } from '$lib/stores/billing';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { IconPencil } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Fieldset, Icon, Layout, Tag } from '@appwrite.io/pink-svelte';
|
||||
import { Fieldset, Icon, Input, Layout, Tag } from '@appwrite.io/pink-svelte';
|
||||
import type { ComponentType } from 'svelte';
|
||||
|
||||
export let name: string;
|
||||
@@ -15,6 +20,11 @@
|
||||
label: string;
|
||||
leadingIcon?: ComponentType;
|
||||
}[] = [];
|
||||
export let specification: string;
|
||||
export let specificationOptions: {
|
||||
value: string;
|
||||
label: string;
|
||||
}[] = [];
|
||||
|
||||
let showCustomId = false;
|
||||
</script>
|
||||
@@ -49,6 +59,25 @@
|
||||
required
|
||||
{options} />
|
||||
{/key}
|
||||
|
||||
{#if isCloud}
|
||||
<Layout.Stack gap="xs">
|
||||
<InputSelect
|
||||
label="CPU and memory"
|
||||
id="specification"
|
||||
placeholder="Select specification"
|
||||
required
|
||||
disabled={specificationOptions.length < 1}
|
||||
options={specificationOptions}
|
||||
bind:value={specification} />
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Input.Helper state="default">
|
||||
<Link href={$upgradeURL} variant="muted">Upgrade</Link> to Pro or Scale to adjust
|
||||
your CPU and RAM beyond the default.
|
||||
</Input.Helper>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
{#if showEntrypoint}
|
||||
<InputText
|
||||
label="Entrypoint"
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
runtime: template.name
|
||||
});
|
||||
}}
|
||||
href={`${wizardBase}/create-function/template-${starterTemplate.id}`}>
|
||||
href={`${wizardBase}/create-function/template-${starterTemplate.id}?runtime=${runtimeDetail.$id}`}>
|
||||
<Layout.Stack direction="row" gap="s" alignItems="center">
|
||||
<Avatar
|
||||
size="xs"
|
||||
|
||||
+80
-25
@@ -7,10 +7,9 @@
|
||||
import { Wizard } from '$lib/layout';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { installation, repository } from '$lib/stores/vcs';
|
||||
import { Layout } from '@appwrite.io/pink-svelte';
|
||||
import { Icon, Layout, Tooltip, Typography, Upload } from '@appwrite.io/pink-svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import { ID, Runtime, Type } from '@appwrite.io/console';
|
||||
import { ID, Runtime } from '@appwrite.io/console';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
import Details from '../(components)/details.svelte';
|
||||
@@ -18,8 +17,26 @@
|
||||
import { iconPath } from '$lib/stores/app';
|
||||
import { getIconFromRuntime } from '../../store';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
import Configuration from './configuration.svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
const runtimeOptions = data.runtimesList.runtimes.map((runtime) => {
|
||||
return {
|
||||
value: runtime.$id,
|
||||
label: `${runtime.name} - ${runtime.version}`,
|
||||
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key), 'color')}' style='inline-size: var(--icon-size-m)' />`
|
||||
};
|
||||
});
|
||||
|
||||
const specificationOptions = data.specificationsList.specifications.map((size) => ({
|
||||
label:
|
||||
`${size.cpus} CPU, ${size.memory} MB RAM` +
|
||||
(!size.enabled ? ` (Upgrade to use this)` : ''),
|
||||
value: size.slug,
|
||||
disabled: !size.enabled
|
||||
}));
|
||||
let showExitModal = false;
|
||||
|
||||
let formComponent: Form;
|
||||
@@ -31,18 +48,18 @@
|
||||
let entrypoint = '';
|
||||
let buildCommand = '';
|
||||
let scopes: string[] = [];
|
||||
let branch: string;
|
||||
let rootDir = './';
|
||||
let variables: Partial<Models.Variable>[] = [];
|
||||
let silentMode = false;
|
||||
let files: FileList;
|
||||
let specification = specificationOptions[0].value;
|
||||
|
||||
async function create() {
|
||||
try {
|
||||
const rt = Object.values(Runtime).find((r) => r === runtime);
|
||||
console.log(runtime);
|
||||
|
||||
const func = await sdk.forProject.functions.create(
|
||||
id,
|
||||
name,
|
||||
rt,
|
||||
runtime,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
@@ -52,12 +69,12 @@
|
||||
entrypoint,
|
||||
undefined,
|
||||
scopes,
|
||||
$installation.$id,
|
||||
$repository.id,
|
||||
branch,
|
||||
silentMode,
|
||||
rootDir,
|
||||
undefined //TODO: specs
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
specification || undefined
|
||||
);
|
||||
|
||||
// Add domain
|
||||
@@ -77,14 +94,20 @@
|
||||
);
|
||||
await Promise.all(promises);
|
||||
|
||||
await sdk.forProject.functions.createVcsDeployment(func.$id, Type.Branch, branch, true);
|
||||
await sdk.forProject.functions.createDeployment(
|
||||
func.$id,
|
||||
files[0],
|
||||
true,
|
||||
entrypoint,
|
||||
buildCommand
|
||||
);
|
||||
|
||||
trackEvent(Submit.FunctionCreate, {
|
||||
source: 'repository',
|
||||
runtime: runtime
|
||||
});
|
||||
|
||||
await goto(`${base}/project-${$page.params.project}/functions/function=${func.$id}`);
|
||||
await goto(`${base}/project-${$page.params.project}/functions/function-${func.$id}`);
|
||||
|
||||
invalidate(Dependencies.FUNCTION);
|
||||
} catch (e) {
|
||||
@@ -95,14 +118,6 @@
|
||||
trackError(e, Submit.FunctionCreate);
|
||||
}
|
||||
}
|
||||
|
||||
const runtimeOptions = data.runtimesList.runtimes.map((runtime) => {
|
||||
return {
|
||||
value: runtime.name,
|
||||
label: `${runtime.name} - ${runtime.version}`,
|
||||
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key), 'color')}' style='inline-size: var(--icon-size-m)' />`
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -113,18 +128,58 @@
|
||||
title="Create function"
|
||||
bind:showExitModal
|
||||
href={`${base}/project-${$page.params.project}/functions`}
|
||||
column
|
||||
columnSize="s"
|
||||
confirmExit>
|
||||
<Form bind:this={formComponent} onSubmit={create} bind:isSubmitting>
|
||||
<Layout.Stack gap="xl">
|
||||
<Layout.Stack gap="s">
|
||||
<Typography.Text color="--fgcolor-neutral-primary">
|
||||
Upload a zip file (tar.gz) containing your function source code
|
||||
</Typography.Text>
|
||||
<Upload.Dropzone bind:files title="Upload function">
|
||||
<Layout.Stack alignItems="center" gap="s">
|
||||
<Layout.Stack alignItems="center" gap="s">
|
||||
<Layout.Stack
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
direction="row"
|
||||
gap="s">
|
||||
<Typography.Text variant="l-500">
|
||||
Drag and drop file here or click to upload
|
||||
</Typography.Text>
|
||||
<Tooltip>
|
||||
<Layout.Stack
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
inline>
|
||||
<Icon icon={IconInfo} size="s" />
|
||||
</Layout.Stack>
|
||||
<svelte:fragment slot="tooltip"
|
||||
>Only .tar.gz files allowed</svelte:fragment>
|
||||
</Tooltip>
|
||||
</Layout.Stack>
|
||||
<Typography.Caption variant="400"
|
||||
>Max file size 10MB</Typography.Caption>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Upload.Dropzone>
|
||||
{#if files?.length}
|
||||
<Upload.List bind:files />
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
|
||||
<Details
|
||||
bind:name
|
||||
bind:entrypoint
|
||||
bind:id
|
||||
bind:runtime
|
||||
bind:specification
|
||||
{specificationOptions}
|
||||
options={runtimeOptions}
|
||||
showEntrypoint />
|
||||
|
||||
<!-- <Configuration bind:buildCommand bind:scopes /> -->
|
||||
<Configuration bind:buildCommand bind:scopes />
|
||||
</Layout.Stack>
|
||||
</Form>
|
||||
<svelte:fragment slot="aside">
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export const load = async ({ parent }) => {
|
||||
let { installations, runtimesList } = await parent();
|
||||
let { installations, runtimesList, specificationsList } = await parent();
|
||||
|
||||
return {
|
||||
installations,
|
||||
runtimesList
|
||||
runtimesList,
|
||||
specificationsList
|
||||
};
|
||||
};
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<script lang="ts">
|
||||
import { Roles } from '$lib/components/permissions';
|
||||
import { Link } from '$lib/elements';
|
||||
import { InputText } from '$lib/elements/forms';
|
||||
import { Accordion, Fieldset, Layout } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let buildCommand = '';
|
||||
export let scopes: string[] = [];
|
||||
</script>
|
||||
|
||||
<Fieldset legend="Settings">
|
||||
<Layout.Stack>
|
||||
<Accordion title="Build settings" badge="Optional">
|
||||
<Layout.Stack gap="xl">
|
||||
Set up how your project is built.
|
||||
<InputText
|
||||
id="installCommand"
|
||||
label="Install command"
|
||||
bind:value={buildCommand}
|
||||
placeholder="npm install" />
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion title="Execute access" badge="Optional" hideDivider>
|
||||
<Layout.Stack gap="xl">
|
||||
<span>
|
||||
Choose who can execute this function using the client API. <Link
|
||||
external
|
||||
href="https://appwrite.io/docs/advanced/platform/permissions"
|
||||
>Learn more</Link>
|
||||
</span>
|
||||
|
||||
<Roles bind:roles={scopes} />
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
</Layout.Stack>
|
||||
</Fieldset>
|
||||
+22
-11
@@ -24,6 +24,22 @@
|
||||
import RepoCard from './repoCard.svelte';
|
||||
|
||||
export let data;
|
||||
|
||||
const specificationOptions = data.specificationsList.specifications.map((size) => ({
|
||||
label:
|
||||
`${size.cpus} CPU, ${size.memory} MB RAM` +
|
||||
(!size.enabled ? ` (Upgrade to use this)` : ''),
|
||||
value: size.slug,
|
||||
disabled: !size.enabled
|
||||
}));
|
||||
const runtimeOptions = data.runtimesList.runtimes.map((runtime) => {
|
||||
return {
|
||||
value: runtime.$id,
|
||||
label: `${runtime.name} - ${runtime.version}`,
|
||||
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key), 'color')}' style='inline-size: var(--icon-size-m)' />`
|
||||
};
|
||||
});
|
||||
|
||||
let showExitModal = false;
|
||||
|
||||
let formComponent: Form;
|
||||
@@ -39,14 +55,7 @@
|
||||
let rootDir = './';
|
||||
let variables: Partial<Models.Variable>[] = [];
|
||||
let silentMode = false;
|
||||
|
||||
const runtimeOptions = data.runtimesList.runtimes.map((runtime) => {
|
||||
return {
|
||||
value: runtime.name,
|
||||
label: `${runtime.name} - ${runtime.version}`,
|
||||
leadingHtml: `<img src='${$iconPath(getIconFromRuntime(runtime.key), 'color')}' style='inline-size: var(--icon-size-m)' />`
|
||||
};
|
||||
});
|
||||
let specification = specificationOptions[0].value;
|
||||
|
||||
onMount(async () => {
|
||||
installation.set(data.installation);
|
||||
@@ -74,7 +83,7 @@
|
||||
branch,
|
||||
silentMode,
|
||||
rootDir,
|
||||
undefined //TODO: specs
|
||||
specification || undefined
|
||||
);
|
||||
|
||||
// Add domain
|
||||
@@ -101,7 +110,7 @@
|
||||
runtime: runtime
|
||||
});
|
||||
|
||||
await goto(`${base}/project-${$page.params.project}/functions/function=${func.$id}`);
|
||||
await goto(`${base}/project-${$page.params.project}/functions/function-${func.$id}`);
|
||||
|
||||
invalidate(Dependencies.FUNCTION);
|
||||
} catch (e) {
|
||||
@@ -132,6 +141,8 @@
|
||||
bind:entrypoint
|
||||
bind:id
|
||||
bind:runtime
|
||||
bind:specification
|
||||
{specificationOptions}
|
||||
options={runtimeOptions}
|
||||
showEntrypoint />
|
||||
|
||||
@@ -161,7 +172,7 @@
|
||||
submissionLoader
|
||||
on:click={() => formComponent.triggerSubmit()}
|
||||
disabled={$isSubmitting}>
|
||||
Create
|
||||
Deploy
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
</Wizard>
|
||||
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
export const load = async ({ parent, params, url }) => {
|
||||
const { installations, runtimesList } = await parent();
|
||||
const { installations, runtimesList, specificationsList } = await parent();
|
||||
|
||||
const [repository] = await Promise.all([
|
||||
sdk.forProject.vcs.getRepository(url.searchParams.get('installation'), params.repository)
|
||||
@@ -13,6 +13,7 @@ export const load = async ({ parent, params, url }) => {
|
||||
(installation) => installation.$id === url.searchParams.get('installation')
|
||||
),
|
||||
repository,
|
||||
runtimesList
|
||||
runtimesList,
|
||||
specificationsList
|
||||
};
|
||||
};
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
export let scopes: string[] = [];
|
||||
</script>
|
||||
|
||||
<Fieldset legend="Configuration">
|
||||
<Fieldset legend="Settings">
|
||||
<Layout.Stack>
|
||||
<Accordion title="Build settings" badge="Optional">
|
||||
<Layout.Stack gap="xl">
|
||||
|
||||
+25
-3
@@ -30,6 +30,14 @@
|
||||
|
||||
export let data;
|
||||
|
||||
const specificationOptions = data.specificationsList.specifications.map((size) => ({
|
||||
label:
|
||||
`${size.cpus} CPU, ${size.memory} MB RAM` +
|
||||
(!size.enabled ? ` (Upgrade to use this)` : ''),
|
||||
value: size.slug,
|
||||
disabled: !size.enabled
|
||||
}));
|
||||
|
||||
let showExitModal = false;
|
||||
let isCreatingRepository = false;
|
||||
let hasInstallations = !!data?.installations?.total;
|
||||
@@ -54,8 +62,15 @@
|
||||
let selectedScopes: string[] = [];
|
||||
let execute = false;
|
||||
let variables: Partial<Models.TemplateVariable>[] = [];
|
||||
let specification = specificationOptions[0].value;
|
||||
|
||||
onMount(async () => {
|
||||
if ($page.url.searchParams.has('runtime')) {
|
||||
console.log(runtime);
|
||||
console.log($page.url.searchParams.get('runtime'));
|
||||
runtime = $page.url.searchParams.get('runtime') as Runtime;
|
||||
console.log(runtime);
|
||||
}
|
||||
if (!$installation?.$id) {
|
||||
$installation = data.installations.installations[0];
|
||||
}
|
||||
@@ -125,7 +140,7 @@
|
||||
branch,
|
||||
silentMode,
|
||||
rootDir,
|
||||
undefined //TODO: specs
|
||||
specification || undefined
|
||||
);
|
||||
|
||||
// Add domain
|
||||
@@ -228,7 +243,14 @@
|
||||
})}
|
||||
|
||||
<Layout.Stack gap="xxl">
|
||||
<Details bind:name bind:id bind:runtime bind:entrypoint {options} />
|
||||
<Details
|
||||
bind:name
|
||||
bind:id
|
||||
bind:runtime
|
||||
bind:entrypoint
|
||||
bind:specification
|
||||
{specificationOptions}
|
||||
{options} />
|
||||
|
||||
<Permissions
|
||||
templateScopes={data.template.scopes}
|
||||
@@ -329,7 +351,7 @@
|
||||
size="s"
|
||||
on:click={() => formComponent.triggerSubmit()}
|
||||
disabled={$isSubmitting || (connectBehaviour === 'now' && !selectedRepository)}>
|
||||
Create
|
||||
Deploy
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
</Wizard>
|
||||
|
||||
+3
-2
@@ -1,12 +1,13 @@
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
export const load = async ({ parent, params }) => {
|
||||
let { installations, runtimesList } = await parent();
|
||||
let { installations, runtimesList, specificationsList } = await parent();
|
||||
const template = await sdk.forProject.functions.getTemplate(params.template);
|
||||
|
||||
return {
|
||||
installations,
|
||||
template,
|
||||
runtimesList
|
||||
runtimesList,
|
||||
specificationsList
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -79,6 +79,7 @@
|
||||
id={variable.name}
|
||||
value={variable.name}
|
||||
readonly
|
||||
required
|
||||
label={i === 0 ? 'Key' : null} />
|
||||
<svelte:component
|
||||
this={selectComponent(variable.type)}
|
||||
@@ -119,6 +120,7 @@
|
||||
id={variable.name}
|
||||
value={variable.name}
|
||||
readonly
|
||||
required
|
||||
label={i === 0 ? 'Key' : null} />
|
||||
<svelte:component
|
||||
this={selectComponent(variable.type)}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { canWriteFunctions } from '$lib/stores/roles';
|
||||
import { ActionMenu, Icon, Popover } from '@appwrite.io/pink-svelte';
|
||||
import CreateCli from './createCli.svelte';
|
||||
import CreateGit from './createGit.svelte';
|
||||
import CreateManual from './createManual.svelte';
|
||||
import CreateCli from './(modals)/createCli.svelte';
|
||||
import CreateGit from './(modals)/createGit.svelte';
|
||||
import CreateManual from './(modals)/createManual.svelte';
|
||||
import { showCreateDeployment } from './store';
|
||||
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user