-
Notifications
You must be signed in to change notification settings - Fork 125
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cloud UI: create page for a project's Scheduled Reports (#3241)
* Display a project's dashboards in a table * Refactor `Tag` component to accept a `color` prop * Change `Search` component to white color * Add `ContentContainer` helper layout component * Edit copy * Create `Tab` components using `svelte-headlessui` * Use tabs to navigate between a project's subroutes * Display scheduled reports in a table * Move file * Rename component * Add icon * Add file * Fix import * Remove project hero * Add `ContentContainer` * Fix issues with `dashboards/listing` directory * Add status badge to "Logs" tab * Hide "Reports" tab for now * Fix import * Fix CSS selector * Fix import * Match Figma mocks * Only show Logs tab to admins * Add fallback/localized error for dashboards table * Add URL slug to dashboard table row * Better sort copy * Restore the `ProjectHero` while no project tabs * Better "last refresh" date * Fix up sorting behavior * Move type, add comment * Make the click target bigger * Add tooltip for last refresh date * Create dedicated slot for an empty table * Nit * Make whole cell clickable * Fix svelte-check * Better typing * Decompose object * Move `ProjectTabs` into runtime context * Fix refresh of logs page * Remove old padding * Center the dashboards table * Add "No logs" view * Bugfix * Use `$table` not `get(table)` * Reset table filter when changing projects * Hide sort button for now * Show reports tab * Fix row padding * Rename "InfoCell" -> "CompositeCell" * Center the table * Match dashboards table * Fix padding on other Search instances * Use `luxon` * Add report icon; make entire row clickable * Use `CheckCircleOutline` icon * Clean up header * Add table empty state * Adjust left padding in table header * Creating `listing` subdirectory * Remove redirect from project to dashboard * Fetch reports from runtime * Add error state * Add 0 reports state * Move code * Remove unused props * Move data fetching to `selectors.ts` * Format report `owner` * Account for reports not-yet-run * Use `cronstrue` to translate cron expressions to natural language * Add owner's name; fix status badge * Fix lint
- Loading branch information
1 parent
4279acb
commit 03f9bdf
Showing
19 changed files
with
441 additions
and
9 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,16 +16,17 @@ | |
"@fontsource/fira-mono": "^4.5.0", | ||
"@playwright/test": "^1.25.0", | ||
"@rgossiaux/svelte-headlessui": "^2.0.0", | ||
"@rilldata/svelte-query": "^4.29.20-0.0.1", | ||
"@sveltejs/adapter-static": "^1.0.0", | ||
"@sveltejs/kit": "^1.5.0", | ||
"@rilldata/svelte-query": "^4.29.20-0.0.1", | ||
"@tanstack/svelte-query": "npm:@rilldata/[email protected]", | ||
"@types/cookie": "^0.5.1", | ||
"@typescript-eslint/eslint-plugin": "^5.27.0", | ||
"@typescript-eslint/parser": "^5.27.0", | ||
"autoprefixer": "^10.4.13", | ||
"axios": "^0.27.2", | ||
"cookie": "^0.4.1", | ||
"cronstrue": "^2.41.0", | ||
"eslint": "^8.16.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-svelte3": "^4.0.0", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
web-admin/src/features/scheduled-reports/listing/NoReportsCTA.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<script lang="ts"> | ||
import ReportIcon from "@rilldata/web-common/components/icons/ReportIcon.svelte"; | ||
</script> | ||
|
||
<div | ||
class="m-auto mt-20 pb-10 flex-col justify-center items-center gap-y-4 inline-flex" | ||
> | ||
<div class="flex flex-col justify-center items-center"> | ||
<div class="relative"> | ||
<ReportIcon className="text-slate-300 w-12 h-12" /> | ||
</div> | ||
</div> | ||
<div | ||
class="flex flex-col gap-y-2 justify-center items-center text-center text-sm" | ||
> | ||
<div class="text-gray-600 font-semibold"> | ||
You don't have any reports yet | ||
</div> | ||
<div> | ||
<span style="text-gray-500 font-normal" | ||
>Learn how to create a report in our | ||
</span><a href="https://docs.rilldata.com/" target="_blank">docs</a> | ||
</div> | ||
</div> | ||
</div> |
15 changes: 15 additions & 0 deletions
15
web-admin/src/features/scheduled-reports/listing/ReportsError.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<script lang="ts"> | ||
</script> | ||
|
||
<div | ||
class="m-auto mt-20 pb-10 flex-col justify-center items-center gap-y-4 inline-flex" | ||
> | ||
<div | ||
class="flex flex-col gap-y-2 justify-center items-center text-center text-sm" | ||
> | ||
<div class="text-gray-600 font-semibold">Error loading reports</div> | ||
<div class="text-gray-500 font-normal"> | ||
If this error persists, please contact support. | ||
</div> | ||
</div> | ||
</div> |
90 changes: 90 additions & 0 deletions
90
web-admin/src/features/scheduled-reports/listing/ReportsTable.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<script lang="ts"> | ||
import Spinner from "@rilldata/web-common/features/entity-management/Spinner.svelte"; | ||
import { EntityStatus } from "@rilldata/web-common/features/entity-management/types"; | ||
import type { V1Resource } from "@rilldata/web-common/runtime-client"; | ||
import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; | ||
import { ColumnDef, flexRender } from "@tanstack/svelte-table"; | ||
import Table from "../../../components/table/Table.svelte"; | ||
import { useReports } from "../selectors"; | ||
import NoReportsCTA from "./NoReportsCTA.svelte"; | ||
import ReportsError from "./ReportsError.svelte"; | ||
import ReportsTableCompositeCell from "./ReportsTableCompositeCell.svelte"; | ||
import ReportsTableEmpty from "./ReportsTableEmpty.svelte"; | ||
import ReportsTableHeader from "./ReportsTableHeader.svelte"; | ||
export let organization: string; | ||
export let project: string; | ||
$: reports = useReports($runtime.instanceId); | ||
/** | ||
* Table column definitions. | ||
* - "composite": Renders all dashboard data in a single cell. | ||
* - Others: Used for sorting and filtering but not displayed. | ||
* | ||
* Note: TypeScript error prevents using `ColumnDef<DashboardResource, string>[]`. | ||
* Relevant issues: | ||
* - https://github.com/TanStack/table/issues/4241 | ||
* - https://github.com/TanStack/table/issues/4302 | ||
*/ | ||
const columns: ColumnDef<V1Resource, string>[] = [ | ||
{ | ||
id: "composite", | ||
cell: (info) => | ||
flexRender(ReportsTableCompositeCell, { | ||
organization: organization, | ||
project: project, | ||
id: info.row.original.meta.name.name, | ||
title: info.row.original.report.spec.title, | ||
lastRun: | ||
info.row.original.report.state.executionHistory[0]?.reportTime, | ||
frequency: info.row.original.report.spec.refreshSchedule.cron, | ||
ownerId: | ||
info.row.original.report.spec.annotations["admin_owner_user_id"], | ||
lastRunErrorMessage: | ||
info.row.original.report.state.executionHistory[0]?.errorMessage, | ||
}), | ||
}, | ||
{ | ||
id: "name", | ||
accessorFn: (row) => row.meta.name.name, | ||
}, | ||
{ | ||
id: "lastRun", | ||
accessorFn: (row) => row.report.state.currentExecution.reportTime, | ||
}, | ||
// { | ||
// id: "nextRun", | ||
// accessorFn: (row) => row.nextRun, | ||
// }, | ||
// { | ||
// id: "actions", | ||
// cell: ({ row }) => | ||
// flexRender(ReportsTableActionCell, { | ||
// title: row.original.name, | ||
// }), | ||
// }, | ||
]; | ||
const columnVisibility = { | ||
name: false, | ||
lastRun: false, | ||
}; | ||
</script> | ||
|
||
{#if $reports.isLoading} | ||
<div class="m-auto mt-20"> | ||
<Spinner status={EntityStatus.Running} size="24px" /> | ||
</div> | ||
{:else if $reports.isError} | ||
<ReportsError /> | ||
{:else if $reports.isSuccess} | ||
{#if $reports.data.resources.length === 0} | ||
<NoReportsCTA /> | ||
{:else} | ||
<Table {columns} data={$reports?.data?.resources} {columnVisibility}> | ||
<ReportsTableHeader slot="header" /> | ||
<ReportsTableEmpty slot="empty" /> | ||
</Table> | ||
{/if} | ||
{/if} |
16 changes: 16 additions & 0 deletions
16
web-admin/src/features/scheduled-reports/listing/ReportsTableActionCell.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<script lang="ts"> | ||
import ThreeDot from "@rilldata/web-common/components/icons/ThreeDot.svelte"; | ||
export let reportName: string; | ||
</script> | ||
|
||
<button | ||
class="text-gray-500 hover:text-blue-500 hover:bg-slate-200 grid place-items-center rounded-sm" | ||
on:click={() => console.log(`open actions for ${reportName}`)} | ||
> | ||
<ThreeDot size="16px" /> | ||
</button> | ||
|
||
<!-- TODO: Menu for admins --> | ||
|
||
<!-- TODO: Menu for viewers --> |
54 changes: 54 additions & 0 deletions
54
web-admin/src/features/scheduled-reports/listing/ReportsTableCompositeCell.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<script lang="ts"> | ||
import CancelCircleInverse from "@rilldata/web-common/components/icons/CancelCircleInverse.svelte"; | ||
import CheckCircleOutline from "@rilldata/web-common/components/icons/CheckCircleOutline.svelte"; | ||
import ReportIcon from "@rilldata/web-common/components/icons/ReportIcon.svelte"; | ||
import cronstrue from "cronstrue"; | ||
import { createAdminServiceListProjectMembers } from "../../../client"; | ||
import { formatDateToCustomString } from "../tableUtils"; | ||
export let organization: string; | ||
export let project: string; | ||
export let id: string; | ||
export let title: string; | ||
export let lastRun: string | undefined; | ||
export let frequency: string; | ||
export let ownerId: string; | ||
export let lastRunErrorMessage: string | undefined; | ||
const humanReadableFrequency = cronstrue.toString(frequency); | ||
const membersQuery = createAdminServiceListProjectMembers( | ||
organization, | ||
project | ||
); | ||
$: owner = $membersQuery.data?.members.find( | ||
(member) => member.userId === ownerId | ||
); | ||
</script> | ||
|
||
<a href={`reports/${id}`} class="flex flex-col gap-y-0.5 group px-4 py-[5px]"> | ||
<div class="flex gap-x-2 items-center"> | ||
<ReportIcon size={"14px"} className="text-slate-500" /> | ||
<div class="text-gray-700 text-sm font-semibold group-hover:text-blue-600"> | ||
{title} | ||
</div> | ||
{#if lastRun} | ||
{#if lastRunErrorMessage} | ||
<CancelCircleInverse className="text-red-500" /> | ||
{:else} | ||
<CheckCircleOutline className="text-blue-500" /> | ||
{/if} | ||
{/if} | ||
</div> | ||
<div class="flex gap-x-1 text-gray-500 text-xs font-normal"> | ||
{#if !lastRun} | ||
<span>Hasn't run yet</span> | ||
{:else} | ||
<span>Last run {formatDateToCustomString(new Date(lastRun))}</span> | ||
{/if} | ||
<span>•</span> | ||
<span>{humanReadableFrequency}</span> | ||
<span>•</span> | ||
<span>Created by {owner?.userName || "a project admin"}</span> | ||
</div> | ||
</a> |
1 change: 1 addition & 0 deletions
1
web-admin/src/features/scheduled-reports/listing/ReportsTableEmpty.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<span class="text-gray-500"> No reports found. </span> |
103 changes: 103 additions & 0 deletions
103
web-admin/src/features/scheduled-reports/listing/ReportsTableHeader.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<script lang="ts"> | ||
import { Search } from "@rilldata/web-common/components/search"; | ||
import type { Table } from "@tanstack/table-core/src/types"; | ||
import { getContext } from "svelte"; | ||
import type { Readable } from "svelte/store"; | ||
const table = getContext("table") as Readable<Table<unknown>>; | ||
// Search | ||
let filter = ""; | ||
$: filterTable(filter); | ||
function filterTable(filter: string) { | ||
$table.setGlobalFilter(filter); | ||
} | ||
// Number of reports | ||
$: numReports = $table.getRowModel().rows.length; | ||
// Sort | ||
// function sortAlphabetically() { | ||
// $table.setSorting([{ id: "monocolumn", desc: false }]); | ||
// } | ||
// function sortByMostRecentlyRun() { | ||
// $table.setSorting([{ id: "lastRun", desc: true }]); | ||
// } | ||
// function sortByNextToRun() { | ||
// $table.setSorting([{ id: "monocolumn", desc: false }]); | ||
// } | ||
// let openSortMenu = false; | ||
// function closeSortMenu() { | ||
// openSortMenu = false; | ||
// } | ||
</script> | ||
|
||
<thead> | ||
<tr> | ||
<td | ||
class="pl-2 pr-4 py-2 max-w-[800px] flex items-center gap-x-2 bg-slate-100" | ||
> | ||
<!-- Search bar --> | ||
<div class="px-2 grow"> | ||
<Search placeholder="Search" autofocus={false} bind:value={filter} /> | ||
</div> | ||
|
||
<!-- Spacer --> | ||
<div class="grow" /> | ||
|
||
<!-- filter menu button (future work) --> | ||
<!-- <Button on:click={() => console.log("open filter menu")} type="secondary"> | ||
<span>Filter</span> | ||
<CaretDownIcon /> | ||
</Button> --> | ||
|
||
<!-- Number of reports --> | ||
<span class="shrink-0" | ||
>{numReports} report{numReports !== 1 ? "s" : ""}</span | ||
> | ||
|
||
<!-- Sort button --> | ||
<!-- <WithTogglableFloatingElement active={openSortMenu}> | ||
<Button on:click={() => (openSortMenu = true)} type="secondary"> | ||
<span>Sort</span> | ||
<CaretDownIcon /> | ||
</Button> | ||
<Menu | ||
slot="floating-element" | ||
minWidth="0px" | ||
on:item-select={closeSortMenu} | ||
on:click-outside={closeSortMenu} | ||
on:escape={closeSortMenu} | ||
> | ||
<MenuItem on:select={sortAlphabetically}>Alphabetical</MenuItem> | ||
<MenuItem on:select={sortByMostRecentlyRun} | ||
>Most recently run</MenuItem | ||
> | ||
<MenuItem on:select={sortByNextToRun} disabled>Next to run</MenuItem> | ||
</Menu> | ||
</WithTogglableFloatingElement> --> | ||
</td> | ||
</tr> | ||
</thead> | ||
|
||
<!-- | ||
Rounded table corners are tricky: | ||
- `border-radius` does not apply to table elements when `border-collapse` is `collapse`. | ||
- You can only apply `border-radius` to <td>, not <tr> or <table>. | ||
--> | ||
<style lang="postcss"> | ||
thead tr td { | ||
@apply border-y; | ||
} | ||
thead tr td:first-child { | ||
@apply border-l rounded-tl-sm; | ||
} | ||
thead tr td:last-child { | ||
@apply border-r rounded-tr-sm; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors"; | ||
import { | ||
createRuntimeServiceGetResource, | ||
createRuntimeServiceListResources, | ||
} from "@rilldata/web-common/runtime-client"; | ||
|
||
export function useReports(instanceId: string) { | ||
return createRuntimeServiceListResources(instanceId, { | ||
kind: ResourceKind.Report, | ||
}); | ||
} | ||
|
||
export function useReport(instanceId: string, name: string) { | ||
return createRuntimeServiceGetResource(instanceId, { | ||
"name.name": name, | ||
"name.kind": ResourceKind.Report, | ||
}); | ||
} |
Oops, something went wrong.
03f9bdf
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 Published on https://ui.rilldata.io as production
🚀 Deployed on https://654bb0df13188772e27f409b--rill-ui-stage.netlify.app