Skip to content

feat: add recently viewed activity dashboard widget#16837

Open
GermanJablo wants to merge 4 commits into
wip/modular-dashboard-default-card-stale-20260526from
GermanJablo/feat/dashboard-recently-viewed-widget
Open

feat: add recently viewed activity dashboard widget#16837
GermanJablo wants to merge 4 commits into
wip/modular-dashboard-default-card-stale-20260526from
GermanJablo/feat/dashboard-recently-viewed-widget

Conversation

@GermanJablo
Copy link
Copy Markdown
Contributor

@GermanJablo GermanJablo commented Jun 2, 2026

Summary

Stacked on top of #16812.

Adds an activity dashboard widget that lists the documents the current user has recently viewed in the admin, most recent first.

  • New per-user recently-viewed preference storing only identity + timestamp (collectionSlug, id, viewedAt), recorded server-side in renderDocument when a collection document is opened (full-page and drawer). The write is wrapped in try/catch + logger so it can never break a document view.
  • The widget computes display fields (title from useAsTitle, a collection type pill or an upload thumbnail, and a relative timestamp) at render time, querying each collection under access control (overrideAccess: false). Deleted or now-forbidden documents drop out of the list automatically.
  • Relative timestamps share a single utility (formatRelativeDate / getRelativeTimeFormat) with the collection-query widget, so both render dates identically and locale-aware (e.g. "5m ago").
  • Collection filtering uses an excludedCollections exclusion list under the hood, surfaced to the user as an inclusion filter: every collection is checked by default and unchecking one adds it to the exclusions, so newly added collections show up automatically.
  • i18n keys added to en.ts + clientKeys.ts and translated across all locales.

Test plan

  • Unit test for the merge/dedup/cap helper (recentlyViewed.spec.ts).
  • e2e: view two documents, return to the dashboard, assert they appear in the activity widget most-recent-first.
  • e2e: collections filter renders inclusion checkboxes (all checked by default) and unchecking a collection excludes its documents from the widget.
  • Manual: open documents in different collections and confirm they appear, with type pills and thumbnails for uploads.

Deferred to follow-ups

  • Per-row remove (X): needs a client component + preference mutation; this PR ships a read-only list.
  • A "recently edited" tab.

Known limitations

  • Because display fields are computed under access control, deleted or now-forbidden docs drop out of the list (desired). Stale identity entries remain in the preference until they age out of the cap.

Introduces an "activity" dashboard widget that lists the documents the
current user has recently viewed in the admin, most recent first.

- Adds a per-user `recently-viewed` preference (identity + timestamp only)
  recorded server-side in renderDocument when a collection document opens.
- The widget computes display fields (title, type pill / thumbnail, absolute
  timestamp) at render time under access control, so deleted or now-forbidden
  documents drop out automatically.
- Collection filtering uses an `excludedCollections` exclusion list, so new
  collections appear by default.
- Adds i18n keys + translations, registers the widget, and covers it with a
  unit test for the merge/dedup/cap helper and an e2e test.

Deferred to follow-ups: per-row remove (X) and a "recently edited" tab.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

📦 esbuild Bundle Analysis for payload

This analysis was generated by esbuild-bundle-analyzer. 🤖

Meta File Out File Size (raw) Note
packages/next/meta_index.json esbuild/index.js 1.03 MB 🆕 Added
packages/payload/meta_index.json esbuild/index.js 1.41 MB 🆕 Added
packages/payload/meta_shared.json esbuild/exports/shared.js 192.65 KB 🆕 Added
packages/richtext-lexical/meta_client.json esbuild/exports/client_optimized/index.js 304.12 KB 🆕 Added
packages/ui/meta_client.json esbuild/exports/client_optimized/index.js 1.28 MB 🆕 Added
packages/ui/meta_shared.json esbuild/exports/shared_optimized/index.js 18.56 KB 🆕 Added
Largest paths These visualization shows top 20 largest paths in the bundle.

Meta file: packages/next/meta_index.json, Out file: esbuild/index.js

