From d25cfd942a7d2877d58a650d723edb48a62f3bb8 Mon Sep 17 00:00:00 2001
From: Patrizio Bekerle <patrizio@bekerle.com>
Date: Tue, 23 Jun 2020 14:10:11 +0200
Subject: [PATCH] Add more webdav file handling and table columns (#26)

---
 src/vpu-nextcloud-file-picker.js | 125 ++++++++++++++++++++-----------
 1 file changed, 82 insertions(+), 43 deletions(-)

diff --git a/src/vpu-nextcloud-file-picker.js b/src/vpu-nextcloud-file-picker.js
index 5411094..0efd6a0 100644
--- a/src/vpu-nextcloud-file-picker.js
+++ b/src/vpu-nextcloud-file-picker.js
@@ -24,8 +24,8 @@ export class NextcloudFilePicker extends ScopedElementsMixin(VPULitElement) {
         this.loginWindow = null;
         this.isPickerActive = false;
         this.statusText = "";
+        this.lastDirectoryPath = "/";
         this.directoryPath = "/";
-        this.directoryContents = [];
         this.webDavClient = null;
         this.tabulatorTable = null;
 
@@ -49,7 +49,6 @@ export class NextcloudFilePicker extends ScopedElementsMixin(VPULitElement) {
             isPickerActive: { type: Boolean, attribute: false },
             statusText: { type: String, attribute: false },
             directoryPath: { type: String, attribute: false },
-            directoryContents: { type: Array, attribute: false },
         };
     }
 
@@ -73,16 +72,43 @@ export class NextcloudFilePicker extends ScopedElementsMixin(VPULitElement) {
     connectedCallback() {
         super.connectedCallback();
 
-        this.updateComplete.then(()=>{
+        this.updateComplete.then(() => {
             // see: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
             window.addEventListener('message', this._onReceiveWindowMessage);
 
             // http://tabulator.info/docs/4.7
-            this.tabulatorTable = new Tabulator(this._("#directory-content-table"), {});
+            // TODO: format size and lastmod
+            // TODO: translation of column headers
+            // TODO: mime type icon
+            this.tabulatorTable = new Tabulator(this._("#directory-content-table"), {
+                layout: "fitDataStretch",
+                selectable: true,
+                columns: [
+                    {title: "Filename", field: "basename"},
+                    {title: "Size", field: "size", formatter: (cell, formatterParams, onRendered) => {
+                            return cell.getRow().getData().type === "directory" ? "" : humanFileSize(cell.getValue());}},
+                    {title: "Type", field: "type"},
+                    {title: "Mime", field: "mime"},
+                    {title: "Last modified", field: "lastmod", sorter: "date"},
+                ],
+                rowClick: (e, row) => {
+                    const data = row.getData();
+
+                    switch(data.type) {
+                        case "directory":
+                            this.directoryClicked(e, data);
+                            break;
+                        case "file":
+                            console.log("file selected", data);
+                            break;
+                    }
+                },
+            });
         });
     }
 
     openFilePicker() {
+        // TODO: translation
         this.statusText = "Auth in progress";
         this.loginWindow = window.open(this.authUrl, "Nextcloud Login",
             "width=400,height=400,menubar=no,scrollbars=no,status=no,titlebar=no,toolbar=no");
@@ -107,7 +133,7 @@ export class NextcloudFilePicker extends ScopedElementsMixin(VPULitElement) {
                 }
             );
 
-            this.loadDirectory("");
+            this.loadDirectory("/");
         }
     }
 
@@ -117,20 +143,18 @@ export class NextcloudFilePicker extends ScopedElementsMixin(VPULitElement) {
      * @param path
      */
     loadDirectory(path) {
+        // TODO: translation
         this.statusText = "Loading directory from Nextcloud: " + path;
+        this.lastDirectoryPath = this.directoryPath;
         this.directoryPath = path;
-        this.directoryContents = [];
 
         // https://github.com/perry-mitchell/webdav-client#getdirectorycontents
         this.webDavClient
-            .getDirectoryContents(path)
+            .getDirectoryContents(path, {details: true})
             .then(contents => {
                 console.log("contents", contents);
                 this.statusText = "";
-                this.directoryContents = contents;
-
-                this.tabulatorTable.setData(contents);
-
+                this.tabulatorTable.setData(contents.data);
                 this.isPickerActive = true;
             }).catch(error => {
             console.error(error.message);
@@ -139,6 +163,43 @@ export class NextcloudFilePicker extends ScopedElementsMixin(VPULitElement) {
         });
     }
 
+    directoryClicked(event, file) {
+        this.loadDirectory(file.filename);
+        event.preventDefault();
+    }
+
+    downloadFiles(files) {
+        files.forEach((file) => this.downloadFile(file));
+    }
+
+    downloadFile(file) {
+        this.statusText = "Loading " + file.filename + "...";
+
+        // https://github.com/perry-mitchell/webdav-client#getfilecontents
+        this.webDavClient
+            .getFileContents(file.filename)
+            .then(contents => {
+                console.log("contents", contents);
+                // TODO: Generate file and send event
+                this.statusText = "";
+            }).catch(error => {
+            console.error(error.message);
+            this.statusText = error.message;
+        });
+    }
+
+    /**
+     * Returns the parent directory path
+     *
+     * @returns {string} parent directory path
+     */
+    getParentDirectoryPath() {
+        let path = this.directoryPath.replace(/\/$/, "");
+        path = path.replace(path.split("/").pop(), "").replace(/\/$/, "");
+
+        return (path === "") ? "/" : path;
+    }
+
     static get styles() {
         // language=css
         return css`
@@ -151,31 +212,6 @@ export class NextcloudFilePicker extends ScopedElementsMixin(VPULitElement) {
         `;
     }
 
-    /**
-     * Returns the list of files in a directory
-     *
-     * @returns {*[]}
-     */
-    getDirectoryContentsHtml() {
-        let results = [];
-
-        // this.directoryContents.forEach((content) => {
-        //     results.push(html`
-        //         <tr>
-        //             <td><a href="#" @click="${(e) => { this.fileClicked(content, e); }}">${content.filename}</a></td>
-        //             <td>${content.size}</td>
-        //         </tr>
-        //     `);
-        // });
-
-        return results;
-    }
-
-    fileClicked(file, event) {
-        this.loadDirectory(this.directoryPath + file.filename);
-        event.preventDefault();
-    }
-
     render() {
         commonUtils.initAssetBaseURL('vpu-tabulator-table');
         const tabulatorCss = commonUtils.getAssetURL('local/vpu-signature/tabulator-tables/css/tabulator.min.css');
@@ -194,13 +230,16 @@ export class NextcloudFilePicker extends ScopedElementsMixin(VPULitElement) {
             </div>
             <div class="block ${classMap({hidden: !this.isPickerActive})}">
                 <h2>${this.directoryPath}</h2>
-                <table id="directory-content-table">
-                    <thead>
-                        <th>Filename</th>
-                        <th>Size</th>
-                    </thead>
-                    <tbody>${this.getDirectoryContentsHtml()}</tbody>
-                </table>
+                <button class="button is-small"
+                        title="${i18n.t('nextcloud-file-picker.folder-last')}"
+                        @click="${() => { this.loadDirectory(this.lastDirectoryPath); }}">&#8678;</button>
+                <button class="button is-small"
+                        title="${i18n.t('nextcloud-file-picker.folder-up')}"
+                        @click="${() => { this.loadDirectory(this.getParentDirectoryPath()); }}">&#8679;</button>
+                <table id="directory-content-table"></table>
+                <button class="button"
+                        title="${i18n.t('nextcloud-file-picker.folder-up')}"
+                        @click="${() => { this.downloadFiles(this.tabulatorTable.getSelectedData()); }}">${i18n.t('nextcloud-file-picker.select-files')}</button>
             </div>
         `;
     }
-- 
GitLab