diff --git a/web-admin/src/features/dashboards/listing/DashboardsTable.svelte b/web-admin/src/features/dashboards/listing/DashboardsTable.svelte index 2b486833a596..50927507d261 100644 --- a/web-admin/src/features/dashboards/listing/DashboardsTable.svelte +++ b/web-admin/src/features/dashboards/listing/DashboardsTable.svelte @@ -10,20 +10,28 @@ import { renderComponent } from "tanstack-table-8-svelte-5"; import DashboardsTableCompositeCell from "./DashboardsTableCompositeCell.svelte"; import { useDashboards, useIsInitialBuild } from "./selectors"; - import { Search } from "@rilldata/web-common/components/search"; import { UrlParamsState } from "web-common/src/lib/store-utils/url-params-state.svelte.ts"; import { getAllTagsForResources } from "@rilldata/web-common/features/resources/resource-tag-utils.ts"; import ResizableSidebar from "@rilldata/web-common/layout/ResizableSidebar.svelte"; import DashboardsTagSidebar from "@rilldata/web-admin/features/dashboards/listing/DashboardsTagSidebar.svelte"; import { filterResources } from "@rilldata/web-common/features/resources/resource-filter-utils.ts"; + import { + DashboardTableSortOptions, + getDashboardFavouritesStore, + RecentlyUsedDashboards, + } from "./dashboard-favourites.ts"; import { DebouncedRuneStore } from "@rilldata/web-common/lib/store-utils/types.svelte.ts"; import { m } from "@rilldata/web-common/lib/i18n/gen/messages"; import { escapeHtml } from "@rilldata/web-common/lib/i18n"; + import { TableToolbar } from "@rilldata/web-common/components/table-toolbar"; + import { dedupe } from "@rilldata/web-common/lib/arrayUtils.ts"; + + type DashboardRow = V1Resource & { lastUsed: number }; let { isEmbedded = false, isPreview = false, - previewLimit = 5, + previewLimit = undefined, }: { isEmbedded?: boolean; isPreview?: boolean; @@ -37,6 +45,13 @@ 500, ); + const sortStore = UrlParamsState.createStringParam("sort"); + let sortingOption = $derived( + DashboardTableSortOptions.find( + (option) => option.value === sortStore.value, + ) ?? DashboardTableSortOptions[0], + ); + const runtimeClient = useRuntimeClient(); let { organization, project } = $derived(page.params); @@ -66,14 +81,38 @@ ), ); - let displayData = $derived( - isPreview ? filteredDashboards.slice(0, previewLimit) : filteredDashboards, + let dashboardFavourites = $derived( + getDashboardFavouritesStore(organization, project), + ); + let recentlyUsedDashboards = $derived( + new RecentlyUsedDashboards(organization, project), + ); + + let validDashboardFavourites = $derived( + dedupe( + dashboardFavourites.value.filter((f) => + filteredDashboards.find((r) => r.meta?.name?.name?.toLowerCase() === f), + ), + (e) => e, + ), ); let hasMoreDashboards = $derived( isPreview && filteredDashboards.length > previewLimit, ); + let displayData = $derived( + filteredDashboards.map( + (r): DashboardRow => ({ + ...r, + lastUsed: + recentlyUsedDashboards.recentlyUsed.value[ + r.meta?.name?.name?.toLowerCase() ?? "" + ] ?? 0, + }), + ), + ); + const columns = [ { id: "composite", @@ -103,6 +142,8 @@ organization, project, tags, + dashboardFavourites, + recentlyUsedDashboards, }); }, }, @@ -135,6 +176,10 @@ return isMetricsExplorer ? row.explore.spec.description : ""; }, }, + { + id: "lastUsed", + accessorFn: (row: DashboardRow) => row.lastUsed, + }, ]; const columnVisibility = { @@ -142,9 +187,8 @@ name: false, lastRefreshed: false, description: false, + lastUsed: false, }; - - const initialSorting = [{ id: "name", desc: false }]; {#if isLoading || isBuilding} @@ -156,16 +200,11 @@ {:else if isSuccess}