Path Size
../../node_modules ${{\color{Goldenrod}{ █████████████████████ }}}$ 84.0%, 861.10 KB
dist/views/Version ${{\color{Goldenrod}{ █▎ }}}$ 5.3%, 54.61 KB
dist/views/Dashboard ${{\color{Goldenrod}{ ▌ }}}$ 2.1%, 21.85 KB
dist/views/Document ${{\color{Goldenrod}{ ▍ }}}$ 1.7%, 17.30 KB
dist/views/List ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 15.51 KB
dist/views/Root ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 10.01 KB
dist/views/Account ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 6.13 KB
dist/views/API ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 6.13 KB
dist/views/Versions ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 5.74 KB
dist/views/Login ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 4.62 KB
dist/layouts/Root ${{\color{Goldenrod}{ }}}$ 0.4%, 3.61 KB
dist/views/ForgotPassword ${{\color{Goldenrod}{ }}}$ 0.3%, 3.22 KB
dist/views/CreateFirstUser ${{\color{Goldenrod}{ }}}$ 0.3%, 3.02 KB
dist/views/ResetPassword ${{\color{Goldenrod}{ }}}$ 0.2%, 2.46 KB
dist/views/Logout ${{\color{Goldenrod}{ }}}$ 0.2%, 1.96 KB
dist/views/Verify ${{\color{Goldenrod}{ }}}$ 0.1%, 1.35 KB
dist/utilities/initReq.js ${{\color{Goldenrod}{ }}}$ 0.1%, 1.15 KB
dist/views/NotFound ${{\color{Goldenrod}{ }}}$ 0.1%, 1.04 KB
dist/adapters/router.js ${{\color{Goldenrod}{ }}}$ 0.1%, 659 B
dist/adapters/server.js ${{\color{Goldenrod}{ }}}$ 0.1%, 531 B
(other) ${{\color{Goldenrod}{ ████ }}}$ 16.0%, 164.48 KB

Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js

Path Size
../../node_modules ${{\color{Goldenrod}{ █████████████████ }}}$ 68.3%, 959.51 KB
dist/fields/hooks ${{\color{Goldenrod}{ ▊ }}}$ 3.1%, 44.07 KB
dist/collections/operations ${{\color{Goldenrod}{ ▋ }}}$ 2.9%, 40.23 KB
dist/versions/migrations ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 18.50 KB
dist/auth/operations ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 15.63 KB
dist/fields/config ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 13.40 KB
dist/globals/operations ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 13.40 KB
dist/utilities/configToJSONSchema.js ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 13.10 KB
dist/queues/operations ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 12.63 KB
dist/fields/validations.js ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 10.57 KB
dist/collections/config ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 9.53 KB
dist/bin/generateImportMap ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 9.44 KB
dist/config/orderable ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.92 KB
dist/uploads/fetchAPI-multipart ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.80 KB
dist/index.js ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.77 KB
dist/hierarchy/utils ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 7.65 KB
dist/database/migrations ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 7.54 KB
dist/config/sanitize.js ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 6.89 KB
dist/collections/endpoints ${{\color{Goldenrod}{ }}}$ 0.4%, 6.23 KB
dist/auth/strategies ${{\color{Goldenrod}{ }}}$ 0.4%, 5.43 KB
(other) ${{\color{Goldenrod}{ ███████▉ }}}$ 31.7%, 445.15 KB

Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js

