Merge branch 'main' of github.com:appwrite/console into feat-usage-sh-1.4

 Conflicts:
	package-lock.json
	package.json
This commit is contained in:
shimon
2023-11-26 10:56:00 +02:00
76 changed files with 274 additions and 282 deletions
+1 -3
View File
@@ -145,6 +145,4 @@ dist
.stylelintcache
# SvelteKit build / generate output
.svelte-kit
.svelte-kit
+1 -5
View File
@@ -58,7 +58,6 @@
"eslint-plugin-svelte": "^2.33.0",
"jsdom": "^22.1.0",
"kleur": "^4.1.5",
"pre-commit": "^1.2.2",
"prettier": "^3.0.3",
"prettier-plugin-svelte": "^3.0.3",
"sass": "^1.66.1",
@@ -71,8 +70,5 @@
"vite": "^4.4.9",
"vitest": "^0.29.7"
},
"type": "module",
"pre-commit": [
"lint"
]
"type": "module"
}
+4 -4
View File
@@ -382,9 +382,9 @@
}
:global(.theme-dark) .card {
--cmd-center-bg: hsl(var(--color-neutral-100-new));
--cmd-center-bg: hsl(var(--color-neutral-100));
--cmd-center-border: hsl(var(--color-neutral-150));
--cmd-center-shadow: 0px 16px 32px 0px hsl(var(--color-neutral-110-new));
--cmd-center-shadow: 0px 16px 32px 0px hsl(var(--color-neutral-110));
--kbd-bg: hsl(var(--color-neutral-150));
@@ -394,8 +394,8 @@
--result-bg: hsl(var(--color-neutral-200));
--footer-bg: linear-gradient(
180deg,
hsl(var(--color-neutral-100-new)) 0%,
hsl(var(--color-neutral-85-new)) 100%
hsl(var(--color-neutral-100)) 0%,
hsl(var(--color-neutral-85)) 100%
);
--icon-color: hsl(var(--color-neutral-70));
+16 -13
View File
@@ -7,6 +7,7 @@
import { trackEvent } from '$lib/actions/analytics';
export let single = false;
export let noMedia = false;
export let target: string = null;
export let href: string = null;
@@ -23,21 +24,23 @@
<article class="card u-grid u-cross-center u-width-full-line common-section">
<div
class="u-flex u-flex-vertical u-cross-center u-gap-24 u-width-full-line u-overflow-hidden">
<button
type="button"
on:click|preventDefault
on:click={track}
aria-label={`create {target}`}>
{#if $app.themeInUse === 'dark'}
<img src={EmptyDark} alt="create" aria-hidden="true" width="376" />
{:else}
<img src={EmptyLight} alt="create" aria-hidden="true" width="376" />
{/if}
</button>
{#if !noMedia}
<button
type="button"
on:click|preventDefault
on:click={track}
aria-label="create {target}">
{#if $app.themeInUse === 'dark'}
<img src={EmptyDark} alt="create" aria-hidden="true" width="376" />
{:else}
<img src={EmptyLight} alt="create" aria-hidden="true" width="376" />
{/if}
</button>
{/if}
<slot>
<div class="u-text-center">
<Heading size="7" tag="h2" trimmed={false}>
Create your first {target} to get started.
Create a {target} to get started.
</Heading>
<p class="body-text-2 u-bold u-margin-block-start-4">
Need a hand? Learn more in our documentation.
@@ -49,7 +52,7 @@
{href}
text
event="empty_documentation"
ariaLabel={`create {target}`}>Documentation</Button>
ariaLabel="create {target}">Documentation</Button>
<Button secondary on:click on:click={track}>
Create {target}
</Button>
@@ -4,8 +4,11 @@
import InputText from '$lib/elements/forms/inputText.svelte';
import { Query } from '@appwrite.io/console';
import { createEventDispatcher } from 'svelte';
import { columns } from '../store';
import { tags, type Column, type Operator, queries } from './store';
import { tags, type Operator, queries } from './store';
import type { Column } from '$lib/helpers/types';
import type { Writable } from 'svelte/store';
export let columns: Writable<Column[]>;
const dispatch = createEventDispatcher<{
clear: void;
@@ -31,22 +34,22 @@
'greater than': {
toQuery: (attr, input) => Query.greaterThan(attr, Number(input)),
toTag: (attribute, input) => `**${attribute}** greater than **${input}**`,
types: ['integer', 'double']
types: ['integer', 'double', 'datetime']
},
'greater than or equal to': {
toQuery: (attr, input) => Query.greaterThanEqual(attr, Number(input)),
toTag: (attribute, input) => `**${attribute}** greater than or equal to **${input}**`,
types: ['integer', 'double']
types: ['integer', 'double', 'datetime']
},
'less than': {
toQuery: Query.lessThan,
toTag: (attribute, input) => `**${attribute}** less than **${input}**`,
types: ['integer', 'double']
types: ['integer', 'double', 'datetime']
},
'less than or equal to': {
toQuery: Query.lessThanEqual,
toTag: (attribute, input) => `**${attribute}** less than or equal to **${input}**`,
types: ['integer', 'double']
types: ['integer', 'double', 'datetime']
},
equal: {
toQuery: Query.equal,
@@ -97,19 +100,17 @@
// This Map is keyed by tags, and has a query as the value
function addFilter() {
if (column && operator) {
queries.addFilter({ column, operator, value });
value = null;
}
if (!column || !operator) return;
queries.addFilter({ column, operator, value: value ?? '' });
value = null;
}
function tagFormat(node: HTMLElement) {
node.innerHTML = node.innerHTML.replace(/\*\*(.*?)\*\*/g, '<b>$1</b>');
}
$: isDisabled = (function getDisabled() {
return !operator || (!operator?.hideInput && !value);
})();
$: isDisabled = !operator;
</script>
<div>
@@ -134,6 +135,16 @@
<div class="u-margin-block-start-8">
{#if column.type === 'integer' || column.type === 'double'}
<InputNumber id="value" bind:value placeholder="Enter value" />
{:else if column.type === 'boolean'}
<InputSelect
id="value"
placeholder="Select a value"
required={true}
options={[
{ label: 'True', value: true },
{ label: 'False', value: false }
].filter(Boolean)}
bind:value />
{:else}
<InputText id="value" bind:value placeholder="Enter value" />
{/if}
@@ -2,8 +2,16 @@
import { beforeNavigate } from '$app/navigation';
import { Drop, Modal } from '$lib/components';
import { Button } from '$lib/elements/forms';
import type { Column } from '$lib/helpers/types';
import type { Writable } from 'svelte/store';
import Content from './content.svelte';
import { queries, queriesAreDirty, tags } from './store';
import { queries, queriesAreDirty, queryParamToMap, tags } from './store';
export let query = '[]';
export let columns: Writable<Column[]>;
const parsedQueries = queryParamToMap(query);
queries.set(parsedQueries);
// We need to separate them so we don't trigger Drop's handlers
let showFiltersDesktop = false;
@@ -33,6 +41,7 @@
<div class="dropped card">
<p>Apply filter rules to refine the table view</p>
<Content
{columns}
on:apply={(e) => (applied = e.detail.applied)}
on:clear={() => (applied = 0)} />
<hr />
@@ -61,7 +70,10 @@
description="Apply filter rules to refine the table view"
bind:show={showFiltersMobile}
size="big">
<Content on:apply={(e) => (applied = e.detail.applied)} on:clear={() => (applied = 0)} />
<Content
{columns}
on:apply={(e) => (applied = e.detail.applied)}
on:clear={() => (applied = 0)} />
<svelte:fragment slot="footer">
<Button text on:click={queries.clearAll}>Clear all</Button>
<Button on:click={queries.apply} disabled={!$queriesAreDirty}>Apply</Button
+1
View File
@@ -0,0 +1 @@
export { default as filters } from './filters.svelte';
@@ -1,17 +1,9 @@
import { goto } from '$app/navigation';
import { derived, get, writable, type Writable } from 'svelte/store';
import type { columns } from '../store';
import { derived, get, writable } from 'svelte/store';
import { page } from '$app/stores';
import deepEqual from 'deep-equal';
const columnTypes = ['string', 'integer', 'double', 'boolean', 'datetime', 'relationship'] as const;
type ColumnType = (typeof columnTypes)[number];
type StoreValues<Store> = Store extends Writable<infer T> ? T : never;
export type Column = Omit<StoreValues<typeof columns>[number], 'type'> & {
type: ColumnType;
};
import type { Column, ColumnType } from '$lib/helpers/types';
export type Operator = {
toTag: (attribute: string, input?: string | number) => string;
+1 -1
View File
@@ -127,7 +127,7 @@
</button>
{/if}
</div>
<p>
<p class="u-margin-block-start-4">
<slot name="description">
{description}
</slot>
+18 -15
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { Button, FormList, Helper, InputText } from '$lib/elements/forms';
import { Button, FormItem, FormList, Helper, InputText } from '$lib/elements/forms';
import { createEventDispatcher } from 'svelte';
import { Modal } from '..';
import type { Writable } from 'svelte/store';
@@ -25,21 +25,24 @@
$: disabled = !value || $groups.has(value);
</script>
<Modal title="Custom permission" bind:show on:close={reset} onSubmit={create}>
<p class="text">
Custom permissions allow you to grant access to specific users or teams using their ID and
role.
</p>
<Modal
title="Custom permission"
description="Custom permissions allow you to grant access to specific users or teams using their ID and
role."
bind:show
on:close={reset}
onSubmit={create}>
<FormList>
<InputText
showLabel={false}
id="custom-permission"
label="Custom permission"
placeholder="user:[USER_ID] or team:[TEAM_ID]/[ROLE]"
bind:value />
<Helper type="neutral">
A permission should be formatted as: user:[USER_ID] or team:[TEAM_ID]/[ROLE]¸
</Helper>
<FormItem>
<InputText
id="custom-permission"
label="Role"
placeholder="user:[USER_ID] or team:[TEAM_ID]/[ROLE]"
bind:value />
<Helper type="neutral">
A permission should be formatted as: user:[USER_ID] or team:[TEAM_ID]/[ROLE]¸
</Helper>
</FormItem>
</FormList>
<svelte:fragment slot="footer">
+12 -6
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { Button, FormList, Helper, InputText } from '$lib/elements/forms';
import { Button, FormItem, FormList, Helper, InputText } from '$lib/elements/forms';
import { createEventDispatcher } from 'svelte';
import { Modal } from '..';
import type { Writable } from 'svelte/store';
@@ -32,12 +32,18 @@
$: disabled = !value || $groups.has(value);
</script>
<Modal title="Label" bind:show on:close={reset} onSubmit={create}>
<p class="text">Labels allow you to grant access to users with the specfied label.</p>
<Modal
title="Label"
description="Labels allow you to grant access to users with the specfied label."
bind:show
on:close={reset}
onSubmit={create}>
<FormList>
<InputText showLabel={false} id="label" label="Label" placeholder="admin" bind:value />
<Helper type={isError ? 'warning' : 'neutral'}
>Only alphanumeric characters are allowed.</Helper>
<FormItem>
<InputText id="label" label="Label" placeholder="Enter label" bind:value />
<Helper type={isError ? 'warning' : 'neutral'}
>Only alphanumeric characters are allowed.</Helper>
</FormItem>
</FormList>
<svelte:fragment slot="footer">
+1 -1
View File
@@ -143,7 +143,7 @@
</Actions>
</div>
<div class="common-section">
<span class="text"> Add a role to get started </span>
<span class="text"> Add a role </span>
</div>
</div>
</article>
+1 -9
View File
@@ -1,12 +1,3 @@
<script context="module" lang="ts">
export type Column = {
id: string;
title: string;
show: boolean;
width?: number;
};
</script>
<script lang="ts">
import { Button, InputChoice } from '$lib/elements/forms';
import { DropList } from '.';
@@ -16,6 +7,7 @@
import { onMount } from 'svelte';
import { View } from '$lib/helpers/load';
import { tooltip } from '$lib/actions/tooltip';
import type { Column } from '$lib/helpers/types';
export let columns: Writable<Column[]>;
export let view: View;
+27 -2
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FormItem, Helper, Label } from '.';
import NullCheckbox from './nullCheckbox.svelte';
export let label: string;
export let showLabel = true;
@@ -8,6 +9,7 @@
export let id: string;
export let value = '';
export let required = false;
export let nullable = false;
export let disabled = false;
export let readonly = false;
export let autofocus = false;
@@ -33,9 +35,22 @@
error = element.validationMessage;
}
let prevValue = '';
function handleNullChange(e: CustomEvent<boolean>) {
const isNull = e.detail;
if (isNull) {
prevValue = value;
value = null;
} else {
value = prevValue;
}
}
$: if (value) {
error = null;
}
$: isNullable = nullable && !required;
</script>
<FormItem>
@@ -43,7 +58,7 @@
{label}
</Label>
<div class="input-text-wrapper" style="--amount-of-buttons:1; --button-size: 1rem">
<div class="input-text-wrapper">
<input
{id}
{disabled}
@@ -55,7 +70,17 @@
class="input-text"
bind:value
bind:this={element}
on:invalid={handleInvalid} />
on:invalid={handleInvalid}
style:--amount-of-buttons={isNullable ? 2.75 : 1}
style:--button-size={isNullable ? '2rem' : '1rem'} />
{#if isNullable}
<ul
class="buttons-list u-cross-center u-gap-8 u-position-absolute u-inset-block-start-8 u-inset-block-end-8 u-inset-inline-end-12">
<li class="buttons-list-item">
<NullCheckbox checked={value === null} on:change={handleNullChange} />
</li>
</ul>
{/if}
</div>
{#if error}
<Helper type="warning">{error}</Helper>
+1 -1
View File
@@ -29,7 +29,7 @@
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.typeMismatch) {
error = 'Your email should be formatted as: name@example.com';
error = 'Emails should be formatted as: name@example.com';
return;
}
if (element.validity.valueMissing) {
+4 -4
View File
@@ -2,7 +2,6 @@
import { toggle } from '$lib/helpers/array';
import { isHTMLInputElement } from '$lib/helpers/types';
import { TableCell } from '.';
import { InputCheckbox } from '../forms';
export let id: string;
export let selectedIds: string[] = [];
@@ -30,9 +29,10 @@
tabindex="-1"
on:click={handleClick}
on:keypress={handleClick} />
<InputCheckbox
bind:element={el}
id="select-{id}"
<input
{id}
type="checkbox"
bind:this={el}
checked={selectedIds.includes(id)}
on:click={handleClick} />
</TableCell>
+2 -3
View File
@@ -1,8 +1,6 @@
<script lang="ts">
import { isHTMLInputElement } from '$lib/helpers/types';
import { TableCellHead } from '.';
import { InputCheckbox } from '../forms';
export let selected: string[] = [];
export let pageItemsIds: string[] = [];
@@ -25,9 +23,10 @@
</script>
<TableCellHead width={10}>
<InputCheckbox
<input
id="select-all"
indeterminate={someSelected && !allSelected}
type="checkbox"
checked={allSelected}
on:click={handleClick} />
</TableCellHead>
+4
View File
@@ -32,6 +32,10 @@ export function getSearch(url: URL): string | undefined {
return url.searchParams.get('search') ?? undefined;
}
export function getQuery(url: URL): string | undefined {
return url.searchParams.get('query') ?? undefined;
}
type TabElement = { href: string; title: string; hasChildren?: boolean };
export function isTabSelected(
+10
View File
@@ -12,3 +12,13 @@ export function isHTMLInputElement(el: unknown): el is HTMLInputElement {
// eslint-disable-next-line @typescript-eslint/ban-types
export type Prettify<T> = T & {};
const columnTypes = ['string', 'integer', 'double', 'boolean', 'datetime', 'relationship'] as const;
export type ColumnType = (typeof columnTypes)[number];
export type Column = {
id: string;
title: string;
type: ColumnType;
show: boolean;
width?: number;
};
+5
View File
@@ -24,6 +24,11 @@
{/if}
</div>
</li>
<li class="inline-links-item">
<a href="https://appwrite.io/docs" target="_blank" rel="noreferrer">
<span class="text">Docs</span>
</a>
</li>
<li class="inline-links-item">
<a href="https://appwrite.io/terms" target="_blank" rel="noreferrer">
<span class="text">Terms</span>
+1 -1
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import { Heading, ViewSelector } from '$lib/components';
import type { View } from '$lib/helpers/load';
import type { Column } from '$lib/components/viewSelector.svelte';
import type { Column } from '$lib/helpers/types';
import type { Writable } from 'svelte/store';
export let title: string;
+1 -1
View File
@@ -7,7 +7,7 @@ const TemplateRuntimes = {
NODE: { name: 'node', versions: ['20.0', '19.0', '18.0', '16.0', '14.5'] },
PHP: { name: 'php', versions: ['8.2', '8.1', '8.0'] },
RUBY: { name: 'ruby', versions: ['3.2', '3.1', '3.0'] },
PYTHON: { name: 'python', versions: ['3.11', '3.10', '3.9', '3.8'] },
PYTHON: { name: 'python', versions: ['3.12', '3.11', '3.10', '3.9', '3.8'] },
DART: { name: 'dart', versions: ['3.1', '3.0', '2.19', '2.18', '2.17', '2.16', '2.16'] },
BUN: { name: 'bun', versions: ['1.0'] }
};
+2 -7
View File
@@ -285,13 +285,8 @@
.git-container .overlay {
background: linear-gradient(
0,
#fcfcff 18.49%,
#fcfcff 68.91%,
rgba(252, 252, 255, 0.5) 95.8%
hsl(var(--p-card-bg-color)) 68.91%,
hsl(var(--p-card-bg-color) / 0.5) 95.8%
);
}
.theme-dark .git-container .overlay {
background: linear-gradient(0, #1b1b28 18.49%, #1b1b28 68.91%, rgba(27, 27, 40, 0.5) 95.8%);
}
</style>
@@ -7,13 +7,13 @@
<WizardStep>
<svelte:fragment slot="title">Execution permissions</svelte:fragment>
<svelte:fragment slot="subtitle">
Choose who can execute this function using the client API. For more information, check out
the <a
Choose who can execute this function using the client API. For more information, visit our
<a
href="https://appwrite.io/docs/advanced/platform/permissions"
target="_blank"
rel="noopener noreferrer"
class="link">
Permissions Guide
Permissions guide
</a>.
</svelte:fragment>
@@ -26,9 +26,9 @@
</script>
<WizardStep>
<svelte:fragment slot="title">Git</svelte:fragment>
<svelte:fragment slot="title">Branch</svelte:fragment>
<svelte:fragment slot="subtitle">
Configure the Git repository that will trigger your function deployments when updated.
Choose the Git branch that will trigger your function deployments when updated.
</svelte:fragment>
<Box radius="small">
-70
View File
@@ -213,76 +213,6 @@
pointer-events: none;
}
:root {
/** Neutral **/
--color-neutral-0-new: 0 0% 100%; /* #ffffff */
--color-neutral-5-new: 240 11% 98%; /* #FAFAFB */
--color-neutral-10-new: 240 9% 94%; /* #EDEDF0 */
--color-neutral-15-new: 240 4% 85%; /* #D8D8DB */
--color-neutral-20-new: 240 3% 77%; /* #C3C3C6 */
--color-neutral-50-new: 240 2% 52%; /* #818186 */
--color-neutral-60-new: 240 2% 43%; /* #6C6C71 */
--color-neutral-70-new: 240 3% 35%; /* #56565C */
--color-neutral-80-new: 240 4% 27%; /* #414146 */
--color-neutral-85-new: 240 4% 18%; /* #2D2D31 */
--color-neutral-90-new: 240 7% 12%; /* #1D1D21 */
--color-neutral-100-new: 240 6% 10%; /* #19191C */
--color-neutral-110-new: 240 5% 8%; /* #141416 */
--color-neutral-0: var(--color-neutral-0-new);
--color-neutral-5: var(--color-neutral-5-new);
--color-neutral-10: var(--color-neutral-10-new);
--color-neutral-30: var(--color-neutral-15-new);
--color-neutral-50: var(--color-neutral-20-new);
--color-neutral-70: var(--color-neutral-50-new);
--color-neutral-100: var(--color-neutral-60-new);
--color-neutral-120: var(--color-neutral-70-new);
--color-neutral-150: var(--color-neutral-80-new);
--color-neutral-200: var(--color-neutral-85-new);
--color-neutral-300: var(--color-neutral-90-new);
--color-neutral-400: var(--color-neutral-100-new);
--color-neutral-500: var(--color-neutral-110-new);
// --color-neutral-0: 0 0% 100%; /* #ffffff */
// --color-neutral-5: 240 11% 98%; /* #FAFAFB */
// --color-neutral-10: 240 9% 94%; /* #EDEDF0 */
// --color-neutral-15: 240 4% 85%; /* #D8D8DB */
// --color-neutral-20: 240 3% 77%; /* #C3C3C6 */
// --color-neutral-50: 240 2% 52%; /* #818186 */
// --color-neutral-60: 240 2% 43%; /* #6C6C71 */
// --color-neutral-70: 240 3% 35%; /* #56565C */
// --color-neutral-80: 240 4% 27%; /* #414146 */
// --color-neutral-85: 240 4% 18%; /* #2D2D31 */
// --color-neutral-90: 240 7% 12%; /* #1D1D21 */
// --color-neutral-100: 240 6% 10%; /* #19191C */
}
.theme-dark .modal::backdrop {
background-color: hsl(240 5% 8% / 0.6);
}
.theme-dark .card-header {
background: var(--url) #18181b;
background-repeat: no-repeat;
background-position: top right;
}
.theme-light .card-header {
background-color: #fbfbfc;
background-repeat: no-repeat;
background-position: top right;
}
.theme-dark .card {
--p-card-bg-color: var(--color-neutral-100-new);
}
.is-cloud {
--heading-font: 'Aeonik Pro', arial, sans-serif;
.heading-level {
+1 -1
View File
@@ -13,7 +13,7 @@ export const load: LayoutLoad = async ({ depends, url }) => {
depends(Dependencies.ACCOUNT);
try {
const account = await sdk.forConsole.account.get();
const account = await sdk.forConsole.account.get<{ organization?: string }>();
LogRocket.identify(account.$id, {
name: account.name,
+1 -1
View File
@@ -22,7 +22,7 @@
});
</script>
<Heading tag="h1" size="1">Missing Redirect URL</Heading>
<Heading tag="h1" size="1">Missing redirect URL</Heading>
<p>
Your Magic URL login flow is missing a proper redirect URL. Please check the
<a href="https://appwrite.io/docs/references/cloud/client-web/account#createMagicURLSession"
+1 -1
View File
@@ -33,7 +33,7 @@
{:catch}
<article class="card u-padding-16">
<div class="u-flex u-flex-vertical u-gap-16">
<Heading tag="h1" size="4">Missing Redirect URL</Heading>
<Heading tag="h1" size="4">Missing redirect URL</Heading>
<p class="text">
Your OAuth login flow is missing a proper redirect URL. Please check the
<a
+1 -1
View File
@@ -33,7 +33,7 @@
{:catch}
<article class="card u-padding-16">
<div class="u-flex u-flex-vertical u-gap-16">
<Heading tag="h1" size="4">Missing Redirect URL</Heading>
<Heading tag="h1" size="4">Missing redirect URL</Heading>
<p class="text">
Your OAuth login flow is missing a proper redirect URL. Please check the
<a
+2 -2
View File
@@ -3,9 +3,9 @@ import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ parent }) => {
const { organizations } = await parent();
const { organizations, account } = await parent();
if (organizations.total) {
const teamId = localStorage.getItem('organization') ?? organizations.teams[0].$id;
const teamId = account.prefs.organization ?? organizations.teams[0].$id;
throw redirect(303, `${base}/console/organization-${teamId}`);
} else {
throw redirect(303, `${base}/console/onboarding`);
@@ -65,14 +65,14 @@
<section class="drop-section">
<ul class="drop-list">
<DropListItem icon="plus" on:click={() => newOrgModal.set(true)}>
New Organization
New organization
</DropListItem>
</ul>
</section></svelte:fragment>
</DropList>
<div class="u-margin-inline-start-auto">
<div class="u-flex u-gap-16">
<a href={`${path}/members`}>
<a href={`${path}/members`} class="is-not-mobile">
<AvatarGroup size={40} {avatars} total={$members?.total ?? 0} />
</a>
<Button secondary on:click={() => newMemberModal.set(true)}>
@@ -9,8 +9,7 @@ export const load: LayoutLoad = async ({ params, depends }) => {
try {
const project = await sdk.forConsole.projects.get(params.project);
localStorage.setItem('project', project.$id);
localStorage.setItem('organization', project.teamId);
sdk.forConsole.account.updatePrefs({ organization: project.teamId });
preferences.loadTeamPrefs(project.teamId);
return {
@@ -47,7 +47,7 @@
{#if $authMethods && $OAuthProviders}
<Container>
<CardGrid>
<Heading tag="h2" size="7">Auth Methods</Heading>
<Heading tag="h2" size="7">Auth methods</Heading>
<p>Enable the authentication methods you wish to use.</p>
<svelte:fragment slot="aside">
<form class="form">
@@ -58,12 +58,13 @@
</TableHeader>
<TableBody>
{#each data.memberships.memberships as membership}
{@const username = membership.userName ? membership.userName : '-'}
<TableRowLink
href={`${base}/console/project-${project}/auth/user-${membership.userId}`}>
<TableCellText title="Name">
<div class="u-flex u-gap-12 u-cross-center">
<AvatarInitials size={32} name={membership.userName} />
<span>{membership.userName ? membership.userName : 'n/a'}</span>
<AvatarInitials size={32} name={username} />
<span>{username}</span>
</div>
</TableCellText>
<TableCellText onlyDesktop title="Roles">{membership.roles}</TableCellText>
@@ -56,7 +56,7 @@
<Form onSubmit={updatePrefs}>
<CardGrid>
<Heading tag="h6" size="7">Team Preferences</Heading>
<Heading tag="h6" size="7">Team preferences</Heading>
<p>
You can update your team's preferences by storing shared information on the teams's
objects so they can easily be shared across members.
@@ -37,7 +37,8 @@
<CardGrid>
<Heading tag="h6" size="7">Phone</Heading>
<p>
Update user's phone. A phone number must contain leading '+' and maximum of 15 digits.
Update user's phone. Phone number must start with '+' and maximum of 15 digits, for
example: +14155552671.
</p>
<svelte:fragment slot="aside">
<ul>
@@ -115,7 +115,7 @@
}
}}>
<span class="icon-plus" aria-hidden="true" />
<span class="text">Add Preference</span>
<span class="text">Add preference</span>
</Button>
</form>
</svelte:fragment>
@@ -1,15 +1,9 @@
import type { Column } from '$lib/helpers/types';
import { writable } from 'svelte/store';
export type Column = {
id: string;
title: string;
show: boolean;
width?: number;
};
export const columns = writable<Column[]>([
{ id: '$id', title: 'Database ID', show: true, width: 150 },
{ id: 'name', title: 'Name', show: true, width: 120 },
{ id: '$createdAt', title: 'Created', show: true, width: 120 },
{ id: '$updatedAt', title: 'Updated', show: true, width: 120 }
{ id: '$id', title: 'Database ID', type: 'string', show: true, width: 150 },
{ id: 'name', title: 'Name', type: 'string', show: true, width: 120 },
{ id: '$createdAt', title: 'Created', type: 'string', show: true, width: 120 },
{ id: '$updatedAt', title: 'Updated', type: 'string', show: true, width: 120 }
]);
@@ -1,14 +1,15 @@
<script lang="ts">
import { page } from '$app/stores';
import { Empty, EmptySearch, Heading, PaginationWithLimit } from '$lib/components';
import Filters from '$lib/components/filters/filters.svelte';
import { hasPageQueries, queries } from '$lib/components/filters/store';
import ViewSelector from '$lib/components/viewSelector.svelte';
import { Button } from '$lib/elements/forms';
import type { ColumnType } from '$lib/helpers/types';
import { Container } from '$lib/layout';
import { preferences } from '$lib/stores/preferences';
import { wizard } from '$lib/stores/wizard';
import type { PageData } from './$types';
import Filters from './(filters)/filters.svelte';
import { hasPageQueries, queries } from './(filters)/store';
import CreateAttributeDropdown from './attributes/createAttributeDropdown.svelte';
import type { Option } from './attributes/store';
import CreateAttribute from './createAttribute.svelte';
@@ -27,7 +28,7 @@
$collection.attributes.map((attribute) => ({
id: attribute.key,
title: attribute.key,
type: attribute.type,
type: attribute.type as ColumnType,
show: selected?.includes(attribute.key) ?? true
}))
);
@@ -54,7 +55,7 @@
</Button>
</div>
<Filters />
<Filters query={data.query} {columns} />
<div class="u-flex u-main-end u-gap-16">
<ViewSelector
@@ -114,7 +115,7 @@
{:else}
<Empty single target="attribute" on:click={() => (showCreateDropdown = true)}>
<div class="u-text-center">
<Heading size="7" tag="h2">Create your first attribute to get started.</Heading>
<Heading size="7" tag="h2">Create an attribute to get started.</Heading>
<p class="body-text-2 u-bold u-margin-block-start-4">
Need a hand? Learn more in our documentation.
</p>
@@ -1,10 +1,9 @@
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
import { getLimit, getPage, getView, pageToOffset, View } from '$lib/helpers/load';
import { getLimit, getPage, getQuery, getView, pageToOffset, View } from '$lib/helpers/load';
import { sdk } from '$lib/stores/sdk';
import { Query } from '@appwrite.io/console';
import type { PageLoad } from './$types';
import { queries, queryParamToMap } from './(filters)/store';
import { queries, queryParamToMap } from '$lib/components/filters/store';
export const load: PageLoad = async ({ params, depends, url, route }) => {
depends(Dependencies.DOCUMENTS);
@@ -12,6 +11,7 @@ export const load: PageLoad = async ({ params, depends, url, route }) => {
const limit = getLimit(url, route, PAGE_LIMIT);
const view = getView(url, route, View.Grid);
const offset = pageToOffset(page, limit);
const query = getQuery(url);
const paramQueries = url.searchParams.get('query');
const parsedQueries = queryParamToMap(paramQueries || '[]');
@@ -21,6 +21,7 @@ export const load: PageLoad = async ({ params, depends, url, route }) => {
offset,
limit,
view,
query,
documents: await sdk.forProject.databases.listDocuments(
params.database,
params.collection,
@@ -69,7 +69,8 @@
id="default"
label="Default value"
bind:value={data.default}
disabled={data.required || data.array} />
disabled={data.required || data.array}
nullable={!data.required && !data.array} />
<InputChoice id="required" label="Required" bind:value={data.required} disabled={data.array}>
Indicate whether this is a required attribute
</InputChoice>
@@ -92,8 +92,8 @@
<Alert type="info">
<svelte:fragment slot="title">Document security is disabled</svelte:fragment>
<p class="text">
If you want to assign document permissions, navigate to Collection settings
and enable document security. Otherwise, only collection permissions will be
If you want to assign document permissions. Go to Collection settings and
enable document security. Otherwise, only collection permissions will be
used.
</p>
</Alert>
@@ -15,4 +15,5 @@
{optionalText}
showLabel={!!label?.length}
required={attribute.required}
nullable={!attribute.required}
bind:value />
@@ -124,7 +124,7 @@
{:else}
<Empty single target="attribute" on:click={() => (showCreateDropdown = true)}>
<div class="u-text-center">
<Heading size="7" tag="h2">Create your first attribute to get started.</Heading>
<Heading size="7" tag="h2">Create an attribute to get started.</Heading>
<p class="body-text-2 u-bold u-margin-block-start-4">
Need a hand? Learn more in our documentation.
</p>
@@ -58,12 +58,12 @@
<CardGrid>
<Heading tag="h6" size="7">Permissions</Heading>
<p class="text">
Choose who can access your collection and documents. For more information, check out the <a
Choose who can access your collection and documents. For more about <a
href="https://appwrite.io/docs/products/databases/permissions"
target="_blank"
rel="noopener noreferrer"
class="link">
Permissions guide
Permissions
</a>.
</p>
<svelte:fragment slot="aside">
@@ -1,4 +1,5 @@
import { page } from '$app/stores';
import type { Column } from '$lib/helpers/types';
import type { Models } from '@appwrite.io/console';
import { derived, writable } from 'svelte/store';
@@ -16,14 +17,6 @@ export type Attributes =
type Collection = Omit<Models.Collection, 'attributes'> & {
attributes: Array<Attributes>;
};
export type Column = {
id: string;
title: string;
show: boolean;
type?: string;
twoWay?: string;
width?: number;
};
export const collection = derived(page, ($page) => $page.data.collection as Collection);
export const attributes = derived(
@@ -29,6 +29,7 @@
import RelationshipsModal from './relationshipsModal.svelte';
import { attributes, collection, columns } from './store';
import { clickOnEnter } from '$lib/helpers/a11y';
import type { ColumnType } from '$lib/helpers/types';
export let data: PageData;
@@ -89,7 +90,7 @@
$collection.attributes.map((attribute) => ({
id: attribute.key,
title: attribute.key,
type: attribute.type,
type: attribute.type as ColumnType,
show: selected?.includes(attribute.key) ?? true
}))
);
@@ -157,9 +158,11 @@
<TableCellCheck bind:selectedIds={selectedDb} id={document.$id} />
<TableCell width={150}>
<Id value={document.$id}>
{document.$id}
</Id>
{#key document.$id}
<Id value={document.$id}>
{document.$id}
</Id>
{/key}
</TableCell>
{#each $columns as column}
@@ -9,7 +9,7 @@
<WizardStep>
<svelte:fragment slot="title">Permissions</svelte:fragment>
<svelte:fragment slot="subtitle">
Choose who can access your collection and documents. For more information, check out the <a
Choose who can access your collection and documents. For more information, visit our <a
href="https://appwrite.io/docs/products/databases/permissions"
target="_blank"
rel="noopener noreferrer"
@@ -1,5 +1,5 @@
import { page } from '$app/stores';
import type { Column } from '$lib/components/viewSelector.svelte';
import type { Column } from '$lib/helpers/types';
import type { Models } from '@appwrite.io/console';
import { derived, writable } from 'svelte/store';
@@ -7,8 +7,8 @@ export const database = derived(page, ($page) => $page.data.database as Models.D
export const showCreate = writable(false);
export const columns = writable<Column[]>([
{ id: '$id', title: 'Collection ID', show: true, width: 150 },
{ id: 'name', title: 'Name', show: true, width: 120 },
{ id: '$createdAt', title: 'Created', show: true, width: 120 },
{ id: '$updatedAt', title: 'Updated', show: true, width: 120 }
{ id: '$id', title: 'Collection ID', type: 'string', show: true, width: 150 },
{ id: 'name', title: 'Name', type: 'string', show: true, width: 120 },
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 120 },
{ id: '$updatedAt', title: 'Updated', type: 'datetime', show: true, width: 120 }
]);
@@ -16,6 +16,6 @@
</GridItem1>
{/each}
<svelte:fragment slot="empty">
<p>Create a new database</p>
<p>Create a database</p>
</svelte:fragment>
</CardContainer>
@@ -1,9 +1,9 @@
import type { Column } from '$lib/components/viewSelector.svelte';
import type { Column } from '$lib/helpers/types';
import { writable } from 'svelte/store';
export const columns = writable<Column[]>([
{ id: '$id', title: 'Database ID', show: true, width: 150 },
{ id: 'name', title: 'Name', show: true, width: 120 },
{ id: '$createdAt', title: 'Created', show: true, width: 120 },
{ id: '$updatedAt', title: 'Updated', show: true, width: 120 }
{ id: '$id', title: 'Database ID', type: 'string', show: true, width: 150 },
{ id: 'name', title: 'Name', type: 'string', show: true, width: 120 },
{ id: '$createdAt', title: 'Created', type: 'datetime', show: true, width: 120 },
{ id: '$updatedAt', title: 'Updated', type: 'datetime', show: true, width: 120 }
]);
@@ -152,6 +152,25 @@
</div>
</svelte:fragment>
</CardGrid>
{:else if $deploymentList.total}
<Empty noMedia single>
<Create secondary round>
<i class="icon-plus" />
</Create>
<div class="u-text-center">
<p class="body-text-2 u-margin-block-start-4">
Add a new deployment, or activate an existing one to see your function in
action. <br />Learn more about deployments in our
<a
class="link"
target="_blank"
rel="noopener noreferrer"
href="https://appwrite.io/docs/products/functions/deployment"
>documentation</a
>.
</p>
</div>
</Empty>
{:else}
<Empty single target="deployment">
<div class="u-text-center">
@@ -8,6 +8,7 @@
import { showCreateDeployment } from './store';
export let secondary = false;
export let round = false;
// This allows us to know which one to open when the user uses the shortcut in the command center
export let main = false;
let show = false;
@@ -23,11 +24,13 @@
</script>
<DropList bind:show placement="bottom-end">
<Button {secondary} on:click={() => (show = !show)} event="create_deployment">
{#if !secondary}
<span class="icon-plus" aria-hidden="true" />
{/if}
<span class="text">Create deployment</span>
<Button {secondary} {round} on:click={() => (show = !show)} event="create_deployment">
<slot>
{#if !secondary}
<span class="icon-plus" aria-hidden="true" />
{/if}
<span class="text">Create deployment</span>
</slot>
</Button>
<svelte:fragment slot="list">
<DropListItem
@@ -141,7 +141,7 @@
</Button>
</div>
{:else}
<Empty on:click={() => (showEvents = true)}>Add an event to get started</Empty>
<Empty on:click={() => (showEvents = true)}>Add an event</Empty>
{/if}
</svelte:fragment>
@@ -65,15 +65,14 @@
<Form onSubmit={updatePermissions}>
<CardGrid>
<Heading tag="h6" size="7" id="permissions">Execute Access</Heading>
<Heading tag="h6" size="7" id="permissions">Execute access</Heading>
<p>
Choose who can execute this function using the client API. For more information, check
out the <a
Choose who can execute this function using the client API. Learn more about <a
href="https://appwrite.io/docs/advanced/platform/permissions"
target="_blank"
rel="noopener noreferrer"
class="link">
Permissions guide
Permissions
</a>.
</p>
<svelte:fragment slot="aside">
@@ -8,7 +8,7 @@
<svelte:fragment slot="title">Permissions</svelte:fragment>
<svelte:fragment slot="subtitle">
Choose which users have permission to execute this function using Client SDKs. For more
information, check out the <a
information, visit our <a
href="https://appwrite.io/docs/advanced/platform/permissions"
target="_blank"
rel="noopener noreferrer"
@@ -56,7 +56,7 @@
</Button>
</div>
{:else}
<Empty on:click={() => (showCreate = !showCreate)}>Add an event to get started</Empty>
<Empty on:click={() => (showCreate = !showCreate)}>Add an event</Empty>
{/if}
</WizardStep>
@@ -114,7 +114,7 @@
</Button>
</div>
{:else}
<Empty on:click={() => (showCreate = !showCreate)}>Create a variable to get started</Empty>
<Empty on:click={() => (showCreate = !showCreate)}>Create a variable</Empty>
{/if}
</WizardStep>
@@ -24,7 +24,7 @@
</script>
<div class="common-section u-flex u-gap-12">
<Heading tag="h3" size="7">API Keys</Heading>
<Heading tag="h3" size="7">API keys</Heading>
<span class="u-margin-inline-start-auto">
<Button on:click={createApiKey}>
<span class="icon-plus" aria-hidden="true" />
@@ -45,7 +45,7 @@
<Form onSubmit={updateExpire}>
<CardGrid>
<Heading tag="h6" size="7">Expiration Date</Heading>
<Heading tag="h6" size="7">Expiration date</Heading>
<p class="text">Set a date after which your API key will expire.</p>
<svelte:fragment slot="aside">
{#if isExpired}
@@ -55,7 +55,7 @@
<div class="card">
<header class="card-header common-section grid-1-2" style:--url={`url(${onBoardIntro})`}>
<div class="grid-1-2-col-1">
<h2 class="heading-level-5">Getting started guide</h2>
<h2 class="heading-level-5">Getting started</h2>
<p class="u-line-height-1-5 u-margin-block-start-12">
Here are some next steps to start building
</p>
@@ -161,10 +161,6 @@
<div class="common-section u-text-center">
<h7 class="heading-level-7">Add a platform to view data about your project</h7>
</div>
<div class="u-margin-block-start-16 u-text-center" style:max-width="550px">
Get insights on bandwidth usage, requests, realtime connections and more after
making your first API call
</div>
</div>
</div>
</article>
@@ -140,7 +140,7 @@
{/if}
<slot>
<div class="u-text-center">
<Heading size="7" tag="h4">Create your first platform to get started.</Heading>
<Heading size="7" tag="h4">Create a platform to get started.</Heading>
<p class="body-text-2 u-bold u-margin-block-start-4">
Need a hand? Learn more in our documentation.
</p>
@@ -155,16 +155,16 @@
</Button>
<svelte:fragment slot="list">
<DropListItem on:click={() => addPlatform(Platform.Web)}>
Web App
Web
</DropListItem>Ï
<DropListItem on:click={() => addPlatform(Platform.Flutter)}>
Flutter App
Flutter
</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.Android)}>
Android App
Android
</DropListItem>
<DropListItem on:click={() => addPlatform(Platform.Apple)}>
Apple App
Apple
</DropListItem>
</svelte:fragment>
</DropList>
@@ -46,7 +46,7 @@
<Form onSubmit={updateHostname}>
<CardGrid>
<Heading tag="h6" size="7">Package Name</Heading>
<Heading tag="h6" size="7">Package name</Heading>
<p class="text">
Your package name is generally the applicationId in your app-level build.gradle file.
</p>
@@ -46,7 +46,7 @@
<Form onSubmit={updateHostname}>
<CardGrid>
<Heading tag="h6" size="7">Package Name</Heading>
<Heading tag="h6" size="7">Package name</Heading>
<p class="text">
Your package name is generally the applicationId in your app-level build.gradle file.
</p>
@@ -46,7 +46,7 @@
<Form onSubmit={updateHostname}>
<CardGrid>
<Heading tag="h6" size="7">Package Name</Heading>
<Heading tag="h6" size="7">Package name</Heading>
<p class="text">Your application name.</p>
<svelte:fragment slot="aside">
<FormList>
@@ -46,7 +46,7 @@
<Form onSubmit={updateHostname}>
<CardGrid>
<Heading tag="h6" size="7">Package Name</Heading>
<Heading tag="h6" size="7">Package name</Heading>
<p class="text">Your application name.</p>
<svelte:fragment slot="aside">
<FormList>
@@ -21,7 +21,7 @@ client
<svelte:fragment slot="title">Initialize SDK</svelte:fragment>
<h2 class="heading-level-7">Initialize your SDK</h2>
<p>
<p data-private>
Initialize your SDK by pointing the client to your Appwrite project using your <Id
value={project}>Project ID</Id>
</p>
@@ -41,7 +41,7 @@
<Form onSubmit={updateName}>
<CardGrid>
<Heading tag="h6" size="7">API Credentials</Heading>
<Heading tag="h6" size="7">API credentials</Heading>
<p class="text">Access Appwrite services using your API Endpoint and Project ID.</p>
<svelte:fragment slot="aside">
<FormList>
@@ -99,7 +99,7 @@
</Button>
</div>
{:else}
<Empty on:click={() => (showCreateEvent = true)}>Add an event to get started</Empty>
<Empty on:click={() => (showCreateEvent = true)}>Add an event</Empty>
{/if}
</svelte:fragment>
@@ -8,7 +8,7 @@
</script>
<CardGrid>
<Heading tag="h2" size="7">Signature Key</Heading>
<Heading tag="h2" size="7">Signature key</Heading>
<p>
Add the Signature Key to the X-Appwrite-Webhook-Signature header to validate your webhooks. <a
href="https://appwrite.io/docs/advanced/platform/webhooks#verification"
@@ -50,7 +50,7 @@
</Button>
</div>
{:else}
<Empty on:click={() => (showCreate = !showCreate)}>Add an event to get started</Empty>
<Empty on:click={() => (showCreate = !showCreate)}>Add an event</Empty>
{/if}
</WizardStep>
@@ -86,7 +86,7 @@
</GridItem1>
{/each}
<svelte:fragment slot="empty">
<p>Add a new bucket</p>
<p>Create a bucket</p>
</svelte:fragment>
</CardContainer>
@@ -70,7 +70,7 @@
{/if}
<Heading tag="h6" size="7">Permissions</Heading>
<p class="text">
Choose who can access your buckets and files. For more information, check out the
Choose who can access your buckets and files. For more information, visit our
<a
href="https://appwrite.io/docs/advanced/platform/permissions"
target="_blank"
@@ -136,9 +136,8 @@
<Alert type="info">
<svelte:fragment slot="title">File security is disabled</svelte:fragment>
<p class="text">
If you want to assign document permissions, navigate to Bucket settings
and enable file security. Otherwise, only Bucket permissions will be
used.
If you want to assign document permissions. Go to Bucket settings and
enable file security. Otherwise, only Bucket permissions will be used.
</p>
</Alert>
{/if}
@@ -260,8 +260,7 @@
<CardGrid hideOverflow>
<Heading tag="h6" size="7" id="permissions">Permissions</Heading>
<p class="text">
Choose who can access your buckets and files. For more information, check out
the <a
Choose who can access your buckets and files. For more information, visit our <a
href="https://appwrite.io/docs/advanced/platform/permissions"
target="_blank"
rel="noopener noreferrer"