mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
fix: paginator
This commit is contained in:
@@ -173,84 +173,90 @@
|
||||
</Table.Root>
|
||||
{:then response}
|
||||
{#if response?.length}
|
||||
<Paginator
|
||||
items={response}
|
||||
let:paginatedItems
|
||||
hideFooter={response?.length <= 6}
|
||||
limit={6}>
|
||||
<Table.Root columns={1} let:root>
|
||||
{#each paginatedItems as repo}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
{#if action === 'select'}
|
||||
<input
|
||||
class="is-small u-margin-inline-end-8"
|
||||
type="radio"
|
||||
name="repositories"
|
||||
bind:group={selectedRepository}
|
||||
onchange={() => repository.set(repo)}
|
||||
value={repo.id} />
|
||||
{/if}
|
||||
{#if product === 'sites'}
|
||||
{#if repo?.framework && repo.framework !== 'other'}
|
||||
<Avatar size="xs" alt={repo.name}>
|
||||
<SvgIcon
|
||||
name={getFrameworkIcon(repo.framework)}
|
||||
iconSize="small" />
|
||||
</Avatar>
|
||||
{:else}
|
||||
<Avatar size="xs" alt={repo.name} empty />
|
||||
{/if}
|
||||
{:else}
|
||||
{@const iconName = repo?.runtime
|
||||
? repo.runtime.split('-')[0]
|
||||
: undefined}
|
||||
<Avatar size="xs" alt={repo.name} empty={!iconName}>
|
||||
<SvgIcon name={iconName} iconSize="small" />
|
||||
</Avatar>
|
||||
{/if}
|
||||
<Paginator items={response} hideFooter={response?.length <= 6} limit={6}>
|
||||
{#snippet children(paginatedItems)}
|
||||
<Table.Root columns={1} let:root>
|
||||
{#each paginatedItems as repo}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack
|
||||
gap="s"
|
||||
direction="row"
|
||||
alignItems="center">
|
||||
<Typography.Text
|
||||
truncate
|
||||
color="--fgcolor-neutral-secondary">
|
||||
{repo.name}
|
||||
</Typography.Text>
|
||||
{#if repo.private}
|
||||
<Icon
|
||||
size="s"
|
||||
icon={IconLockClosed}
|
||||
color="--fgcolor-neutral-tertiary" />
|
||||
alignItems="center"
|
||||
gap="s">
|
||||
{#if action === 'select'}
|
||||
<input
|
||||
class="is-small u-margin-inline-end-8"
|
||||
type="radio"
|
||||
name="repositories"
|
||||
bind:group={selectedRepository}
|
||||
onchange={() => repository.set(repo)}
|
||||
value={repo.id} />
|
||||
{/if}
|
||||
<time datetime={repo.pushedAt}>
|
||||
<Typography.Caption
|
||||
variant="400"
|
||||
truncate
|
||||
color="--fgcolor-neutral-tertiary">
|
||||
{timeFromNow(repo.pushedAt)}
|
||||
</Typography.Caption>
|
||||
</time>
|
||||
</Layout.Stack>
|
||||
{#if action === 'button'}
|
||||
<Layout.Stack
|
||||
direction="row"
|
||||
justifyContent="flex-end">
|
||||
<PinkButton.Button
|
||||
{#if product === 'sites'}
|
||||
{#if repo?.framework && repo.framework !== 'other'}
|
||||
<Avatar size="xs" alt={repo.name}>
|
||||
<SvgIcon
|
||||
name={getFrameworkIcon(
|
||||
repo.framework
|
||||
)}
|
||||
iconSize="small" />
|
||||
</Avatar>
|
||||
{:else}
|
||||
<Avatar size="xs" alt={repo.name} empty />
|
||||
{/if}
|
||||
{:else}
|
||||
{@const iconName = repo?.runtime
|
||||
? repo.runtime.split('-')[0]
|
||||
: undefined}
|
||||
<Avatar
|
||||
size="xs"
|
||||
variant="secondary"
|
||||
on:click={() => connect(repo)}>
|
||||
Connect
|
||||
</PinkButton.Button>
|
||||
alt={repo.name}
|
||||
empty={!iconName}>
|
||||
<SvgIcon name={iconName} iconSize="small" />
|
||||
</Avatar>
|
||||
{/if}
|
||||
<Layout.Stack
|
||||
gap="s"
|
||||
direction="row"
|
||||
alignItems="center">
|
||||
<Typography.Text
|
||||
truncate
|
||||
color="--fgcolor-neutral-secondary">
|
||||
{repo.name}
|
||||
</Typography.Text>
|
||||
{#if repo.private}
|
||||
<Icon
|
||||
size="s"
|
||||
icon={IconLockClosed}
|
||||
color="--fgcolor-neutral-tertiary" />
|
||||
{/if}
|
||||
<time datetime={repo.pushedAt}>
|
||||
<Typography.Caption
|
||||
variant="400"
|
||||
truncate
|
||||
color="--fgcolor-neutral-tertiary">
|
||||
{timeFromNow(repo.pushedAt)}
|
||||
</Typography.Caption>
|
||||
</time>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{#if action === 'button'}
|
||||
<Layout.Stack
|
||||
direction="row"
|
||||
justifyContent="flex-end">
|
||||
<PinkButton.Button
|
||||
size="xs"
|
||||
variant="secondary"
|
||||
on:click={() => connect(repo)}>
|
||||
Connect
|
||||
</PinkButton.Button>
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/snippet}
|
||||
</Paginator>
|
||||
{:else}
|
||||
<EmptySearch hidePages hidePagination bind:search target="repositories">
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
hideFooter = false,
|
||||
hidePages = true,
|
||||
hasLimit = false,
|
||||
name = 'items'
|
||||
name = 'items',
|
||||
children
|
||||
} = $props();
|
||||
|
||||
let total = $derived(items.length);
|
||||
@@ -20,7 +21,7 @@
|
||||
</script>
|
||||
|
||||
<Layout.Stack gap="s">
|
||||
<slot {paginatedItems} {limit} />
|
||||
{@render children(paginatedItems, limit)}
|
||||
|
||||
{#if !hideFooter}
|
||||
<Layout.Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
|
||||
+31
-30
@@ -52,37 +52,38 @@
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
</div>
|
||||
<Paginator
|
||||
items={members.memberships}
|
||||
let:paginatedItems
|
||||
hideFooter={members?.total <= 5}>
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Members</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Joined</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each paginatedItems as member}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<AvatarInitials
|
||||
size="xs"
|
||||
name={member.userName
|
||||
? member.userName
|
||||
: member.userEmail} />
|
||||
<Layout.Stack gap="none">
|
||||
<Typography.Text>
|
||||
{member.userName ? member.userName : member.userEmail}
|
||||
</Typography.Text>
|
||||
<Paginator items={members.memberships} hideFooter={members?.total <= 5}>
|
||||
{#snippet children(paginatedItems: typeof members.memberships)}
|
||||
<Table.Root columns={2} let:root>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell {root}>Members</Table.Header.Cell>
|
||||
<Table.Header.Cell {root}>Joined</Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each paginatedItems as member}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell {root}>
|
||||
<Layout.Stack direction="row" alignItems="center" gap="s">
|
||||
<AvatarInitials
|
||||
size="xs"
|
||||
name={member.userName
|
||||
? member.userName
|
||||
: member.userEmail} />
|
||||
<Layout.Stack gap="none">
|
||||
<Typography.Text>
|
||||
{member.userName
|
||||
? member.userName
|
||||
: member.userEmail}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<DualTimeView time={member.joined ?? member.$createdAt} />
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</Table.Cell>
|
||||
<Table.Cell {root}>
|
||||
<DualTimeView time={member.joined ?? member.$createdAt} />
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/snippet}
|
||||
</Paginator>
|
||||
{:else}
|
||||
<EmptyCardCloud service="members" eventSource="organization_usage" />
|
||||
|
||||
+26
-24
@@ -27,34 +27,36 @@
|
||||
|
||||
<Modal bind:show title={selectedRelationship?.key} hideFooter>
|
||||
{#if data?.length}
|
||||
<Paginator items={data} {limit} let:paginatedItems>
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[{ id: '$id', width: 150 }, ...args.map((id) => ({ id }))]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="$id" {root}>Document ID</Table.Header.Cell>
|
||||
{#if args?.length}
|
||||
{#each args as arg}
|
||||
<Table.Header.Cell column={arg} {root}>{arg}</Table.Header.Cell>
|
||||
{/each}
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
{#each paginatedItems as doc}
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${projectId}/databases/database-${databaseId}/collection-${selectedRelationship.relatedCollection}/document-${doc.$id}`}
|
||||
on:click={() => (show = false)}>
|
||||
<Table.Cell column="$id" {root}>
|
||||
<Id value={doc.$id}>{doc.$id}</Id>
|
||||
</Table.Cell>
|
||||
<Paginator items={data} {limit}>
|
||||
{#snippet children(paginatedItems: typeof data)}
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[{ id: '$id', width: 150 }, ...args.map((id) => ({ id }))]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="$id" {root}>Document ID</Table.Header.Cell>
|
||||
{#if args?.length}
|
||||
{#each args as arg}
|
||||
<Table.Cell column={arg} {root}>{doc[arg]}</Table.Cell>
|
||||
<Table.Header.Cell column={arg} {root}>{arg}</Table.Header.Cell>
|
||||
{/each}
|
||||
{/if}
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</svelte:fragment>
|
||||
{#each paginatedItems as doc}
|
||||
<Table.Row.Link
|
||||
{root}
|
||||
href={`${base}/project-${projectId}/databases/database-${databaseId}/collection-${selectedRelationship.relatedCollection}/document-${doc.$id}`}
|
||||
on:click={() => (show = false)}>
|
||||
<Table.Cell column="$id" {root}>
|
||||
<Id value={doc.$id}>{doc.$id}</Id>
|
||||
</Table.Cell>
|
||||
{#if args?.length}
|
||||
{#each args as arg}
|
||||
<Table.Cell column={arg} {root}>{doc[arg]}</Table.Cell>
|
||||
{/each}
|
||||
{/if}
|
||||
</Table.Row.Link>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/snippet}
|
||||
</Paginator>
|
||||
{/if}
|
||||
</Modal>
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
<Container>
|
||||
<Layout.GridFraction start={1} end={3} gap="xxl">
|
||||
<Layout.Stack gap="xl">
|
||||
<SearchQuery search={data.search} placeholder="Search template" />
|
||||
<SearchQuery placeholder="Search template" />
|
||||
<Layout.Stack>
|
||||
<Accordion title="Use case">
|
||||
<Layout.Stack>
|
||||
@@ -140,86 +140,88 @@
|
||||
</Layout.Stack>
|
||||
<Layout.Stack gap="l">
|
||||
{#if data.templates?.length > 0}
|
||||
<Paginator
|
||||
items={data.templates}
|
||||
let:paginatedItems
|
||||
limit={12}
|
||||
hidePages={false}
|
||||
hasLimit>
|
||||
<Layout.Grid columns={2} columnsXL={3} columnsXS={1}>
|
||||
{#each paginatedItems as template}
|
||||
{@const baseRuntimes = getBaseRuntimes(template.runtimes)}
|
||||
{@const displayed = baseRuntimes.slice(0, 2)}
|
||||
{@const hidden = baseRuntimes.slice(1, -1)}
|
||||
<PinkCard.Base radius="m" padding="xs">
|
||||
<Layout.Stack height="100%" justifyContent="space-between" gap="xl">
|
||||
<Layout.Stack gap="xxxs">
|
||||
<Typography.Text
|
||||
variant="m-500"
|
||||
color="--fgcolor-neutral-primary">
|
||||
{template.name}
|
||||
</Typography.Text>
|
||||
|
||||
<Typography.Text variant="m-400">
|
||||
{template.tagline}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Paginator items={data.templates} limit={12} hidePages={false} hasLimit>
|
||||
{#snippet children(paginatedItems: typeof data.templates)}
|
||||
<Layout.Grid columns={2} columnsXL={3} columnsXS={1}>
|
||||
{#each paginatedItems as template}
|
||||
{@const baseRuntimes = getBaseRuntimes(template.runtimes)}
|
||||
{@const displayed = baseRuntimes.slice(0, 2)}
|
||||
{@const hidden = baseRuntimes.slice(1, -1)}
|
||||
<PinkCard.Base radius="m" padding="xs">
|
||||
<Layout.Stack
|
||||
direction="row"
|
||||
height="100%"
|
||||
justifyContent="space-between"
|
||||
alignItems="center">
|
||||
<AvatarGroup>
|
||||
{#each displayed as runtime}
|
||||
{@const icon = getIconFromRuntime(runtime.name)}
|
||||
{#if icon}
|
||||
<Avatar alt={runtime.name} size="xs">
|
||||
<SvgIcon name={icon} iconSize="small" />
|
||||
</Avatar>
|
||||
{/if}
|
||||
{/each}
|
||||
{#if hidden.length}
|
||||
<Tooltip>
|
||||
<Avatar alt="hidden runtime number" size="xs">
|
||||
<span style:font-size="10px">
|
||||
+{hidden.length}
|
||||
</span>
|
||||
</Avatar>
|
||||
<span slot="tooltip">
|
||||
{hidden.map((n) => n.name).join(', ')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{/if}
|
||||
</AvatarGroup>
|
||||
gap="xl">
|
||||
<Layout.Stack gap="xxxs">
|
||||
<Typography.Text
|
||||
variant="m-500"
|
||||
color="--fgcolor-neutral-primary">
|
||||
{template.name}
|
||||
</Typography.Text>
|
||||
|
||||
<Typography.Text variant="m-400">
|
||||
{template.tagline}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack
|
||||
direction="row"
|
||||
gap="s"
|
||||
alignItems="center"
|
||||
inline>
|
||||
<Button
|
||||
href={`${base}/project-${page.params.project}/functions/templates/template-${template.id}`}
|
||||
text>
|
||||
<span class="text">Details</span>
|
||||
</Button>
|
||||
{#if $canWriteFunctions}
|
||||
<ContainerButton
|
||||
title="functions"
|
||||
disabled={buttonDisabled}
|
||||
buttonType="secondary"
|
||||
buttonHref={`${base}/project-${page.params.project}/functions/create-function/template-${template.id}`}
|
||||
showIcon={false}
|
||||
buttonText="Create"
|
||||
buttonEventData={{
|
||||
source: 'functions_template'
|
||||
}}
|
||||
buttonEvent="create_function" />
|
||||
{/if}
|
||||
justifyContent="space-between"
|
||||
alignItems="center">
|
||||
<AvatarGroup>
|
||||
{#each displayed as runtime}
|
||||
{@const icon = getIconFromRuntime(runtime.name)}
|
||||
{#if icon}
|
||||
<Avatar alt={runtime.name} size="xs">
|
||||
<SvgIcon name={icon} iconSize="small" />
|
||||
</Avatar>
|
||||
{/if}
|
||||
{/each}
|
||||
{#if hidden.length}
|
||||
<Tooltip>
|
||||
<Avatar
|
||||
alt="hidden runtime number"
|
||||
size="xs">
|
||||
<span style:font-size="10px">
|
||||
+{hidden.length}
|
||||
</span>
|
||||
</Avatar>
|
||||
<span slot="tooltip">
|
||||
{hidden.map((n) => n.name).join(', ')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{/if}
|
||||
</AvatarGroup>
|
||||
<Layout.Stack
|
||||
direction="row"
|
||||
gap="s"
|
||||
alignItems="center"
|
||||
inline>
|
||||
<Button
|
||||
href={`${base}/project-${page.params.project}/functions/templates/template-${template.id}`}
|
||||
text>
|
||||
<span class="text">Details</span>
|
||||
</Button>
|
||||
{#if $canWriteFunctions}
|
||||
<ContainerButton
|
||||
title="functions"
|
||||
disabled={buttonDisabled}
|
||||
buttonType="secondary"
|
||||
buttonHref={`${base}/project-${page.params.project}/functions/create-function/template-${template.id}`}
|
||||
showIcon={false}
|
||||
buttonText="Create"
|
||||
buttonEventData={{
|
||||
source: 'functions_template'
|
||||
}}
|
||||
buttonEvent="create_function" />
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</PinkCard.Base>
|
||||
{/each}
|
||||
</Layout.Grid>
|
||||
</PinkCard.Base>
|
||||
{/each}
|
||||
</Layout.Grid>
|
||||
{/snippet}
|
||||
</Paginator>
|
||||
{:else if data?.search}
|
||||
<EmptySearch hidePagination search={data.search}>
|
||||
|
||||
@@ -180,114 +180,118 @@
|
||||
<Paginator
|
||||
items={variables}
|
||||
limit={6}
|
||||
let:paginatedItems
|
||||
hideFooter={variables.length <= 6}>
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'key', width: 200 },
|
||||
{ id: 'value' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="key" {root}
|
||||
>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell column="value" {root}
|
||||
>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root}
|
||||
></Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each paginatedItems as variable}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="key" {root}
|
||||
>{variable.key}</Table.Cell>
|
||||
<Table.Cell column="value" {root}>
|
||||
<!-- TODO: fix max width -->
|
||||
<div style="max-width: 20rem">
|
||||
{#if variable.secret}
|
||||
<Tooltip maxWidth="26rem">
|
||||
<Badge
|
||||
content="Secret"
|
||||
variant="secondary"
|
||||
size="s" />
|
||||
<svelte:fragment slot="tooltip">
|
||||
This value is secret, you cannot see
|
||||
its value.
|
||||
{#snippet children(paginatedItems: typeof variables)}
|
||||
<Table.Root
|
||||
let:root
|
||||
columns={[
|
||||
{ id: 'key', width: 200 },
|
||||
{ id: 'value' },
|
||||
{ id: 'actions', width: 40 }
|
||||
]}>
|
||||
<svelte:fragment slot="header" let:root>
|
||||
<Table.Header.Cell column="key" {root}
|
||||
>Key</Table.Header.Cell>
|
||||
<Table.Header.Cell column="value" {root}
|
||||
>Value</Table.Header.Cell>
|
||||
<Table.Header.Cell column="actions" {root}
|
||||
></Table.Header.Cell>
|
||||
</svelte:fragment>
|
||||
{#each paginatedItems as variable}
|
||||
<Table.Row.Base {root}>
|
||||
<Table.Cell column="key" {root}
|
||||
>{variable.key}</Table.Cell>
|
||||
<Table.Cell column="value" {root}>
|
||||
<!-- TODO: fix max width -->
|
||||
<div style="max-width: 20rem">
|
||||
{#if variable.secret}
|
||||
<Tooltip maxWidth="26rem">
|
||||
<Badge
|
||||
content="Secret"
|
||||
variant="secondary"
|
||||
size="s" />
|
||||
<svelte:fragment slot="tooltip">
|
||||
This value is secret, you cannot
|
||||
see its value.
|
||||
</svelte:fragment>
|
||||
</Tooltip>
|
||||
{:else}
|
||||
<InteractiveText
|
||||
variant="secret"
|
||||
isVisible={false}
|
||||
text={variable.value} />
|
||||
{/if}
|
||||
</div>
|
||||
</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<div style="margin-inline-start: auto">
|
||||
<Popover
|
||||
padding="none"
|
||||
placement="bottom-end"
|
||||
let:toggle>
|
||||
<PinkButton.Button
|
||||
icon
|
||||
variant="text"
|
||||
size="s"
|
||||
aria-label="More options"
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
toggle(e);
|
||||
}}>
|
||||
<Icon
|
||||
icon={IconDotsHorizontal}
|
||||
size="s" />
|
||||
</PinkButton.Button>
|
||||
|
||||
<svelte:fragment
|
||||
slot="tooltip"
|
||||
let:toggle>
|
||||
<ActionMenu.Root>
|
||||
{#if !variable?.secret}
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconPencil}
|
||||
on:click={(e) => {
|
||||
toggle(e);
|
||||
currentVariable =
|
||||
variable;
|
||||
showUpdate = true;
|
||||
}}>
|
||||
Update
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
{#if !variable?.secret}
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconEyeOff}
|
||||
on:click={(e) => {
|
||||
toggle(e);
|
||||
|
||||
currentVariable =
|
||||
variable;
|
||||
showSecretModal = true;
|
||||
}}>
|
||||
Secret
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
<ActionMenu.Item.Button
|
||||
status="danger"
|
||||
leadingIcon={IconTrash}
|
||||
on:click={(e) => {
|
||||
toggle(e);
|
||||
currentVariable =
|
||||
variable;
|
||||
showDelete = true;
|
||||
}}>
|
||||
Delete
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
</svelte:fragment>
|
||||
</Tooltip>
|
||||
{:else}
|
||||
<InteractiveText
|
||||
variant="secret"
|
||||
isVisible={false}
|
||||
text={variable.value} />
|
||||
{/if}
|
||||
</div>
|
||||
</Table.Cell>
|
||||
<Table.Cell column="actions" {root}>
|
||||
<div style="margin-inline-start: auto">
|
||||
<Popover
|
||||
padding="none"
|
||||
placement="bottom-end"
|
||||
let:toggle>
|
||||
<PinkButton.Button
|
||||
icon
|
||||
variant="text"
|
||||
size="s"
|
||||
aria-label="More options"
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
toggle(e);
|
||||
}}>
|
||||
<Icon
|
||||
icon={IconDotsHorizontal}
|
||||
size="s" />
|
||||
</PinkButton.Button>
|
||||
|
||||
<svelte:fragment slot="tooltip" let:toggle>
|
||||
<ActionMenu.Root>
|
||||
{#if !variable?.secret}
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconPencil}
|
||||
on:click={(e) => {
|
||||
toggle(e);
|
||||
currentVariable =
|
||||
variable;
|
||||
showUpdate = true;
|
||||
}}>
|
||||
Update
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
{#if !variable?.secret}
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconEyeOff}
|
||||
on:click={(e) => {
|
||||
toggle(e);
|
||||
|
||||
currentVariable =
|
||||
variable;
|
||||
showSecretModal = true;
|
||||
}}>
|
||||
Secret
|
||||
</ActionMenu.Item.Button>
|
||||
{/if}
|
||||
<ActionMenu.Item.Button
|
||||
status="danger"
|
||||
leadingIcon={IconTrash}
|
||||
on:click={(e) => {
|
||||
toggle(e);
|
||||
currentVariable = variable;
|
||||
showDelete = true;
|
||||
}}>
|
||||
Delete
|
||||
</ActionMenu.Item.Button>
|
||||
</ActionMenu.Root>
|
||||
</svelte:fragment>
|
||||
</Popover>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
</Popover>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
</Table.Row.Base>
|
||||
{/each}
|
||||
</Table.Root>
|
||||
{/snippet}
|
||||
</Paginator>
|
||||
{:else}
|
||||
<Empty on:click={() => (showCreate = true)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { EmptySearch, PaginationWithLimit, Paginator, SvgIcon } from '$lib/components';
|
||||
import { EmptySearch, Paginator, SvgIcon } from '$lib/components';
|
||||
import { Button, InputSearch } from '$lib/elements/forms';
|
||||
import { page } from '$app/state';
|
||||
import Wizard from '$lib/layout/wizard.svelte';
|
||||
@@ -125,43 +125,40 @@
|
||||
</svelte:fragment>
|
||||
<Layout.Stack gap="l">
|
||||
{#if data.templates?.length > 0}
|
||||
<Paginator
|
||||
items={data.templates}
|
||||
let:paginatedItems
|
||||
limit={12}
|
||||
hidePages={false}
|
||||
hasLimit>
|
||||
<Layout.Grid columns={3} columnsXS={2} columnsXXS={1}>
|
||||
{#each paginatedItems as template (template.name)}
|
||||
{@const templateFrameworks = template.frameworks.map((t) => t.name)}
|
||||
<Paginator items={data.templates} limit={12} hidePages={false} hasLimit>
|
||||
{#snippet children(paginatedItems: typeof data.templates)}
|
||||
<Layout.Grid columns={3} columnsXS={2} columnsXXS={1}>
|
||||
{#each paginatedItems as template (template.name)}
|
||||
{@const templateFrameworks = template.frameworks.map((t) => t.name)}
|
||||
|
||||
<Card.Link
|
||||
variant="secondary"
|
||||
href={`${base}/project-${page.params.project}/sites/create-site/templates/template-${template.key}`}
|
||||
padding="xxs">
|
||||
<Card.Media
|
||||
title={template.name}
|
||||
src={$app.themeInUse === 'dark'
|
||||
? template?.screenshotDark ||
|
||||
`${base}/images/sites/screenshot-placeholder-dark.svg`
|
||||
: template?.screenshotLight ||
|
||||
`${base}/images/sites/screenshot-placeholder-light.svg`}
|
||||
alt={template.name}
|
||||
avatar>
|
||||
<svelte:fragment slot="avatar">
|
||||
<Tooltip>
|
||||
<SvgIcon
|
||||
name={getFrameworkIcon(templateFrameworks[0])}
|
||||
iconSize="small" />
|
||||
<svelte:fragment slot="tooltip">
|
||||
{capitalize(templateFrameworks[0])}
|
||||
</svelte:fragment>
|
||||
</Tooltip>
|
||||
</svelte:fragment>
|
||||
</Card.Media>
|
||||
</Card.Link>
|
||||
{/each}
|
||||
</Layout.Grid>
|
||||
<Card.Link
|
||||
variant="secondary"
|
||||
href={`${base}/project-${page.params.project}/sites/create-site/templates/template-${template.key}`}
|
||||
padding="xxs">
|
||||
<Card.Media
|
||||
title={template.name}
|
||||
src={$app.themeInUse === 'dark'
|
||||
? template?.screenshotDark ||
|
||||
`${base}/images/sites/screenshot-placeholder-dark.svg`
|
||||
: template?.screenshotLight ||
|
||||
`${base}/images/sites/screenshot-placeholder-light.svg`}
|
||||
alt={template.name}
|
||||
avatar>
|
||||
<svelte:fragment slot="avatar">
|
||||
<Tooltip>
|
||||
<SvgIcon
|
||||
name={getFrameworkIcon(templateFrameworks[0])}
|
||||
iconSize="small" />
|
||||
<svelte:fragment slot="tooltip">
|
||||
{capitalize(templateFrameworks[0])}
|
||||
</svelte:fragment>
|
||||
</Tooltip>
|
||||
</svelte:fragment>
|
||||
</Card.Media>
|
||||
</Card.Link>
|
||||
{/each}
|
||||
</Layout.Grid>
|
||||
{/snippet}
|
||||
</Paginator>
|
||||
{:else}
|
||||
<EmptySearch
|
||||
|
||||
@@ -7,19 +7,13 @@ export const columns = writable<Column[]>([
|
||||
title: 'Domain',
|
||||
type: 'string',
|
||||
format: 'string',
|
||||
width: { min: 200, max: 550 }
|
||||
width: { min: 200 }
|
||||
},
|
||||
|
||||
{
|
||||
id: 'redirectUrl',
|
||||
title: 'Redirect to',
|
||||
id: 'target',
|
||||
title: 'Target',
|
||||
type: 'string',
|
||||
width: { min: 120, max: 400 }
|
||||
},
|
||||
{
|
||||
id: 'deploymentVcsProviderBranch',
|
||||
title: 'Production branch',
|
||||
type: 'string',
|
||||
width: { min: 90, max: 220 }
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -36,12 +36,12 @@
|
||||
{domain.domain}
|
||||
</Typography.Text>
|
||||
</Link>
|
||||
{:else if column.id === 'redirectUrl'}
|
||||
<!-- TODO design redirect status code -->
|
||||
{domain?.redirectUrl || 'No redirect'}
|
||||
{domain?.redirectStatusCode ? `(${domain.redirectStatusCode})` : ''}
|
||||
{:else if column.id === 'deploymentVcsProviderBranch'}
|
||||
{domain.deploymentVcsProviderBranch || '-'}
|
||||
{:else if column.id === 'target'}
|
||||
{domain?.redirectUrl
|
||||
? 'Redirect to ' + domain.redirectUrl
|
||||
: domain?.deploymentVcsProviderBranch
|
||||
? 'Deployed from' + domain.deploymentVcsProviderBranch
|
||||
: '-'}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
|
||||
+40
-37
@@ -123,43 +123,46 @@
|
||||
{@const items = prodReadyDeployments.deployments.filter(
|
||||
(prodDeployment) => prodDeployment.$id !== deployment.$id
|
||||
)}
|
||||
<Paginator {items} let:paginatedItems hideFooter={items?.length <= 6} limit={6}>
|
||||
{#each paginatedItems as prodDeployment}
|
||||
<LabelCard
|
||||
padding="xs"
|
||||
radius="s"
|
||||
title={toLocaleDateTime(prodDeployment.$createdAt)}
|
||||
bind:group={selectedDeploymentId}
|
||||
value={prodDeployment.$id}>
|
||||
<Layout.Stack gap="s" direction="row" alignItems="center">
|
||||
<Typography.Caption
|
||||
variant="400"
|
||||
color="--fgcolor-neutral-secondary">
|
||||
{calculateSize(deployment.buildSize)}
|
||||
</Typography.Caption>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="2"
|
||||
height="3"
|
||||
viewBox="0 0 2 3"
|
||||
fill="none">
|
||||
<circle cx="1" cy="1.5" r="1" fill="currentColor" />
|
||||
</svg>
|
||||
<Typography.Caption
|
||||
variant="400"
|
||||
color="--fgcolor-neutral-secondary"
|
||||
truncate>
|
||||
{capitalize(timeFromNow(prodDeployment.$createdAt))}
|
||||
{#if prodDeployment?.providerCommitAuthorUrl && prodDeployment?.providerCommitAuthor}
|
||||
by <Link
|
||||
size="s"
|
||||
href={prodDeployment.providerCommitAuthorUrl}
|
||||
external>{prodDeployment.providerCommitAuthor}</Link>
|
||||
{/if}
|
||||
</Typography.Caption>
|
||||
</Layout.Stack>
|
||||
</LabelCard>
|
||||
{/each}
|
||||
<Paginator {items} hideFooter={items?.length <= 6} limit={6}>
|
||||
{#snippet children(paginatedItems: typeof items)}
|
||||
{#each paginatedItems as prodDeployment}
|
||||
<LabelCard
|
||||
padding="xs"
|
||||
radius="s"
|
||||
title={toLocaleDateTime(prodDeployment.$createdAt)}
|
||||
bind:group={selectedDeploymentId}
|
||||
value={prodDeployment.$id}>
|
||||
<Layout.Stack gap="s" direction="row" alignItems="center">
|
||||
<Typography.Caption
|
||||
variant="400"
|
||||
color="--fgcolor-neutral-secondary">
|
||||
{calculateSize(deployment.buildSize)}
|
||||
</Typography.Caption>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="2"
|
||||
height="3"
|
||||
viewBox="0 0 2 3"
|
||||
fill="none">
|
||||
<circle cx="1" cy="1.5" r="1" fill="currentColor" />
|
||||
</svg>
|
||||
<Typography.Caption
|
||||
variant="400"
|
||||
color="--fgcolor-neutral-secondary"
|
||||
truncate>
|
||||
{capitalize(timeFromNow(prodDeployment.$createdAt))}
|
||||
{#if prodDeployment?.providerCommitAuthorUrl && prodDeployment?.providerCommitAuthor}
|
||||
by <Link
|
||||
size="s"
|
||||
href={prodDeployment.providerCommitAuthorUrl}
|
||||
external
|
||||
>{prodDeployment.providerCommitAuthor}</Link>
|
||||
{/if}
|
||||
</Typography.Caption>
|
||||
</Layout.Stack>
|
||||
</LabelCard>
|
||||
{/each}
|
||||
{/snippet}
|
||||
</Paginator>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
|
||||
Reference in New Issue
Block a user