download url
This commit is contained in:
@@ -40,7 +40,6 @@ interface UseDocumentPreviewArgs {
|
|||||||
};
|
};
|
||||||
selectedFolder?: FolderId | null;
|
selectedFolder?: FolderId | null;
|
||||||
api: ApiClient;
|
api: ApiClient;
|
||||||
resolveApiPath?: (path: string) => string;
|
|
||||||
notifyApiError: (error: unknown, message: string) => void;
|
notifyApiError: (error: unknown, message: string) => void;
|
||||||
navigate: NavigateHandler;
|
navigate: NavigateHandler;
|
||||||
locationPathname: string;
|
locationPathname: string;
|
||||||
@@ -67,7 +66,6 @@ const useDocumentPreview = ({
|
|||||||
documentsManager,
|
documentsManager,
|
||||||
selectedFolder,
|
selectedFolder,
|
||||||
api,
|
api,
|
||||||
resolveApiPath,
|
|
||||||
notifyApiError,
|
notifyApiError,
|
||||||
navigate,
|
navigate,
|
||||||
locationPathname,
|
locationPathname,
|
||||||
@@ -109,7 +107,7 @@ const useDocumentPreview = ({
|
|||||||
async (documentId: DocumentId, { force = false }: { force?: boolean } = {}): Promise<DocumentLink | null> => {
|
async (documentId: DocumentId, { force = false }: { force?: boolean } = {}): Promise<DocumentLink | null> => {
|
||||||
if (!documentId) return null;
|
if (!documentId) return null;
|
||||||
|
|
||||||
const existing = documentLinks.get(documentId) || null;
|
const existing = documentLinks.get(documentId);
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const expiresAt = Number.isFinite(existing?.expiresAt) ? Number(existing?.expiresAt) : null;
|
const expiresAt = Number.isFinite(existing?.expiresAt) ? Number(existing?.expiresAt) : null;
|
||||||
if (!force && existing && (!expiresAt || expiresAt > now)) {
|
if (!force && existing && (!expiresAt || expiresAt > now)) {
|
||||||
@@ -123,17 +121,17 @@ const useDocumentPreview = ({
|
|||||||
const request: Promise<DocumentLink | null> = (async () => {
|
const request: Promise<DocumentLink | null> = (async () => {
|
||||||
try {
|
try {
|
||||||
const docResponse = await api.get<{ document?: Record<string, any> }>(`/documents/${documentId}`);
|
const docResponse = await api.get<{ document?: Record<string, any> }>(`/documents/${documentId}`);
|
||||||
const downloadPath = docResponse.data?.document?.current_version?.download_path;
|
const download = docResponse.data?.document?.current_version?.download || null;
|
||||||
if (!downloadPath || !resolveApiPath) {
|
const downloadUrl = download?.url;
|
||||||
throw new Error('Document missing download path');
|
if (!downloadUrl) {
|
||||||
|
throw new Error('Document missing download url');
|
||||||
}
|
}
|
||||||
|
|
||||||
const href = resolveApiPath(downloadPath);
|
|
||||||
const entry: DocumentLink = {
|
const entry: DocumentLink = {
|
||||||
url: href,
|
url: downloadUrl,
|
||||||
contentType: docResponse.data?.document?.current_version?.version?.content_type || null,
|
contentType: docResponse.data?.document?.current_version?.version?.content_type || null,
|
||||||
filename: docResponse.data?.document?.filename,
|
filename: docResponse.data?.document?.filename,
|
||||||
expiresAt: Date.now() + 5 * 60 * 1000,
|
expiresAt: download?.expires_at,
|
||||||
};
|
};
|
||||||
setDocumentLinks((prev) => {
|
setDocumentLinks((prev) => {
|
||||||
const next = new Map(prev);
|
const next = new Map(prev);
|
||||||
@@ -152,7 +150,7 @@ const useDocumentPreview = ({
|
|||||||
previewInflightRef.current.set(documentId, request);
|
previewInflightRef.current.set(documentId, request);
|
||||||
return request;
|
return request;
|
||||||
},
|
},
|
||||||
[documentLinks, api, resolveApiPath, notifyApiError],
|
[documentLinks, api, notifyApiError],
|
||||||
);
|
);
|
||||||
|
|
||||||
const ensurePreviewData = useCallback(
|
const ensurePreviewData = useCallback(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export interface AssetObject {
|
|||||||
ordinal?: number;
|
ordinal?: number;
|
||||||
url?: string | null;
|
url?: string | null;
|
||||||
metadata?: Record<string, unknown> | null;
|
metadata?: Record<string, unknown> | null;
|
||||||
expires_at?: number | null;
|
expires_at?: number;
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,10 +16,8 @@ export interface AssetLike {
|
|||||||
id?: Identifier;
|
id?: Identifier;
|
||||||
asset_type?: string;
|
asset_type?: string;
|
||||||
cardinality?: number | null;
|
cardinality?: number | null;
|
||||||
url?: string | null;
|
download?: { url: string; expires_at: number } | null;
|
||||||
expires_at?: number | null;
|
|
||||||
metadata?: Record<string, unknown> | null;
|
metadata?: Record<string, unknown> | null;
|
||||||
expiresAt?: number | null;
|
|
||||||
assets?: Record<string, AssetLike> | AssetLike[] | null;
|
assets?: Record<string, AssetLike> | AssetLike[] | null;
|
||||||
objects?: AssetObject[] | null;
|
objects?: AssetObject[] | null;
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
@@ -37,19 +35,11 @@ export interface DocumentLike {
|
|||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const resolveAssetExpiresAt = (
|
export const resolveAssetExpiresAt = (asset?: { download?: { expires_at: number } | null } | null): number | null =>
|
||||||
asset?: { expiresAt?: number | null; expires_at?: number | null } | null,
|
asset?.download?.expires_at ?? null;
|
||||||
): number | null => {
|
|
||||||
const camel = Number(asset?.expiresAt);
|
export const resolveAssetUrl = (asset?: { download?: { url: string } | null } | null): string | null =>
|
||||||
if (Number.isFinite(camel)) {
|
asset?.download?.url ?? null;
|
||||||
return camel;
|
|
||||||
}
|
|
||||||
const snake = Number(asset?.expires_at);
|
|
||||||
if (Number.isFinite(snake)) {
|
|
||||||
return snake;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type EnsureAssetUrl = (
|
export type EnsureAssetUrl = (
|
||||||
documentId: Identifier,
|
documentId: Identifier,
|
||||||
@@ -78,7 +68,7 @@ export const getAssetFromVersion = (currentVersion: Nullable<DocumentVersionLike
|
|||||||
if (!currentVersion) {
|
if (!currentVersion) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return getAssetFromGroup(currentVersion.assets ?? null, assetType);
|
return getAssetFromGroup(currentVersion.assets, assetType);
|
||||||
};
|
};
|
||||||
|
|
||||||
const normalizeAssetObjects = (objects?: AssetObject[] | null): AssetObject[] => {
|
const normalizeAssetObjects = (objects?: AssetObject[] | null): AssetObject[] => {
|
||||||
@@ -140,10 +130,11 @@ export class AssetView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ordinal === 1 && this.asset) {
|
if (ordinal === 1 && this.asset) {
|
||||||
if (this.asset.url || this.asset.metadata) {
|
const primaryUrl = resolveAssetUrl(this.asset);
|
||||||
|
if (primaryUrl || this.asset.metadata) {
|
||||||
return {
|
return {
|
||||||
ordinal: 1,
|
ordinal: 1,
|
||||||
url: this.asset.url || null,
|
url: primaryUrl || null,
|
||||||
metadata: this.asset.metadata || null,
|
metadata: this.asset.metadata || null,
|
||||||
expires_at: resolveAssetExpiresAt(this.asset),
|
expires_at: resolveAssetExpiresAt(this.asset),
|
||||||
};
|
};
|
||||||
@@ -242,7 +233,7 @@ class AssetManager {
|
|||||||
{ force = false }: { force?: boolean } = {},
|
{ force = false }: { force?: boolean } = {},
|
||||||
): Promise<Nullable<AssetLike>> {
|
): Promise<Nullable<AssetLike>> {
|
||||||
if (!documentId || !asset?.id) {
|
if (!documentId || !asset?.id) {
|
||||||
return Promise.resolve(asset ?? null);
|
return Promise.resolve(asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseAsset = this.assetCache.get(asset.id) || asset;
|
const baseAsset = this.assetCache.get(asset.id) || asset;
|
||||||
@@ -258,7 +249,8 @@ class AssetManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (baseAsset.url && (!assetExpiresAt || assetExpiresAt > now)) {
|
const assetUrl = resolveAssetUrl(baseAsset);
|
||||||
|
if (assetUrl && (!assetExpiresAt || assetExpiresAt > now)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -288,13 +280,13 @@ class AssetManager {
|
|||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
const cachedEntry = this.assetCache.get(asset.id) || baseAsset;
|
const cachedEntry = this.assetCache.get(asset.id) || baseAsset;
|
||||||
const combined = { ...cachedEntry, ...asset, ...data };
|
const combined = { ...cachedEntry, ...asset, ...data };
|
||||||
const expiresAt =
|
const expires_at =
|
||||||
resolveAssetExpiresAt(data)
|
resolveAssetExpiresAt(data)
|
||||||
?? resolveAssetExpiresAt(combined)
|
?? resolveAssetExpiresAt(combined);
|
||||||
?? Date.now() + this.assetPresignTtlMs;
|
|
||||||
const entry = {
|
const entry = {
|
||||||
...combined,
|
...combined,
|
||||||
expiresAt,
|
url: resolveAssetUrl(combined),
|
||||||
|
expires_at,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.rememberAsset(entry);
|
this.rememberAsset(entry);
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ export type DocumentLike = OcrDocumentLike;
|
|||||||
const asyncFalse = async () => false;
|
const asyncFalse = async () => false;
|
||||||
|
|
||||||
const resolveDocumentDownloadHref = (document?: DocumentLike | null, resolveApiPath?: ResolveApiPath | null): string | null => {
|
const resolveDocumentDownloadHref = (document?: DocumentLike | null, resolveApiPath?: ResolveApiPath | null): string | null => {
|
||||||
if (!document || !resolveApiPath) {
|
if (!document) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const downloadPath = (document.current_version as { download_path?: string | null } | null)?.download_path;
|
const downloadUrl = (document.current_version as { download?: { url: string } | null } | null)?.download?.url;
|
||||||
if (!downloadPath) {
|
if (!downloadUrl) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return resolveApiPath(downloadPath);
|
return resolveApiPath ? resolveApiPath(downloadUrl) : downloadUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasDocumentOcrAsset = (document?: DocumentLike | null, getDocumentAsset?: GetDocumentAsset | null): boolean => {
|
const hasDocumentOcrAsset = (document?: DocumentLike | null, getDocumentAsset?: GetDocumentAsset | null): boolean => {
|
||||||
|
|||||||
@@ -450,7 +450,6 @@ const useDocumentsWorkspace = ({
|
|||||||
documentsManager,
|
documentsManager,
|
||||||
selectedFolder,
|
selectedFolder,
|
||||||
api,
|
api,
|
||||||
resolveApiPath,
|
|
||||||
notifyApiError,
|
notifyApiError,
|
||||||
navigate,
|
navigate,
|
||||||
locationPathname: location.pathname,
|
locationPathname: location.pathname,
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ interface DocumentLike {
|
|||||||
correspondents?: Array<{ id?: string | number; name?: string }>;
|
correspondents?: Array<{ id?: string | number; name?: string }>;
|
||||||
current_version?: {
|
current_version?: {
|
||||||
version_number?: number;
|
version_number?: number;
|
||||||
|
download?: { url?: string | null; expires_at?: number } | null;
|
||||||
version?: { content_type?: string | null } | null;
|
version?: { content_type?: string | null } | null;
|
||||||
|
filename?: string | null;
|
||||||
} | null;
|
} | null;
|
||||||
documentLink?: {
|
documentLink?: {
|
||||||
url: string;
|
url: string;
|
||||||
@@ -261,11 +263,8 @@ const DocumentViewerPanel: React.FC<DocumentViewerPanelProps> = ({
|
|||||||
if (!document) {
|
if (!document) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const downloadPath = document.current_version?.download_path;
|
const downloadUrl = document.current_version?.download?.url;
|
||||||
if (!downloadPath) {
|
const href = resolveApiPath ? resolveApiPath(downloadUrl) : downloadUrl;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const href = resolveApiPath ? resolveApiPath(downloadPath) : downloadPath;
|
|
||||||
if (!href) {
|
if (!href) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,8 @@ import type {
|
|||||||
GetAsset as AssetManagerGetAsset,
|
GetAsset as AssetManagerGetAsset,
|
||||||
} from '../asset_manager';
|
} from '../asset_manager';
|
||||||
|
|
||||||
interface DocumentVersion extends DocumentVersionLike {
|
|
||||||
download_path?: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DocumentLike extends AssetManagerDocumentLike {
|
export interface DocumentLike extends AssetManagerDocumentLike {
|
||||||
current_version?: DocumentVersion | null;
|
current_version?: DocumentVersionLike | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AssetLike = AssetManagerAssetLike;
|
export type AssetLike = AssetManagerAssetLike;
|
||||||
|
|||||||
Reference in New Issue
Block a user