From 0251b9f13c4a9f4e1928d595f178097fa3e9c046 Mon Sep 17 00:00:00 2001 From: Brian Holmes <120223836+briangregoryholmes@users.noreply.github.com> Date: Fri, 10 May 2024 09:45:06 -0400 Subject: [PATCH] Feat/Refactor: EventBus and Notifications (#4869) * initial commit * import fix * persist link notifications --- .../src/features/bookmarks/Bookmarks.svelte | 6 +- .../bookmarks/CreateBookmarkDialog.svelte | 6 +- .../bookmarks/EditBookmarkDialog.svelte | 4 +- .../share/ShareDashboardButton.svelte | 8 +- .../metadata/RunNowButton.svelte | 4 +- .../timestamp-profile/TimestampBound.svelte | 6 +- .../timestamp-profile/TimestampDetail.svelte | 4 +- .../notifications/Notification.svelte | 195 ++++++++---------- .../notifications/NotificationCenter.svelte | 43 ++-- .../PersistedLinkNotification.svelte | 37 ---- .../PersistedNotification.svelte | 31 --- .../src/components/notifications/index.ts | 1 - .../notifications/notificationStore.ts | 100 --------- .../virtualized-table/VirtualTable.svelte | 5 +- .../virtualized-table/core/Cell.svelte | 4 +- .../core/ColumnHeader.svelte | 4 +- .../features/alerts/CreateAlertDialog.svelte | 7 +- .../features/alerts/EditAlertDialog.svelte | 4 +- .../big-number/MeasureBigNumber.svelte | 4 +- .../dimension-table/DimensionDisplay.svelte | 6 +- .../leaderboard/LeaderboardListItem.svelte | 4 +- .../TimeDimensionDisplay.svelte | 6 +- .../src/features/entity-management/actions.ts | 8 +- .../features/entity-management/ui-actions.ts | 6 +- .../file-explorer/FileExplorer.svelte | 4 +- .../ai-generation/generateMetricsView.ts | 6 +- .../CreateScheduledReportDialog.svelte | 7 +- .../EditScheduledReportDialog.svelte | 4 +- .../src/features/sources/createModel.ts | 4 +- .../sources/modal/RequestConnectorForm.svelte | 4 +- .../src/features/sources/modal/file-upload.ts | 4 +- .../src/lib/actions/shift-click-action.ts | 4 +- web-common/src/lib/event-bus/event-bus.ts | 45 ++++ web-common/src/lib/event-bus/events.ts | 16 ++ .../src/routes/(application)/+layout.svelte | 2 - web-local/src/routes/+layout.svelte | 3 + 36 files changed, 238 insertions(+), 368 deletions(-) delete mode 100644 web-common/src/components/notifications/PersistedLinkNotification.svelte delete mode 100644 web-common/src/components/notifications/PersistedNotification.svelte delete mode 100644 web-common/src/components/notifications/index.ts delete mode 100644 web-common/src/components/notifications/notificationStore.ts create mode 100644 web-common/src/lib/event-bus/event-bus.ts create mode 100644 web-common/src/lib/event-bus/events.ts diff --git a/web-admin/src/features/bookmarks/Bookmarks.svelte b/web-admin/src/features/bookmarks/Bookmarks.svelte index 1c69bb34429..8a528cfff3d 100644 --- a/web-admin/src/features/bookmarks/Bookmarks.svelte +++ b/web-admin/src/features/bookmarks/Bookmarks.svelte @@ -17,12 +17,12 @@ import EditBookmarkDialog from "@rilldata/web-admin/features/bookmarks/EditBookmarkDialog.svelte"; import { getBookmarkDataForDashboard } from "@rilldata/web-admin/features/bookmarks/getBookmarkDataForDashboard"; import type { BookmarkEntry } from "@rilldata/web-admin/features/bookmarks/selectors"; - import { notifications } from "@rilldata/web-common/components/notifications"; import { useDashboardStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors"; import { runtime } from "@rilldata/web-common/runtime-client/runtime-store"; import { useQueryClient } from "@tanstack/svelte-query"; import { BookmarkIcon } from "lucide-svelte"; + import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus"; $: metricsViewName = $page.params.dashboard; @@ -50,7 +50,7 @@ await homeBookmarkModifier( getBookmarkDataForDashboard($dashboardStore, false, false), ); - notifications.send({ + eventBus.emit("notification", { message: "Home bookmark created", }); return queryClient.refetchQueries( @@ -67,7 +67,7 @@ await $bookmarkDeleter.mutateAsync({ bookmarkId: bookmark.resource.id, }); - notifications.send({ + eventBus.emit("notification", { message: `Bookmark ${bookmark.resource.displayName} deleted`, }); return queryClient.refetchQueries( diff --git a/web-admin/src/features/bookmarks/CreateBookmarkDialog.svelte b/web-admin/src/features/bookmarks/CreateBookmarkDialog.svelte index 2c227e7f0f8..7103fd273aa 100644 --- a/web-admin/src/features/bookmarks/CreateBookmarkDialog.svelte +++ b/web-admin/src/features/bookmarks/CreateBookmarkDialog.svelte @@ -10,7 +10,7 @@ } from "@rilldata/web-admin/client"; import { Button } from "@rilldata/web-common/components/button"; import { getBookmarkDataForDashboard } from "@rilldata/web-admin/features/bookmarks/getBookmarkDataForDashboard"; - import { notifications } from "@rilldata/web-common/components/notifications"; + import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus"; import { useDashboardStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors"; import { useQueryClient } from "@tanstack/svelte-query"; @@ -57,14 +57,14 @@ }, }); handleReset(); - queryClient.refetchQueries( + await queryClient.refetchQueries( getAdminServiceListBookmarksQueryKey({ projectId: $projectId.data ?? "", resourceKind: ResourceKind.MetricsView, resourceName: metricsViewName, }), ); - notifications.send({ + eventBus.emit("notification", { message: "Bookmark created", }); handleClose(); diff --git a/web-admin/src/features/bookmarks/EditBookmarkDialog.svelte b/web-admin/src/features/bookmarks/EditBookmarkDialog.svelte index 6907ed00770..15443655247 100644 --- a/web-admin/src/features/bookmarks/EditBookmarkDialog.svelte +++ b/web-admin/src/features/bookmarks/EditBookmarkDialog.svelte @@ -11,7 +11,7 @@ import { Button } from "@rilldata/web-common/components/button"; import { getBookmarkDataForDashboard } from "@rilldata/web-admin/features/bookmarks/getBookmarkDataForDashboard"; import type { BookmarkEntry } from "@rilldata/web-admin/features/bookmarks/selectors"; - import { notifications } from "@rilldata/web-common/components/notifications"; + import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus"; import { useDashboardStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores"; import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors"; import { useQueryClient } from "@tanstack/svelte-query"; @@ -63,7 +63,7 @@ resourceName: metricsViewName, }), ); - notifications.send({ + eventBus.emit("notification", { message: "Bookmark updated", }); handleClose(); diff --git a/web-admin/src/features/dashboards/share/ShareDashboardButton.svelte b/web-admin/src/features/dashboards/share/ShareDashboardButton.svelte index 986611ba37f..2770a67510b 100644 --- a/web-admin/src/features/dashboards/share/ShareDashboardButton.svelte +++ b/web-admin/src/features/dashboards/share/ShareDashboardButton.svelte @@ -2,13 +2,13 @@ import Button from "@rilldata/web-common/components/button/Button.svelte"; import * as DropdownMenu from "@rilldata/web-common/components/dropdown-menu"; import Link from "@rilldata/web-common/components/icons/Link.svelte"; - import { notifications } from "@rilldata/web-common/components/notifications"; + import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus"; - function handleCopyLink() { + async function handleCopyLink() { // Copy the current URL to the clipboard - navigator.clipboard.writeText(window.location.href); + await navigator.clipboard.writeText(window.location.href); - notifications.send({ + eventBus.emit("notification", { message: "Link copied to clipboard", }); } diff --git a/web-admin/src/features/scheduled-reports/metadata/RunNowButton.svelte b/web-admin/src/features/scheduled-reports/metadata/RunNowButton.svelte index 03b694cf1b1..a311451e892 100644 --- a/web-admin/src/features/scheduled-reports/metadata/RunNowButton.svelte +++ b/web-admin/src/features/scheduled-reports/metadata/RunNowButton.svelte @@ -1,7 +1,7 @@ diff --git a/web-common/src/components/notifications/NotificationCenter.svelte b/web-common/src/components/notifications/NotificationCenter.svelte index b8611366a58..b9a70b92017 100644 --- a/web-common/src/components/notifications/NotificationCenter.svelte +++ b/web-common/src/components/notifications/NotificationCenter.svelte @@ -1,27 +1,24 @@ -{#key $notificationStore.id} - {#if $notificationStore.id} - {#if $notificationStore?.options?.persisted} - notificationStore.clear()}> -
{$notificationStore.message}
-
{$notificationStore.detail}
-
- {:else if $notificationStore?.options?.persistedLink && $notificationStore.link} - notificationStore.clear()} - /> - {:else} - - {$notificationStore.message} - - {/if} - {/if} -{/key} +{#if notification} + +{/if} diff --git a/web-common/src/components/notifications/PersistedLinkNotification.svelte b/web-common/src/components/notifications/PersistedLinkNotification.svelte deleted file mode 100644 index c7d97674ba4..00000000000 --- a/web-common/src/components/notifications/PersistedLinkNotification.svelte +++ /dev/null @@ -1,37 +0,0 @@ - - -
-
- - - {message} - -
- -
- dispatch("clear")} bgDark> - - -
-
diff --git a/web-common/src/components/notifications/PersistedNotification.svelte b/web-common/src/components/notifications/PersistedNotification.svelte deleted file mode 100644 index c0dae08c69e..00000000000 --- a/web-common/src/components/notifications/PersistedNotification.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - -
-
-

