import { createAssetView } from '../asset_manager'; export const ASSET_PRESIGN_TTL_MS = 240 * 1000; // backend issues 5 min tokens; refresh slightly early export const DEFAULT_FOLDER_NAME = 'Documents'; export const DEFAULT_SORT_FIELD = 'title'; export const DEFAULT_SORT_DIRECTION = 'asc'; export const SORT_FIELD_VALUES = ['title', 'issued_at', 'created_at', 'updated_at']; export const TAG_FILTER_UNTAGGED = '__UNTAGGED__'; const ROW_KEY_SEPARATOR = ':'; const DOCUMENT_ROW_PREFIX = 'document'; const FOLDER_ROW_PREFIX = 'folder'; export const resolveApiPath = (path = '') => path; const makeRowKey = (type, id) => id ? `${type}${ROW_KEY_SEPARATOR}${id}` : `${type}${ROW_KEY_SEPARATOR}`; const normalizeRowKey = (key: string | number | null) => String(key ?? ''); const getRowType = (key) => normalizeRowKey(key).split(ROW_KEY_SEPARATOR, 1)[0] ?? ''; export const getRowId = (key) => { const normalized = normalizeRowKey(key); const separatorIndex = normalized.indexOf(ROW_KEY_SEPARATOR); if (separatorIndex === -1) return normalized; return normalized.slice(separatorIndex + 1); }; export const isDocumentRowKey = (key) => getRowType(key) === DOCUMENT_ROW_PREFIX; export const isFolderRowKey = (key) => getRowType(key) === FOLDER_ROW_PREFIX; export const resolveDocumentRowKey = (documentId) => documentId ? makeRowKey(DOCUMENT_ROW_PREFIX, documentId) : null; export const resolveFolderRowKey = (folderId) => folderId ? makeRowKey(FOLDER_ROW_PREFIX, folderId) : null; export const hasFiles = (event) => Array.from(event.dataTransfer?.types || []).includes('Files'); const isAssetEquivalent = (lhs, rhs) => { if (!lhs || !rhs) return false; const lhsView = createAssetView(lhs); const rhsView = createAssetView(rhs); const lhsPrimaryMetadata = lhsView.getPrimaryMetadata() || lhs?.metadata; const rhsPrimaryMetadata = rhsView.getPrimaryMetadata() || rhs?.metadata; const lhsCardinality = lhsView.getCardinality() || lhs?.cardinality || null; const rhsCardinality = rhsView.getCardinality() || rhs?.cardinality || null; const lhsObjects = lhsView.getObjects(); const rhsObjects = rhsView.getObjects(); const objectsComparable = lhsObjects.length === rhsObjects.length && lhsObjects.every((entry, index) => { const other = rhsObjects[index]; if (!other) return false; if (entry.ordinal !== other.ordinal) return false; if (entry.url && other.url && entry.url === other.url) { return true; } if (!entry.url && !other.url) { return JSON.stringify(entry.metadata || null) === JSON.stringify(other.metadata || null); } return entry.url === other.url; }); return ( lhs.id === rhs.id && lhs.url === rhs.url && lhsPrimaryMetadata?.width === rhsPrimaryMetadata?.width && lhsPrimaryMetadata?.height === rhsPrimaryMetadata?.height && lhs.mime_type === rhs.mime_type && lhs.asset_type === rhs.asset_type && lhs.updated_at === rhs.updated_at && lhsCardinality === rhsCardinality && objectsComparable ); }; const mergeAssetIntoGroup = (group, assetData) => { if (!assetData || !assetData.asset_type) { if (Array.isArray(group)) { return group; } return group || {}; } if (Array.isArray(group) || !group) { const list = Array.isArray(group) ? group : []; const index = list.findIndex((item) => item?.id === assetData.id); if (index >= 0) { const existing = list[index]; if (isAssetEquivalent(existing, assetData)) { return list; } const next = list.slice(); next[index] = { ...existing, ...assetData }; return next; } return list.concat({ ...assetData }); } const key = assetData.asset_type; const previous = group?.[key]; if (previous && isAssetEquivalent(previous, assetData)) { return group; } const next = { ...(group || {}) }; next[key] = { ...(previous || {}), ...assetData }; return next; }; export const mergeAssetIntoDocument = (doc, assetData) => { if (!doc) return doc; const existingGroup = doc.current_version?.assets || null; const nextGroup = mergeAssetIntoGroup(existingGroup, assetData); if (nextGroup === existingGroup) { return doc; } const updatedCurrentVersion = doc.current_version ? { ...doc.current_version, assets: nextGroup } : { assets: nextGroup }; return { ...doc, current_version: updatedCurrentVersion }; }; export const createRootNode = () => ({ id: 'root', name: DEFAULT_FOLDER_NAME, parentId: null, children: [], expanded: true, loaded: false, hasChildren: false, });