mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge pull request #274 from appwrite/refactor/api-details-page
Refactor: API key page design details
This commit is contained in:
@@ -61,5 +61,7 @@
|
||||
</div>
|
||||
{#if error}
|
||||
<Helper type="warning">{error}</Helper>
|
||||
{:else}
|
||||
<slot name="helper" />
|
||||
{/if}
|
||||
</FormItem>
|
||||
|
||||
@@ -22,3 +22,20 @@ export const toLocaleDateTime = (datetime: string | number) => {
|
||||
|
||||
return date.toLocaleDateString('en', options);
|
||||
};
|
||||
|
||||
export const isSameDay = (date1: Date, date2: Date) => {
|
||||
return (
|
||||
date1.getFullYear() === date2.getFullYear() &&
|
||||
date1.getMonth() === date2.getMonth() &&
|
||||
date1.getDate() === date2.getDate()
|
||||
);
|
||||
};
|
||||
|
||||
export const isValidDate = (date: string) => {
|
||||
return !isNaN(new Date(date).getTime());
|
||||
};
|
||||
|
||||
export const diffDays = (date1: Date, date2: Date) => {
|
||||
const diffTime = Math.abs(date2.getTime() - date1.getTime());
|
||||
return Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
||||
};
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@
|
||||
trackEvent('submit_key_update_scopes');
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: 'API Key scopes has been updated'
|
||||
message: 'API Key scopes have been updated'
|
||||
});
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
|
||||
+22
-5
@@ -1,12 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import CardGrid from '$lib/components/cardGrid.svelte';
|
||||
import Heading from '$lib/components/heading.svelte';
|
||||
import { Alert, CardGrid, Heading } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Form } from '$lib/elements/forms';
|
||||
import Button from '$lib/elements/forms/button.svelte';
|
||||
import FormList from '$lib/elements/forms/formList.svelte';
|
||||
import { Button, Form, FormList } from '$lib/elements/forms';
|
||||
import { diffDays } from '$lib/helpers/date';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdkForConsole } from '$lib/stores/sdk';
|
||||
import { project } from '../../../store';
|
||||
@@ -37,6 +35,11 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let alertsDismissed = false;
|
||||
$: isExpiring =
|
||||
!alertsDismissed && $key.expire && diffDays(new Date(), new Date($key.expire)) < 14;
|
||||
$: isExpired = !alertsDismissed && $key.expire !== null && new Date($key.expire) < new Date();
|
||||
</script>
|
||||
|
||||
<Form on:submit={updateExpire}>
|
||||
@@ -44,6 +47,20 @@
|
||||
<Heading tag="h6" size="7">Update Expiration Date</Heading>
|
||||
<p class="text">Set a date after which your API Key will expire.</p>
|
||||
<svelte:fragment slot="aside">
|
||||
{#if isExpired}
|
||||
<Alert type="error" dismissible on:dismiss={() => (alertsDismissed = true)}>
|
||||
<span slot="title">Your API Key has expired</span>
|
||||
<p>
|
||||
For security reasons, we recommend you delete your expired key and create a
|
||||
new one.
|
||||
</p>
|
||||
</Alert>
|
||||
{:else if isExpiring}
|
||||
<Alert type="warning" dismissible on:dismiss={() => (alertsDismissed = true)}>
|
||||
<span slot="title">Your API Key is about to expire</span>
|
||||
<p>Update the expiration date to keep the key active</p>
|
||||
</Alert>
|
||||
{/if}
|
||||
<FormList>
|
||||
<ExpirationInput bind:value={expiration} />
|
||||
</FormList>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script lang="ts">
|
||||
import Helper from '$lib/elements/forms/helper.svelte';
|
||||
import InputDateTime from '$lib/elements/forms/inputDateTime.svelte';
|
||||
import InputSelect from '$lib/elements/forms/inputSelect.svelte';
|
||||
import { isSameDay, isValidDate, toLocaleDate } from '$lib/helpers/date';
|
||||
|
||||
function incrementToday(value: number, type: 'day' | 'month' | 'year'): string {
|
||||
const date = new Date();
|
||||
@@ -19,18 +21,7 @@
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
export let value: string | null = null;
|
||||
let expirationSelect = value === null ? null : 'custom';
|
||||
let expirationCustom: string | null = value ?? null;
|
||||
|
||||
$: {
|
||||
value = expirationSelect === 'custom' ? expirationCustom : expirationSelect;
|
||||
}
|
||||
</script>
|
||||
|
||||
<InputSelect
|
||||
bind:value={expirationSelect}
|
||||
options={[
|
||||
const options = [
|
||||
{
|
||||
label: 'Never',
|
||||
value: null
|
||||
@@ -55,9 +46,42 @@
|
||||
label: 'Custom Date',
|
||||
value: 'custom'
|
||||
}
|
||||
]}
|
||||
id="preset"
|
||||
label="Expiration Date" />
|
||||
];
|
||||
|
||||
export let value: string | null = null;
|
||||
|
||||
function initExpirationSelect() {
|
||||
if (value === null || !isValidDate(value)) return null;
|
||||
|
||||
let result = 'custom';
|
||||
for (const option of options) {
|
||||
if (!isValidDate(option.value)) continue;
|
||||
|
||||
if (isSameDay(new Date(option.value), new Date(value))) {
|
||||
result = option.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
let expirationSelect = initExpirationSelect();
|
||||
let expirationCustom: string | null = value ?? null;
|
||||
|
||||
$: {
|
||||
if (!isSameDay(new Date(expirationSelect), new Date(value))) {
|
||||
value = expirationSelect === 'custom' ? expirationCustom : expirationSelect;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<InputSelect bind:value={expirationSelect} {options} id="preset" label="Expiration Date">
|
||||
<svelte:fragment slot="helper">
|
||||
{#if expirationSelect !== 'custom' && expirationSelect !== null}
|
||||
<Helper type="neutral">Your key will expire in {toLocaleDate(value)}</Helper>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</InputSelect>
|
||||
{#if expirationSelect === 'custom'}
|
||||
<InputDateTime id="expire" label="" bind:value={expirationCustom} showLabel={false} />
|
||||
{/if}
|
||||
|
||||
@@ -77,10 +77,15 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="u-flex u-cross-center u-main-end">
|
||||
<Button text on:click={deselectAll}>Deselect all</Button>
|
||||
<Button text on:click={selectAll}>Select all</Button>
|
||||
</div>
|
||||
<ul class="buttons-list u-main-end">
|
||||
<li class="buttons-list-item">
|
||||
<Button text on:click={deselectAll}>Deselect all</Button>
|
||||
</li>
|
||||
<li class="buttons-list-item">
|
||||
<Button text on:click={selectAll}>Select all</Button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<Collapsible>
|
||||
{#each [Category.Auth, Category.Database, Category.Functions, Category.Storage, Category.Other] as category}
|
||||
{@const checked = categoryState(category, scopes)}
|
||||
@@ -96,8 +101,11 @@
|
||||
{category}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="subtitle">
|
||||
({allScopes.filter((n) => n.category === category && scopes.includes(n.scope))
|
||||
.length} Scopes)
|
||||
{@const scopesLength = allScopes.filter(
|
||||
(n) => n.category === category && scopes.includes(n.scope)
|
||||
).length}
|
||||
({scopesLength}
|
||||
{scopesLength === 1 ? 'Scope' : 'Scopes'})
|
||||
</svelte:fragment>
|
||||
<div class="form">
|
||||
<FormList>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import { toLocaleDate, toLocaleDateTime } from '$lib/helpers/date';
|
||||
import {
|
||||
toLocaleDate,
|
||||
toLocaleDateTime,
|
||||
isSameDay,
|
||||
isValidDate,
|
||||
diffDays
|
||||
} from '$lib/helpers/date';
|
||||
|
||||
describe('local date', () => {
|
||||
[
|
||||
@@ -22,3 +28,52 @@ describe('local date time', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('is same day', () => {
|
||||
const entries: Array<[string, string, boolean]> = [
|
||||
['2022-11-15 08:26:28', '2022-11-15 08:26:28', true],
|
||||
['2022-11-15 08:26:28', '2022-11-16 08:26:28', false],
|
||||
['2022-11-15 08:26:28', '2022-11-15 08:26:29', true],
|
||||
['2022-11-15 08:26:28', '2022-11-15 08:26:27', true]
|
||||
];
|
||||
|
||||
entries.forEach(([value1, value2, expected]) => {
|
||||
it(`${value1} ${value2}`, () => {
|
||||
expect(isSameDay(new Date(value1), new Date(value2))).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('is valid date', () => {
|
||||
const entries: Array<[string, boolean]> = [
|
||||
['2022-11-15 08:26:28', true],
|
||||
['2022-11-15 08:26:28', true],
|
||||
['abc', false],
|
||||
['2022-11-15', true],
|
||||
['123.123.123', false]
|
||||
];
|
||||
|
||||
entries.forEach(([value, expected]) => {
|
||||
it(value, () => {
|
||||
expect(isValidDate(value)).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('diff days', () => {
|
||||
const entries: Array<[string, string, number]> = [
|
||||
['2022-11-15 08:26:28', '2022-11-15 08:26:28', 0],
|
||||
['2022-11-15 08:26:28', '2022-11-16 08:26:28', 1],
|
||||
['2022-11-15 08:26:28', '2022-11-16 08:26:27', 0],
|
||||
['2022-11-15 08:26:28', '2022-11-14 08:26:29', 0],
|
||||
['2022-11-15 08:26:28', '2022-11-14 08:26:27', 1],
|
||||
['2022-11-15 08:26:28', '2022-11-20 08:26:29', 5],
|
||||
['2022-11-15 08:26:28', '2022-11-20 08:26:27', 4]
|
||||
];
|
||||
|
||||
entries.forEach(([value1, value2, expected]) => {
|
||||
it(`${value1} ${value2}`, () => {
|
||||
expect(diffDays(new Date(value1), new Date(value2))).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user