Release v0.1.3
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { apiFetch, apiUrl, authHeaders, csrfToken, type ApiSettings } from "@govoplan/core-webui";
|
||||
import { ApiError, apiFetch, apiUrl, authHeaders, csrfToken, type ApiSettings } from "@govoplan/core-webui";
|
||||
|
||||
export type FileSpace = {
|
||||
id: string;
|
||||
@@ -40,6 +40,7 @@ export type ManagedFile = {
|
||||
export type FileListResponse = { files: ManagedFile[] };
|
||||
export type FileSpacesResponse = { spaces: FileSpace[] };
|
||||
export type FileUploadResponse = { files: ManagedFile[] };
|
||||
export type FileUploadProgress = { loaded: number; total?: number; percentage: number | null };
|
||||
export type FileFolder = {
|
||||
id: string;
|
||||
tenant_id: string;
|
||||
@@ -102,7 +103,16 @@ export function listFiles(settings: ApiSettings, params: { owner_type?: string;
|
||||
export async function uploadFiles(
|
||||
settings: ApiSettings,
|
||||
files: File[],
|
||||
options: { owner_type: "user" | "group"; owner_id: string; path?: string; campaign_id?: string; unpack_zip?: boolean; conflict_strategy?: ConflictStrategy; conflict_resolutions?: ConflictResolution[] }
|
||||
options: {
|
||||
owner_type: "user" | "group";
|
||||
owner_id: string;
|
||||
path?: string;
|
||||
campaign_id?: string;
|
||||
unpack_zip?: boolean;
|
||||
conflict_strategy?: ConflictStrategy;
|
||||
conflict_resolutions?: ConflictResolution[];
|
||||
onProgress?: (progress: FileUploadProgress) => void;
|
||||
}
|
||||
): Promise<FileUploadResponse> {
|
||||
const form = new FormData();
|
||||
files.forEach((file) => form.append("files", file));
|
||||
@@ -113,9 +123,54 @@ export async function uploadFiles(
|
||||
if (options.unpack_zip) form.append("unpack_zip", "true");
|
||||
if (options.conflict_strategy) form.append("conflict_strategy", options.conflict_strategy);
|
||||
if (options.conflict_resolutions?.length) form.append("conflict_resolutions_json", JSON.stringify(options.conflict_resolutions));
|
||||
if (options.onProgress) return uploadFilesWithProgress(settings, form, options.onProgress);
|
||||
return apiFetch<FileUploadResponse>(settings, "/api/v1/files/upload", { method: "POST", body: form });
|
||||
}
|
||||
|
||||
function uploadFilesWithProgress(
|
||||
settings: ApiSettings,
|
||||
form: FormData,
|
||||
onProgress: (progress: FileUploadProgress) => void
|
||||
): Promise<FileUploadResponse> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", apiUrl(settings, "/api/v1/files/upload"));
|
||||
xhr.withCredentials = true;
|
||||
for (const [key, value] of authHeaders(settings)) xhr.setRequestHeader(key, value);
|
||||
const csrf = csrfToken();
|
||||
if (csrf) xhr.setRequestHeader("X-CSRF-Token", csrf);
|
||||
|
||||
xhr.upload.onprogress = (event) => {
|
||||
const total = event.lengthComputable ? event.total : undefined;
|
||||
onProgress({
|
||||
loaded: event.loaded,
|
||||
total,
|
||||
percentage: total && total > 0 ? Math.round((event.loaded / total) * 100) : null
|
||||
});
|
||||
};
|
||||
|
||||
xhr.onerror = () => reject(new Error("Upload failed because the network request could not be completed."));
|
||||
xhr.onabort = () => reject(new Error("Upload was cancelled."));
|
||||
xhr.onload = () => {
|
||||
const responseText = xhr.responseText || "";
|
||||
if (xhr.status < 200 || xhr.status >= 300) {
|
||||
reject(new ApiError(xhr.status, xhr.statusText, responseText));
|
||||
return;
|
||||
}
|
||||
onProgress({ loaded: 1, total: 1, percentage: 100 });
|
||||
if (xhr.status === 204 || !responseText) {
|
||||
resolve({ files: [] });
|
||||
return;
|
||||
}
|
||||
const contentType = xhr.getResponseHeader("content-type") || "";
|
||||
resolve(contentType.includes("application/json") ? JSON.parse(responseText) as FileUploadResponse : { files: [] });
|
||||
};
|
||||
|
||||
onProgress({ loaded: 0, total: undefined, percentage: 0 });
|
||||
xhr.send(form);
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteFile(settings: ApiSettings, fileId: string): Promise<BulkDeleteResponse> {
|
||||
return apiFetch<BulkDeleteResponse>(settings, `/api/v1/files/${fileId}`, { method: "DELETE" });
|
||||
}
|
||||
@@ -124,13 +179,22 @@ export function bulkDeleteFiles(settings: ApiSettings, fileIds: string[]): Promi
|
||||
return apiFetch<BulkDeleteResponse>(settings, "/api/v1/files/bulk-delete", { method: "POST", body: JSON.stringify({ file_ids: fileIds }) });
|
||||
}
|
||||
|
||||
export function shareFileWithCampaign(settings: ApiSettings, fileId: string, campaignId: string): Promise<FileShare> {
|
||||
return apiFetch<FileShare>(settings, `/api/v1/files/${fileId}/shares`, {
|
||||
export type FileBulkShareResponse = { shares: FileShare[]; shared_count: number };
|
||||
|
||||
export function shareFilesWithCampaign(settings: ApiSettings, fileIds: string[], campaignId: string): Promise<FileBulkShareResponse> {
|
||||
return apiFetch<FileBulkShareResponse>(settings, "/api/v1/files/bulk-shares", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ target_type: "campaign", target_id: campaignId, permission: "read" })
|
||||
body: JSON.stringify({ file_ids: fileIds, target_type: "campaign", target_id: campaignId, permission: "read" })
|
||||
});
|
||||
}
|
||||
|
||||
export async function shareFileWithCampaign(settings: ApiSettings, fileId: string, campaignId: string): Promise<FileShare> {
|
||||
const response = await shareFilesWithCampaign(settings, [fileId], campaignId);
|
||||
const share = response.shares[0];
|
||||
if (!share) throw new Error("File share was not created.");
|
||||
return share;
|
||||
}
|
||||
|
||||
export function bulkRenameFiles(
|
||||
settings: ApiSettings,
|
||||
payload: { file_ids: string[]; folder_paths?: string[]; owner_type?: "user" | "group"; owner_id?: string; mode: "direct" | "prefix" | "suffix" | "replace"; new_name?: string; find?: string; replacement?: string; prefix?: string; suffix?: string; recursive?: boolean; dry_run?: boolean }
|
||||
|
||||
Reference in New Issue
Block a user