This commit is contained in:
Torsten Dittmann
2022-08-16 17:47:03 +02:00
48 changed files with 1113 additions and 1039 deletions
+417 -578
View File
File diff suppressed because it is too large Load Diff
+12 -13
View File
@@ -8,7 +8,6 @@
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync",
"check": "svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint .",
@@ -26,33 +25,33 @@
"tippy.js": "^6.3.7"
},
"devDependencies": {
"@playwright/test": "^1.24.0",
"@sveltejs/adapter-auto": "1.0.0-next.63",
"@sveltejs/kit": "1.0.0-next.390",
"@playwright/test": "^1.25.0",
"@sveltejs/adapter-auto": "1.0.0-next.64",
"@sveltejs/kit": "1.0.0-next.405",
"@sveltejs/vite-plugin-svelte": "^1.0.1",
"@testing-library/dom": "^8.16.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/dom": "^8.17.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/svelte": "^3.1.3",
"@testing-library/user-event": "^14.3.0",
"@types/gtag.js": "^0.0.10",
"@typescript-eslint/eslint-plugin": "^5.30.7",
"@typescript-eslint/parser": "^5.30.7",
"@vitest/ui": "^0.18.1",
"eslint": "^8.20.0",
"@typescript-eslint/eslint-plugin": "^5.33.1",
"@typescript-eslint/parser": "^5.33.1",
"@vitest/ui": "^0.22.0",
"eslint": "^8.22.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte3": "^4.0.0",
"pre-commit": "^1.2.2",
"prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.7.0",
"sass": "^1.53.0",
"sass": "^1.54.4",
"svelte": "^3.49.0",
"svelte-check": "^2.8.0",
"svelte-jester": "^2.3.2",
"svelte-preprocess": "^4.10.7",
"tslib": "^2.4.0",
"typescript": "^4.7.4",
"vite": "^3.0.0",
"vitest": "^0.18.1"
"vite": "^3.0.8",
"vitest": "^0.22.0"
},
"type": "module",
"pre-commit": [
+1 -1
View File
@@ -17,7 +17,7 @@
<span class="icon-x" aria-hidden="true" />
</button>
<p class="u-flex-basis-100-percent">
<slot />
<slot name="subtitle" />
</p>
</header>
<div class="modal-content">
+13 -3
View File
@@ -3,13 +3,18 @@
import type { Buttons } from '../stores/notifications';
export let dismissible = false;
export let type: '' | 'info' | 'success' | 'warning' | 'danger' = 'info';
export let type: 'info' | 'success' | 'warning' | 'error' = 'info';
export let buttons: Buttons[] = [];
const dispatch = createEventDispatcher();
</script>
<section class={`alert is-${type} `}>
<section
class="alert"
class:is-success={type === 'success'}
class:is-warning={type === 'warning'}
class:is-danger={type === 'error'}
class:is-info={type === 'info'}>
<div class="alert-grid">
{#if dismissible}
<button
@@ -19,7 +24,12 @@
<span class="icon-x" aria-hidden="true" />
</button>
{/if}
<span class="icon-info" aria-hidden="true" />
<span
class:icon-info={type === 'info'}
class:icon-check-circle={type === 'success'}
class:icon-exclamation={type === 'warning'}
class:icon-exclamation-circle={type === 'error'}
aria-hidden="true" />
<div class="content">
{#if $$slots.title}
<h6 class="title">
+17 -8
View File
@@ -1,15 +1,13 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import { browser } from '$app/env';
import { createEventDispatcher } from 'svelte';
import { fade, fly, type FadeParams, type FlyParams } from 'svelte/transition';
import { Alert } from '$lib/components';
export let show = false;
export let size: 'small' | 'big' = null;
export let warning = false;
let browser = false;
//TODO: explore other solutions compatible with testing library
onMount(() => {
browser = true;
});
export let error: string = null;
const dispatch = createEventDispatcher();
const transitionFly: FlyParams = {
@@ -26,19 +24,20 @@
closeModal();
}
};
const handleBLur = (event: MouseEvent) => {
const target: Partial<HTMLElement> = event.target;
if (target.hasAttribute('data-curtain')) {
closeModal();
}
};
const closeModal = () => {
show = false;
dispatch('close');
};
/**
* Workaround until https://github.com/sveltejs/svelte/issues/3105 is resolved.
*/
$: if (browser) {
if (show) {
document.body.classList.add('u-overflow-hidden');
@@ -76,6 +75,16 @@
</button>
</header>
<div class="modal-content">
{#if error}
<Alert
dismissible
type="warning"
on:dismiss={() => {
error = null;
}}>
{error}
</Alert>
{/if}
<slot />
</div>
{#if $$slots.footer}
+1 -1
View File
@@ -1,3 +1,3 @@
<form class="form" on:submit|preventDefault>
<form class="form common-section" on:submit|preventDefault>
<slot />
</form>
+17 -23
View File
@@ -1,30 +1,24 @@
<script lang="ts">
export let type: false | 'success' | 'warning' | 'error' = 'warning';
let icon = '';
switch (type) {
case 'success':
icon = 'check-circle';
break;
case 'warning':
icon = 'exclamation';
break;
case 'error':
icon = 'exclamation-circle';
break;
default:
icon = '';
break;
}
export let type: 'success' | 'warning' | 'error' | 'info' | 'neutral' = 'warning';
</script>
<li class={`helper u-${type} u-margin-block-start-8"`}>
{#if icon !== ''}
<span class={`icon-${icon}`} aria-hidden="true" />
<p
class="helper u-margin-block-start-12"
class:u-info={type === 'info'}
class:u-error={type === 'error'}
class:u-success={type === 'success'}
class:u-warning={type === 'warning'}
class:u-neutral={type === 'neutral'}>
{#if type}
<span
class:icon-info={type === 'info'}
class:icon-error={type === 'error'}
class:icon-success={type === 'success'}
class:icon-warning={type === 'warning'}
class:icon-neutral={type === 'neutral'}
aria-hidden="true" />
{/if}
<span class="text">
<slot />
</span>
</li>
</p>
+28 -2
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let label: string;
export let showLabel = true;
@@ -7,11 +7,37 @@
export let value = false;
export let required = false;
export let disabled = false;
let element: HTMLInputElement;
let error: string;
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
<label class:u-hide={!showLabel} class="label" for={id}>{label}</label>
<div class="input-text-wrapper">
<input {id} {disabled} {required} type="checkbox" bind:checked={value} />
<input
{id}
{disabled}
{required}
type="checkbox"
bind:this={element}
bind:checked={value}
on:invalid={handleInvalid} />
</div>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
@@ -7,9 +7,11 @@
export let placeholder = '';
export let required = false;
export let autofocus = false;
let element: HTMLInputElement;
let unique = true;
let bench = '';
const toggle = async () => {
unique = !unique;
if (unique) {
+25 -3
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let label: string;
export let showLabel = true;
@@ -14,12 +14,30 @@
export let autocomplete = false;
let element: HTMLInputElement;
let error: string;
onMount(() => {
if (element && autofocus) {
element.focus();
}
});
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.typeMismatch) {
error = 'Your email should be formatted as: name@example.com';
return;
}
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
@@ -31,10 +49,14 @@
{disabled}
{required}
{readonly}
autocomplete={autocomplete ? 'on' : 'off'}
type="email"
class="input-text"
autocomplete={autocomplete ? 'on' : 'off'}
bind:value
bind:this={element} />
bind:this={element}
on:invalid={handleInvalid} />
</div>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+1 -1
View File
@@ -12,6 +12,6 @@
<FormItem>
<label class:u-hide={!showLabel} class="label" for={id}>{label}</label>
<div class="input-text-wrapper">
<input {id} {disabled} {required} bind:files type="file" />
<input {id} {disabled} {required} type="file" bind:files />
</div>
</FormItem>
+22 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let label: string;
export let showLabel = true;
@@ -16,12 +16,28 @@
export let step: number | 'any' = 1;
let element: HTMLInputElement;
let error: string;
onMount(() => {
if (element && autofocus) {
element.focus();
}
});
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
@@ -39,6 +55,10 @@
type="number"
class="input-text"
bind:value
bind:this={element} />
bind:this={element}
on:invalid={handleInvalid} />
</div>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+37 -8
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let id: string;
export let label: string;
@@ -13,8 +13,11 @@
export let meter = false;
export let autocomplete = false;
export let showPasswordButton = false;
export let minlength = 8;
export let maxlength: number = null;
let element: HTMLInputElement;
let error: string;
let showInPlainText = false;
onMount(() => {
@@ -23,7 +26,24 @@
}
});
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
if (element.validity.tooShort) {
error = 'Password should contain at least 8 characters';
return;
}
error = element.validationMessage;
};
$: strength = value ? value.length * 10 : 0;
$: if (value) {
error = null;
}
</script>
<FormItem>
@@ -31,27 +51,32 @@
<div class="input-text-wrapper">
{#if showInPlainText}
<input
type="text"
{id}
name={id}
{placeholder}
{required}
{disabled}
autocomplete={autocomplete ? 'on' : 'off'}
{minlength}
{maxlength}
name={id}
type="text"
class="input-text"
autocomplete={autocomplete ? 'on' : 'off'}
bind:value
bind:this={element} />
bind:this={element}
on:invalid={handleInvalid} />
{:else}
<input
{id}
{placeholder}
{disabled}
{required}
autocomplete={autocomplete ? 'on' : 'off'}
{minlength}
{maxlength}
type="password"
class="input-text"
autocomplete={autocomplete ? 'on' : 'off'}
bind:value
bind:this={element} />
bind:this={element}
on:invalid={handleInvalid} />
{/if}
{#if meter}
@@ -67,6 +92,7 @@
{/if}
{#if showPasswordButton}
<button
type="button"
on:click={() => (showInPlainText = !showInPlainText)}
class="show-password-button"
aria-label="show password">
@@ -77,4 +103,7 @@
</button>
{/if}
</div>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+30 -4
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let label: string;
export let showLabel = true;
@@ -14,13 +14,35 @@
export let autocomplete = false;
export let maxlength: number = null;
const pattern = String.raw`^\+?[1-9]\d{1,14}$`;
let element: HTMLInputElement;
let error: string;
onMount(() => {
if (element && autofocus) {
element.focus();
}
});
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.patternMismatch) {
error = "Allowed characters: leading '+' and maximum of 15 digits";
return;
}
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
@@ -32,11 +54,15 @@
{disabled}
{required}
{maxlength}
{pattern}
{readonly}
type="text"
autocomplete={autocomplete ? 'on' : 'off'}
type="tel"
class="input-text"
bind:value
bind:this={element} />
bind:this={element}
on:invalid={handleInvalid} />
</div>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+31 -2
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let label: string;
export let showLabel = true;
@@ -9,11 +9,40 @@
export let name: string;
export let required = false;
export let disabled = false;
let element: HTMLInputElement;
let error: string;
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
<div class="input-text-wrapper">
<input {id} {name} {disabled} {required} {value} type="radio" bind:group />
<input
{id}
{name}
{disabled}
{required}
{value}
type="radio"
bind:group
bind:this={element}
on:invalid={handleInvalid} />
<label class:u-hide={!showLabel} class="label" for={id}>{label}</label>
</div>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+3 -8
View File
@@ -40,16 +40,11 @@
{required}
type="search"
class="input-text"
on:input={valueChange}
bind:this={element} />
bind:this={element}
on:input={valueChange} />
<span class="icon-search" aria-hidden="true" />
{#if isWithEndButton && value}
<button
class="x-button"
aria-label="Clear search"
on:click={() => {
value = '';
}}>
<button class="x-button" aria-label="Clear search" on:click={() => (value = '')}>
<span class="icon-x" aria-hidden="true" />
</button>
{/if}
+28 -2
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let label: string;
export let showLabel = true;
@@ -12,12 +12,35 @@
value: string | boolean | number;
label: string;
}[];
let element: HTMLSelectElement;
let error: string;
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
<label class:u-hide={!showLabel} class="label" for={id}>{label}</label>
<div class="select">
<select bind:value {id} {required} {disabled}>
<select
{id}
{required}
{disabled}
bind:this={element}
bind:value
on:invalid={handleInvalid}>
{#if placeholder}
<option value={null} disabled selected hidden>{placeholder}</option>
{/if}
@@ -29,4 +52,7 @@
</select>
<span class="icon-cheveron-down" aria-hidden="true" />
</div>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+24 -2
View File
@@ -1,11 +1,28 @@
<script lang="ts">
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let label: string;
export let id: string;
export let value = false;
export let required = false;
export let disabled = false;
let element: HTMLInputElement;
let error: string;
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
@@ -18,11 +35,16 @@
type="checkbox"
class="switch"
role="switch"
bind:this={element}
bind:checked={value}
on:change />
on:change
on:invalid={handleInvalid} />
</div>
<div class="choice-item-content">
<div class="choice-item-title">{label}</div>
</div>
</label>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+23 -8
View File
@@ -1,19 +1,19 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let id: string;
export let label: string;
export let showLabel = true;
export let tags: string[] = [];
export let placeholder = '';
export let helper = '';
export let autofocus = false;
export let disabled = false;
export let readonly = false;
let value = '';
let element: HTMLInputElement;
let error: string;
onMount(() => {
if (element && autofocus) {
@@ -50,6 +50,20 @@
const removeValue = (value: string) => {
tags = tags.filter((tag) => tag !== value);
};
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
@@ -75,19 +89,20 @@
</ul>
</div>
<input
type="text"
class="tags-input-text"
{id}
{placeholder}
{disabled}
{readonly}
type="text"
class="tags-input-text"
bind:value
bind:this={element}
on:keydown={handleInput}
on:blur={addValue}
bind:value
bind:this={element} />
on:invalid={handleInvalid} />
</div>
</div>
{#if helper}
<p class="helper u-margin-block-start-12">{helper}</p>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+22 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let label: string;
export let showLabel = true;
@@ -15,12 +15,28 @@
export let maxlength: number = null;
let element: HTMLInputElement;
let error: string;
onMount(() => {
if (element && autofocus) {
element.focus();
}
});
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
@@ -37,6 +53,10 @@
type="text"
class="input-text"
bind:value
bind:this={element} />
bind:this={element}
on:invalid={handleInvalid} />
</div>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+20 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from 'svelte';
import { FormItem } from '.';
import { FormItem, Helper } from '.';
export let label: string;
export let showLabel = true;
@@ -14,12 +14,26 @@
export let maxlength: number = null;
let element: HTMLTextAreaElement;
let error: string;
onMount(() => {
if (element && autofocus) {
element.focus();
}
});
const handleInvalid = (event: Event) => {
event.preventDefault();
if (element.validity.valueMissing) {
error = 'This field is required';
return;
}
error = element.validationMessage;
};
$: if (value) {
error = null;
}
</script>
<FormItem>
@@ -34,6 +48,10 @@
{maxlength}
class="input-text"
bind:value
bind:this={element} />
bind:this={element}
on:invalid={handleInvalid} />
</div>
{#if error}
<Helper type="warning">{error}</Helper>
{/if}
</FormItem>
+12 -24
View File
@@ -6,37 +6,25 @@
export let title: Notification['title'];
export let buttons: Notification['buttons'];
let icon: string;
switch (type) {
case 'success':
icon = 'check-circle';
break;
case 'warning':
icon = 'exclamation';
break;
case 'error':
icon = 'exclamation-circle';
break;
case 'info':
icon = 'info';
break;
default:
icon = '';
break;
}
const dispatch = createEventDispatcher();
</script>
<li class={`alert-sticky is-${type}`}>
<li
class="alert-sticky"
class:is-success={type === 'success'}
class:is-warning={type === 'warning'}
class:is-error={type === 'error'}
class:is-info={type === 'info'}>
<button class="x-button" aria-label="close alert" on:click={() => dispatch('dismiss')}>
<span class="icon-x" aria-hidden="true" />
</button>
<div class="alert-sticky-image">
<span class={`icon-${icon}`} aria-hidden="true" />
<span
class:icon-check-cirle={type === 'success'}
class:icon-exclamation={type === 'warning'}
class:icon-exclamation-circle={type === 'error'}
class:icon-info={type === 'info'}
aria-hidden="true" />
</div>
<div class="alert-sticky-content">
{#if title}
+5 -5
View File
@@ -68,7 +68,7 @@
class="icon-button is-no-desktop"
aria-label="Open Menu"
on:click={() => (isOpen = !isOpen)}>
<span class={isOpen ? 'icon-x' : 'icon-menu'} aria-hidden="true" />
<span class:icon-x={isOpen} class:icon-menu={!isOpen} aria-hidden="true" />
</button>
<slot name="header" />
</header>
@@ -88,10 +88,10 @@
</h1>
{#if $copyData?.value}
<Copy value={$copyData.value}>
<Pill button
><span
class="icon-duplicate"
aria-hidden="true" />{$copyData.text}</Pill>
<Pill button>
<span class="icon-duplicate" aria-hidden="true" />
{$copyData.text}
</Pill>
</Copy>
{/if}
</svelte:fragment>
@@ -17,6 +17,7 @@
export let provider: Provider;
let { keyID, teamID, p8 } = JSON.parse(provider.secret);
let error: string;
const projectId = $page.params.project;
const update = async () => {
@@ -35,24 +36,22 @@
provider.active ? 'enabled' : 'disabled'
}`
});
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
</script>
<Form on:submit={update}>
<Modal size="big" bind:show={showModal}>
<Modal {error} size="big" bind:show={showModal}>
<svelte:fragment slot="header">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
To use {provider.name} authentication in your application, first fill in this form. For
more info you can
<a class="link" href={provider.docs} target="_blank" rel="noopener noreferrer"
>visit the docs.</a>
<a class="link" href={provider.docs} target="_blank" rel="noopener noreferrer">
visit the docs.
</a>
</p>
<InputSwitch
id="state"
@@ -9,14 +9,15 @@
Form,
FormList
} from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdkForConsole } from '$lib/stores/sdk';
import type { Provider } from '$lib/stores/oauth-providers';
import { addNotification } from '$lib/stores/notifications';
export let showModal = false;
export let provider: Provider;
let { clientSecret, auth0Domain } = JSON.parse(provider.secret);
let error: string;
const projectId = $page.params.project;
const update = async () => {
@@ -35,17 +36,14 @@
provider.active ? 'enabled' : 'disabled'
}`
});
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
</script>
<Form on:submit={update}>
<Modal size="big" bind:show={showModal}>
<Modal {error} size="big" bind:show={showModal}>
<svelte:fragment slot="header">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -10,7 +10,7 @@
const dispatch = createEventDispatcher();
let name: string, id: string;
let name: string, id: string, error: string;
let showDropdown = false;
const create = async () => {
@@ -24,11 +24,8 @@
message: `${team.name} has been created`
});
dispatch('created', team);
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
@@ -37,11 +34,12 @@
}
$: if (!showCreate) {
showDropdown = false;
error = null;
}
</script>
<Form on:submit={create}>
<Modal size="big" bind:show={showCreate}>
<Modal {error} size="big" bind:show={showCreate}>
<svelte:fragment slot="header">Create Team</svelte:fragment>
<FormList>
<InputText
@@ -60,7 +58,9 @@
{:else}
<InnerModal bind:show={showDropdown}>
<svelte:fragment slot="title">Team ID</svelte:fragment>
Enter a custom team ID. Leave blank for a randomly generated one.
<svelte:fragment slot="subtitle">
Enter a custom team ID. Leave blank for a randomly generated one.
</svelte:fragment>
<svelte:fragment slot="content">
<div class="form">
<InputText
@@ -19,6 +19,7 @@
let showDropdown = false;
let name: string, mail: string, pass: string, id: string;
let error: string;
const create = async () => {
try {
@@ -31,11 +32,8 @@
message: `${user.name} has been created`
});
dispatch('created', user);
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
@@ -44,11 +42,12 @@
}
$: if (!showCreate) {
showDropdown = false;
error = null;
}
</script>
<Form on:submit={create}>
<Modal size="big" bind:show={showCreate}>
<Modal {error} size="big" bind:show={showCreate}>
<svelte:fragment slot="header">Create User</svelte:fragment>
<FormList>
<InputText
@@ -73,15 +72,18 @@
{#if !showDropdown}
<div>
<Pill button on:click={() => (showDropdown = !showDropdown)}
><span class="icon-pencil" aria-hidden="true" /><span class="text">
<Pill button on:click={() => (showDropdown = !showDropdown)}>
<span class="icon-pencil" aria-hidden="true" /><span class="text">
User ID
</span></Pill>
</span>
</Pill>
</div>
{:else}
<InnerModal bind:show={showDropdown}>
<svelte:fragment slot="title">User ID</svelte:fragment>
Enter a custom user ID. Leave blank for a randomly generated one.
<svelte:fragment slot="subtitle">
Enter a custom user ID. Leave blank for a randomly generated one.
</svelte:fragment>
<svelte:fragment slot="content">
<div class="form">
<InputText
@@ -96,9 +98,10 @@
<span
class="icon-info u-cross-center u-margin-block-start-2 u-line-height-1 u-icon-small"
aria-hidden="true" />
<span class="text u-line-height-1-5"
>Allowed characters: alphanumeric, hyphen, non-leading
underscore, period</span>
<span class="text u-line-height-1-5">
Allowed characters: alphanumeric, hyphen, non-leading
underscore, period
</span>
</div>
</div>
</svelte:fragment>
@@ -9,13 +9,17 @@
Form,
FormList
} from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdkForConsole } from '$lib/stores/sdk';
import type { Provider } from '$lib/stores/oauth-providers';
import { addNotification } from '$lib/stores/notifications';
export let showModal = false;
export let provider: Provider;
const projectId = $page.params.project;
let error: string;
const update = async () => {
try {
await sdkForConsole.projects.updateOAuth2(
@@ -31,17 +35,14 @@
provider.active ? 'enabled' : 'disabled'
}`
});
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
</script>
<Form on:submit={update}>
<Modal size="big" bind:show={showModal}>
<Modal {error} size="big" bind:show={showModal}>
<svelte:fragment slot="header">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -9,15 +9,18 @@
Form,
FormList
} from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdkForConsole } from '$lib/stores/sdk';
import type { Provider } from '$lib/stores/oauth-providers';
import { addNotification } from '$lib/stores/notifications';
export let showModal = false;
export let provider: Provider;
let { clientSecret, tenantID } = JSON.parse(provider.secret);
let error: string;
const projectId = $page.params.project;
const update = async () => {
try {
const secret = JSON.stringify({ clientSecret, tenantID });
@@ -35,24 +38,22 @@
provider.active ? 'enabled' : 'disabled'
}`
});
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
</script>
<Form on:submit={update}>
<Modal size="big" bind:show={showModal}>
<Modal {error} size="big" bind:show={showModal}>
<svelte:fragment slot="header">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
To use {provider.name} authentication in your application, first fill in this form. For
more info you can
<a class="link" href={provider.docs} target="_blank" rel="noopener noreferrer"
>visit the docs.</a>
<a class="link" href={provider.docs} target="_blank" rel="noopener noreferrer">
visit the docs.
</a>
</p>
<InputSwitch
id="state"
@@ -9,16 +9,18 @@
Form,
FormList
} from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdkForConsole } from '$lib/stores/sdk';
import type { Provider } from '$lib/stores/oauth-providers';
import { addNotification } from '$lib/stores/notifications';
export let showModal = false;
export let provider: Provider;
let { clientSecret, oktaDomain, authorizationServerId } = JSON.parse(provider.secret);
let error: string;
const projectId = $page.params.project;
const update = async () => {
try {
const secret = JSON.stringify({ clientSecret, oktaDomain, authorizationServerId });
@@ -35,17 +37,14 @@
provider.active ? 'enabled' : 'disabled'
}`
});
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
</script>
<Form on:submit={update}>
<Modal size="big" bind:show={showModal}>
<Modal {error} size="big" bind:show={showModal}>
<svelte:fragment slot="header">{provider.name} OAuth2 Settings</svelte:fragment>
<FormList>
<p>
@@ -11,7 +11,8 @@
const dispatch = createEventDispatcher();
let name: string, email: string, roles: [];
let name: string, email: string, roles: string[];
let error: string;
const create = async () => {
const url = `${$page.url.origin}/console/${$page.params.project}/authentication/teams/${$page.params.team}/members`;
@@ -32,17 +33,14 @@
roles = [];
showCreate = false;
dispatch('created', user);
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
</script>
<Form on:submit={create}>
<Modal bind:show={showCreate}>
<Modal {error} size="big" bind:show={showCreate}>
<svelte:fragment slot="header">Create Membership</svelte:fragment>
<FormList>
<InputEmail
@@ -35,9 +35,8 @@
</script>
<Form on:submit={deleteMembership}>
<Modal warning={true} bind:show={showDelete}>
<Modal bind:show={showDelete} warning>
<svelte:fragment slot="header">Delete Member</svelte:fragment>
<p>
Are you sure you want to delete <b>{selectedMembership.userName}</b> from '{selectedMembership.teamName}'?
</p>
@@ -26,7 +26,7 @@
</script>
<Form on:submit={deleteTeam}>
<Modal warning={true} bind:show={showDelete}>
<Modal bind:show={showDelete} warning>
<svelte:fragment slot="header">Delete Team</svelte:fragment>
<p>
@@ -2,7 +2,7 @@
import { page } from '$app/stores';
import { Avatar, CardGrid, Box } from '$lib/components';
import { Container } from '$lib/layout';
import { Button, InputText, Helper } from '$lib/elements/forms';
import { Button, InputText, Form } from '$lib/elements/forms';
import { sdkForProject } from '$lib/stores/sdk';
import { toLocaleDateTime } from '$lib/helpers/date';
import { addNotification } from '$lib/stores/notifications';
@@ -14,9 +14,6 @@
const getAvatar = (name: string) => sdkForProject.avatars.getInitials(name, 48, 48).toString();
let showDelete = false;
let showError: false | 'name' | 'email' | 'password' = false;
let errorMessage = 'Something went wrong';
let errorType: 'error' | 'warning' | 'success' = 'error';
let teamName: string = null;
onMount(async () => {
@@ -24,12 +21,6 @@
teamName ??= $team.name;
});
function addError(location: typeof showError, message: string, type: typeof errorType) {
showError = location;
errorMessage = message;
errorType = type;
}
async function updateName() {
try {
await sdkForProject.teams.update($page.params.team, teamName);
@@ -43,7 +34,10 @@
type: 'success'
});
} catch (error) {
addError('name', error.message, 'error');
addNotification({
message: error.message,
type: 'error'
});
}
}
</script>
@@ -65,31 +59,30 @@
</svelte:fragment>
</CardGrid>
<CardGrid>
<h6 class="heading-level-7">Update Name</h6>
<Form on:submit={updateName}>
<CardGrid>
<h6 class="heading-level-7">Update Name</h6>
<svelte:fragment slot="aside">
<ul>
<InputText
id="name"
label="Name"
placeholder="Enter team name"
autocomplete={false}
bind:value={teamName} />
{#if showError === 'name'}
<Helper type={errorType}>{errorMessage}</Helper>
{/if}
</ul>
</svelte:fragment>
<svelte:fragment slot="aside">
<ul>
<InputText
id="name"
label="Name"
placeholder="Enter team name"
autocomplete={false}
bind:value={teamName} />
</ul>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button
disabled={teamName === $team.name || !teamName}
on:click={() => {
updateName();
}}>Update</Button>
</svelte:fragment>
</CardGrid>
<svelte:fragment slot="actions">
<Button
disabled={teamName === $team.name || !teamName}
on:click={() => {
updateName();
}}>Update</Button>
</svelte:fragment>
</CardGrid>
</Form>
<CardGrid>
<div>
@@ -27,7 +27,7 @@
</script>
<Form on:submit={deleteAllMemberships}>
<Modal warning={true} bind:show={showDeleteAll}>
<Modal bind:show={showDeleteAll} warning>
<svelte:fragment slot="header">Delete All Memberships</svelte:fragment>
<p>
@@ -26,9 +26,8 @@
</script>
<Form on:submit={deleteAllSessions}>
<Modal warning={true} bind:show={showDeleteAll}>
<Modal bind:show={showDeleteAll} warning>
<svelte:fragment slot="header">Delete All Sessions</svelte:fragment>
<p>
Are you sure you want to delete <b>all of {$user.name}'s sessions?</b>
</p>
@@ -35,7 +35,7 @@
</script>
<Form on:submit={deleteMembership}>
<Modal warning={true} bind:show={showDelete}>
<Modal bind:show={showDelete} warning>
<svelte:fragment slot="header">Delete Member</svelte:fragment>
<p>
Are you sure you want to delete <b>{selectedMembership.userName}</b> from '{selectedMembership.teamName}'?
@@ -26,7 +26,7 @@
</script>
<Form on:submit={deleteSession}>
<Modal warning={true} bind:show={showDelete}>
<Modal bind:show={showDelete} warning>
<svelte:fragment slot="header">Delete Sessions</svelte:fragment>
<p>Are you sure you want to delete this session?</p>
@@ -30,7 +30,7 @@
</script>
<Form on:submit={deleteUser}>
<Modal warning={true} bind:show={showDelete}>
<Modal bind:show={showDelete} warning>
<svelte:fragment slot="header">Delete User</svelte:fragment>
<p>Are you sure you want to delete <b>{$user.name}</b> from '{$project.name}'?</p>
<svelte:fragment slot="footer">
@@ -5,11 +5,11 @@
import { Pill } from '$lib/elements';
import {
Button,
Form,
InputText,
InputEmail,
InputPassword,
InputPhone,
Helper
InputPhone
} from '$lib/elements/forms';
import { Container } from '$lib/layout';
import { sdkForProject } from '$lib/stores/sdk';
@@ -28,10 +28,8 @@
arePrefsDisabled = true;
}
}
let showDelete = false;
let showError: false | 'name' | 'email' | 'phone' | 'password' = false;
let errorMessage = 'Something went wrong';
let errorType: 'error' | 'warning' | 'success' = 'error';
let userName: string = null,
userEmail: string = null,
userPhone: string = null,
@@ -53,12 +51,6 @@
const getAvatar = (name: string) => sdkForProject.avatars.getInitials(name, 48, 48).toString();
function addError(location: typeof showError, message: string, type: typeof errorType) {
showError = location;
errorMessage = message;
errorType = type;
}
async function updateVerificationEmail() {
showVerifcationDropdown = false;
try {
@@ -118,53 +110,60 @@
const breadcrumb = $breadcrumbs.get($breadcrumbs.size);
breadcrumb.title = userName;
$breadcrumbs = $breadcrumbs.set($breadcrumbs.size, breadcrumb);
showError = false;
addNotification({
message: 'Name has been updated',
type: 'success'
});
} catch (error) {
addError('name', error.message, 'error');
addNotification({
message: error.message,
type: 'error'
});
}
}
async function updateEmail() {
try {
await sdkForProject.users.updateEmail($user.$id, userEmail);
$user.email = userEmail;
showError = false;
addNotification({
message: 'Email has been updated',
type: 'success'
});
} catch (error) {
addError('email', error.message, 'error');
addNotification({
message: error.message,
type: 'error'
});
}
}
async function updatePhone() {
try {
await sdkForProject.users.updatePhone($user.$id, userPhone);
$user.phone = userPhone;
showError = false;
addNotification({
message: 'Phone has been updated',
type: 'success'
});
} catch (error) {
addError('phone', error.message, 'error');
addNotification({
message: error.message,
type: 'error'
});
}
}
async function updatePassword() {
try {
await sdkForProject.users.updatePassword($user.$id, newPassword);
newPassword = null;
showError = false;
addNotification({
message: 'Password has been updated',
type: 'success'
});
} catch (error) {
addError('password', error.message, 'error');
addNotification({
message: error.message,
type: 'error'
});
}
}
@@ -236,7 +235,8 @@
text={$user.status}
secondary={!$user.status}
on:click={() => updateStatus()}
>{$user.status ? 'Block account' : 'Unblock account'}</Button>
>{$user.status ? 'Block account' : 'Unblock account'}
</Button>
{#if $user.status}
{#if $user.phone && $user.email}
<DropList
@@ -252,12 +252,16 @@
{$user.emailVerification ? 'Unverify' : 'Verify'} account
</Button>
<svelte:fragment slot="list">
<DropListItem icon="mail" on:click={() => updateVerificationEmail()}
>{$user.emailVerification ? 'Unverify' : 'Verify'} email</DropListItem>
<DropListItem
icon="mail"
on:click={() => updateVerificationEmail()}>
{$user.emailVerification ? 'Unverify' : 'Verify'} email
</DropListItem>
<DropListItem
icon="phone"
on:click={() => updateVerificationPhone()}>
{$user.phoneVerification ? 'Unverify' : 'Verify'} phone</DropListItem>
{$user.phoneVerification ? 'Unverify' : 'Verify'} phone
</DropListItem>
</svelte:fragment>
</DropList>
{:else if !$user.phone}
@@ -271,182 +275,175 @@
{/if}
</svelte:fragment>
</CardGrid>
<CardGrid>
<h6 class="heading-level-7">Update Name</h6>
<svelte:fragment slot="aside">
<ul>
<InputText
id="name"
label="Name"
placeholder="Enter name"
autocomplete={false}
bind:value={userName} />
{#if showError === 'name'}
<Helper type={errorType}>{errorMessage}</Helper>
{/if}
</ul>
</svelte:fragment>
<Form on:submit={updateName}>
<CardGrid>
<h6 class="heading-level-7">Update Name</h6>
<svelte:fragment slot="actions">
<Button
disabled={userName === $user.name || !userName}
on:click={() => {
updateName();
}}>Update</Button>
</svelte:fragment>
</CardGrid>
<CardGrid>
<h6 class="heading-level-7">Update Email</h6>
<svelte:fragment slot="aside">
<ul>
<InputEmail
id="email"
label="Email"
placeholder="Enter email"
autocomplete={false}
bind:value={userEmail} />
{#if showError === 'email'}
<Helper type={errorType}>{errorMessage}</Helper>
{/if}
</ul>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button
disabled={userEmail === $user.email || !userEmail}
on:click={() => {
updateEmail();
}}>Update</Button>
</svelte:fragment>
</CardGrid>
<CardGrid>
<h6 class="heading-level-7">Update Phone</h6>
<svelte:fragment slot="aside">
<ul>
<InputPhone
id="phone"
label="Phone"
placeholder="Enter phone number"
autocomplete={false}
bind:value={userPhone} />
{#if showError === 'phone'}
<Helper type={errorType}>{errorMessage}</Helper>
{/if}
</ul>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button
disabled={userPhone === $user.phone || !userPhone}
on:click={() => {
updatePhone();
}}>Update</Button>
</svelte:fragment>
</CardGrid>
<CardGrid>
<div>
<h6 class="heading-level-7">Update Password</h6>
</div>
<p>
Enter a new password. A password must contain <b> at least 8 characters.</b>
</p>
<svelte:fragment slot="aside">
<ul>
<InputPassword
id="newPassword"
label="New Password"
placeholder="Enter new password"
autocomplete={false}
meter={false}
showPasswordButton={true}
bind:value={newPassword} />
{#if showError === 'password'}
<Helper type={errorType}>{errorMessage}</Helper>
{/if}
</ul>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button
disabled={!newPassword}
on:click={() => {
updatePassword();
}}>Update</Button>
</svelte:fragment>
</CardGrid>
<CardGrid>
<h6 class="heading-level-7">User Preferences</h6>
<p>
You can update your user preferences by storing information on the user's objects so
they can easily be shared across devices and sessions.
</p>
<svelte:fragment slot="aside">
<form class="form u-grid u-gap-16">
<ul class="form-list">
{#if prefs}
{#each prefs as [key, value], index}
<li class="form-item is-multiple">
<div class="form-item-part u-stretch">
<label class="label" for={`key-${index}`}>Key</label>
<div class="input-text-wrapper">
<input
id={`key-${key}`}
placeholder="Enter key"
type="text"
class="input-text"
bind:value={key} />
</div>
</div>
<div class="form-item-part u-stretch">
<label class="label" for={`value-${index}`}>Value</label>
<div class="input-text-wrapper">
<input
id={`value-${value}`}
placeholder="Enter value"
type="text"
class="input-text"
bind:value />
</div>
</div>
<div class="form-item-part u-cross-child-end">
<Button
text
disabled={(!key || !value) && index === 0}
on:click={() => {
if (index === 0) {
prefs = [['', '']];
} else {
prefs.splice(index, 1);
prefs = prefs;
}
}}>
<span class="icon-x" aria-hidden="true" />
</Button>
</div>
</li>
{/each}
{/if}
<svelte:fragment slot="aside">
<ul>
<InputText
id="name"
label="Name"
placeholder="Enter name"
autocomplete={false}
bind:value={userName} />
</ul>
<button
class="button is-text u-padding-inline-0"
disabled={prefs?.length
? !prefs[prefs.length - 1][0] || !prefs[prefs.length - 1][1]
: true}
on:click={() => {
prefs.push(['', '']);
prefs = prefs;
}}>
<span class="icon-plus" aria-hidden="true" />
<span class="text"> Add preference </span></button>
</form>
</svelte:fragment>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button disabled={arePrefsDisabled} on:click={() => updatePrefs()}>Update</Button>
</svelte:fragment>
</CardGrid>
<svelte:fragment slot="actions">
<Button disabled={userName === $user.name || !userName} submit>Update</Button>
</svelte:fragment>
</CardGrid>
</Form>
<Form on:submit={updateEmail}>
<CardGrid>
<h6 class="heading-level-7">Update Email</h6>
<svelte:fragment slot="aside">
<ul>
<InputEmail
id="email"
label="Email"
placeholder="Enter email"
autocomplete={false}
bind:value={userEmail} />
</ul>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button disabled={userEmail === $user.email || !userEmail} submit>
Update
</Button>
</svelte:fragment>
</CardGrid>
</Form>
<Form on:submit={updatePhone}>
<CardGrid>
<h6 class="heading-level-7">Update Phone</h6>
<svelte:fragment slot="aside">
<ul>
<InputPhone
id="phone"
label="Phone"
placeholder="Enter phone number"
autocomplete={false}
bind:value={userPhone} />
</ul>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button disabled={userPhone === $user.phone || !userPhone} submit>
Update
</Button>
</svelte:fragment>
</CardGrid>
</Form>
<Form on:submit={updatePassword}>
<CardGrid>
<div>
<h6 class="heading-level-7">Update Password</h6>
</div>
<p>
Enter a new password. A password must contain <b>at least 8 characters.</b>
</p>
<svelte:fragment slot="aside">
<ul>
<InputPassword
id="newPassword"
label="New Password"
placeholder="Enter new password"
autocomplete={false}
meter={false}
showPasswordButton={true}
bind:value={newPassword} />
</ul>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button disabled={!newPassword} submit>Update</Button>
</svelte:fragment>
</CardGrid>
</Form>
<Form on:submit={updatePrefs}>
<CardGrid>
<h6 class="heading-level-7">User Preferences</h6>
<p>
You can update your user preferences by storing information on the user's
objects so they can easily be shared across devices and sessions.
</p>
<svelte:fragment slot="aside">
<form class="form u-grid u-gap-16">
<ul class="form-list">
{#if prefs}
{#each prefs as [key, value], index}
<li class="form-item is-multiple">
<div class="form-item-part u-stretch">
<label class="label" for={`key-${index}`}>Key</label>
<div class="input-text-wrapper">
<input
id={`key-${key}`}
placeholder="Enter key"
type="text"
class="input-text"
bind:value={key} />
</div>
</div>
<div class="form-item-part u-stretch">
<label class="label" for={`value-${index}`}>
Value
</label>
<div class="input-text-wrapper">
<input
id={`value-${value}`}
placeholder="Enter value"
type="text"
class="input-text"
bind:value />
</div>
</div>
<div class="form-item-part u-cross-child-end">
<Button
text
disabled={(!key || !value) && index === 0}
on:click={() => {
if (index === 0) {
prefs = [['', '']];
} else {
prefs.splice(index, 1);
prefs = prefs;
}
}}>
<span class="icon-x" aria-hidden="true" />
</Button>
</div>
</li>
{/each}
{/if}
</ul>
<Button
text
on:click={() => {
if (prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]) {
prefs.push(['', '']);
prefs = prefs;
}
}}>
<span class="icon-plus" aria-hidden="true" />
<span class="text">Add Preference</span>
</Button>
</form>
</svelte:fragment>
<svelte:fragment slot="actions">
<Button disabled={arePrefsDisabled} submit>Update</Button>
</svelte:fragment>
</CardGrid>
</Form>
<CardGrid>
<div>
@@ -3,14 +3,15 @@
import { CardGrid } from '$lib/components';
import { collection } from '../../store';
import { doc } from './store';
import Attribute from './_attribute.svelte';
import { onMount } from 'svelte';
import { page } from '$app/stores';
import { sdkForProject } from '$lib/stores/sdk';
import { addNotification } from '$lib/stores/notifications';
import Attribute from './_attribute.svelte';
let currentDoc: string;
let updateBtnDisabled = true;
onMount(async () => {
await doc.load($collection.$id, $page.params.document);
currentDoc = JSON.stringify($doc);
@@ -2,8 +2,6 @@
import { Modal, InnerModal } from '$lib/components';
import { Pill } from '$lib/elements';
import { Button, InputText, Form, FormList } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdkForProject } from '$lib/stores/sdk';
import { createEventDispatcher } from 'svelte';
@@ -14,6 +12,7 @@
let name = '';
let id: string = null;
let showDropdown = false;
let error: string;
const create = async () => {
try {
@@ -25,11 +24,8 @@
name = null;
showCreate = false;
dispatch('created', bucket);
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
@@ -38,11 +34,12 @@
}
$: if (!showCreate) {
showDropdown = false;
error = null;
}
</script>
<Form on:submit={create}>
<Modal size="big" bind:show={showCreate}>
<Modal {error} size="big" bind:show={showCreate}>
<svelte:fragment slot="header">Create Bucket</svelte:fragment>
<FormList>
<InputText
@@ -55,15 +52,17 @@
{#if !showDropdown}
<div>
<Pill button on:click={() => (showDropdown = !showDropdown)}
><span class="icon-pencil" aria-hidden="true" /><span class="text">
Bucket ID
</span></Pill>
<Pill button on:click={() => (showDropdown = !showDropdown)}>
<span class="icon-pencil" aria-hidden="true" />
<span class="text"> Bucket ID </span>
</Pill>
</div>
{:else}
<InnerModal bind:show={showDropdown}>
<svelte:fragment slot="title">Bucket ID</svelte:fragment>
<p>Enter a custom bucket ID. Leave blank for a randomly generated one.</p>
<svelte:fragment slot="subtitle">
Enter a custom bucket ID. Leave blank for a randomly generated one.
</svelte:fragment>
<svelte:fragment slot="content">
<div class="form">
<InputText
@@ -78,9 +77,10 @@
<span
class="icon-info u-cross-center u-margin-block-start-2 u-line-height-1 u-icon-small"
aria-hidden="true" />
<span class="text u-line-height-1-5"
>Allowed characters: alphanumeric, hyphen, non-leading
underscore, period</span>
<span class="text u-line-height-1-5">
Allowed characters: alphanumeric, hyphen, non-leading
underscore, period
</span>
</div>
</div>
</svelte:fragment>
@@ -4,7 +4,6 @@
import { Modal, Alert, InnerModal } from '$lib/components';
import { sdkForProject } from '$lib/stores/sdk';
import { createEventDispatcher } from 'svelte';
import { addNotification } from '$lib/stores/notifications';
import { page } from '$app/stores';
import { uploader } from '$lib/stores/uploader';
import { bucket } from './store';
@@ -20,6 +19,7 @@
let read: string[] = [];
let write: string[] = [];
let id: string = null;
let error: string;
let showDropdown = false;
const create = async () => {
@@ -36,11 +36,8 @@
showDropdown = false;
uploader.addFile(file);
dispatch('created');
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} catch ({ message }) {
error = message;
}
};
@@ -71,9 +68,8 @@
}
$: if (!showCreate) {
id = null;
id = files = error = null;
list = new DataTransfer();
files = null;
read = [];
write = [];
}
@@ -86,7 +82,7 @@
<input bind:files id="file" type="file" style="display: none" />
<Form on:submit={create}>
<Modal bind:show={showCreate}>
<Modal {error} bind:show={showCreate}>
<svelte:fragment slot="header">Upload File</svelte:fragment>
<FormList>
<div>
@@ -137,7 +133,9 @@
{:else}
<InnerModal bind:show={showDropdown}>
<svelte:fragment slot="title">File ID</svelte:fragment>
<p>Enter a custom file ID. Leave blank for a randomly generated one.</p>
<svelte:fragment slot="subtitle">
Enter a custom file ID. Leave blank for a randomly generated one.
</svelte:fragment>
<svelte:fragment slot="content">
<div class="form">
<InputText
@@ -25,7 +25,7 @@
</script>
<Form on:submit={deleteUser}>
<Modal warning={true} bind:show={showDelete}>
<Modal bind:show={showDelete} warning>
<svelte:fragment slot="header">Delete Bucket</svelte:fragment>
<p>Are you sure you want to delete <b>{$bucket.name}</b>?</p>
<svelte:fragment slot="footer">
@@ -26,7 +26,7 @@
</script>
<Form on:submit={deleteFile}>
<Modal warning={true} bind:show={showDelete}>
<Modal bind:show={showDelete} warning>
<svelte:fragment slot="header">Delete File</svelte:fragment>
<p>Are you sure you want to delete <b>{file.name}</b>?</p>
<svelte:fragment slot="footer">
@@ -25,7 +25,7 @@
</script>
<Form on:submit={deleteFile}>
<Modal warning={true} bind:show={showDelete}>
<Modal bind:show={showDelete} warning>
<svelte:fragment slot="header">Delete File</svelte:fragment>
<p>Are you sure you want to delete <b>{$file.name}</b>?</p>
<svelte:fragment slot="footer">
-1
View File
@@ -9,7 +9,6 @@ test('shows phone input', () => {
expect(getByText('input')).toBeInTheDocument();
expect(input).toBeInTheDocument();
expect(input).toHaveAttribute('type', 'tel');
});
test('shows phone input - required', () => {
+1 -1
View File
@@ -19,7 +19,7 @@ const config = {
include: ['tests/**/*.test.ts'],
globals: true,
environment: 'jsdom',
thread: true
threads: true
}
};