From 4597f49d14314eb2e9704a9eb2acf9c0858f3184 Mon Sep 17 00:00:00 2001 From: Ezequiel Adrian Schwartzman Date: Tue, 24 Dec 2024 10:31:33 -0300 Subject: [PATCH] Added UI for notifications log system --- ui/index.html | 1 + ui/src/GameSpace/GameSpace.svelte | 17 ++ ui/src/GameSpace/topbar/ActivityLog.svelte | 190 ++++++++++++++++++++ ui/src/GameSpace/topbar/PeopleBar.svelte | 27 +-- ui/src/GameSpace/ui/TopBarDropButton.svelte | 72 ++++++++ ui/src/lib/util.ts | 50 ++++++ ui/src/shared/tooltip.ts | 15 +- 7 files changed, 359 insertions(+), 13 deletions(-) create mode 100644 ui/src/GameSpace/topbar/ActivityLog.svelte create mode 100644 ui/src/GameSpace/ui/TopBarDropButton.svelte diff --git a/ui/index.html b/ui/index.html index ec43314..37a9112 100644 --- a/ui/index.html +++ b/ui/index.html @@ -8,5 +8,6 @@ +
diff --git a/ui/src/GameSpace/GameSpace.svelte b/ui/src/GameSpace/GameSpace.svelte index 3582e60..9c32c49 100644 --- a/ui/src/GameSpace/GameSpace.svelte +++ b/ui/src/GameSpace/GameSpace.svelte @@ -29,6 +29,7 @@ import { cloneDeep } from 'lodash'; import { COLORS, colorSequence, uuid } from '~/lib/util'; import NameTitleInput from './ui/NameTitleInput.svelte'; + import ActivityLog from './topbar/ActivityLog.svelte'; export let gameSpace: GameSpaceSyn; export let asAsset: boolean = false; @@ -146,6 +147,13 @@ {#if $state}
+
{#if !asAsset}
+ +
{#if !$permissions.isArchived} {#if sidebar === 'elementsLibrary' && $isSteward} diff --git a/ui/src/GameSpace/topbar/ActivityLog.svelte b/ui/src/GameSpace/topbar/ActivityLog.svelte new file mode 100644 index 0000000..5efec6b --- /dev/null +++ b/ui/src/GameSpace/topbar/ActivityLog.svelte @@ -0,0 +1,190 @@ + + + + +
+ {#each log as l} + {@const unseen = isUnseen(l)} + {@const date = new Date(l.time)} + {@const notificationActivated = notificationIsActivatedForLogType(l.type)} +
+ {LOG_TYPES_ICONS[l.type]} +
+ {l.message} + {relativeTimeFormat(date)} +
+
+ {#if unseen} +
+ {/if} +
+ +
+ {/each} +
+
diff --git a/ui/src/GameSpace/topbar/PeopleBar.svelte b/ui/src/GameSpace/topbar/PeopleBar.svelte index c6838f1..5723727 100644 --- a/ui/src/GameSpace/topbar/PeopleBar.svelte +++ b/ui/src/GameSpace/topbar/PeopleBar.svelte @@ -1,10 +1,10 @@
@@ -41,7 +35,18 @@ > {/if} -
diff --git a/ui/src/GameSpace/ui/TopBarDropButton.svelte b/ui/src/GameSpace/ui/TopBarDropButton.svelte new file mode 100644 index 0000000..f783fd4 --- /dev/null +++ b/ui/src/GameSpace/ui/TopBarDropButton.svelte @@ -0,0 +1,72 @@ + + + + +
+ + {#if isOpen} +
ev.stopPropagation()} + style={`max-height: ${maxHeight}px`} + > +
{title}
+
+ +
+
+ {/if} +
diff --git a/ui/src/lib/util.ts b/ui/src/lib/util.ts index c8f4d0f..f3c6280 100644 --- a/ui/src/lib/util.ts +++ b/ui/src/lib/util.ts @@ -108,3 +108,53 @@ export const wrapFns = (fns: (() => void)[]) => () => fns.forEach((fn) => fn()); export const EMPTY_IMAGE = new Image(1, 1); EMPTY_IMAGE.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='; + +// Using Intl.RelativeTimeFormat create a string like: +// - Just now +// - 7 minutes ago +// - 1 hour ago +// - Yesterday +// - 2 days ago +// - 1 week ago +// - 1 month ago +// - More than a year ago +export const relativeTimeFormat = (date: Date): string => { + const now = new Date(); + const diff = now.getTime() - date.getTime(); + const second = 1000; + const minute = second * 60; + const hour = minute * 60; + const day = hour * 24; + + const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' }); + + if (diff < minute) { + return rtf.format(-Math.round(diff / second), 'seconds'); + } else if (diff < hour) { + return rtf.format(-Math.round(diff / minute), 'minutes'); + } else if (diff < day) { + return rtf.format(-Math.round(diff / hour), 'hours'); + } else if (diff < day * 2) { + return 'Yesterday'; + } else if (diff < day * 7) { + return rtf.format(-Math.round(diff / day), 'days'); + } else if (diff < day * 30) { + return rtf.format(-Math.round(diff / (day * 7)), 'weeks'); + } else if (diff < day * 365) { + return rtf.format(-Math.round(diff / (day * 30)), 'months'); + } else { + return 'More than a year ago'; + } +}; + +// Using Intl.DateTimeFormat format time like: 6 Feb 2015 14:30 +export const timeFormat = (date: Date): string => { + const options: Intl.DateTimeFormatOptions = { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + }; + return new Intl.DateTimeFormat('en-US', options).format(date); +}; diff --git a/ui/src/shared/tooltip.ts b/ui/src/shared/tooltip.ts index 6ab7ce1..4f11aba 100644 --- a/ui/src/shared/tooltip.ts +++ b/ui/src/shared/tooltip.ts @@ -1,8 +1,17 @@ // @unocss-include -import { tooltip as svooltip } from 'svooltip'; +import { type Placement, tooltip as svooltip } from 'svooltip'; // Wrapper around svooltip where I can set defaults for all the uses of tooltip -export function tooltip(node: HTMLElement, content: string) { +export function tooltip( + node: HTMLElement, + content: string | { content: string; placement: Placement }, +) { if (!content) return; - return svooltip(node, { content }); + const text = typeof content === 'string' ? content : content.content; + const placement = typeof content === 'string' ? 'bottom' : content.placement; + return svooltip(node, { + content: text, + placement, + target: document.getElementById('tooltips'), + }); }