Merge branch 'master' into 14078-obtain-configuration-data-from-discovery-endpoint
[arvados-workbench2.git] / src / services / collection-service / collection-service.ts
index bc9128171254eebe3b9a42c5cfad5ea86ec56856..1c62ec5a68b471b89e646e6d698d99b423a421b8 100644 (file)
@@ -2,53 +2,70 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { serverApi } from "../../common/api/server-api";
-import FilterBuilder, { FilterField } from "../../common/api/filter-builder";
-import { ArvadosResource } from "../response";
-import { Collection } from "../../models/collection";
-import { getResourceKind } from "../../models/resource";
-
-interface CollectionResource extends ArvadosResource {
-    name: string;
-    description: string;
-    properties: any;
-    portable_data_hash: string;
-    manifest_text: string;
-    replication_desired: number;
-    replication_confirmed: number;
-    replication_confirmed_at: string;
-    trash_at: string;
-    delete_at: string;
-    is_trashed: boolean;
-}
+import { CommonResourceService } from "~/common/api/common-resource-service";
+import { CollectionResource } from "~/models/collection";
+import { AxiosInstance } from "axios";
+import { CollectionFile, CollectionDirectory } from "~/models/collection-file";
+import { WebDAV } from "~/common/webdav";
+import { AuthService } from "../auth-service/auth-service";
+import { mapTreeValues } from "~/models/tree";
+import { parseFilesResponse } from "./collection-service-files-response";
+import { fileToArrayBuffer } from "~/common/file";
 
-interface CollectionsResponse {
-    offset: number;
-    limit: number;
-    items: CollectionResource[];
-}
+export type UploadProgress = (fileId: number, loaded: number, total: number, currentTime: number) => void;
 
-export default class CollectionService {
-    public getCollectionList = (parentUuid?: string): Promise<Collection[]> => {
-        if (parentUuid) {
-            const fb = new FilterBuilder();
-            fb.addLike(FilterField.OWNER_UUID, parentUuid);
-            return serverApi.get<CollectionsResponse>('/collections', { params: {
-                filters: fb.get()
-            }}).then(resp => {
-                const collections = resp.data.items.map(g => ({
-                    name: g.name,
-                    createdAt: g.created_at,
-                    modifiedAt: g.modified_at,
-                    href: g.href,
-                    uuid: g.uuid,
-                    ownerUuid: g.owner_uuid,
-                    kind: getResourceKind(g.kind)
-                } as Collection));
-                return collections;
-            });
-        } else {
-            return Promise.resolve([]);
+export class CollectionService extends CommonResourceService<CollectionResource> {
+    constructor(serverApi: AxiosInstance, private webdavClient: WebDAV, private authService: AuthService) {
+        super(serverApi, "collections");
+    }
+
+    async files(uuid: string) {
+        const request = await this.webdavClient.propfind(`/c=${uuid}`);
+        if (request.responseXML != null) {
+            const filesTree = parseFilesResponse(request.responseXML);
+            return mapTreeValues(this.extendFileURL)(filesTree);
         }
+        return Promise.reject();
     }
+
+    async deleteFiles(collectionUuid: string, filePaths: string[]) {
+        for (const path of filePaths) {
+            await this.webdavClient.delete(`/c=${collectionUuid}${path}`);
+        }
+    }
+
+    async uploadFiles(collectionUuid: string, files: File[], onProgress?: UploadProgress) {
+        // files have to be uploaded sequentially
+        for (let idx = 0; idx < files.length; idx++) {
+            await this.uploadFile(collectionUuid, files[idx], idx, onProgress);
+        }
+    }
+
+    moveFile(collectionUuid: string, oldPath: string, newPath: string) {
+        return this.webdavClient.move(
+            `/c=${collectionUuid}${oldPath}`,
+            `/c=${collectionUuid}${encodeURI(newPath)}`
+        );
+    }
+
+    private extendFileURL = (file: CollectionDirectory | CollectionFile) => ({
+        ...file,
+        url: this.webdavClient.defaults.baseURL + file.url + '?api_token=' + this.authService.getApiToken()
+    })
+
+    private async uploadFile(collectionUuid: string, file: File, fileId: number, onProgress: UploadProgress = () => { return; }) {
+        const fileURL = `/c=${collectionUuid}/${file.name}`;
+        const fileContent = await fileToArrayBuffer(file);
+        const requestConfig = {
+            headers: {
+                'Content-Type': 'text/octet-stream'
+            },
+            onUploadProgress: (e: ProgressEvent) => {
+                onProgress(fileId, e.loaded, e.total, Date.now());
+            }
+        };
+        return this.webdavClient.put(fileURL, fileContent, requestConfig);
+
+    }
+
 }