Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions messages/en-us.json
Original file line number Diff line number Diff line change
Expand Up @@ -1895,8 +1895,8 @@
"helperMonth": "Due within a month",
"helperSemesterEnd": "Due before semester end",
"helperSemesterStart": "Semester start",
"advancedShow": "More settings",
"advancedHide": "Hide more settings",
"advancedShow": "Other optional settings",
"advancedHide": "Hide optional settings",
"tagMajor": "Major assignment",
"tagTeam": "Team required",
"tagDefault": "Standard",
Expand Down
4 changes: 2 additions & 2 deletions messages/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -1861,8 +1861,8 @@
"helperMonth": "一月内提交",
"helperSemesterEnd": "学期末前提交",
"helperSemesterStart": "学期开始",
"advancedShow": "更多设置",
"advancedHide": "收起更多设置",
"advancedShow": "其他可选设置",
"advancedHide": "收起其他可选设置",
"tagMajor": "大作业",
"tagTeam": "需要组队",
"tagDefault": "常规作业",
Expand Down
23 changes: 13 additions & 10 deletions src/features/admin/components/AdminBusVersionsMobileList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as Empty from "$lib/components/ui/empty/index.js";
import * as Item from "$lib/components/ui/item/index.js";
import AdminBusVersionActions from "./AdminBusVersionActions.svelte";
import AdminBusVersionStatusBadge from "./AdminBusVersionStatusBadge.svelte";
import AdminListShell from "./AdminListShell.svelte";
import type {
AdminBusCopy,
AdminBusEnhancedAction,
Expand All @@ -27,14 +28,15 @@ export let versions: AdminBusVersion[];
</Empty.Header>
</Empty.Root>
{:else}
<Item.Group class="xl:hidden gap-0 border-y" data-testid="admin-bus-mobile-list">
{#each versions as version, index (version.id)}
<Item.Root class="items-start px-1 py-3" size="sm">
<AdminListShell class="xl:hidden">
<Item.Group class="gap-0" data-testid="admin-bus-mobile-list">
{#each versions as version, index (version.id)}
<Item.Root class="items-start px-1 py-3" size="sm">
<Item.Content class="min-w-0">
<Item.Title>{version.title}</Item.Title>
<Item.Description class="break-all font-mono">{version.key}</Item.Description>
<Item.Title title={version.title}>{version.title}</Item.Title>
<Item.Description class="truncate font-mono" title={version.key}>{version.key}</Item.Description>
{#if version.sourceMessage}
<Item.Description class="line-clamp-none">{version.sourceMessage}</Item.Description>
<Item.Description class="truncate" title={version.sourceMessage}>{version.sourceMessage}</Item.Description>
{/if}
</Item.Content>
<Item.Actions>
Expand Down Expand Up @@ -71,8 +73,9 @@ export let versions: AdminBusVersion[];
</div>
{/if}
</Item.Footer>
</Item.Root>
{#if index < versions.length - 1}<Item.Separator class="my-0" />{/if}
{/each}
</Item.Group>
</Item.Root>
{#if index < versions.length - 1}<Item.Separator class="my-0" />{/if}
{/each}
</Item.Group>
</AdminListShell>
{/if}
127 changes: 68 additions & 59 deletions src/features/admin/components/AdminBusVersionsTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as Empty from "$lib/components/ui/empty/index.js";
import * as Table from "$lib/components/ui/table/index.js";
import AdminBusVersionActions from "./AdminBusVersionActions.svelte";
import AdminBusVersionStatusBadge from "./AdminBusVersionStatusBadge.svelte";
import AdminTableShell from "./AdminTableShell.svelte";
import type {
AdminBusCopy,
AdminBusEnhancedAction,
Expand All @@ -22,65 +23,73 @@ export let versions: AdminBusVersion[];
</script>

<div class="hidden min-w-0 xl:block">
<Table.Root class="w-full">
<Table.Header>
<Table.Row>
<Table.Head>{copy.colTitle}</Table.Head>
<Table.Head>{copy.colKey}</Table.Head>
<Table.Head class="text-right">{copy.colTrips}</Table.Head>
<Table.Head>{copy.colEffective}</Table.Head>
<Table.Head class="text-right">{copy.colImported}</Table.Head>
<Table.Head class="text-center">{copy.colStatus}</Table.Head>
<Table.Head class="w-20 text-right">
<span class="sr-only">{copy.colActions}</span>
</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each versions as version}
<Table.Row class="group">
<Table.Cell>
<TruncatedText class="font-medium" text={version.title} />
<TruncatedText
class="text-muted-foreground text-xs"
text={version.sourceMessage}
/>
</Table.Cell>
<Table.Cell>
<span class="font-mono text-sm">{version.key}</span>
</Table.Cell>
<Table.Cell class="text-right tabular-nums">{version.tripCount}</Table.Cell>
<Table.Cell class="text-muted-foreground">
{formatEffectiveRange(version)}
</Table.Cell>
<Table.Cell class="whitespace-nowrap text-right tabular-nums text-muted-foreground">
{formatImportedAt(version.importedAt)}
</Table.Cell>
<Table.Cell class="text-center">
<AdminBusVersionStatusBadge {copy} {version} />
</Table.Cell>
<Table.Cell class="w-20 text-right">
<AdminBusVersionActions
{copy}
{enhancedAction}
{isPending}
{onDelete}
{pendingAction}
{version}
/>
</Table.Cell>
</Table.Row>
{:else}
<AdminTableShell label={copy.colTitle}>
<Table.Root class="w-full min-w-[68rem]">
<Table.Header>
<Table.Row>
<Table.Cell class="p-0" colspan={7}>
<Empty.Root class="min-h-20 rounded-none border-0 px-2 py-6">
<Empty.Header>
<Empty.Description>{copy.noVersions}</Empty.Description>
</Empty.Header>
</Empty.Root>
</Table.Cell>
<Table.Head class="w-[25%]">{copy.colTitle}</Table.Head>
<Table.Head class="w-[17%]">{copy.colKey}</Table.Head>
<Table.Head class="w-[9%] text-right">{copy.colTrips}</Table.Head>
<Table.Head class="w-[18%]">{copy.colEffective}</Table.Head>
<Table.Head class="w-[14%] text-right">{copy.colImported}</Table.Head>
<Table.Head class="w-[10%] text-center">{copy.colStatus}</Table.Head>
<Table.Head class="w-20 min-w-20 text-right">
<span class="sr-only">{copy.colActions}</span>
</Table.Head>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</Table.Header>
<Table.Body>
{#each versions as version}
<Table.Row class="group">
<Table.Cell class="max-w-0">
<span class="block max-w-full" title={version.title}>
<TruncatedText class="font-medium" text={version.title} />
</span>
<span class="block max-w-full" title={version.sourceMessage}>
<TruncatedText
class="text-muted-foreground text-xs"
text={version.sourceMessage}
/>
</span>
</Table.Cell>
<Table.Cell class="max-w-0">
<span class="block max-w-full truncate font-mono text-sm" title={version.key}>
{version.key}
</span>
</Table.Cell>
<Table.Cell class="text-right tabular-nums">{version.tripCount}</Table.Cell>
<Table.Cell class="text-muted-foreground">
{formatEffectiveRange(version)}
</Table.Cell>
<Table.Cell class="whitespace-nowrap text-right tabular-nums text-muted-foreground">
{formatImportedAt(version.importedAt)}
</Table.Cell>
<Table.Cell class="text-center">
<AdminBusVersionStatusBadge {copy} {version} />
</Table.Cell>
<Table.Cell class="w-20 min-w-20 text-right">
<AdminBusVersionActions
{copy}
{enhancedAction}
{isPending}
{onDelete}
{pendingAction}
{version}
/>
</Table.Cell>
</Table.Row>
{:else}
<Table.Row>
<Table.Cell class="p-0" colspan={7}>
<Empty.Root class="min-h-20 rounded-none border-0 px-2 py-6">
<Empty.Header>
<Empty.Description>{copy.noVersions}</Empty.Description>
</Empty.Header>
</Empty.Root>
</Table.Cell>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</AdminTableShell>
</div>
15 changes: 15 additions & 0 deletions src/features/admin/components/AdminListShell.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script lang="ts">
import type { Snippet } from "svelte";
import { cn } from "$lib/utils.js";

type Props = {
children: Snippet;
class?: string;
};

let { children, class: className = "" }: Props = $props();
</script>

<div class={cn("min-w-0 max-w-full border-y", className)} data-slot="admin-list-shell">
{@render children()}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ export let targetLabel: AdminModerationCommentFormatter;
{/if}
</div>
</Table.Cell>
<Table.Cell>
{commentAuthorLabel(comment)}
<Table.Cell class="max-w-0">
{@const author = commentAuthorLabel(comment)}
<span class="block max-w-full truncate" title={author}>{author}</span>
</Table.Cell>
<Table.Cell>
<a
class="block min-w-0 overflow-hidden hover:underline"
class="block min-w-0 max-w-full overflow-hidden hover:underline"
href={targetHref(comment)}
title={targetLabel(comment)}
>
<TruncatedText text={targetLabel(comment)} />
</a>
Expand All @@ -59,7 +61,7 @@ export let targetLabel: AdminModerationCommentFormatter;
status={comment.status}
/>
</Table.Cell>
<Table.Cell class="w-12 text-right">
<Table.Cell class="w-14 min-w-14 text-right">
<TableRowActions class="justify-end">
<TableIconButton
label={copy.manageComment}
Expand Down
67 changes: 35 additions & 32 deletions src/features/admin/components/AdminModerationCommentsMobile.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import ChevronRightIcon from "@lucide/svelte/icons/chevron-right";
import { Button } from "$lib/components/ui/button/index.js";
import * as Item from "$lib/components/ui/item/index.js";
import AdminListShell from "./AdminListShell.svelte";
import type {
AdminModerationComment,
AdminModerationCommentFormatter,
Expand All @@ -18,35 +19,37 @@ export let statusLabel: AdminModerationCommentStatusFormatter;
export let targetLabel: AdminModerationCommentFormatter;
</script>

<Item.Group class="xl:hidden gap-0 border-y" data-testid="admin-moderation-mobile-list">
{#each comments as comment, index (comment.id)}
<Item.Root class="items-start px-1 py-3">
<Item.Content class="min-w-0">
<Item.Title>{targetLabel(comment)}</Item.Title>
<Item.Description>
{commentAuthorLabel(comment)} · {formatDate(comment.createdAt)}
</Item.Description>
<Item.Description class="line-clamp-3 whitespace-pre-wrap">
{comment.body}
</Item.Description>
</Item.Content>
<Item.Actions class="shrink-0 flex-wrap self-start">
<ModerationStatusBadge
label={statusLabel(comment.status)}
status={comment.status}
/>
<Button
aria-label={manageLabel}
onclick={() => onManage(comment)}
size="sm"
type="button"
variant="ghost"
>
{manageLabel}
<ChevronRightIcon aria-hidden="true" data-icon="inline-end" />
</Button>
</Item.Actions>
</Item.Root>
{#if index < comments.length - 1}<Item.Separator class="my-0" />{/if}
{/each}
</Item.Group>
<AdminListShell class="xl:hidden">
<Item.Group class="gap-0" data-testid="admin-moderation-mobile-list">
{#each comments as comment, index (comment.id)}
<Item.Root class="items-start px-1 py-3">
<Item.Content class="min-w-0">
<Item.Title>{targetLabel(comment)}</Item.Title>
<Item.Description>
{commentAuthorLabel(comment)} · {formatDate(comment.createdAt)}
</Item.Description>
<Item.Description class="line-clamp-3 whitespace-pre-wrap">
{comment.body}
</Item.Description>
</Item.Content>
<Item.Actions class="shrink-0 flex-wrap self-start">
<ModerationStatusBadge
label={statusLabel(comment.status)}
status={comment.status}
/>
<Button
aria-label={manageLabel}
onclick={() => onManage(comment)}
size="sm"
type="button"
variant="ghost"
>
{manageLabel}
<ChevronRightIcon aria-hidden="true" data-icon="inline-end" />
</Button>
</Item.Actions>
</Item.Root>
{#if index < comments.length - 1}<Item.Separator class="my-0" />{/if}
{/each}
</Item.Group>
</AdminListShell>
59 changes: 31 additions & 28 deletions src/features/admin/components/AdminModerationCommentsTable.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import * as Table from "$lib/components/ui/table/index.js";
import AdminModerationCommentTableRow from "./AdminModerationCommentTableRow.svelte";
import AdminTableShell from "./AdminTableShell.svelte";
import type {
AdminModerationComment,
AdminModerationCommentFormatter,
Expand All @@ -19,32 +20,34 @@ export let targetLabel: AdminModerationCommentFormatter;
</script>

<div class="hidden min-w-0 xl:block">
<Table.Root class="w-full">
<Table.Header>
<Table.Row>
<Table.Head>{copy.content}</Table.Head>
<Table.Head>{copy.author}</Table.Head>
<Table.Head>{copy.postedIn}</Table.Head>
<Table.Head class="text-right">{copy.createdAt}</Table.Head>
<Table.Head class="text-center">{copy.status}</Table.Head>
<Table.Head class="w-12 text-right">
<span class="sr-only">{copy.actions}</span>
</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each comments as comment}
<AdminModerationCommentTableRow
{comment}
{commentAuthorLabel}
{copy}
{formatDate}
{onManage}
{statusLabel}
{targetHref}
{targetLabel}
/>
{/each}
</Table.Body>
</Table.Root>
<AdminTableShell label={copy.content}>
<Table.Root class="w-full min-w-[64rem]">
<Table.Header>
<Table.Row>
<Table.Head class="w-[34%]">{copy.content}</Table.Head>
<Table.Head class="w-[16%]">{copy.author}</Table.Head>
<Table.Head class="w-[20%]">{copy.postedIn}</Table.Head>
<Table.Head class="w-[14%] text-right">{copy.createdAt}</Table.Head>
<Table.Head class="w-[10%] text-center">{copy.status}</Table.Head>
<Table.Head class="w-14 min-w-14 text-right">
<span class="sr-only">{copy.actions}</span>
</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each comments as comment}
<AdminModerationCommentTableRow
{comment}
{commentAuthorLabel}
{copy}
{formatDate}
{onManage}
{statusLabel}
{targetHref}
{targetLabel}
/>
{/each}
</Table.Body>
</Table.Root>
</AdminTableShell>
</div>
Loading
Loading