diff --git a/package-lock.json b/package-lock.json
index ccc8970fce64c9e629e256c140a55a7b664c9367..79f7a671d91d3d6e8f17adbabbc5a6d3745ef5ad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8628,6 +8628,11 @@
         }
       }
     },
+    "tabulator-tables": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-4.7.0.tgz",
+      "integrity": "sha512-FOFn13Vxuv0qJXZkwfEVBvT8fjm+VOdpcryclftCvf8i+8P1hJhKftyBfVtOqlPLWM0B0o8pNHZaV+JKY/IJSA=="
+    },
     "tar": {
       "version": "4.4.13",
       "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
diff --git a/package.json b/package.json
index 5247af1fd308598d89d440b03776dac62a28a27f..76bdbb72957bb5e6e058d717a4214a23c630ee8d 100644
--- a/package.json
+++ b/package.json
@@ -50,6 +50,7 @@
     "lit-html": "^1.2.1",
     "pdfjs-dist": "^2.4.456",
     "source-sans-pro": "^2.45.0",
+    "tabulator-tables": "^4.7.0",
     "universal-router": "^9.0.1",
     "vpu-app-shell": "file:./vendor/app-shell",
     "vpu-auth": "file:./vendor/auth",
diff --git a/rollup.config.js b/rollup.config.js
index 9dcfa435c906683065a9a2a5bf495d507358428d..f9f91a8f4b0db466c7bb15dc6683e3096f6c7f8d 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -272,6 +272,7 @@ Dependencies:
                 {src: 'assets/manifest.json', dest: 'dist', rename: pkg.name + '.manifest.json'},
                 {src: 'assets/*.metadata.json', dest: 'dist'},
                 {src: 'node_modules/vpu-common/assets/icons/*.svg', dest: 'dist/local/vpu-common/icons'},
+                {src: 'node_modules/tabulator-tables/dist/css', dest: 'dist/local/' + pkg.name + '/tabulator-tables'},
             ],
         }),
         useBabel && babel({
diff --git a/src/vpu-file-picker.js b/src/vpu-file-picker.js
index b1c81f60022ac4c676261e7cdd0d80bb82bc2819..40a17c851e4a4322e3be70a329b7afe4996b4da6 100644
--- a/src/vpu-file-picker.js
+++ b/src/vpu-file-picker.js
@@ -3,8 +3,12 @@ import {css, html} from 'lit-element';
 import {ScopedElementsMixin} from '@open-wc/scoped-elements';
 import VPULitElement from 'vpu-common/vpu-lit-element';
 import {MiniSpinner} from 'vpu-common';
+import * as commonUtils from 'vpu-common/utils';
 import * as commonStyles from 'vpu-common/styles';
 import { createClient } from "webdav/web";
+import {classMap} from 'lit-html/directives/class-map.js';
+import {humanFileSize} from "vpu-common/i18next";
+import Tabulator from 'tabulator-tables';
 
 const i18n = createI18nInstance();
 
@@ -18,6 +22,12 @@ export class FilePicker extends ScopedElementsMixin(VPULitElement) {
         this.authUrl = '';
         this.webDavUrl = '';
         this.loginWindow = null;
+        this.isPickerActive = false;
+        this.statusText = "";
+        this.directoryPath = "/";
+        this.directoryContents = [];
+        this.webDavClient = null;
+        this.tabulatorTable = null;
 
         this._onReceiveWindowMessage = this.onReceiveWindowMessage.bind(this);
     }
@@ -36,6 +46,10 @@ export class FilePicker extends ScopedElementsMixin(VPULitElement) {
             lang: { type: String },
             authUrl: { type: String, attribute: "auth-url" },
             webDavUrl: { type: String, attribute: "web-dav-url" },
+            isPickerActive: { type: Boolean, attribute: false },
+            statusText: { type: String, attribute: false },
+            directoryPath: { type: String, attribute: false },
+            directoryContents: { type: Array, attribute: false },
         };
     }
 
@@ -62,15 +76,18 @@ export class FilePicker extends ScopedElementsMixin(VPULitElement) {
         this.updateComplete.then(()=>{
             // see: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
             window.addEventListener('message', this._onReceiveWindowMessage);
+
+            this.tabulatorTable = new Tabulator(this._("#directory-content-table"), {});
         });
     }
 
     openFilePicker() {
+        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");
     }
 
-    async onReceiveWindowMessage(event) {
+    onReceiveWindowMessage(event) {
         const data = event.data;
         console.log("data", data);
 
@@ -80,7 +97,8 @@ export class FilePicker extends ScopedElementsMixin(VPULitElement) {
 
             const apiUrl = this.webDavUrl + "/" + data.loginName;
 
-            const client = createClient(
+            // https://github.com/perry-mitchell/webdav-client/blob/master/API.md#module_WebDAV.createClient
+            this.webDavClient = createClient(
                 apiUrl,
                 {
                     username: data.loginName,
@@ -88,54 +106,101 @@ export class FilePicker extends ScopedElementsMixin(VPULitElement) {
                 }
             );
 
-            const directoryItems = await client.getDirectoryContents("/");
-
-            console.log("directoryItems", directoryItems);
-
-            return;
-
-            fetch(apiUrl, {
-                method: 'PROPFIND',
-                headers: {
-                    'Content-Type': 'text/xml',
-                    'Authorization': 'Basic ' + btoa(data.loginName + ":" + data.token),
-                },
-                data: "<?xml version=\"1.0\"?>" +
-                "<a:propfind xmlns:a=\"DAV:\">" +
-                "<a:prop><a:resourcetype />" +
-                "</a:prop>" +
-                "</a:propfind>"
-            })
-                .then(result => {
-                    console.log("result", result);
-
-                    if (!result.ok) throw result;
-
-                    return result.text();
-                })
-                .then((xml) => {
-                    console.log("xml", xml);
-                }).catch(error => {
-                    console.error("error", error);
-                });
+            this.loadDirectory("");
         }
     }
 
+    /**
+     * Loads the directory from WebDAV
+     *
+     * @param path
+     */
+    loadDirectory(path) {
+        this.statusText = "Loading directory from Nextcloud: " + path;
+        this.directoryPath = path;
+        this.directoryContents = [];
+
+        // https://github.com/perry-mitchell/webdav-client#getdirectorycontents
+        this.webDavClient
+            .getDirectoryContents(path)
+            .then(contents => {
+                console.log("contents", contents);
+                this.statusText = "";
+                this.directoryContents = contents;
+
+                this.tabulatorTable.setData(contents);
+
+                this.isPickerActive = true;
+            }).catch(error => {
+            console.error(error.message);
+            this.statusText = error.message;
+            this.isPickerActive = false;
+        });
+    }
+
     static get styles() {
         // language=css
         return css`
             ${commonStyles.getGeneralCSS()}
             ${commonStyles.getButtonCSS()}
+
+            .block {
+                margin-bottom: 10px;
+            }
         `;
     }
 
+    /**
+     * 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');
+        console.log("tabulatorCss", tabulatorCss);
+
         return html`
-            <div>
+            <link rel="stylesheet" href="${tabulatorCss}">
+            <div class="block">
                 <button class="button"
                         title="${i18n.t('file-picker.open-file-picker')}"
                         @click="${async () => { this.openFilePicker(); } }">${i18n.t('file-picker.open')}</button>
             </div>
+            <div class="block ${classMap({hidden: this.statusText === ""})}">
+                <vpu-mini-spinner style="font-size: 0.7em"></vpu-mini-spinner>
+                ${this.statusText}
+            </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>
+            </div>
         `;
     }
 }