mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge pull request #1969 from appwrite/fix-domain-table
Ready for Sites, Domains
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
import { get } from 'svelte/store';
|
||||
import { user } from '$lib/stores/user';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
const userPreferences = () => get(user)?.prefs;
|
||||
|
||||
export const joinWaitlistSites = () => {
|
||||
const prefs = userPreferences();
|
||||
const newPrefs = {
|
||||
...prefs,
|
||||
joinWaitlistSites: true
|
||||
};
|
||||
|
||||
sdk.forConsole.account.updatePrefs(newPrefs);
|
||||
|
||||
if (sessionStorage) {
|
||||
sessionStorage.setItem('joinWaitlistSites', 'true');
|
||||
}
|
||||
};
|
||||
|
||||
export const isOnWaitlistSites = (): boolean => {
|
||||
const prefs = userPreferences();
|
||||
const joinedInPrefs = 'joinWaitlistSites' in prefs;
|
||||
|
||||
let joinedInSession = false;
|
||||
if (sessionStorage) {
|
||||
joinedInSession = sessionStorage.getItem('joinWaitlistSites') === 'true';
|
||||
}
|
||||
|
||||
return joinedInSession || joinedInPrefs;
|
||||
};
|
||||
+2
-1
@@ -17,6 +17,7 @@
|
||||
import { invalidate } from '$app/navigation';
|
||||
import type { RecordType } from '$lib/stores/domains';
|
||||
import { createRecord } from '$lib/helpers/domains';
|
||||
import { showPriority } from './table.svelte';
|
||||
|
||||
export let show = false;
|
||||
|
||||
@@ -110,7 +111,7 @@
|
||||
</span>
|
||||
</Tooltip>
|
||||
</InputNumber>
|
||||
{#if type === 'MX'}
|
||||
{#if showPriority(type)}
|
||||
<InputNumber
|
||||
id="priority"
|
||||
label="Priority"
|
||||
|
||||
@@ -5,7 +5,7 @@ import { derived, writable } from 'svelte/store';
|
||||
|
||||
export const domain = derived(page, ($page) => $page.data.domain as Models.Domain);
|
||||
export const columns = writable<Column[]>([
|
||||
{ id: 'name', title: 'Name', type: 'string', width: { min: 150 } },
|
||||
{ id: 'name', title: 'Name', type: 'string', width: { min: 200 } },
|
||||
{ id: 'type', title: 'Type', type: 'string', width: 125 },
|
||||
{ id: 'value', title: 'Value', type: 'string', width: 250 },
|
||||
{ id: 'ttl', title: 'TTL', type: 'integer', width: 100 },
|
||||
|
||||
+29
-4
@@ -1,3 +1,12 @@
|
||||
<script lang="ts" context="module">
|
||||
import type { RecordType } from '$lib/stores/domains';
|
||||
|
||||
export function showPriority(record: Models.DnsRecord | RecordType): boolean {
|
||||
const type = typeof record === 'string' ? record : record.type;
|
||||
return type.toLowerCase() === 'mx' || type.toLowerCase() === 'srv';
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { PaginationWithLimit } from '$lib/components';
|
||||
import {
|
||||
@@ -29,6 +38,15 @@
|
||||
let showEdit = false;
|
||||
let showDelete = false;
|
||||
let selectedRecord: Models.DnsRecord = null;
|
||||
|
||||
function formatRecordName(name: string) {
|
||||
const limit = 30;
|
||||
return {
|
||||
value: name.length > limit ? `${name.slice(0, limit)}...` : name,
|
||||
truncated: name.length > limit,
|
||||
whole: name
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
@@ -47,9 +65,16 @@
|
||||
{#each $columns as column}
|
||||
<Table.Cell column={column.id} {root}>
|
||||
{#if column.id === 'name'}
|
||||
<Typography.Code>
|
||||
{record.name}
|
||||
</Typography.Code>
|
||||
{@const formatted = formatRecordName(record.name)}
|
||||
<Tooltip placement="bottom" disabled={!formatted.truncated}>
|
||||
<Typography.Text truncate>{formatted.value}</Typography.Text>
|
||||
<span
|
||||
slot="tooltip"
|
||||
style:white-space="pre-wrap"
|
||||
style:word-break="break-all">
|
||||
{formatted.whole}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{:else if column.id === 'type'}
|
||||
<Typography.Text>
|
||||
{record.type}
|
||||
@@ -70,7 +95,7 @@
|
||||
</Typography.Text>
|
||||
{:else if column.id === 'priority'}
|
||||
<Typography.Text>
|
||||
{record?.priority ?? '-'}
|
||||
{showPriority(record) ? (record?.priority ?? '0') : '-'}
|
||||
</Typography.Text>
|
||||
{:else if column.id === 'comment'}
|
||||
<Typography.Text truncate>
|
||||
|
||||
+16
-13
@@ -20,6 +20,7 @@
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import type { RecordType } from '$lib/stores/domains';
|
||||
import { updateRecord } from '$lib/helpers/domains';
|
||||
import { showPriority } from './table.svelte';
|
||||
|
||||
export let show = false;
|
||||
export let selectedRecord: Models.DnsRecord;
|
||||
@@ -101,19 +102,21 @@
|
||||
</span>
|
||||
</Tooltip>
|
||||
</InputNumber>
|
||||
<InputNumber
|
||||
id="priority"
|
||||
label="Priority"
|
||||
placeholder="Enter number"
|
||||
bind:value={record.priority}>
|
||||
<Tooltip slot="info">
|
||||
<Icon icon={IconInfo} size="s" />
|
||||
<span slot="tooltip">
|
||||
Sets the priority for this DNS record. Lower numbers indicate higher
|
||||
priority (e.g., 10 is higher than 20).
|
||||
</span>
|
||||
</Tooltip>
|
||||
</InputNumber>
|
||||
{#if showPriority(record)}
|
||||
<InputNumber
|
||||
id="priority"
|
||||
label="Priority"
|
||||
placeholder="Enter number"
|
||||
bind:value={record.priority}>
|
||||
<Tooltip slot="info">
|
||||
<Icon icon={IconInfo} size="s" />
|
||||
<span slot="tooltip">
|
||||
Sets the priority for this DNS record. Lower numbers indicate higher
|
||||
priority (e.g., 10 is higher than 20).
|
||||
</span>
|
||||
</Tooltip>
|
||||
</InputNumber>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
|
||||
<InputTextarea
|
||||
|
||||
@@ -11,14 +11,12 @@
|
||||
import { isServiceLimited } from '$lib/stores/billing';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { canWriteSites } from '$lib/stores/roles.js';
|
||||
import { Card, Icon, Layout, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { Icon, Layout } from '@appwrite.io/pink-svelte';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { app } from '$lib/stores/app';
|
||||
import CreateSiteModal from './createSiteModal.svelte';
|
||||
import EmptyLight from './(images)/empty-sites-light.svg';
|
||||
import EmptyDark from './(images)/empty-sites-dark.svg';
|
||||
import EmptyLightMobile from './(images)/empty-sites-light-mobile.svg';
|
||||
import EmptyDarkMobile from './(images)/empty-sites-dark-mobile.svg';
|
||||
import Grid from './grid.svelte';
|
||||
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
import { columns } from './store';
|
||||
@@ -28,15 +26,10 @@
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { APPWRITE_OFFICIALS_ORG, isCloud } from '$lib/system';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { isOnWaitlistSites, joinWaitlistSites } from '$lib/helpers/waitlist';
|
||||
import { isSmallViewport } from '$lib/stores/viewport';
|
||||
|
||||
export let data;
|
||||
|
||||
let show = false;
|
||||
let isOnWaitlist = isOnWaitlistSites();
|
||||
|
||||
$: $registerCommands([
|
||||
{
|
||||
@@ -46,7 +39,6 @@
|
||||
},
|
||||
keys: ['c'],
|
||||
disabled:
|
||||
!showSites ||
|
||||
isServiceLimited('sites', $organization?.billingPlan, data.siteList?.total) ||
|
||||
!$canWriteSites,
|
||||
icon: IconPlus,
|
||||
@@ -63,123 +55,46 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Controls visibility of Sites feature:
|
||||
* - Shown if running on self-hosted
|
||||
* - Shown on cloud only if the organization is Appwrite's.
|
||||
* - Hidden on cloud for any non-Appwrite organization.
|
||||
*/
|
||||
$: showSites = !isCloud || $organization.$id === APPWRITE_OFFICIALS_ORG;
|
||||
|
||||
$: isDark = $app.themeInUse === 'dark';
|
||||
|
||||
$: imgSrc = isDark
|
||||
? $isSmallViewport
|
||||
? EmptyDarkMobile
|
||||
: EmptyDark
|
||||
: $isSmallViewport
|
||||
? EmptyLightMobile
|
||||
: EmptyLight;
|
||||
|
||||
$: imgClass = $isSmallViewport ? 'mobile' : 'desktop';
|
||||
|
||||
function addToWaitlist() {
|
||||
joinWaitlistSites();
|
||||
addNotification({
|
||||
type: 'success',
|
||||
title: 'Waitlist joined',
|
||||
message: "We'll let you know as soon as Appwrite Sites is ready for you."
|
||||
});
|
||||
|
||||
isOnWaitlist = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
{#if showSites}
|
||||
<Layout.Stack direction="row" justifyContent="space-between">
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<SearchQuery placeholder="Search by name" />
|
||||
</Layout.Stack>
|
||||
<Layout.Stack direction="row" alignItems="center" justifyContent="flex-end">
|
||||
<ViewSelector
|
||||
{columns}
|
||||
view={data.view}
|
||||
hideColumns
|
||||
hideView={!data.siteList.total} />
|
||||
{#if $canWriteSites}
|
||||
<Button on:mousedown={() => (show = true)} event="create_site" size="s">
|
||||
<Icon icon={IconPlus} slot="start" size="s" />
|
||||
Create site
|
||||
</Button>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
<Layout.Stack direction="row" justifyContent="space-between">
|
||||
<Layout.Stack direction="row" alignItems="center">
|
||||
<SearchQuery placeholder="Search by name" />
|
||||
</Layout.Stack>
|
||||
{#if data.siteList.total}
|
||||
{#if data.view === View.Grid}
|
||||
<Grid siteList={data.siteList} />
|
||||
{:else}
|
||||
<Table siteList={data.siteList} />
|
||||
<Layout.Stack direction="row" alignItems="center" justifyContent="flex-end">
|
||||
<ViewSelector {columns} view={data.view} hideColumns hideView={!data.siteList.total} />
|
||||
{#if $canWriteSites}
|
||||
<Button on:mousedown={() => (show = true)} event="create_site" size="s">
|
||||
<Icon icon={IconPlus} slot="start" size="s" />
|
||||
Create site
|
||||
</Button>
|
||||
{/if}
|
||||
<PaginationWithLimit
|
||||
name="Sites"
|
||||
limit={data.limit}
|
||||
offset={data.offset}
|
||||
total={data.siteList.total} />
|
||||
{:else if data.search}
|
||||
<EmptySearch target="sites" />
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
{#if data.siteList.total}
|
||||
{#if data.view === View.Grid}
|
||||
<Grid siteList={data.siteList} />
|
||||
{:else}
|
||||
<Empty
|
||||
single
|
||||
allowCreate={$canWriteSites}
|
||||
href="https://appwrite.io/docs/products/sites"
|
||||
description="Deploy and manage your web your web applications with Sites. "
|
||||
target="site"
|
||||
src={$app.themeInUse === 'dark' ? EmptyDark : EmptyLight}
|
||||
on:click={() => (show = true)}>
|
||||
</Empty>
|
||||
<Table siteList={data.siteList} />
|
||||
{/if}
|
||||
<PaginationWithLimit
|
||||
name="Sites"
|
||||
limit={data.limit}
|
||||
offset={data.offset}
|
||||
total={data.siteList.total} />
|
||||
{:else if data.search}
|
||||
<EmptySearch target="sites" />
|
||||
{:else}
|
||||
<Card.Base padding="m">
|
||||
<Layout.Stack gap="xxl">
|
||||
<img src={imgSrc} alt="create" aria-hidden="true" height="242" class={imgClass} />
|
||||
|
||||
<Layout.Stack>
|
||||
{#if isOnWaitlist}
|
||||
<Typography.Title size="s" align="center" color="--fgcolor-neutral-primary">
|
||||
You've successfully joined the Sites waitlist
|
||||
</Typography.Title>
|
||||
|
||||
<Typography.Text align="center" color="--fgcolor-neutral-secondary">
|
||||
We can't wait for you to try out Sites on Cloud. You will get access
|
||||
soon.
|
||||
</Typography.Text>
|
||||
{:else}
|
||||
<Layout.Stack gap="m" alignItems="center">
|
||||
<Typography.Title
|
||||
size="s"
|
||||
align="center"
|
||||
color="--fgcolor-neutral-primary">
|
||||
Appwrite Sites is in high demand
|
||||
</Typography.Title>
|
||||
|
||||
<div style:max-width="600px">
|
||||
<Typography.Text align="center" color="--fgcolor-neutral-secondary">
|
||||
To ensure a smooth experience for everyone, we’re rolling out
|
||||
access gradually. Join the waitlist and be one of the first to
|
||||
deploy with Sites.
|
||||
</Typography.Text>
|
||||
</div>
|
||||
|
||||
<div style:margin-block-start="1rem">
|
||||
<Button on:click={addToWaitlist}>Join waitlist</Button>
|
||||
</div>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Card.Base>
|
||||
<Empty
|
||||
single
|
||||
allowCreate={$canWriteSites}
|
||||
href="https://appwrite.io/docs/products/sites"
|
||||
description="Deploy and manage your web your web applications with Sites. "
|
||||
target="site"
|
||||
src={$app.themeInUse === 'dark' ? EmptyDark : EmptyLight}
|
||||
on:click={() => (show = true)}>
|
||||
</Empty>
|
||||
{/if}
|
||||
</Container>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user