Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
16c2252
Migrate alerts and reports tables to shared `ResourceListRow` component
royendo Apr 3, 2026
dc59f2b
Update resource list rows to flat divider style
royendo Apr 3, 2026
f8c4500
Add dropdown action menus to alert and report rows
royendo Apr 3, 2026
810eaf6
Use icon-only badges for dashboard, alert, and report rows
royendo Apr 3, 2026
591a518
Align subtitle text with title text in dashboard rows
royendo Apr 3, 2026
5c6dd9f
Wire up dropdown actions for alert and report rows
royendo Apr 3, 2026
576e7fe
prettier
royendo Apr 3, 2026
944a1f4
Merge branch 'main' into royendo/alert-report-table-migrate
royendo Apr 6, 2026
7dce573
revert to badge + label
royendo Apr 7, 2026
8866662
local code review,
royendo Apr 7, 2026
7ce3fdc
Update +page.svelte
royendo Apr 7, 2026
38d7cdc
TODO
royendo Apr 7, 2026
235e909
fix e2e, updated to Dashboards
royendo Apr 7, 2026
d951af2
refactor: code review fixes for resource list components
royendo Apr 7, 2026
291dfe1
no more magic
royendo Apr 7, 2026
ae7aaeb
Update DashboardsTableCompositeCell.svelte
royendo Apr 7, 2026
aab26b0
consolidate resource deletion to single modal
royendo Apr 7, 2026
cfdefb0
Merge branch 'main' into royendo/alert-report-table-migrate
royendo Apr 7, 2026
3960a0a
change to confirm on delete
royendo Apr 7, 2026
fb1efd3
Merge branch 'main' into royendo/alert-report-table-migrate
royendo Apr 24, 2026
f21dd3d
Merge remote-tracking branch 'origin/main' into royendo/alert-report-…
royendo Apr 24, 2026
d4b9164
apply filters and table to dashboard,alert,report
royendo Apr 24, 2026
79e3256
prettier
royendo Apr 25, 2026
0793509
refactor: address code review feedback for table redesign
royendo Apr 25, 2026
028d9a5
fix: sort dashboards by `meta.createdOn` for the Newest/Oldest toggle
royendo Apr 25, 2026
1761179
refactor: extract `applyTableFilters` / `toggleArrayValue` helpers
royendo Apr 25, 2026
a4d6f7a
Merge `main` into `royendo/alert-report-table-migrate`
royendo Apr 27, 2026
6d07022
refactor: migrate `ProjectLogsPage` to `TableToolbar`
royendo Apr 27, 2026
741ac86
refactor: migrate users, groups, and guests pages to `TableToolbar`
royendo Apr 27, 2026
e26e360
fix: address final review feedback for table redesign
royendo Apr 27, 2026
4b1a33a
test: align alert leaderboard assertion with new comparison row format
royendo Apr 27, 2026
4fd84d0
test: force cursor off leaderboard row before asserting
royendo Apr 27, 2026
c1303af
Merge remote-tracking branch 'origin/main' into royendo/alert-report-…
royendo Apr 27, 2026
75794e4
as designed, tags need 9283
royendo Apr 28, 2026
04eb4c3
fix web-admin
royendo Apr 28, 2026
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
20 changes: 20 additions & 0 deletions web-admin/src/features/alerts/CreateAlert.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script lang="ts">
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import { Button } from "@rilldata/web-common/components/button";
import GuardedDialog from "@rilldata/web-common/components/dialog/GuardedDialog.svelte";
import {
Expand Down Expand Up @@ -28,6 +30,24 @@
$: hasTimeDimension = !!$metricsView?.data?.timeDimension;

let open = false;

// Auto-open when arriving from the dashboards listing's "Create alert" item.
// Strip the query param afterwards so a refresh doesn't reopen the dialog.
$: if (
!open &&
$page.url.searchParams.get("action") === "create-alert" &&
hasTimeDimension &&
$dashboardStore &&
!$isCustomTimeRange
) {
open = true;
const url = new URL($page.url);
url.searchParams.delete("action");
void goto(url.pathname + url.search, {
replaceState: true,
noScroll: true,
});
}
</script>

{#if hasTimeDimension && $dashboardStore}
Expand Down
11 changes: 6 additions & 5 deletions web-admin/src/features/alerts/history/AlertHistoryTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import NoAlertRunsYet from "@rilldata/web-admin/features/alerts/history/NoAlertRunsYet.svelte";
import { useAlert } from "@rilldata/web-admin/features/alerts/selectors";
import ResourceList from "@rilldata/web-common/features/resources/ResourceList.svelte";
import type { V1AlertExecution } from "@rilldata/web-common/runtime-client/gen/index.schemas";
import { type V1AlertExecution } from "@rilldata/web-common/runtime-client";
import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2";
import type { ColumnDef } from "tanstack-table-8-svelte-5";
import { renderComponent } from "tanstack-table-8-svelte-5";
Expand All @@ -14,10 +14,11 @@

$: alertQuery = useAlert(runtimeClient, alert);

$: history = $alertQuery.data?.resource?.alert?.state?.executionHistory ?? [];

/**
* Table column definitions.
* - "composite": Renders all dashboard data in a single cell.
* - Others: Used for sorting and filtering but not displayed.
* - "composite": Renders all execution data in a single cell.
*/
const columns: ColumnDef<V1AlertExecution>[] = [
{
Expand Down Expand Up @@ -46,13 +47,13 @@
</div>
{:else if $alertQuery.isLoading}
<div class="text-fg-secondary">Loading...</div>
{:else if !$alertQuery.data?.resource.alert.state.executionHistory.length}
{:else if !history.length}
<NoAlertRunsYet />
{:else}
<ResourceList
kind="alert"
{columns}
data={$alertQuery.data?.resource.alert.state.executionHistory}
data={history}
toolbar={false}
fixedRowHeight={false}
/>
Expand Down
94 changes: 94 additions & 0 deletions web-admin/src/features/alerts/listing/AlertActionsCell.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<script lang="ts">
import { goto } from "$app/navigation";
import { createAdminServiceDeleteAlert } from "@rilldata/web-admin/client";
import IconButton from "@rilldata/web-common/components/button/IconButton.svelte";
import * as DropdownMenu from "@rilldata/web-common/components/dropdown-menu";
import ThreeDot from "@rilldata/web-common/components/icons/ThreeDot.svelte";
import DeleteConfirmDialog from "@rilldata/web-common/features/resources/DeleteConfirmDialog.svelte";
import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus";
import { getRuntimeServiceListResourcesQueryKey } from "@rilldata/web-common/runtime-client";
import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2";
import { useQueryClient } from "@tanstack/svelte-query";
import { Pencil, Trash2Icon } from "lucide-svelte";

export let organization: string;
export let project: string;
export let id: string;
export let title: string;
export let isCreatedByCode: boolean;

const runtimeClient = useRuntimeClient();
const queryClient = useQueryClient();
const deleteAlert = createAdminServiceDeleteAlert();

let isDropdownOpen = false;
let isDeleteConfirmOpen = false;

function handleEdit() {
void goto(`/${organization}/${project}/-/alerts/${id}`);
}

async function handleDelete() {
try {
await $deleteAlert.mutateAsync({
org: organization,
project,
name: id,
});
await queryClient.invalidateQueries({
queryKey: getRuntimeServiceListResourcesQueryKey(
runtimeClient.instanceId,
),
});
} catch {
eventBus.emit("notification", {
message: "Failed to delete alert",
type: "error",
});
}
}
</script>

{#if !isCreatedByCode}
<div class="flex justify-end" data-no-row-click>
<DropdownMenu.Root bind:open={isDropdownOpen}>
<DropdownMenu.Trigger class="flex-none">
<IconButton
rounded
active={isDropdownOpen}
ariaLabel={`Actions for ${title}`}
>
<ThreeDot size="16px" />
</IconButton>
</DropdownMenu.Trigger>
<DropdownMenu.Content side="bottom" align="start" class="min-w-[95px]">
<DropdownMenu.Item
class="font-normal flex items-center"
onclick={handleEdit}
>
<Pencil size="12px" />
<span class="ml-2">Edit</span>
</DropdownMenu.Item>
<DropdownMenu.Item
class="font-normal flex items-center"
type="destructive"
onclick={() => {
isDeleteConfirmOpen = true;
}}
>
<Trash2Icon size="12px" />
<span class="ml-2">Delete</span>
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
</div>

<DeleteConfirmDialog
bind:open={isDeleteConfirmOpen}
title="Delete this alert?"
onDelete={handleDelete}
>
The alert "<strong>{title}</strong>" will be permanently deleted and will no
longer trigger notifications.
</DeleteConfirmDialog>
{/if}
15 changes: 0 additions & 15 deletions web-admin/src/features/alerts/listing/AlertOwnerBullet.svelte

This file was deleted.

22 changes: 22 additions & 0 deletions web-admin/src/features/alerts/listing/AlertOwnerCell.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts">
import ProjectAccessControls from "../../projects/ProjectAccessControls.svelte";
import { useAlertOwnerName } from "../selectors";

export let organization: string;
export let project: string;
export let ownerId: string;

$: ownerName = useAlertOwnerName(organization, project, ownerId);
</script>

<ProjectAccessControls {organization} {project}>
<svelte:fragment slot="manage-project">
{#if $ownerName.isSuccess}
<span class="truncate">
{$ownerName.data ?? "Code-defined"}
</span>
{:else}
<span class="text-fg-tertiary">—</span>
{/if}
</svelte:fragment>
</ProjectAccessControls>
31 changes: 31 additions & 0 deletions web-admin/src/features/alerts/listing/AlertStatusCell.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script lang="ts">
import StatusTextCell from "@rilldata/web-common/features/resources/cells/StatusTextCell.svelte";
import {
V1AssertionStatus,
type V1Resource,
} from "@rilldata/web-common/runtime-client";

export let resource: V1Resource;

type Tone = "default" | "muted" | "success" | "destructive";

$: ({ label, tone } = describeStatus(resource));

function describeStatus(r: V1Resource): { label: string; tone: Tone } {
const last = r.alert?.state?.executionHistory?.[0];
if (!last) return { label: "Pending", tone: "muted" };

switch (last.result?.status) {
case V1AssertionStatus.ASSERTION_STATUS_FAIL:
return { label: "Triggered", tone: "destructive" };
case V1AssertionStatus.ASSERTION_STATUS_PASS:
return { label: "OK", tone: "success" };
case V1AssertionStatus.ASSERTION_STATUS_ERROR:
return { label: "Error", tone: "destructive" };
default:
return { label: "Pending", tone: "muted" };
}
}
</script>

<StatusTextCell {label} {tone} />
Loading
Loading