-
- dispatch("clear")} - bgDark - > - - -
-
-
-
- -
-
diff --git a/web-common/src/components/notifications/index.ts b/web-common/src/components/notifications/index.ts deleted file mode 100644 index 3893d475026..00000000000 --- a/web-common/src/components/notifications/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as notifications } from "./notificationStore"; diff --git a/web-common/src/components/notifications/notificationStore.ts b/web-common/src/components/notifications/notificationStore.ts deleted file mode 100644 index 78d48cc83f5..00000000000 --- a/web-common/src/components/notifications/notificationStore.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { Readable } from "svelte/store"; -import { derived, writable } from "svelte/store"; - -const NOTIFICATION_TIMEOUT = 3500; - -interface NotificationStore extends Readable { - timeoutID: ReturnType; - send: (args: NotificationMessageArguments) => void; - clear: () => void; -} - -export interface Link { - text: string; - href: string; -} - -interface NotificationMessageArguments { - message: string; - type?: string; - detail?: string; - link?: Link; - options?: NotificationOptions; -} - -interface NotificationMessage { - id: string; - type?: string; - message: string; - detail?: string; - link?: Link; - options?: NotificationOptions; -} - -interface NotificationOptions { - width?: number; - persisted?: boolean; - persistedLink?: boolean; -} - -function createNotificationStore(): NotificationStore { - const _notification = writable({} as NotificationMessage); - let timeout: ReturnType | undefined = undefined; - - function send({ - message, - type = "default", - detail, - link, - options = {}, - }: NotificationMessageArguments): void { - const notificationMessage: NotificationMessage = { - id: id(), - message, - type, - detail, - link, - options, - }; - _notification.set(notificationMessage); - } - - function clear(): void { - _notification.set({} as NotificationMessage); - } - - const notifications: Readable = derived( - _notification, - ($notification, set) => { - // if there already was a notification, let's clear the timer - // and reset it here. - clearTimeout(timeout); - set($notification); - // if this is not the reset message, set the timer. - if ( - $notification.id && - !$notification.options?.persisted && - !$notification.options?.persistedLink - ) { - timeout = setTimeout(clear, NOTIFICATION_TIMEOUT); - } - }, - ); - const { subscribe } = notifications; - - return { - timeoutID: timeout, - subscribe, - send, - clear: () => { - clearTimeout(timeout); - clear(); - }, - }; -} - -function id(): string { - return "_" + Math.random().toString(36).substr(2, 9); -} - -export default createNotificationStore(); diff --git a/web-common/src/components/virtualized-table/VirtualTable.svelte b/web-common/src/components/virtualized-table/VirtualTable.svelte index 970b078fac6..6f9b1561025 100644 --- a/web-common/src/components/virtualized-table/VirtualTable.svelte +++ b/web-common/src/components/virtualized-table/VirtualTable.svelte @@ -21,7 +21,7 @@ import StackingWord from "@rilldata/web-common/components/tooltip/StackingWord.svelte"; import TooltipShortcutContainer from "@rilldata/web-common/components/tooltip/TooltipShortcutContainer.svelte"; import { formatDataTypeAsDuckDbQueryString } from "@rilldata/web-common/lib/formatters"; - import { notifications } from "@rilldata/web-common/components/notifications"; + import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus"; import FormattedDataType from "@rilldata/web-common/components/data-types/FormattedDataType.svelte"; import { isClipboardApiSupported } from "@rilldata/web-common/lib/actions/shift-click-action"; import type { @@ -224,9 +224,10 @@ hovering.type, ); await navigator.clipboard.writeText(exportedValue); - notifications.send({ + eventBus.emit("notification", { message: `copied value "${exportedValue}" to clipboard`, }); + return; } diff --git a/web-common/src/components/virtualized-table/core/Cell.svelte b/web-common/src/components/virtualized-table/core/Cell.svelte index dee9bfad960..fb56771d16c 100644 --- a/web-common/src/components/virtualized-table/core/Cell.svelte +++ b/web-common/src/components/virtualized-table/core/Cell.svelte @@ -1,6 +1,6 @@