Merge branch 'main' of github.com:appwrite/console into billing

This commit is contained in:
Arman
2023-09-11 10:31:05 +02:00
21 changed files with 353 additions and 243 deletions
+4 -3
View File
@@ -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;
+1 -1
View File
@@ -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>
+1 -2
View File
@@ -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();
+5
View File
@@ -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++;
+148 -4
View File
@@ -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'
}
]
}
];
+11 -10
View File
@@ -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.
@@ -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">
@@ -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"
@@ -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" }`}
@@ -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>
@@ -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}