X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/4b7d15c94685ca3e34ebb905a4803f895367ad09..aac3dfbed3d02cc6a2240add62439ee0dda3f335:/src/common/webdav.ts diff --git a/src/common/webdav.ts b/src/common/webdav.ts index 24dacbde..93ec21cb 100644 --- a/src/common/webdav.ts +++ b/src/common/webdav.ts @@ -2,101 +2,133 @@ // // SPDX-License-Identifier: AGPL-3.0 +import { customEncodeURI } from "./url"; + export class WebDAV { - static create(config?: Partial, createRequest?: () => XMLHttpRequest) { - return new WebDAV(config, createRequest); - } defaults: WebDAVDefaults = { - baseUrl: '', + baseURL: '', headers: {}, }; - propfind = (url: string, config: PropfindConfig = {}) => + constructor(config?: Partial, private createRequest = () => new XMLHttpRequest()) { + if (config) { + this.defaults = { ...this.defaults, ...config }; + } + } + + propfind = (url: string, config: WebDAVRequestConfig = {}) => this.request({ ...config, url, method: 'PROPFIND' }) - put = (url: string, config: PutConfig = {}) => + put = (url: string, data?: any, config: WebDAVRequestConfig = {}) => this.request({ ...config, url, - method: 'PUT' + method: 'PUT', + data }) - copy = (url: string, { destination, ...config }: CopyConfig) => + upload = (url: string, files: File[], config: WebDAVRequestConfig = {}) => { + return Promise.all( + files.map(file => this.request({ + ...config, url, + method: 'PUT', + data: file + })) + ); + } + + copy = (url: string, destination: string, config: WebDAVRequestConfig = {}) => this.request({ ...config, url, method: 'COPY', - headers: { ...config.headers, Destination: this.defaults.baseUrl + destination } + headers: { + ...config.headers, + Destination: this.defaults.baseURL + ? this.defaults.baseURL.replace(/\/+$/, '') + '/' + destination.replace(/^\/+/, '') + : destination + } }) - move = (url: string, { destination, ...config }: MoveConfig) => + move = (url: string, destination: string, config: WebDAVRequestConfig = {}) => this.request({ ...config, url, method: 'MOVE', - headers: { ...config.headers, Destination: this.defaults.baseUrl + destination } + headers: { + ...config.headers, + Destination: this.defaults.baseURL + ? this.defaults.baseURL.replace(/\/+$/, '') + '/' + destination.replace(/^\/+/, '') + : destination + } }) - delete = (url: string, config: DeleteConfig = {}) => + delete = (url: string, config: WebDAVRequestConfig = {}) => this.request({ ...config, url, method: 'DELETE' }) - private constructor(config?: Partial, private createRequest = () => new XMLHttpRequest()) { - if (config) { - this.defaults = { ...this.defaults, ...config }; - } - } - private request = (config: RequestConfig) => { return new Promise((resolve, reject) => { const r = this.createRequest(); - r.open(config.method, this.defaults.baseUrl + config.url); + this.defaults.baseURL = this.defaults.baseURL.replace(/\/+$/, ''); + r.open(config.method, + `${this.defaults.baseURL + ? this.defaults.baseURL+'/' + : ''}${customEncodeURI(config.url)}`); const headers = { ...this.defaults.headers, ...config.headers }; Object .keys(headers) .forEach(key => r.setRequestHeader(key, headers[key])); - if (config.onProgress) { - r.addEventListener('progress', config.onProgress); + if (!(window as any).cancelTokens) { + Object.assign(window, { cancelTokens: {} }); } - r.addEventListener('load', () => resolve(r)); - r.addEventListener('error', () => reject(r)); + (window as any).cancelTokens[config.url] = () => { + resolve(r); + r.abort(); + } - r.send(config.data); - }); + if (config.onUploadProgress) { + r.upload.addEventListener('progress', config.onUploadProgress); + } - } -} + // This event gets triggered on *any* server response + r.addEventListener('load', () => { + if (r.status >= 400) { + return reject(r); + } else { + return resolve(r); + } + }); -export interface PropfindConfig extends BaseConfig { } + // This event gets triggered on network errors + r.addEventListener('error', () => { + return reject(r); + }); -export interface PutConfig extends BaseConfig { - data?: any; -} + r.upload.addEventListener('error', () => { + return reject(r); + }); -export interface CopyConfig extends BaseConfig { - destination: string; -} - -export interface MoveConfig extends BaseConfig { - destination: string; + r.send(config.data); + }); + } } -export interface DeleteConfig extends BaseConfig { } - -interface BaseConfig { +export interface WebDAVRequestConfig { headers?: { [key: string]: string; }; + onUploadProgress?: (event: ProgressEvent) => void; } interface WebDAVDefaults { - baseUrl: string; + baseURL: string; headers: { [key: string]: string }; } @@ -105,5 +137,5 @@ interface RequestConfig { url: string; headers?: { [key: string]: string }; data?: any; - onProgress?: (event: ProgressEvent) => void; -} + onUploadProgress?: (event: ProgressEvent) => void; +} \ No newline at end of file