135 lines
4.5 KiB
TypeScript
135 lines
4.5 KiB
TypeScript
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,
|
|
});
|