mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'main' of github.com:appwrite/console into billing
This commit is contained in:
@@ -15,9 +15,10 @@
|
||||
const { input, handleSubmit, completion, isLoading, complete, error } = useCompletion({
|
||||
api: endpoint + '/console/assistant',
|
||||
headers: {
|
||||
'x-appwrite-mode': 'admin',
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
'content-type': 'application/json',
|
||||
'x-appwrite-project': 'console'
|
||||
},
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
let question = $input;
|
||||
|
||||
@@ -41,5 +41,5 @@
|
||||
{options}
|
||||
bind:value={limit}
|
||||
on:change={limitChange} />
|
||||
<p class="text">{name} per page. Total results: {sum}</p>
|
||||
<p class="text">{name} per page. Total results: {sum >= 5000 ? `${sum}+` : sum}</p>
|
||||
</div>
|
||||
|
||||
@@ -30,8 +30,7 @@
|
||||
* Cancel navigation when wizard is open and triggered by popstate
|
||||
*/
|
||||
beforeNavigate((n) => {
|
||||
const external = n?.to?.url?.hostname !== globalThis?.location?.hostname;
|
||||
if (external) return;
|
||||
if (n.willUnload) return;
|
||||
if (!($wizard.show || $wizard.cover)) return;
|
||||
if (n.type === 'popstate') {
|
||||
n.cancel();
|
||||
|
||||
@@ -75,8 +75,13 @@
|
||||
|
||||
wizard.setInterceptor(null);
|
||||
if (isLastStep) {
|
||||
$wizard.nextDisabled = true;
|
||||
trackEvent('wizard_finish');
|
||||
dispatch('finish');
|
||||
//Reactivate button in case there are errors
|
||||
setTimeout(() => {
|
||||
$wizard.nextDisabled = false;
|
||||
}, 2000);
|
||||
} else {
|
||||
if (steps.get($wizard.step + 1)?.disabled) {
|
||||
$wizard.step++;
|
||||
|
||||
@@ -132,7 +132,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
{
|
||||
name: 'node-18.0',
|
||||
commands: 'npm install && npm run setup',
|
||||
entrypoint: 'src/main.js && npm run setup',
|
||||
entrypoint: 'src/main.js',
|
||||
providerRootDirectory: 'node/discord-command-bot'
|
||||
},
|
||||
{
|
||||
@@ -150,9 +150,25 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
variables: [
|
||||
{
|
||||
name: 'DISCORD_PUBLIC_KEY',
|
||||
description: `Discord Public Key to verify request signature. <a class="u-bold" target="_blank" href="https://discord.com/developers/docs/tutorials/hosting-on-cloudflare-workers#creating-an-app-on-discord">Learn more</a>.`,
|
||||
description: `Public Key of your application in Discord Developer Portal. <a class="u-bold" target="_blank" href="https://discord.com/developers/docs/tutorials/hosting-on-cloudflare-workers#creating-an-app-on-discord">Learn more</a>.`,
|
||||
value: '',
|
||||
placeholder: 'd1efb...aec35',
|
||||
placeholder: 'db9...980',
|
||||
required: true,
|
||||
type: 'password'
|
||||
},
|
||||
{
|
||||
name: 'DISCORD_APPLICATION_ID',
|
||||
description: `ID of your application in Discord Developer Portal. <a class="u-bold" target="_blank" href="https://discord.com/developers/docs/tutorials/hosting-on-cloudflare-workers#creating-an-app-on-discord">Learn more</a>.`,
|
||||
value: '',
|
||||
placeholder: '427...169',
|
||||
required: true,
|
||||
type: 'password'
|
||||
},
|
||||
{
|
||||
name: 'DISCORD_TOKEN',
|
||||
description: `Bot token of your application in Discord Developer Portal. <a class="u-bold" target="_blank" href="https://discord.com/developers/docs/tutorials/hosting-on-cloudflare-workers#creating-an-app-on-discord">Learn more</a>.`,
|
||||
value: '',
|
||||
placeholder: 'NDI...LUfg',
|
||||
required: true,
|
||||
type: 'password'
|
||||
}
|
||||
@@ -698,7 +714,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
value: '',
|
||||
placeholder: 'smtp.mailgun.org',
|
||||
required: true,
|
||||
type: 'url'
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
name: 'SMTP_PORT',
|
||||
@@ -737,6 +753,134 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
type: 'text'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
icon: 'icon-stripe',
|
||||
id: 'subscriptions-with-stripe',
|
||||
name: 'Subscriptions with Stripe',
|
||||
tagline: 'Receive recurring card payments and grant subscribers extra permissions.',
|
||||
permissions: ['any'],
|
||||
events: [],
|
||||
cron: '',
|
||||
timeout: 15,
|
||||
usecases: ['Utilities'],
|
||||
runtimes: [
|
||||
{
|
||||
name: 'node-18.0',
|
||||
commands: 'npm install',
|
||||
entrypoint: 'src/main.js',
|
||||
providerRootDirectory: 'node/subscriptions-with-stripe'
|
||||
}
|
||||
],
|
||||
instructions: `For documentation and instructions check out <a target="_blank" rel="noopener noreferrer" class="link" href="https://github.com/appwrite/templates/tree/main/node/subscriptions-with-stripe">file</a>.`,
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
description: `The API Key to talk to Appwrite backend APIs. <a class="u-bold" target="_blank" href="https://appwrite.io/docs/getting-started-for-server">Learn more</a>.`,
|
||||
value: '',
|
||||
placeholder: 'd1efb...aec35',
|
||||
required: true,
|
||||
type: 'password'
|
||||
},
|
||||
{
|
||||
name: 'APPWRITE_ENDPOINT',
|
||||
description: `The URL endpoint of the Appwrite server. <a class="u-bold" target="_blank" href="https://appwrite.io/docs/getting-started-for-server">Learn more</a>.`,
|
||||
value: 'https://cloud.appwrite.io/v1',
|
||||
placeholder: 'https://cloud.appwrite.io/v1',
|
||||
required: false,
|
||||
type: 'url'
|
||||
},
|
||||
{
|
||||
name: 'STRIPE_SECRET_KEY',
|
||||
description: `Secret for sending requests to the Stripe API. <a class="u-bold" target="_blank" href="https://stripe.com/docs/keys">Learn more</a>.`,
|
||||
placeholder: 'sk_test_51J...',
|
||||
required: true,
|
||||
type: 'password'
|
||||
},
|
||||
{
|
||||
name: 'STRIPE_WEBHOOK_SECRET',
|
||||
description: `Secret used to validate the Stripe Webhook signature. <a class="u-bold" target="_blank" href="https://stripe.com/docs/webhooks">Learn more</a>.`,
|
||||
placeholder: 'whsec_...',
|
||||
required: true,
|
||||
type: 'password'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
icon: 'icon-stripe',
|
||||
id: 'payments-with-stripe',
|
||||
name: 'Payments with Stripe',
|
||||
tagline: 'Receive card payments and store paid orders.',
|
||||
permissions: ['any'],
|
||||
events: [],
|
||||
cron: '',
|
||||
timeout: 15,
|
||||
usecases: ['Utilities'],
|
||||
runtimes: [
|
||||
{
|
||||
name: 'node-18.0',
|
||||
commands: 'npm install && npm run setup',
|
||||
entrypoint: 'src/main.js',
|
||||
providerRootDirectory: 'node/payments-with-stripe'
|
||||
}
|
||||
],
|
||||
instructions: `For documentation and instructions check out <a target="_blank" rel="noopener noreferrer" class="link" href="https://github.com/appwrite/templates/tree/main/node/payments-with-stripe">file</a>.`,
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
description: `The API Key to talk to Appwrite backend APIs. <a class="u-bold" target="_blank" href="https://appwrite.io/docs/getting-started-for-server">Learn more</a>.`,
|
||||
value: '',
|
||||
placeholder: 'd1efb...aec35',
|
||||
required: true,
|
||||
type: 'password'
|
||||
},
|
||||
{
|
||||
name: 'APPWRITE_ENDPOINT',
|
||||
description: `The URL endpoint of the Appwrite server. <a class="u-bold" target="_blank" href="https://appwrite.io/docs/getting-started-for-server">Learn more</a>.`,
|
||||
value: 'https://cloud.appwrite.io/v1',
|
||||
placeholder: 'https://cloud.appwrite.io/v1',
|
||||
required: false,
|
||||
type: 'url'
|
||||
},
|
||||
{
|
||||
name: 'STRIPE_SECRET_KEY',
|
||||
description: `Secret for sending requests to the Stripe API. <a class="u-bold" target="_blank" href="https://stripe.com/docs/keys">Learn more</a>.`,
|
||||
placeholder: 'sk_test_51J...',
|
||||
required: true,
|
||||
type: 'password'
|
||||
},
|
||||
{
|
||||
name: 'STRIPE_WEBHOOK_SECRET',
|
||||
description: `Secret used to validate the Stripe Webhook signature. <a class="u-bold" target="_blank" href="https://stripe.com/docs/webhooks">Learn more</a>.`,
|
||||
placeholder: 'whsec_...',
|
||||
required: true,
|
||||
type: 'password'
|
||||
},
|
||||
{
|
||||
name: 'APPWRITE_DATABASE_ID',
|
||||
description: `The ID of the database to store paid orders. <a class="u-bold" target="_blank" href="https://appwrite.io/docs/databases">Learn more</a>.`,
|
||||
value: 'orders',
|
||||
placeholder: 'orders',
|
||||
required: false,
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
name: 'APPWRITE_COLLECTION_ID',
|
||||
description: `The ID of the collection to store paid orders. <a class="u-bold" target="_blank" href="https://appwrite.io/docs/collections">Learn more</a>.`,
|
||||
value: 'orders',
|
||||
placeholder: 'orders',
|
||||
required: false,
|
||||
type: 'text'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -106,21 +106,22 @@
|
||||
</li>
|
||||
{/each}
|
||||
{:then response}
|
||||
{@const runtimes = response.runtimes}
|
||||
{#each quickStart.runtimes.filter((_template, index) => index < 6) as runtime}
|
||||
{@const runtimeDetail = runtimes.find(
|
||||
(r) => r.$id === runtime.name
|
||||
)}
|
||||
{@const runtimes = new Map(response.runtimes.map((r) => [r.$id, r]))}
|
||||
{@const templates = quickStart.runtimes.filter((_template) =>
|
||||
runtimes.has(_template.name)
|
||||
)}
|
||||
{#each templates.slice(0, 6) as template}
|
||||
{@const runtimeDetail = runtimes.get(template.name)}
|
||||
<li>
|
||||
<button
|
||||
on:click={() => {
|
||||
trackEvent('click_connect_template', {
|
||||
from: 'cover',
|
||||
template: quickStart.id,
|
||||
runtime: runtime.name
|
||||
runtime: template.name
|
||||
});
|
||||
}}
|
||||
on:click={() => connectTemplate(quickStart, runtime.name)}
|
||||
on:click={() => connectTemplate(quickStart, template.name)}
|
||||
class="box u-width-full-line u-flex u-cross-center u-gap-8"
|
||||
style:--box-padding="1rem"
|
||||
style:--box-border-radius="var(--border-radius-small)">
|
||||
@@ -128,9 +129,9 @@
|
||||
<img
|
||||
style:--p-text-size="1.25rem"
|
||||
src={`${base}/icons/${$app.themeInUse}/color/${
|
||||
runtime.name.split('-')[0]
|
||||
template.name.split('-')[0]
|
||||
}.svg`}
|
||||
alt={runtime.name} />
|
||||
alt={template.name} />
|
||||
</div>
|
||||
<div class="body-text-2">
|
||||
{runtimeDetail.name}
|
||||
@@ -139,7 +140,7 @@
|
||||
</li>
|
||||
{/each}
|
||||
|
||||
{#if quickStart.runtimes.length < 6}
|
||||
{#if templates.length < 6}
|
||||
<li
|
||||
use:tooltip={{
|
||||
content: 'More runtimes coming soon'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Box } from '$lib/components';
|
||||
import { Box, SvgIcon } from '$lib/components';
|
||||
import { FormList, InputChoice, InputText } from '$lib/elements/forms';
|
||||
import InputSelectSearch from '$lib/elements/forms/inputSelectSearch.svelte';
|
||||
import { WizardStep } from '$lib/layout';
|
||||
@@ -8,14 +8,6 @@
|
||||
import { choices, installation, repository } from '../store';
|
||||
|
||||
$choices.rootDir ??= '';
|
||||
function getProviderIcon(provider: string) {
|
||||
switch (provider) {
|
||||
case 'github':
|
||||
return 'icon-github';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
async function loadBranches() {
|
||||
const { branches } = await sdk.forProject.vcs.listRepositoryBranches(
|
||||
@@ -40,13 +32,9 @@
|
||||
</svelte:fragment>
|
||||
|
||||
<Box radius="small">
|
||||
<div class="u-flex u-gap-16">
|
||||
<div class="avatar is-size-x-small">
|
||||
<span class={getProviderIcon($repository.provider)} />
|
||||
</div>
|
||||
<div class="u-cross-child-center u-line-height-1-5">
|
||||
<h6 class="u-bold u-trim-1">{$installation.organization}/{$repository.name}</h6>
|
||||
</div>
|
||||
<div class="u-flex u-gap-8 u-cross-center">
|
||||
<SvgIcon name={$repository.provider} iconSize="large" />
|
||||
<h6 class="u-bold u-trim-1">{$installation.organization}/{$repository.name}</h6>
|
||||
</div>
|
||||
{#await loadBranches()}
|
||||
<div class="u-flex u-gap-8 u-cross-center u-main-center">
|
||||
|
||||
@@ -14,8 +14,8 @@ export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
return {
|
||||
header: Header,
|
||||
breadcrumbs: Breadcrumbs,
|
||||
function: sdk.forProject.functions.get(params.function),
|
||||
proxyRuleList: sdk.forProject.proxy.listRules([
|
||||
function: await sdk.forProject.functions.get(params.function),
|
||||
proxyRuleList: await sdk.forProject.proxy.listRules([
|
||||
Query.equal('resourceType', 'function'),
|
||||
Query.equal('resourceId', params.function),
|
||||
Query.limit(1)
|
||||
|
||||
@@ -29,10 +29,9 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import { app } from '$lib/stores/app';
|
||||
import { calculateSize, humanFileSize } from '$lib/helpers/sizeConvertion';
|
||||
import { Query, type Models } from '@appwrite.io/console';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import Delete from './delete.svelte';
|
||||
import Create from './create.svelte';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import Activate from './activate.svelte';
|
||||
import { calculateTime } from '$lib/helpers/timeConversion';
|
||||
import { Pill } from '$lib/elements';
|
||||
@@ -50,34 +49,10 @@
|
||||
let showAlert = true;
|
||||
|
||||
let selectedDeployment: Models.Deployment = null;
|
||||
let activeDeployment: Models.Deployment = null;
|
||||
|
||||
async function getActiveDeployment() {
|
||||
if (!$func?.deployment) return null;
|
||||
const list = await sdk.forProject.functions.listDeployments($page.params.function, [
|
||||
Query.equal('$id', $func.deployment)
|
||||
]);
|
||||
return list?.deployments?.[0];
|
||||
}
|
||||
|
||||
function handleActivate() {
|
||||
invalidate(Dependencies.DEPLOYMENTS);
|
||||
}
|
||||
|
||||
deploymentList.subscribe((list: Models.DeploymentList | null) => {
|
||||
if (list?.deployments) {
|
||||
let activeDep = list.deployments.find(
|
||||
(deployment) => deployment.$id === $func.deployment
|
||||
);
|
||||
if (!activeDep) {
|
||||
getActiveDeployment().then((deployment) => {
|
||||
activeDeployment = deployment;
|
||||
});
|
||||
} else {
|
||||
activeDeployment = activeDep;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
@@ -86,6 +61,7 @@
|
||||
<Create main />
|
||||
</div>
|
||||
{#if $deploymentList?.total}
|
||||
{@const activeDeployment = data.activeDeployment}
|
||||
<div class="common-section">
|
||||
<Heading tag="h3" size="7">Active</Heading>
|
||||
</div>
|
||||
@@ -113,8 +89,8 @@
|
||||
<div class="u-grid-equal-row-size u-gap-4 u-line-height-1">
|
||||
<p><b>Deployment ID</b></p>
|
||||
|
||||
<Id value={$func.deployment}>
|
||||
{$func.deployment}
|
||||
<Id value={activeDeployment.$id}>
|
||||
{activeDeployment.$id}
|
||||
</Id>
|
||||
</div>
|
||||
</div>
|
||||
@@ -197,7 +173,6 @@
|
||||
</div>
|
||||
</Empty>
|
||||
{/if}
|
||||
|
||||
<div class="common-section">
|
||||
<Heading tag="h3" size="7">All</Heading>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends, url, route, parent }) => {
|
||||
await parent();
|
||||
const data = await parent();
|
||||
depends(Dependencies.DEPLOYMENTS);
|
||||
const page = getPage(url);
|
||||
const limit = getLimit(url, route, PAGE_LIMIT);
|
||||
@@ -14,6 +14,12 @@ export const load: PageLoad = async ({ params, depends, url, route, parent }) =>
|
||||
return {
|
||||
offset,
|
||||
limit,
|
||||
activeDeployment: data.function.deployment
|
||||
? await sdk.forProject.functions.getDeployment(
|
||||
params.function,
|
||||
data.function.deployment
|
||||
)
|
||||
: null,
|
||||
deploymentList: await sdk.forProject.functions.listDeployments(params.function, [
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal title="Create CLI deployment" size="big" bind:show>
|
||||
<Modal title="Create CLI deployment" size="big" bind:show headerDivider={false}>
|
||||
<p class="text">
|
||||
Deploy your function using the Appwrite CLI by running the following command inside your
|
||||
function's folder.
|
||||
|
||||
+45
-47
@@ -8,7 +8,7 @@
|
||||
export let show = false;
|
||||
</script>
|
||||
|
||||
<Modal title="Create git deployment" size="big" bind:show headerDivider={false}>
|
||||
<Modal title="Create Git deployment" size="big" bind:show headerDivider={false}>
|
||||
{#if $func.installationId && $func.providerRepositoryId}
|
||||
<p class="text">
|
||||
Deploy your function from the Git provider of your choice by following the steps below.
|
||||
@@ -19,52 +19,50 @@
|
||||
class="link">documentation</a
|
||||
>.
|
||||
</p>
|
||||
<Box>
|
||||
<NumericList>
|
||||
<NumericListItem fullWidth>
|
||||
<span class="text">Checkout your production branch.</span>
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code
|
||||
language="sh"
|
||||
withCopy
|
||||
noMargin
|
||||
noBoxPadding
|
||||
code={`git checkout ${$func.providerBranch}`} />
|
||||
</div>
|
||||
</NumericListItem>
|
||||
<NumericListItem fullWidth>
|
||||
<span class="text"> Add your changes</span>
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code language="sh" withCopy noMargin noBoxPadding code={`git add .`} />
|
||||
</div>
|
||||
</NumericListItem>
|
||||
<NumericListItem fullWidth>
|
||||
<span class="text"> Create a new commit </span>
|
||||
<div class="u-margin-block-start-16 u-min-width-0 u-grid">
|
||||
<Code
|
||||
language="sh"
|
||||
withCopy
|
||||
noMargin
|
||||
noBoxPadding
|
||||
code={`git commit -m "deploying with Appwrite"`} />
|
||||
</div>
|
||||
</NumericListItem>
|
||||
<NumericListItem fullWidth>
|
||||
<span class="text"> Push your new commit</span>
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code
|
||||
language="sh"
|
||||
withCopy
|
||||
noMargin
|
||||
noBoxPadding
|
||||
code={`git push ${$func.providerBranch}`} />
|
||||
</div>
|
||||
</NumericListItem>
|
||||
<NumericListItem>
|
||||
<span class="text"> A new deployment will be triggered automatically. </span>
|
||||
</NumericListItem>
|
||||
</NumericList>
|
||||
</Box>
|
||||
<NumericList>
|
||||
<NumericListItem fullWidth>
|
||||
<span class="text">Checkout your production branch.</span>
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code
|
||||
language="sh"
|
||||
withCopy
|
||||
noMargin
|
||||
noBoxPadding
|
||||
code={`git checkout ${$func.providerBranch}`} />
|
||||
</div>
|
||||
</NumericListItem>
|
||||
<NumericListItem fullWidth>
|
||||
<span class="text"> Add your changes</span>
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code language="sh" withCopy noMargin noBoxPadding code={`git add .`} />
|
||||
</div>
|
||||
</NumericListItem>
|
||||
<NumericListItem fullWidth>
|
||||
<span class="text"> Create a new commit </span>
|
||||
<div class="u-margin-block-start-16 u-min-width-0 u-grid">
|
||||
<Code
|
||||
language="sh"
|
||||
withCopy
|
||||
noMargin
|
||||
noBoxPadding
|
||||
code={`git commit -m "deploying with Appwrite"`} />
|
||||
</div>
|
||||
</NumericListItem>
|
||||
<NumericListItem fullWidth>
|
||||
<span class="text"> Push your new commit</span>
|
||||
<div class="u-margin-block-start-16">
|
||||
<Code
|
||||
language="sh"
|
||||
withCopy
|
||||
noMargin
|
||||
noBoxPadding
|
||||
code={`git push ${$func.providerBranch}`} />
|
||||
</div>
|
||||
</NumericListItem>
|
||||
<NumericListItem>
|
||||
<span class="text"> A new deployment will be triggered automatically. </span>
|
||||
</NumericListItem>
|
||||
</NumericList>
|
||||
{:else}
|
||||
<Box>
|
||||
<div class="u-flex u-gap-16">
|
||||
|
||||
+15
-12
@@ -1,12 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
InputChoice,
|
||||
Button,
|
||||
InputFile,
|
||||
FormList,
|
||||
InputTextarea,
|
||||
InputText
|
||||
} from '$lib/elements/forms';
|
||||
import { InputChoice, Button, InputFile, FormList, InputText } from '$lib/elements/forms';
|
||||
import { Alert, Collapsible, CollapsibleItem, Modal } from '$lib/components';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
@@ -55,7 +48,13 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal title="Create manual deployment" {error} size="big" bind:show onSubmit={create}>
|
||||
<Modal
|
||||
title="Create manual deployment"
|
||||
{error}
|
||||
size="big"
|
||||
bind:show
|
||||
onSubmit={create}
|
||||
headerDivider={false}>
|
||||
<p class="text">
|
||||
Manually deploy a function by uploading a zip file containing the source code and a relative
|
||||
path to the entry point.
|
||||
@@ -66,7 +65,7 @@
|
||||
class="link">Learn more about function deployments</a
|
||||
>.
|
||||
</p>
|
||||
<FormList>
|
||||
<FormList gap={16}>
|
||||
<InputFile
|
||||
label="Gzipped code (tar.gz)"
|
||||
allowedFileExtensions={['gz']}
|
||||
@@ -93,8 +92,12 @@
|
||||
<CollapsibleItem>
|
||||
<svelte:fragment slot="title">Build settings</svelte:fragment>
|
||||
<svelte:fragment slot="subtitle">(optional)</svelte:fragment>
|
||||
<FormList>
|
||||
<InputTextarea
|
||||
<FormList gap={16}>
|
||||
<p class="text">
|
||||
Overwrite your function configuration for a single deployment or save
|
||||
commands for future use.
|
||||
</p>
|
||||
<InputText
|
||||
label="Commands"
|
||||
placeholder="Enter a build commad (e.g. 'npm install')"
|
||||
tooltip="Enter a single command or chain multiple commands with the && operator"
|
||||
|
||||
+3
-2
@@ -113,13 +113,14 @@
|
||||
<Card>
|
||||
<div class="u-stretch u-overflow-hidden">
|
||||
<section class="code-panel">
|
||||
<header class="code-panel-header u-flex u-main-space-between u-width-full-line">
|
||||
<header
|
||||
class="code-panel-header u-flex u-main-space-between u-width-full-line u-flex-wrap u-gap-16">
|
||||
<div class="u-flex u-flex-vertical">
|
||||
<h4 class="u-bold">Build {$func.name}</h4>
|
||||
{#if $deployment.status === 'building'}
|
||||
<span>Building...</span>
|
||||
{:else}
|
||||
{$deployment.status}
|
||||
<span class="u-capitalize">{$deployment.status}</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -147,66 +147,68 @@
|
||||
tooltip="Headers should contain alphanumeric characters (a-z, A-Z, and 0-9) and hyphens only (- and _).">
|
||||
Headers
|
||||
</Label>
|
||||
<div class="form u-grid u-gap-8 u-margin-block-start-8">
|
||||
<FormList>
|
||||
{#if headers}
|
||||
{#each headers as [name, value], index}
|
||||
<FormItem isMultiple>
|
||||
<InputText
|
||||
isMultiple
|
||||
fullWidth
|
||||
label="Name"
|
||||
placeholder="Enter Name"
|
||||
id={`key-${index}`}
|
||||
bind:value={name} />
|
||||
<InputText
|
||||
isMultiple
|
||||
fullWidth
|
||||
label="Value"
|
||||
placeholder="Enter value"
|
||||
id={`value-${index}`}
|
||||
bind:value />
|
||||
<FormItemPart alignEnd>
|
||||
<Button
|
||||
text
|
||||
noMargin
|
||||
disabled={(!name || !value) && index === 0}
|
||||
on:click={() => {
|
||||
if (index === 0) {
|
||||
headers = [['', '']];
|
||||
} else {
|
||||
headers.splice(index, 1);
|
||||
headers = headers;
|
||||
}
|
||||
}}>
|
||||
<span class="icon-x" aria-hidden="true" />
|
||||
</Button>
|
||||
</FormItemPart>
|
||||
</FormItem>
|
||||
{/each}
|
||||
{/if}
|
||||
</FormList>
|
||||
<Button
|
||||
noMargin
|
||||
text
|
||||
disabled={headers?.length &&
|
||||
headers[headers.length - 1][0] &&
|
||||
headers[headers.length - 1][1]
|
||||
? false
|
||||
: true}
|
||||
on:click={() => {
|
||||
if (
|
||||
headers[headers.length - 1][0] &&
|
||||
headers[headers.length - 1][1]
|
||||
) {
|
||||
headers.push(['', '']);
|
||||
headers = headers;
|
||||
}
|
||||
}}>
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Add Header</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form u-grid u-gap-16">
|
||||
<FormList>
|
||||
{#if headers}
|
||||
{#each headers as [name, value], index}
|
||||
<FormItem isMultiple>
|
||||
<InputText
|
||||
isMultiple
|
||||
fullWidth
|
||||
label="Name"
|
||||
placeholder="Enter Name"
|
||||
id={`key-${index}`}
|
||||
bind:value={name} />
|
||||
<InputText
|
||||
isMultiple
|
||||
fullWidth
|
||||
label="Value"
|
||||
placeholder="Enter value"
|
||||
id={`value-${index}`}
|
||||
bind:value />
|
||||
<FormItemPart alignEnd>
|
||||
<Button
|
||||
text
|
||||
disabled={(!name || !value) && index === 0}
|
||||
on:click={() => {
|
||||
if (index === 0) {
|
||||
headers = [['', '']];
|
||||
} else {
|
||||
headers.splice(index, 1);
|
||||
headers = headers;
|
||||
}
|
||||
}}>
|
||||
<span class="icon-x" aria-hidden="true" />
|
||||
</Button>
|
||||
</FormItemPart>
|
||||
</FormItem>
|
||||
{/each}
|
||||
{/if}
|
||||
</FormList>
|
||||
<Button
|
||||
noMargin
|
||||
text
|
||||
disabled={headers?.length &&
|
||||
headers[headers.length - 1][0] &&
|
||||
headers[headers.length - 1][1]
|
||||
? false
|
||||
: true}
|
||||
on:click={() => {
|
||||
if (
|
||||
headers[headers.length - 1][0] &&
|
||||
headers[headers.length - 1][1]
|
||||
) {
|
||||
headers.push(['', '']);
|
||||
headers = headers;
|
||||
}
|
||||
}}>
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Add Header</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<InputTextarea
|
||||
label="Body"
|
||||
placeholder={`{ "myKey": "myValue" }`}
|
||||
|
||||
+2
-2
@@ -64,8 +64,8 @@
|
||||
state="warning"
|
||||
headerDivider={false}>
|
||||
<p data-private>
|
||||
Are you sure you want to disconnect {$func.name}? This will affect future deployments to
|
||||
this function.
|
||||
Are you sure you want to disconnect <b>{$func.name}</b>? This will affect future deployments
|
||||
to this function.
|
||||
</p>
|
||||
<svelte:fragment slot="footer">
|
||||
<Button text on:click={() => (show = false)}>Cancel</Button>
|
||||
|
||||
+7
-16
@@ -102,15 +102,6 @@
|
||||
azure = 'Azure'
|
||||
}
|
||||
|
||||
function getProviderIcon(provider: string) {
|
||||
switch (provider) {
|
||||
case 'github':
|
||||
return 'icon-github';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function getRepositoryLink(repository: Models.ProviderRepository) {
|
||||
switch (repository.provider) {
|
||||
case 'github':
|
||||
@@ -218,21 +209,21 @@
|
||||
</svelte:fragment>
|
||||
{#if repository}
|
||||
<Box radius="small">
|
||||
<div class="u-flex u-gap-16">
|
||||
<div class="avatar is-size-x-small">
|
||||
<span class={getProviderIcon(repository.provider)} />
|
||||
</div>
|
||||
<div class="u-cross-child-center u-line-height-1-5">
|
||||
<div class="u-flex u-gap-8">
|
||||
<SvgIcon name={repository.provider} iconSize="xlarge" />
|
||||
<div class="u-line-height-1-5">
|
||||
<h6 class="u-bold u-trim-1">
|
||||
{repository.name}
|
||||
{#if repository.private}
|
||||
<span
|
||||
class="icon-lock-closed"
|
||||
class="icon-lock-closed u-color-text-gray"
|
||||
style="font-size: var(--icon-size-small)"
|
||||
aria-hidden="true" />
|
||||
{/if}
|
||||
</h6>
|
||||
<p>Last updated: {toLocaleDateTime(repository.pushedAt)}</p>
|
||||
<p class="u-color-text-gray">
|
||||
Last updated: {toLocaleDateTime(repository.pushedAt)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="u-margin-block-start-24">
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
onSubmit={() => {
|
||||
dispatch('promoted');
|
||||
}}
|
||||
icon="exclamation"
|
||||
state="warning"
|
||||
headerDivider={false}>
|
||||
<svelte:fragment slot="title">
|
||||
{isConflicting ? 'Overwrite global variable' : 'Promote variable'}
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
import Modal from '$lib/components/modal.svelte';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import Button from '$lib/elements/forms/button.svelte';
|
||||
import { base } from '$app/paths';
|
||||
import { app } from '$lib/stores/app';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Query, type Models } from '@appwrite.io/console';
|
||||
import { Avatar } from '$lib/components';
|
||||
import { SvgIcon } from '$lib/components';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
|
||||
export let showGitDisconnect: boolean;
|
||||
@@ -68,21 +66,17 @@
|
||||
{#if functions.total}
|
||||
<div class="u-flex u-flex-vertical u-gap-12">
|
||||
{#each functions.functions as func}
|
||||
<div class="u-flex u-main-space-between u-cross-center u-width-full-line">
|
||||
<div class="u-flex u-main-start u-cross-center u-gap-8">
|
||||
<Avatar
|
||||
size={24}
|
||||
name={func.runtime.split('-')[0]}
|
||||
src={`${base}/icons/${$app.themeInUse}/color/${
|
||||
func.runtime.split('-')[0]
|
||||
}.svg`} />
|
||||
|
||||
<div class="u-flex u-main-start u-gap-8">
|
||||
<div class="avatar is-size-x-small">
|
||||
<SvgIcon name={func.runtime.split('-')[0]} />
|
||||
</div>
|
||||
<div
|
||||
class="u-cross-child-center u-flex u-main-space-between u-flex-wrap u-gap-8 u-width-full-line">
|
||||
<h6>{func.name}</h6>
|
||||
<p class="u-x-small" style="color: hsl(var(--color-neutral-70));">
|
||||
Last deployed: {toLocaleDateTime(func.$updatedAt)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p class="u-x-small" style="color: hsl(var(--color-neutral-70));">
|
||||
Last deployed: {toLocaleDateTime(func.$updatedAt)}
|
||||
</p>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -174,8 +174,9 @@
|
||||
</script>
|
||||
|
||||
<CardGrid>
|
||||
<Heading tag="h6" size="7" id="variables"
|
||||
>{isGlobal ? 'Global Variables' : 'Environment Variables'}</Heading>
|
||||
<Heading tag="h6" size="7" id="variables">
|
||||
{isGlobal ? 'Global variables' : 'Environment variables'}
|
||||
</Heading>
|
||||
{#if isGlobal}
|
||||
<p>
|
||||
Set the environment variables or secret keys that will be passed to all functions within
|
||||
@@ -216,7 +217,7 @@
|
||||
</div>
|
||||
{@const sum = variableList.total}
|
||||
{#if sum}
|
||||
<div class="u-flex u-flex-vertical u-gap-16">
|
||||
<div class="u-flex u-flex-vertical u-gap-24">
|
||||
{#if conflictVariables.length > 0}
|
||||
<Alert type="warning">
|
||||
<p class="text">
|
||||
@@ -227,7 +228,7 @@
|
||||
{/if}
|
||||
a naming conflict with a global variable. View global variables in
|
||||
<a
|
||||
href={`${base}/console/project-${$project.$id}/settings/variables`}
|
||||
href={`${base}/console/project-${$project.$id}/settings`}
|
||||
title="Project settings"
|
||||
class="link">
|
||||
project settings</a
|
||||
@@ -237,9 +238,9 @@
|
||||
{/if}
|
||||
<Table noMargin noStyles>
|
||||
<TableHeader>
|
||||
<TableCellHead>Key</TableCellHead>
|
||||
<TableCellHead width={180}>Key</TableCellHead>
|
||||
<TableCellHead width={180}>Value</TableCellHead>
|
||||
<TableCellHead width={30} />
|
||||
<TableCellHead width={40} />
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each variableList.variables.slice(offset, offset + limit) as variable, i}
|
||||
@@ -251,16 +252,16 @@
|
||||
globalVariable.key === variable.key
|
||||
) !== undefined
|
||||
: false}
|
||||
{#if isConflicting}
|
||||
<span
|
||||
class="icon-exclamation u-color-text-warning"
|
||||
aria-hidden="true" />
|
||||
{/if}
|
||||
<div
|
||||
style:display="inline-block"
|
||||
style:margin-left={!isConflicting && hasConflictOnPage
|
||||
? '1.5rem'
|
||||
: '0rem'}>
|
||||
class={isConflicting && hasConflictOnPage
|
||||
? 'u-flex u-gap-4 u-cross-center'
|
||||
: ''}>
|
||||
{#if isConflicting && hasConflictOnPage}
|
||||
<span
|
||||
class="icon-exclamation u-color-text-warning"
|
||||
aria-hidden="true" />
|
||||
{/if}
|
||||
|
||||
<Output value={variable.key} hideCopyIcon>
|
||||
{variable.key}
|
||||
</Output>
|
||||
|
||||
@@ -68,10 +68,13 @@
|
||||
<svelte:fragment slot="title">
|
||||
Import new {isGlobal ? 'global' : 'environment'} variables
|
||||
</svelte:fragment>
|
||||
<div class="u-flex u-flex-vertical u-gap-24">
|
||||
<div class="u-flex u-flex-vertical u-gap-24 u-margin-block-start-8">
|
||||
<p>
|
||||
Import new {isGlobal ? 'global' : 'environment'} variables from .env file that will be passed
|
||||
to {isGlobal ? 'all functions within your project' : 'your function'}.
|
||||
Import new {isGlobal ? 'global' : 'environment'} variables from
|
||||
<span class="inline-code">.env</span>
|
||||
file that will be passed to {isGlobal
|
||||
? 'all functions within your project'
|
||||
: 'your function'}.
|
||||
</p>
|
||||
|
||||
{#if variableList.total > 0}
|
||||
|
||||
Reference in New Issue
Block a user