mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Shared variables support
This commit is contained in:
Generated
+7
-7
@@ -9,7 +9,7 @@
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@analytics/google-analytics": "^1.0.5",
|
||||
"@aw-labs/appwrite-console": "npm:matej-appwrite-console@7.1.8",
|
||||
"@aw-labs/appwrite-console": "npm:matej-appwrite-console@7.1.9",
|
||||
"@aw-labs/icons": "0.0.0-77",
|
||||
"@aw-labs/ui": "0.0.0-77",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
@@ -146,9 +146,9 @@
|
||||
},
|
||||
"node_modules/@aw-labs/appwrite-console": {
|
||||
"name": "matej-appwrite-console",
|
||||
"version": "7.1.8",
|
||||
"resolved": "https://registry.npmjs.org/matej-appwrite-console/-/matej-appwrite-console-7.1.8.tgz",
|
||||
"integrity": "sha512-OhhxzcX0mZAjVSlS5A9U8AOw4LEQ8cPTFLsY86LQTqBqBTjEm+qT5MBTkeaeiEPXdL1+MzoqQgZOL+XXQ+RPJQ==",
|
||||
"version": "7.1.9",
|
||||
"resolved": "https://registry.npmjs.org/matej-appwrite-console/-/matej-appwrite-console-7.1.9.tgz",
|
||||
"integrity": "sha512-3sYGFRfUZK0f6caBHCVTw4F6thKlq1/HgqLg5bOfB+gIz5u8ADRPhjPL5CukdN35vLyJkWvn92rOcCr65tY1tA==",
|
||||
"dependencies": {
|
||||
"cross-fetch": "3.1.5",
|
||||
"isomorphic-form-data": "2.0.0"
|
||||
@@ -7741,9 +7741,9 @@
|
||||
"integrity": "sha512-1Yw7u/COtxx06BfwlI+kVhsa/upKYzmCNrT4c8QDeCY2KMYlnijkUjtHiPU08HxyTIVB5j6d75O0YWVIHwQS8g=="
|
||||
},
|
||||
"@aw-labs/appwrite-console": {
|
||||
"version": "npm:matej-appwrite-console@7.1.8",
|
||||
"resolved": "https://registry.npmjs.org/matej-appwrite-console/-/matej-appwrite-console-7.1.8.tgz",
|
||||
"integrity": "sha512-OhhxzcX0mZAjVSlS5A9U8AOw4LEQ8cPTFLsY86LQTqBqBTjEm+qT5MBTkeaeiEPXdL1+MzoqQgZOL+XXQ+RPJQ==",
|
||||
"version": "npm:matej-appwrite-console@7.1.9",
|
||||
"resolved": "https://registry.npmjs.org/matej-appwrite-console/-/matej-appwrite-console-7.1.9.tgz",
|
||||
"integrity": "sha512-3sYGFRfUZK0f6caBHCVTw4F6thKlq1/HgqLg5bOfB+gIz5u8ADRPhjPL5CukdN35vLyJkWvn92rOcCr65tY1tA==",
|
||||
"requires": {
|
||||
"cross-fetch": "3.1.5",
|
||||
"isomorphic-form-data": "2.0.0"
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
"dependencies": {
|
||||
"@analytics/google-analytics": "^1.0.5",
|
||||
"analytics": "^0.8.1",
|
||||
"@aw-labs/appwrite-console": "npm:matej-appwrite-console@7.1.8",
|
||||
"@aw-labs/appwrite-console": "npm:matej-appwrite-console@7.1.9",
|
||||
"@aw-labs/icons": "0.0.0-77",
|
||||
"@aw-labs/ui": "0.0.0-77",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@
|
||||
|
||||
<Modal bind:show={showCreate} on:submit={handleVariable} size="big">
|
||||
<svelte:fragment slot="header">
|
||||
{selectedVar ? 'Update' : 'Create'} Variable
|
||||
{selectedVar ? 'Update' : 'Create'} Environment Variable
|
||||
</svelte:fragment>
|
||||
<FormList>
|
||||
<InputText
|
||||
@@ -0,0 +1,56 @@
|
||||
<script lang="ts">
|
||||
import { Modal } from '$lib/components';
|
||||
import Code from '$lib/components/code.svelte';
|
||||
import Tab from '$lib/components/tab.svelte';
|
||||
import Tabs from '$lib/components/tabs.svelte';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
|
||||
export let showSnippet = false;
|
||||
export let variableKey: string;
|
||||
|
||||
// TODO: @Meldiron Finish or delete this component
|
||||
|
||||
enum Language {
|
||||
NodeJS,
|
||||
Python,
|
||||
Dart,
|
||||
Ruby,
|
||||
Java
|
||||
}
|
||||
let language: Language = Language.NodeJS;
|
||||
</script>
|
||||
|
||||
<Modal bind:show={showSnippet} size="big">
|
||||
<svelte:fragment slot="header">Code Snippet</svelte:fragment>
|
||||
<p>Snippet of a code showing how to read environment variables in Appwrite Functions.</p>
|
||||
<Tabs>
|
||||
<Tab on:click={() => (language = Language.NodeJS)} selected={language === Language.NodeJS}>
|
||||
Node.JS
|
||||
</Tab>
|
||||
<Tab on:click={() => (language = Language.Python)} selected={language === Language.Python}>
|
||||
Python
|
||||
</Tab>
|
||||
<Tab on:click={() => (language = Language.Dart)} selected={language === Language.Dart}>
|
||||
Dart
|
||||
</Tab>
|
||||
<Tab on:click={() => (language = Language.Ruby)} selected={language === Language.Ruby}>
|
||||
Ruby
|
||||
</Tab>
|
||||
<Tab on:click={() => (language = Language.Java)} selected={language === Language.Java}>
|
||||
Java
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
{#if language === Language.NodeJS}
|
||||
<Code
|
||||
withLineNumbers
|
||||
withCopy
|
||||
language="js"
|
||||
label="JavaScript"
|
||||
code={`process.env['${variableKey}']`} />
|
||||
{/if}
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<Button text on:click={() => (showSnippet = false)}>Close</Button>
|
||||
</svelte:fragment>
|
||||
</Modal>
|
||||
+6
-3
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
// TODO: This is outdated. Update before using
|
||||
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { Modal } from '$lib/components';
|
||||
@@ -28,7 +30,7 @@
|
||||
invalidate(Dependencies.VARIABLES);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: 'Variable uploaded'
|
||||
message: 'Environment Variables uploaded'
|
||||
});
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
@@ -60,9 +62,10 @@
|
||||
</script>
|
||||
|
||||
<Modal bind:show on:submit={handleSubmit}>
|
||||
<svelte:fragment slot="header">Upload Variables</svelte:fragment>
|
||||
<svelte:fragment slot="header">Upload Environment Variables</svelte:fragment>
|
||||
<p>
|
||||
Upload multiple variables via a .env file that will be passed to your function at runtime.
|
||||
Upload multiple environment variables via a .env file that will be passed to your function
|
||||
at runtime and during build.
|
||||
</p>
|
||||
|
||||
<InputFile bind:files label="Attach a file" />
|
||||
@@ -0,0 +1,320 @@
|
||||
<script lang="ts">
|
||||
import Button from '$lib/elements/forms/button.svelte';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import Copy from '../copy.svelte';
|
||||
import Modal from '../modal.svelte';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
import DropList from '../dropList.svelte';
|
||||
import DropListItem from '../dropListItem.svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import Snippet from './snippet.svelte';
|
||||
import Create from './create.svelte';
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
import Alert from '../alert.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import Empty from '../empty.svelte';
|
||||
|
||||
export let variables: { total: number; variables: Partial<Models.Variable>[] };
|
||||
export let isShared = false;
|
||||
export let isWizard = false;
|
||||
|
||||
export let deleteVariable: (variableId: string) => Promise<void>;
|
||||
export let createVariable: (key: string, value: string) => Promise<void>;
|
||||
export let updateVariable: (variableId: string, key: string, value: string) => Promise<void>;
|
||||
|
||||
const sharedVariablesUrl = `/console/project-${$page.params.project}/settings/variables`;
|
||||
|
||||
let showPromote = false;
|
||||
let promoteVariable: Partial<Models.Variable>;
|
||||
|
||||
let showSnippet = false;
|
||||
let snippetKey = '';
|
||||
|
||||
let showVariablesValue = [];
|
||||
let showVariablesDropdown = [];
|
||||
|
||||
let showVariablesModal = false;
|
||||
let selectedVar: Partial<Models.Variable> = null;
|
||||
|
||||
function downloadVariables() {
|
||||
if (variables.total) {
|
||||
let content = variables.variables
|
||||
.map((variable) => `${variable.key}=${variable.value}`)
|
||||
.join('\n');
|
||||
const file = new File([content], '.env', {
|
||||
type: 'application/x-envoy'
|
||||
});
|
||||
|
||||
const link = document.createElement('a');
|
||||
const url = URL.createObjectURL(file);
|
||||
|
||||
link.href = url;
|
||||
link.download = file.name;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleVariableDeleted(variable: Partial<Models.Variable>) {
|
||||
try {
|
||||
await deleteVariable(variable.$id);
|
||||
|
||||
if (!isWizard) {
|
||||
invalidate(Dependencies.VARIABLES);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `Environment variable has been deleted`
|
||||
});
|
||||
trackEvent('submit_variable_delete');
|
||||
}
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePromote(variable: Partial<Models.Variable>) {
|
||||
try {
|
||||
await sdkForProject.project.createVariable(variable.key, variable.value);
|
||||
await deleteVariable(variable.$id);
|
||||
|
||||
if (!isWizard) {
|
||||
invalidate(Dependencies.VARIABLES);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `Environment variable has been promoted`
|
||||
});
|
||||
trackEvent('submit_variable_promote');
|
||||
}
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
});
|
||||
} finally {
|
||||
showPromote = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleVariableCreated(event: CustomEvent<Models.Variable>) {
|
||||
const variable = event.detail;
|
||||
|
||||
try {
|
||||
await createVariable(variable.key, variable.value);
|
||||
showVariablesModal = false;
|
||||
|
||||
if (!isWizard) {
|
||||
invalidate(Dependencies.VARIABLES);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `Environment variable have been created`
|
||||
});
|
||||
trackEvent('submit_variable_create');
|
||||
}
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handleVariableUpdated(event: CustomEvent<Models.Variable>) {
|
||||
const variable = event.detail;
|
||||
try {
|
||||
await updateVariable(variable.$id, variable.key, variable.value);
|
||||
selectedVar = null;
|
||||
showVariablesModal = false;
|
||||
|
||||
if (!isWizard) {
|
||||
invalidate(Dependencies.VARIABLES);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `Environment variable have been updated`
|
||||
});
|
||||
trackEvent('submit_variable_update');
|
||||
}
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if variables.variables.length}
|
||||
{#if !isWizard}
|
||||
<div class="u-flex u-margin-inline-start-auto u-gap-16">
|
||||
<Button secondary on:click={downloadVariables}>
|
||||
<span class="icon-download" />
|
||||
<span class="text">Download .env file</span>
|
||||
</Button>
|
||||
<!-- <Button secondary on:click={() => (showVariablesUpload = true)}>
|
||||
<span class="icon-upload" />
|
||||
<span class="text">Import .env file</span>
|
||||
</Button> -->
|
||||
</div>
|
||||
{/if}
|
||||
<table class="table is-remove-outer-styles">
|
||||
<thead class="table-thead">
|
||||
<tr class="table-row">
|
||||
<th class="table-thead-col">
|
||||
<span class="eyebrow-heading-3">Key</span>
|
||||
</th>
|
||||
<th class="table-thead-col">
|
||||
<span class="eyebrow-heading-3">Value</span>
|
||||
</th>
|
||||
<th class="table-thead-col" style="--p-col-width:40" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="table-tbody">
|
||||
{#if variables.total}
|
||||
{#each variables.variables as variable, i}
|
||||
<tr class="table-row">
|
||||
<td class="table-col" data-title="Key">
|
||||
<span class="text">{variable.key}</span>
|
||||
</td>
|
||||
<td class="table-col u-overflow-visible" data-title="value">
|
||||
<div class="interactive-text-output">
|
||||
{#if showVariablesValue[i]}
|
||||
<span class="text">{variable.value}</span>
|
||||
{:else}
|
||||
<span class="text">••••••••</span>
|
||||
{/if}
|
||||
<div class="u-flex u-cross-child-start u-gap-8">
|
||||
<button
|
||||
on:click|preventDefault={() =>
|
||||
(showVariablesValue[i] = !showVariablesValue[i])}
|
||||
class="interactive-text-output-button"
|
||||
aria-label="show hidden text">
|
||||
{#if showVariablesValue[i]}
|
||||
<span class="icon-eye-off" aria-hidden="true" />
|
||||
{:else}
|
||||
<span class="icon-eye" aria-hidden="true" />
|
||||
{/if}
|
||||
</button>
|
||||
<Copy bind:value={variable.value}>
|
||||
<button
|
||||
class="interactive-text-output-button"
|
||||
aria-label="copy text">
|
||||
<span class="icon-duplicate" aria-hidden="true" />
|
||||
</button>
|
||||
</Copy>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
on:click={() => {
|
||||
snippetKey = variable.key;
|
||||
showSnippet = true;
|
||||
}}
|
||||
use:tooltip={{
|
||||
content: 'Code snippets',
|
||||
hideOnClick: false
|
||||
}}
|
||||
class="interactive-text-output-button"
|
||||
aria-label="copy code">
|
||||
<span class="icon-code" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="table-col u-overflow-visible" data-title="options">
|
||||
<DropList
|
||||
bind:show={showVariablesDropdown[i]}
|
||||
placement="bottom-start"
|
||||
noArrow>
|
||||
<button
|
||||
class="button is-text is-only-icon"
|
||||
aria-label="more options"
|
||||
on:click|preventDefault={() =>
|
||||
(showVariablesDropdown[i] = !showVariablesDropdown[i])}>
|
||||
<span class="icon-dots-horizontal" aria-hidden="true" />
|
||||
</button>
|
||||
<svelte:fragment slot="list">
|
||||
<DropListItem
|
||||
icon="pencil"
|
||||
on:click={() => {
|
||||
selectedVar = variable;
|
||||
showVariablesDropdown[i] = false;
|
||||
showVariablesModal = true;
|
||||
}}>
|
||||
Edit
|
||||
</DropListItem>
|
||||
<DropListItem
|
||||
icon="trash"
|
||||
on:click={async () => {
|
||||
handleVariableDeleted(variable);
|
||||
showVariablesDropdown[i] = false;
|
||||
}}>
|
||||
Delete
|
||||
</DropListItem>
|
||||
{#if !isShared && !isWizard}
|
||||
<DropListItem
|
||||
icon="globe"
|
||||
on:click={() => {
|
||||
showPromote = true;
|
||||
promoteVariable = variable;
|
||||
}}>Promote</DropListItem>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="u-flex u-margin-block-start-16">
|
||||
<button
|
||||
class="button is-text u-padding-inline-0"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
showVariablesModal = true;
|
||||
}}>
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Create environment variables</span>
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<Empty on:click={() => (showVariablesModal = !showVariablesModal)}
|
||||
>Create an environment variable to get started</Empty>
|
||||
{/if}
|
||||
|
||||
{#if !isShared && !isWizard}
|
||||
<Alert type="info">
|
||||
Shared variables from <a href={sharedVariablesUrl} class="link">project settings</a> are also
|
||||
available. When there is name conflict, function variable is used.
|
||||
</Alert>
|
||||
{/if}
|
||||
|
||||
<Snippet bind:showSnippet variableKey={snippetKey} />
|
||||
{#if showVariablesModal}
|
||||
<Create
|
||||
bind:selectedVar
|
||||
bind:showCreate={showVariablesModal}
|
||||
on:created={handleVariableCreated}
|
||||
on:updated={handleVariableUpdated} />
|
||||
{/if}
|
||||
|
||||
{#if !isShared}
|
||||
<Modal bind:show={showPromote} on:submit={() => handlePromote(promoteVariable)} warning>
|
||||
<svelte:fragment slot="header">Promote To Shared Variable</svelte:fragment>
|
||||
<p>
|
||||
Are you sure you want to promote <code>{promoteVariable.key}</code>? This will move
|
||||
variable into project settings and make it visible to all services.
|
||||
</p>
|
||||
<svelte:fragment slot="footer">
|
||||
<Button text on:click={() => (showPromote = false)}>Cancel</Button>
|
||||
<Button secondary submit>Promote</Button>
|
||||
</svelte:fragment>
|
||||
</Modal>
|
||||
{/if}
|
||||
@@ -7,14 +7,13 @@ import {
|
||||
Health,
|
||||
Locale,
|
||||
Projects,
|
||||
Project,
|
||||
Proxy,
|
||||
Storage,
|
||||
Teams,
|
||||
Users
|
||||
} from '@aw-labs/appwrite-console';
|
||||
|
||||
import { Project } from './project';
|
||||
|
||||
const endpoint =
|
||||
import.meta.env.VITE_APPWRITE_ENDPOINT?.toString() ?? `${window?.location?.origin}/v1`;
|
||||
const clientConsole = new Client();
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
optional: true
|
||||
});
|
||||
stepsComponents.set(5, {
|
||||
label: 'Variables',
|
||||
label: 'Environment Variables',
|
||||
component: Step5,
|
||||
optional: true
|
||||
});
|
||||
|
||||
+29
-219
@@ -1,13 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
CardGrid,
|
||||
Box,
|
||||
DropList,
|
||||
DropListItem,
|
||||
Copy,
|
||||
Empty,
|
||||
EventModal
|
||||
} from '$lib/components';
|
||||
import { CardGrid, Box, Empty, EventModal } from '$lib/components';
|
||||
import { Container } from '$lib/layout';
|
||||
import { Button, InputNumber, InputText, InputCron, Form, FormList } from '$lib/elements/forms';
|
||||
import { base } from '$app/paths';
|
||||
@@ -18,9 +10,6 @@
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import Variable from '../../createVariable.svelte';
|
||||
// import Upload from './uploadVariables.svelte';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { Roles } from '$lib/components/permissions';
|
||||
import { symmetricDifference } from '$lib/helpers/array';
|
||||
@@ -33,16 +22,13 @@
|
||||
import type { PageData } from './$types';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import InputSwitch from '$lib/elements/forms/inputSwitch.svelte';
|
||||
import Variables from '$lib/components/environmentVariables/variables.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
const functionId = $page.params.function;
|
||||
let showDelete = false;
|
||||
let selectedVar: Models.Variable = null;
|
||||
// let showVariablesUpload = false;
|
||||
let showVariablesModal = false;
|
||||
let showVariablesValue = [];
|
||||
let showVariablesDropdown = [];
|
||||
let timeout: number = null;
|
||||
let functionName: string = null;
|
||||
let functionSchedule: string = null;
|
||||
@@ -50,6 +36,8 @@
|
||||
let arePermsDisabled = true;
|
||||
let logging: boolean = null;
|
||||
|
||||
// TODO: @Meldiron implement "Promote"
|
||||
|
||||
const eventSet: Writable<Set<string>> = writable(new Set());
|
||||
let showEvents = false;
|
||||
let areEventsDisabled = true;
|
||||
@@ -221,89 +209,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function handleVariableCreated(event: CustomEvent<Models.Variable>) {
|
||||
const variable = event.detail;
|
||||
|
||||
try {
|
||||
await sdkForProject.functions.createVariable(functionId, variable.key, variable.value);
|
||||
showVariablesModal = false;
|
||||
invalidate(Dependencies.VARIABLES);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${$func.name} variables have been updated`
|
||||
});
|
||||
trackEvent('submit_variable_create');
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handleVariableUpdated(event: CustomEvent<Models.Variable>) {
|
||||
const variable = event.detail;
|
||||
try {
|
||||
await sdkForProject.functions.updateVariable(
|
||||
functionId,
|
||||
variable.$id,
|
||||
variable.key,
|
||||
variable.value
|
||||
);
|
||||
selectedVar = null;
|
||||
showVariablesModal = false;
|
||||
invalidate(Dependencies.VARIABLES);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `${$func.name} variables have been updated`
|
||||
});
|
||||
trackEvent('submit_variable_update');
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
async function handleVariableDeleted(variable: Models.Variable) {
|
||||
try {
|
||||
await sdkForProject.functions.deleteVariable(variable.functionId, variable.$id);
|
||||
invalidate(Dependencies.VARIABLES);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `Variable has been deleted`
|
||||
});
|
||||
trackEvent('submit_variable_delete');
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function downloadVariables() {
|
||||
if (data.variables.total) {
|
||||
let content = data.variables.variables
|
||||
.map((variable) => `${variable.key}=${variable.value}`)
|
||||
.join('\n');
|
||||
const file = new File([content], '.env', {
|
||||
type: 'application/x-envoy'
|
||||
});
|
||||
|
||||
const link = document.createElement('a');
|
||||
const url = URL.createObjectURL(file);
|
||||
|
||||
link.href = url;
|
||||
link.download = file.name;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
function handleEvent(event: CustomEvent) {
|
||||
eventSet.set($eventSet.add(event.detail));
|
||||
}
|
||||
@@ -319,6 +224,18 @@
|
||||
areEventsDisabled = false;
|
||||
} else areEventsDisabled = true;
|
||||
}
|
||||
|
||||
async function deleteVariable(variableId: string) {
|
||||
await sdkForProject.functions.deleteVariable($func.$id, variableId);
|
||||
}
|
||||
|
||||
async function createVariable(key: string, value: string) {
|
||||
await sdkForProject.functions.createVariable($func.$id, key, value);
|
||||
}
|
||||
|
||||
async function updateVariable(variableId: string, key: string, value: string) {
|
||||
await sdkForProject.functions.updateVariable($func.$id, variableId, key, value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
@@ -510,120 +427,19 @@
|
||||
</Form>
|
||||
|
||||
<CardGrid>
|
||||
<Heading tag="h6" size="7">Update Function Variables</Heading>
|
||||
<p>Set the variables (or secret keys) that will be passed to your function at runtime.</p>
|
||||
<Heading tag="h6" size="7">Update Function Environment Variables</Heading>
|
||||
<p>
|
||||
Set the environment variables (or secret keys) that will be passed to your function at
|
||||
runtime and during build.
|
||||
</p>
|
||||
|
||||
<svelte:fragment slot="aside">
|
||||
<div class="u-flex u-margin-inline-start-auto u-gap-16">
|
||||
<Button secondary on:click={downloadVariables}>
|
||||
<span class="icon-download" />
|
||||
<span class="text">Download .env file</span>
|
||||
</Button>
|
||||
<!-- <Button secondary on:click={() => (showVariablesUpload = true)}>
|
||||
<span class="icon-upload" />
|
||||
<span class="text">Import .env file</span>
|
||||
</Button> -->
|
||||
</div>
|
||||
<table class="table is-remove-outer-styles">
|
||||
<thead class="table-thead">
|
||||
<tr class="table-row">
|
||||
<th class="table-thead-col">
|
||||
<span class="eyebrow-heading-3">Key</span>
|
||||
</th>
|
||||
<th class="table-thead-col">
|
||||
<span class="eyebrow-heading-3">Value</span>
|
||||
</th>
|
||||
<th class="table-thead-col" style="--p-col-width:40" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="table-tbody">
|
||||
{#if data.variables.total}
|
||||
{#each data.variables.variables as variable, i}
|
||||
<tr class="table-row">
|
||||
<td class="table-col" data-title="Key">
|
||||
<span class="text">{variable.key}</span>
|
||||
</td>
|
||||
<td class="table-col u-overflow-visible" data-title="value">
|
||||
<div class="interactive-text-output">
|
||||
{#if showVariablesValue[i]}
|
||||
<span class="text">{variable.value}</span>
|
||||
{:else}
|
||||
<span class="text">••••••••</span>
|
||||
{/if}
|
||||
<div class="u-flex u-cross-child-start u-gap-8">
|
||||
<button
|
||||
on:click|preventDefault={() =>
|
||||
(showVariablesValue[i] =
|
||||
!showVariablesValue[i])}
|
||||
class="interactive-text-output-button"
|
||||
aria-label="show hidden text">
|
||||
{#if showVariablesValue[i]}
|
||||
<span class="icon-eye-off" aria-hidden="true" />
|
||||
{:else}
|
||||
<span class="icon-eye" aria-hidden="true" />
|
||||
{/if}
|
||||
</button>
|
||||
<Copy bind:value={variable.value}>
|
||||
<button
|
||||
class="interactive-text-output-button"
|
||||
aria-label="copy text">
|
||||
<span
|
||||
class="icon-duplicate"
|
||||
aria-hidden="true" />
|
||||
</button>
|
||||
</Copy>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="table-col u-overflow-visible" data-title="options">
|
||||
<DropList
|
||||
bind:show={showVariablesDropdown[i]}
|
||||
placement="bottom-start"
|
||||
noArrow>
|
||||
<button
|
||||
class="button is-text is-only-icon"
|
||||
aria-label="more options"
|
||||
on:click|preventDefault={() =>
|
||||
(showVariablesDropdown[i] =
|
||||
!showVariablesDropdown[i])}>
|
||||
<span class="icon-dots-horizontal" aria-hidden="true" />
|
||||
</button>
|
||||
<svelte:fragment slot="list">
|
||||
<DropListItem
|
||||
icon="pencil"
|
||||
on:click={() => {
|
||||
selectedVar = variable;
|
||||
showVariablesDropdown[i] = false;
|
||||
showVariablesModal = true;
|
||||
}}>
|
||||
Edit
|
||||
</DropListItem>
|
||||
<DropListItem
|
||||
icon="trash"
|
||||
on:click={async () => {
|
||||
handleVariableDeleted(variable);
|
||||
showVariablesDropdown[i] = false;
|
||||
}}>
|
||||
Delete
|
||||
</DropListItem>
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="u-flex u-margin-block-start-16">
|
||||
<button
|
||||
class="button is-text u-padding-inline-0"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
showVariablesModal = true;
|
||||
}}>
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="text">Create variable</span>
|
||||
</button>
|
||||
</div>
|
||||
<Variables
|
||||
isShared={false}
|
||||
variables={data.variables}
|
||||
{deleteVariable}
|
||||
{createVariable}
|
||||
{updateVariable} />
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
|
||||
@@ -649,12 +465,6 @@
|
||||
</Container>
|
||||
|
||||
<Delete bind:showDelete />
|
||||
{#if showVariablesModal}
|
||||
<Variable
|
||||
bind:selectedVar
|
||||
bind:showCreate={showVariablesModal}
|
||||
on:created={handleVariableCreated}
|
||||
on:updated={handleVariableUpdated} />
|
||||
{/if}
|
||||
|
||||
<!-- <Upload bind:show={showVariablesUpload} on:uploaded={handleVariableCreated} /> -->
|
||||
<EventModal bind:show={showEvents} on:created={handleEvent} />
|
||||
|
||||
@@ -1,120 +1,46 @@
|
||||
<script lang="ts">
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { createFunction } from './store';
|
||||
import Create from '../createVariable.svelte';
|
||||
import { DropList, DropListItem, Secret, Empty } from '$lib/components';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableCellHead,
|
||||
TableCellText,
|
||||
TableHeader,
|
||||
TableRow
|
||||
} from '$lib/elements/table';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import Variables from '$lib/components/environmentVariables/variables.svelte';
|
||||
|
||||
let showCreate = false;
|
||||
|
||||
let selectedVar: Partial<Models.Variable> = null;
|
||||
let showDropdown = [];
|
||||
|
||||
function handleCreated(dispatchEvent: CustomEvent) {
|
||||
createFunction.update((n) => {
|
||||
if (n.vars.length) {
|
||||
n.vars.map((v) => {
|
||||
if (v.key !== dispatchEvent.detail.key) {
|
||||
n.vars.push(dispatchEvent.detail);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
n.vars.push(dispatchEvent.detail);
|
||||
}
|
||||
|
||||
return n;
|
||||
});
|
||||
async function deleteVariable(variableId: string) {
|
||||
const index = $createFunction.vars.findIndex((variable) => variable.$id === variableId);
|
||||
$createFunction.vars.splice(index, 1);
|
||||
$createFunction = $createFunction;
|
||||
}
|
||||
function handleUpdated(dispatchEvent: CustomEvent) {
|
||||
createFunction.update((n) => {
|
||||
n.vars = n.vars.map((v) => (v.key === selectedVar.key ? dispatchEvent.detail : v));
|
||||
return n;
|
||||
});
|
||||
|
||||
async function createVariable(key: string, value: string) {
|
||||
const index = $createFunction.vars.findIndex((variable) => variable.key === key);
|
||||
|
||||
if (index !== -1) {
|
||||
$createFunction.vars[index].key = key;
|
||||
$createFunction.vars[index].value = value;
|
||||
} else {
|
||||
$createFunction.vars.push({ key, value, $id: Date.now().toString() });
|
||||
}
|
||||
|
||||
$createFunction = $createFunction;
|
||||
}
|
||||
|
||||
async function updateVariable(variableId: string, key: string, value: string) {
|
||||
const index = $createFunction.vars.findIndex((variable) => variable.$id === variableId);
|
||||
$createFunction.vars[index].key = key;
|
||||
$createFunction.vars[index].value = value;
|
||||
$createFunction = $createFunction;
|
||||
}
|
||||
</script>
|
||||
|
||||
<WizardStep>
|
||||
<svelte:fragment slot="title">Variables</svelte:fragment>
|
||||
<svelte:fragment slot="title">Environment Variables</svelte:fragment>
|
||||
<svelte:fragment slot="subtitle">
|
||||
Create a variable (or secret key) that will be passed to your function at runtime.
|
||||
Create an environment variable (or secret key) that will be passed to your function at
|
||||
runtime and during build.
|
||||
</svelte:fragment>
|
||||
{#if $createFunction.vars.length}
|
||||
<Table noStyles>
|
||||
<TableHeader>
|
||||
<TableCellHead>Key</TableCellHead>
|
||||
<TableCellHead>Value</TableCellHead>
|
||||
<TableCellHead width={30} />
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{#each $createFunction.vars as variable, i}
|
||||
<TableRow>
|
||||
<TableCellText title="key">
|
||||
{variable.key}
|
||||
</TableCellText>
|
||||
<TableCell showOverflow title="value">
|
||||
<Secret value={variable.value} />
|
||||
</TableCell>
|
||||
<TableCell showOverflow title="options">
|
||||
<DropList bind:show={showDropdown[i]} placement="bottom-start" noArrow>
|
||||
<button
|
||||
class="button is-text is-only-icon"
|
||||
aria-label="more options"
|
||||
on:click|preventDefault={() =>
|
||||
(showDropdown[i] = !showDropdown[i])}>
|
||||
<span class="icon-dots-horizontal" aria-hidden="true" />
|
||||
</button>
|
||||
<svelte:fragment slot="list">
|
||||
<DropListItem
|
||||
icon="pencil"
|
||||
on:click={() => {
|
||||
selectedVar = $createFunction.vars[i];
|
||||
showDropdown[i] = false;
|
||||
showCreate = true;
|
||||
}}>
|
||||
Edit
|
||||
</DropListItem>
|
||||
<DropListItem
|
||||
icon="trash"
|
||||
on:click={() => {
|
||||
$createFunction.vars.splice(i, 1);
|
||||
$createFunction = $createFunction;
|
||||
showDropdown[i] = false;
|
||||
}}>
|
||||
Delete
|
||||
</DropListItem>
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{/each}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div class="u-flex u-margin-block-start-16">
|
||||
<Button text noMargin on:click={() => (showCreate = !showCreate)}>
|
||||
<span class="icon-plus" aria-hidden="true" />
|
||||
<span class="u-text">Create variable</span>
|
||||
</Button>
|
||||
</div>
|
||||
{:else}
|
||||
<Empty on:click={() => (showCreate = !showCreate)}>Create a variable to get started</Empty>
|
||||
{/if}
|
||||
<Variables
|
||||
isWizard={true}
|
||||
{deleteVariable}
|
||||
{createVariable}
|
||||
{updateVariable}
|
||||
variables={{ total: $createFunction.vars.length, variables: $createFunction.vars }} />
|
||||
</WizardStep>
|
||||
|
||||
{#if showCreate}
|
||||
<Create
|
||||
bind:selectedVar
|
||||
bind:showCreate
|
||||
on:created={handleCreated}
|
||||
on:updated={handleUpdated} />
|
||||
{/if}
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
href: `${path}/webhooks`,
|
||||
title: 'Webhooks',
|
||||
event: 'webhooks'
|
||||
},
|
||||
{
|
||||
href: `${path}/variables`,
|
||||
title: 'Shared Variables',
|
||||
event: 'sharedVariables'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<script lang="ts">
|
||||
import CardGrid from '$lib/components/cardGrid.svelte';
|
||||
import Variables from '$lib/components/environmentVariables/variables.svelte';
|
||||
import Heading from '$lib/components/heading.svelte';
|
||||
import Container from '$lib/layout/container.svelte';
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
async function deleteVariable(variableId: string) {
|
||||
await sdkForProject.project.deleteVariable(variableId);
|
||||
}
|
||||
|
||||
async function createVariable(key: string, value: string) {
|
||||
await sdkForProject.project.createVariable(key, value);
|
||||
}
|
||||
|
||||
async function updateVariable(variableId: string, key: string, value: string) {
|
||||
await sdkForProject.project.updateVariable(variableId, key, value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<CardGrid>
|
||||
<Heading tag="h6" size="7">Update Shared Environment Variables</Heading>
|
||||
<p>Set the environment variables (or secret keys) that will be passed to all resources.</p>
|
||||
|
||||
<svelte:fragment slot="aside">
|
||||
<Variables
|
||||
isShared={true}
|
||||
variables={data.variables}
|
||||
{deleteVariable}
|
||||
{createVariable}
|
||||
{updateVariable} />
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
</Container>
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ parent, depends }) => {
|
||||
await parent();
|
||||
depends(Dependencies.VARIABLES);
|
||||
|
||||
return {
|
||||
variables: await sdkForProject.project.listVariables()
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user