Skip to content

Unify file/binary/image field preview into a single Angular thumbnail (dot-file-thumbnail), drop Stencil dependency #36295

Description

@oidacra

Description

In the 34420-unify-component work, the unified file/binary/image field preview (dot-file-field-preview) still delegates thumbnail rendering to two different leaf components depending on the file's origin:

  • Temp files (just uploaded) → dot-temp-file-thumbnail (Angular, libs/ui)
  • Saved assets (contentlet / dotAsset) → dot-contentlet-thumbnail (Stencil web component, dotcms-webcomponents)

This causes two problems:

  1. Inconsistent rendering. The two components size and render the image differently. dot-contentlet-thumbnail is shipped as a prebuilt Stencil bundle, so its host renders as display:block with no height, the image collapses to its natural ratio, and the thumbnail box shows gray bars. Its source SCSS cannot be recompiled from the Angular dev server, so fixes have to be hacked via ::ng-deep overrides in the parent.
  2. Stencil coupling. The Angular components depend on a legacy prebuilt web component just for image-URL resolution and type detection.

Goal (UPDATED — scope expanded to build-and-replace)

Introduce a single Angular presentational thumbnail — dot-content-thumbnail in libs/ui — and replace every Angular usage of dot-contentlet-thumbnail (~10 call sites) plus dot-temp-file-thumbnail in one effort, leaving the Stencil component with zero Angular consumers and marked @deprecated (it stays only for the Stencil-internal dot-card-contentlet and legacy JSP pages).

Naming note: originally scoped as dot-file-thumbnail limited to the file field. Per team decision the scope was expanded to a full build-and-replace and the component was named dot-content-thumbnail (close to the Stencil name without colliding with its still-registered tag, and accurate since it renders contentlets AND temp files).

Architecture (agreed)

  • Viewer + per-type renderers: dot-content-thumbnail orchestrates a loading state machine (loading → loaded | error) and dispatches by resolved type to internal renderers: image/svg/pdf (<img>), video (playable with native controls, or first-frame preview via a #t=0.1 media fragment) and icon (Material Symbols glyph, legacy extension mapping preserved).
  • API: consumers pass the contentlet directly ([contentlet] + optional [options] for fieldVariable/playableVideo) or a pre-resolved model ([thumbnail], used for temp files). Mappers contentletToThumbnailModel / tempFileToThumbnailModel are exported from @dotcms/ui and replicate the legacy URL strategies.
  • Loading UX: PrimeNG-skeleton shimmer replica (uses the --p-skeleton-animation-background token) with a 300ms cross-fade reveal; media errors fall back to the icon renderer. Playable videos are never masked (the native element owns its loading UX).
  • Icon sizing/theming: glyph auto-scales with the container via container queries (iconSize input as exact override); color themeable through --dot-content-thumbnail-icon-color.

Acceptance Criteria

  • A single Angular component dot-content-thumbnail in libs/ui renders the preview thumbnail for both temp files and saved contentlets (no branching between two leaf components in dot-file-field-preview).
  • All ~10 Angular usages of the Stencil dot-contentlet-thumbnail are migrated: file-field preview, asset-search card, browser-selector dataview, content-drive folder list, UVE palette contentlet, block-editor contentlet block + suggestions, relationship field list and select-existing-content dialog.
  • dot-temp-file-thumbnail is deleted (single consumer, absorbed) and the Stencil dot-contentlet-thumbnail is marked @deprecated.
  • The component renders correctly for each media type with full parity to the previous behavior:
    • Raster image (png/jpg/webp) → image preview
    • SVG → image preview, never rasterized: raw vector served through the binary field variable (/contentAsset/image/{inode}/{fieldVariable}), rendered cover-fit like any other image (team decision superseding the original "not cropped" wording)
    • PDF → first-page render thumbnail
    • Video → playable with native controls, or first-frame preview when not playable
    • Any other / unresolvable type → Material Symbols icon fallback (legacy xxxIcon extension mapping preserved)
  • The thumbnail fills its container while preserving proportions via object-fit: cover, with no gray bars, consistent across binary, image and file fields.
  • Observable behavior is unchanged: filename, dimensions, file size, info dialog, edit/download/remove actions all work as before.
  • The temporary ::ng-deep overrides targeting the Stencil internals are removed (dot-file-field-preview, dot-asset-card); CUSTOM_ELEMENTS_SCHEMA removed from the 7 components that only declared it for the web component.
  • Unit tests cover the viewer (type rendering, state machine, error fallback, contentlet/options inputs) and the mappers (all URL strategies, icon translation, temp-file paths).

Priority

Medium

Additional Context

Metadata

Metadata

Assignees

Type

Fields

No fields configured for Task.

Projects

Status
In Review

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions