Skip to content

Asset Management ​

File Information ​

  • Path: app/pages/[brand_name]/files/[id].vue, app/components/card/Asset/
  • Purpose: Complete asset viewing, downloading, and management system

Overview ​

The Asset Management system provides comprehensive functionality for viewing, downloading, and managing digital assets. It supports multiple file types, asset previews, quick actions, bulk operations, and integration with sharing and download systems.

Architecture ​

System Components ​

  1. Asset Details Page: Individual asset view with metadata
  2. Asset Cards: Asset display in grid/list views
  3. Asset Preview: Quick view and full preview dialogs
  4. Asset Actions: Download, share, and other operations
  5. Bulk Operations: Operations on multiple selected assets

Key Features ​

1. Asset Viewing ​

  • Asset detail page with full metadata
  • Quick view dialog for preview without navigation
  • Full preview with zoom and navigation
  • Multiple file type support (images, videos, documents, audio)
  • Asset metadata display (name, size, type, dates, tags)

2. Asset Cards ​

  • Grid view with thumbnails
  • List view with detailed information
  • Selection support (single and multi-select)
  • Quick actions (download, share, view)
  • Loading states with skeleton loaders

3. Asset Preview ​

  • Quick view dialog for fast preview
  • Full-screen preview mode
  • Image zoom and pan
  • Video playback with controls
  • Document preview (PDF, Office files)
  • Keyboard navigation

4. Asset Actions ​

  • Download: Single and bulk downloads
  • Share: Share asset with permissions
  • View Details: Navigate to asset detail page
  • Convert: Asset format conversion (if supported)

5. Bulk Operations ​

  • Multi-select with Shift+Click support
  • Select all functionality
  • Bulk download
  • Bulk share
  • Selection count display

Added by PR #137 (jasmita/riv-1266-brand-portal-development-quick-view-navigation-as-per-final, RIV-1266, merged 2026-10-28). On the collage detail page (/[brand_name]/collage/[id]) and the folder detail page (/[brand_name]/folders/[id]) the card's expand button opens GalleryQuickViewDialog instead of the single-asset QuickViewDialog. The gallery steps through every asset of the collage or folder (not only the loaded page) with arrow buttons, the keyboard, swipe and a thumbnail strip. Every other AssetCard (search, home, share link) still opens QuickViewDialog; the switch is the externalQuickView prop, which only these two pages set.

Entry points ​

TriggerPageCallsAssets shownStarts atServer paging
Card expand button (tooltip Preview, icon expandGalleryIcon)collage, folderopenGallery(file)live list: displayFiles rows without parent_idclicked assetyes, unless the inner search is active (isSearchActive)
Toolbar Preview button (selection toolbar)collageopenGalleryForSelection()snapshot of loaded rows with is_selected and no parent_idfirst selected rowonly when select-all is on (internal_select_all) and search is off
Toolbar Preview buttonfolderopenGalleryForSelection()samefirst selected rowsame

The folder Preview button is disabled, with the tooltip Only applicable for assets, while no asset is selected or any folder is selected. On both pages openGalleryForSelection() returns without opening when no loaded row is selected. Without server paging the gallery only contains the rows already loaded on the page.

Pagination contract ​

Each page hands the dialog a GalleryPagination object (fetchPage, loadedPages = max(currentPage, 1), lastPage, total). Fetches go through queryClient.fetchQuery with staleTime: getDefaultStaleTime() and use the page's current sort.

Collage (useCollageDetails)Folder (useFolderDetails)
QueryqueryKeys.collections.details(collectionId, params) -> collectionApi.getCollageDetailsqueryKeys.folderDetails.details(params) -> foldersApi.fetchFolderDetails
Paramspage, url_workspace_id, total_record: 36 (COLLAGE_ASSETS_PER_PAGE), sort_value, sort_bysort_value, sort_by, workspace_id, category_id (route id), page, total_record: 36
Itemsdata.assets.datadata.assets_with_folder.data, rows with parent_id removed
TotalassetList.assets_id.lengthdata.totalCounts.assets (stored as folderAssetsTotal on every folder load)
Last pagedata.assets.last_pagedata.assets_with_folder.last_page

With select-all on, fetchPage is wrapped so only selected assets come back:

  • Collage: items whose id is in selectedItemAssets (with select-all: every id in assetList.assets_id except loaded rows that were unticked); total = that set's size.
  • Folder: ids of loaded rows that were unticked form deselectedIds. If folderAssetsTotal is larger than the number of loaded asset rows ("capped"), every asset not in deselectedIds counts as selected and total = folderAssetsTotal - deselectedIds.size (never below 0). Otherwise the set is selectedItemAssets minus deselectedIds.

How paging works ​

useGalleryPreviewPager keeps two lists: a head (page 1 onward) and a tail (loaded from the last page backward, so the gallery can wrap from the first asset to the last without loading everything in between). Lists are merged by String(id), so duplicates across pages are dropped. If a fetched page adds nothing new, the next page is fetched in the same run. A failed fetch shows the error in a snackbar and pauses automatic loading until the next explicit load. Every reopen resets the pager.

useGalleryPreviewNavigation decides what Next does:

Previous mirrors it: at the first tail item it loads the page before the tail (backward); at index 0 with loop on it jumps to the last item, loading the last page first (last) when no tail exists yet. While a move is pending both arrow buttons are disabled and the button for that direction shows a spinner; the move completes as soon as the page arrives. loop defaults to true. Prefetch starts when the current index passes 60% of the head (DEFAULT_PREFETCH_RATIO = 0.6, overridable with pagination.prefetchRatio), or 60% into the tail when browsing backwards.

The counter shows {position} of {total}; a position in the tail is counted from the end (total - (count - 1 - index)), so it is correct even when the pages in between were never loaded.

Input ​

InputRule
ArrowLeft / ArrowRightPrevious / next. Ignored while focus is in INPUT, TEXTAREA, SELECT, VIDEO, AUDIO or a contentEditable element
EscapeCloses the dialog
Swipe on the previewHorizontal only; at least 50 px, or a flick of at least 0.5 px/ms and more than 10 px. Not started on buttons, links, form fields, video/audio, sliders or .v-slide-group. Off for a single asset
Drag on the thumbnail strip5 px dead zone, then one step per 88 px (64 px when the window is 600 px or narrower); dragging left moves next
Horizontal wheel / trackpad on the stripSame step size; only when deltaX is larger than deltaY
Thumbnail clickJumps to that asset (ignored right after a drag)

The strip shows an odd number of slots, at least 3 (floor(stripWidth / step)), centred on the current asset. Slots wrap around when loop is on and there are at least as many assets as slots; otherwise slots outside the range stay empty. A slot whose asset is not loaded yet shows a skeleton and triggers a load (right side: next page; left side: page before the tail, or the last page). With one asset, the arrows, counter and strip are hidden.

The two assets on each side of the current one are preloaded as images: videos (mp4, mov, avi, mkv, mpg, webm, wmv, m4v) use thumbnail_file or preview_image; other types use compress_file, then display_file, thumbnail_file, preview_image.

View tracking ​

WhenWhat is sent
Card expand buttonuseAssetCard.onExpandAssetsCount: view-count mutation, dispatchAnalytics, trackActivity(body, { source: "preview" }) (was "card" before)
An asset stays on screen 400 ms (CHANGE_SETTLE_MS)Once per asset per open: useViewAssetsCount mutation, then dispatchAnalytics and trackActivity(payload, { source: "preview" })
Open detail viewdispatchAnalytics and trackActivity (no source), then the asset page (brand_name-files-id) opens in a new tab

Payload: { asset_id: [id], event: "asset", sub_event: "viewed", environment: "dealer" } plus category_id: [route id] on folder routes (route name contains folders or category) or collection_id: Number(route id) otherwise. The start asset is marked as already tracked when the dialog opens, because the card click counted it. If tracking fails, the asset is unmarked and counted again the next time it is shown.

Header actions ​

  • Info tooltip: Uploaded By (user.name, then external_user.name, then created_by, else N/A), Uploaded Date (created_at), Last Modified (modified_at, else updated_at), both MMM D, YYYY; File Type, File Size, Dimension when width and height exist.
  • Download (hidden with hideDownload): downloadFileRef(isImage, asset, false), spinner per asset id, errors in a snackbar. downloadFileRef now awaits downloadStore.downloadFile, so the spinner stays until the download request finishes.
  • Open detail view, close.
  • QuickViewDialog and the asset detail page (useAssetDetails, Uploaded By) also fall back to external_user.name.
  • useCollageDetails.loadCollageAssets("sort") no longer returns early when a page load is in progress or the last page is reached, so sorting a fully loaded collage refetches.
  • _dialogs.scss: the overflow: hidden rule on dialog content skips .galleryDialogContent, so the arrow buttons can sit outside the card.
  • _skeleton.scss: .assetsDetailBox .imageSkeleton gets its own height: 100%; width: 100% rule.

File Structure ​

Core Files ​

Vue Page Files (.vue) ​

  • app/pages/[brand_name]/files/[id].vue - Asset details page
    • Asset metadata display
    • Asset preview
    • Asset actions
    • Asset information

Route: /{brand_name}/files/{id}

Components ​

  • app/components/card/Asset/AssetCard.vue - Asset card component

    • Asset thumbnail display
    • Asset metadata
    • Quick actions
    • Selection support
  • app/components/card/Asset/AssetContainer.vue - Asset container

    • Grid/list layout
    • Asset card rendering
    • Selection management
  • app/components/dialogs/QuickViewDialog.vue - Quick view dialog

    • Asset preview
    • Asset metadata
    • Quick actions
  • app/components/dialogs/GalleryQuickViewDialog.vue - Gallery quick view (collage and folder detail)

    • Paged preview with arrows, keyboard, swipe and thumbnail strip
    • Download and open detail view
  • app/components/dialogs/AssetConverterDialog.vue - Asset converter dialog

    • Format selection
    • Quality settings
    • Conversion progress

Composables ​

  • app/composables/core/pages/useAssetDetails.ts - Asset details composable

    • Asset data fetching
    • Asset operations
    • Asset metadata management
  • app/composables/core/components/card/useAssetCard.ts - Asset card composable

    • Asset card logic
    • Selection handling
    • Action handlers
  • app/composables/core/components/dialogs/useQuickViewDialog.ts - Quick view composable

    • Preview state management
    • Navigation handling

API ​

  • app/composables/api/useAssetsApi.ts - Asset API operations
    • Get asset details
    • Update asset metadata
    • Delete asset
    • Convert asset format

Data Flow ​

Asset Viewing ​

  1. User clicks asset card or navigates to asset URL
  2. Asset details fetched from API
  3. Asset metadata displayed
  4. Asset preview loaded (if applicable)
  5. Actions available (download, share, etc.)

Asset Selection ​

  1. User clicks asset card checkbox or Shift+Click
  2. Selection state updated
  3. Selection count displayed
  4. Bulk actions enabled
  5. Selection persisted across pagination

User Interactions ​

  1. Asset Viewing

    • Click asset card to view details
    • Quick view from card actions
    • Full-screen preview
  2. Asset Selection

    • Single click to select
    • Shift+Click for range selection
    • Select all functionality
  3. Asset Actions

    • Download asset
    • Share asset
    • View asset details
    • Convert asset format
  4. Bulk Operations

    • Download selected assets
    • Share selected assets
    • Clear selection

File Type Support ​

  • Images: JPEG, PNG, GIF, WebP, SVG
  • Videos: MP4, WebM, MOV
  • Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX
  • Audio: MP3, WAV, OGG
  • Other: ZIP, TXT, HTML