Path Size
../../node_modules ${{\color{Goldenrod}{ ███████████████████▉ }}}$ 79.5%, 150.12 KB
dist/fields/validations.js ${{\color{Goldenrod}{ █▍ }}}$ 5.6%, 10.57 KB
dist/config/orderable ${{\color{Goldenrod}{ ▍ }}}$ 1.7%, 3.13 KB
dist/fields/baseFields ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 2.79 KB
dist/utilities/deepCopyObject.js ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 2.54 KB
dist/auth/cookies.js ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 1.55 KB
dist/utilities/flattenTopLevelFields.js ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 1.42 KB
dist/fields/config ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 1.29 KB
dist/utilities/getVersionsConfig.js ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 1.04 KB
dist/utilities/flattenAllFields.js ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 943 B
dist/utilities/unflatten.js ${{\color{Goldenrod}{ }}}$ 0.4%, 779 B
dist/utilities/sanitizeUserDataForEmail.js ${{\color{Goldenrod}{ }}}$ 0.4%, 713 B
dist/utilities/getFieldPermissions.js ${{\color{Goldenrod}{ }}}$ 0.3%, 651 B
dist/collections/config ${{\color{Goldenrod}{ }}}$ 0.3%, 570 B
dist/bin/generateImportMap ${{\color{Goldenrod}{ }}}$ 0.3%, 561 B
dist/auth/sessions.js ${{\color{Goldenrod}{ }}}$ 0.3%, 525 B
dist/fields/getFieldPaths.js ${{\color{Goldenrod}{ }}}$ 0.3%, 485 B
dist/utilities/appendDateTimezoneSelectFields.js ${{\color{Goldenrod}{ }}}$ 0.2%, 451 B
dist/utilities/getSafeRedirect.js ${{\color{Goldenrod}{ }}}$ 0.2%, 423 B
dist/utilities/deepMerge.js ${{\color{Goldenrod}{ }}}$ 0.2%, 413 B
(other) ${{\color{Goldenrod}{ █████▏ }}}$ 20.5%, 38.73 KB

Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js

Path Size
dist/features/blocks ${{\color{Goldenrod}{ ███ }}}$ 12.4%, 37.36 KB
dist/lexical/ui ${{\color{Goldenrod}{ ██▊ }}}$ 11.4%, 34.16 KB
dist/lexical/plugins ${{\color{Goldenrod}{ ██▋ }}}$ 10.9%, 32.88 KB
dist/features/experimental_table ${{\color{Goldenrod}{ ██▎ }}}$ 9.0%, 27.16 KB
dist/packages/@lexical ${{\color{Goldenrod}{ █▌ }}}$ 6.3%, 18.99 KB
dist/features/link ${{\color{Goldenrod}{ █▌ }}}$ 6.3%, 18.81 KB
dist/features/toolbars ${{\color{Goldenrod}{ █▍ }}}$ 5.5%, 16.58 KB
dist/features/upload ${{\color{Goldenrod}{ █▏ }}}$ 4.7%, 14.09 KB
dist/features/textState ${{\color{Goldenrod}{ ▉ }}}$ 3.7%, 11.08 KB
dist/features/relationship ${{\color{Goldenrod}{ ▊ }}}$ 3.1%, 9.39 KB
dist/lexical/utils ${{\color{Goldenrod}{ ▋ }}}$ 2.9%, 8.79 KB
dist/features/converters ${{\color{Goldenrod}{ ▋ }}}$ 2.8%, 8.36 KB
dist/features/debug ${{\color{Goldenrod}{ ▋ }}}$ 2.5%, 7.40 KB
dist/utilities/fieldsDrawer ${{\color{Goldenrod}{ ▌ }}}$ 2.4%, 7.29 KB
dist/lexical/config ${{\color{Goldenrod}{ ▍ }}}$ 1.7%, 5.08 KB
dist/features/lists ${{\color{Goldenrod}{ ▍ }}}$ 1.7%, 5.00 KB
dist/features/format ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 3.46 KB
dist/lexical/LexicalEditor.js ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 3.23 KB
dist/features/horizontalRule ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 3.18 KB
dist/field/Field.js ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 2.84 KB
(other) ${{\color{Goldenrod}{ █████████████████████▉ }}}$ 87.6%, 263.53 KB

Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js

Path Size
../../node_modules ${{\color{Goldenrod}{ ███████████▍ }}}$ 45.9%, 579.79 KB
dist/elements/Hierarchy ${{\color{Goldenrod}{ ▉ }}}$ 3.5%, 44.00 KB
dist/elements/BulkUpload ${{\color{Goldenrod}{ ▌ }}}$ 2.2%, 28.06 KB
dist/views/HierarchyList ${{\color{Goldenrod}{ ▍ }}}$ 1.6%, 20.40 KB
dist/elements/Table ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 19.25 KB
dist/elements/WhereBuilder ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 17.34 KB
dist/views/Edit ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 17.27 KB
dist/forms/Form ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.87 KB
dist/fields/Relationship ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 15.47 KB
dist/fields/Blocks ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 15.11 KB
dist/fields/Upload ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 14.40 KB
dist/elements/QueryPresets ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 10.22 KB
dist/elements/PublishButton ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 9.01 KB
dist/elements/HTMLDiff ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.38 KB
dist/elements/LivePreview ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.25 KB
dist/elements/ReactSelect ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.84 KB
dist/fields/Array ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.76 KB
dist/views/List ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.75 KB
dist/elements/Nav ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.54 KB
dist/elements/RelationshipTable ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 6.69 KB
(other) ${{\color{Goldenrod}{ █████████████▌ }}}$ 54.1%, 684.69 KB

Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js

Path Size
dist/graphics/Logo ${{\color{Goldenrod}{ ███████▊ }}}$ 31.1%, 5.57 KB
../../node_modules ${{\color{Goldenrod}{ ███▋ }}}$ 14.8%, 2.65 KB
dist/graphics/Icon ${{\color{Goldenrod}{ ██▏ }}}$ 8.5%, 1.52 KB
dist/utilities/formatDocTitle ${{\color{Goldenrod}{ █▊ }}}$ 7.4%, 1.32 KB
dist/providers/TableColumns ${{\color{Goldenrod}{ █▏ }}}$ 4.8%, 866 B
dist/utilities/getGlobalData.js ${{\color{Goldenrod}{ █ }}}$ 4.2%, 762 B
dist/utilities/api.js ${{\color{Goldenrod}{ █ }}}$ 4.2%, 756 B
dist/utilities/groupNavItems.js ${{\color{Goldenrod}{ █ }}}$ 4.1%, 734 B
dist/elements/Translation ${{\color{Goldenrod}{ ▋ }}}$ 2.7%, 493 B
dist/utilities/handleTakeOver.js ${{\color{Goldenrod}{ ▋ }}}$ 2.5%, 440 B
dist/utilities/traverseForLocalizedFields.js ${{\color{Goldenrod}{ ▌ }}}$ 2.2%, 399 B
dist/elements/withMergedProps ${{\color{Goldenrod}{ ▍ }}}$ 1.9%, 339 B
dist/utilities/getNavGroups.js ${{\color{Goldenrod}{ ▍ }}}$ 1.9%, 338 B
dist/utilities/getVisibleEntities.js ${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 329 B
dist/elements/WithServerSideProps ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 232 B
dist/utilities/handleGoBack.js ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 180 B
dist/fields/mergeFieldStyles.js ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 159 B
dist/utilities/handleBackToDashboard.js ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 152 B
dist/forms/Form ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 147 B
dist/utilities/abortAndIgnore.js ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 146 B
(other) ${{\color{Goldenrod}{ █████████████████▏ }}}$ 68.9%, 12.36 KB
Details

Next to the size is how much the size has increased or decreased compared with the base branch of this PR.

  • ‼️: Size increased by 20% or more. Special attention should be given to this.
  • ⚠️: Size increased in acceptable range (lower than 20%).
  • ✅: No change or even downsized.
  • 🗑️: The out file is deleted: not found in base branch.
  • 🆕: The out file is newly found: will be added to base branch.

…t configuration

This commit introduces a new `RecentlyViewedCollectionsField` component that allows users to manage collections displayed in the activity widget. The field presents an inclusion filter with checkboxes for all collections, while storing the selections as an exclusion list. Additionally, it updates the dashboard widget configuration to use the new field and modifies the translations to remove the deprecated `widgetExcludedCollectionsLabel`. Comprehensive end-to-end tests are added to ensure functionality and user experience.
This commit introduces a new utility module `formatRelativeDate.ts` that provides functions for formatting ISO date strings as locale-aware relative time strings. The `getRelativeTimeFormat` function creates an `Intl.RelativeTimeFormat` instance for the specified language, falling back to English for unsupported locales. The `formatRelativeDate` function formats dates into human-readable relative time (e.g., "5m ago", "in 2d"). Additionally, the `CollectionQuery` and `RecentlyViewed` widgets are updated to utilize these new functions for rendering relative timestamps, enhancing localization support across the application.
The activity widget collections field passed getTranslation's string | Element
return value to CheckboxInput's label prop, which only accepts StaticLabel,
breaking build:types in CI. Resolve the label to a string before passing it.

Also drop the unused getPreferences export from the rsc bundle (the widget
imports it via relative path and the next package has its own implementation).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant