public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Stefan Reiter <s.reiter@proxmox.com>
To: pve-devel@lists.proxmox.com, pbs-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH proxmox-widget-toolkit 1/3] window: add FileBrowser
Date: Thu,  1 Apr 2021 17:34:42 +0200	[thread overview]
Message-ID: <20210401153444.8711-2-s.reiter@proxmox.com> (raw)
In-Reply-To: <20210401153444.8711-1-s.reiter@proxmox.com>

from proxmox-backup, only names changed

Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---
 src/Makefile              |   1 +
 src/window/FileBrowser.js | 248 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 249 insertions(+)
 create mode 100644 src/window/FileBrowser.js

diff --git a/src/Makefile b/src/Makefile
index 44c11ea..f97c74a 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -64,6 +64,7 @@ JSSRC=					\
 	window/ACMEAccount.js		\
 	window/ACMEPluginEdit.js	\
 	window/ACMEDomains.js		\
+	window/FileBrowser.js		\
 	node/APT.js			\
 	node/NetworkEdit.js		\
 	node/NetworkView.js		\
diff --git a/src/window/FileBrowser.js b/src/window/FileBrowser.js
new file mode 100644
index 0000000..82fd1b2
--- /dev/null
+++ b/src/window/FileBrowser.js
@@ -0,0 +1,248 @@
+Ext.define('proxmox-file-tree', {
+    extend: 'Ext.data.Model',
+
+    fields: ['filepath', 'text', 'type', 'size',
+	{
+	    name: 'mtime',
+	    type: 'date',
+	    dateFormat: 'timestamp',
+	},
+	{
+	    name: 'iconCls',
+	    calculate: function(data) {
+		let icon = 'file-o';
+		switch (data.type) {
+		    case 'b': // block device
+			icon = 'cube';
+			break;
+		    case 'c': // char device
+			icon = 'tty';
+			break;
+		    case 'd':
+			icon = data.expanded ? 'folder-open-o' : 'folder-o';
+			break;
+		    case 'f': //regular file
+			icon = 'file-text-o';
+			break;
+		    case 'h': // hardlink
+			icon = 'file-o';
+			break;
+		    case 'l': // softlink
+			icon = 'link';
+			break;
+		    case 'p': // pipe/fifo
+			icon = 'exchange';
+			break;
+		    case 's': // socket
+			icon = 'plug';
+			break;
+		    default:
+			icon = 'file-o';
+			break;
+		}
+
+		return `fa fa-${icon}`;
+	    },
+	},
+    ],
+    idProperty: 'filepath',
+});
+
+Ext.define("Proxmox.window.FileBrowser", {
+    extend: "Ext.window.Window",
+
+    width: 800,
+    height: 600,
+
+    modal: true,
+
+    controller: {
+	xclass: 'Ext.app.ViewController',
+
+	buildUrl: function(baseurl, params) {
+	    let url = new URL(baseurl, window.location.origin);
+	    for (const [key, value] of Object.entries(params)) {
+		url.searchParams.append(key, value);
+	    }
+
+	    return url.href;
+	},
+
+	downloadFile: function() {
+	    let me = this;
+	    let view = me.getView();
+	    let tree = me.lookup('tree');
+	    let selection = tree.getSelection();
+	    if (!selection || selection.length < 1) return;
+
+	    let data = selection[0].data;
+
+	    let atag = document.createElement('a');
+
+	    atag.download = data.text;
+	    let params = {
+		'backup-id': view['backup-id'],
+		'backup-type': view['backup-type'],
+		'backup-time': view['backup-time'],
+	    };
+	    params.filepath = data.filepath;
+	    atag.download = data.text;
+	    if (data.type === 'd') {
+		atag.download += ".zip";
+	    }
+	    atag.href = me
+	        .buildUrl(`/api2/json/admin/datastore/${view.datastore}/pxar-file-download`, params);
+	    atag.click();
+	},
+
+	fileChanged: function() {
+	    let me = this;
+	    let tree = me.lookup('tree');
+	    let selection = tree.getSelection();
+	    if (!selection || selection.length < 1) return;
+
+	    let data = selection[0].data;
+
+	    let canDownload = false;
+	    switch (data.type) {
+		case 'h':
+		case 'f':
+		    canDownload = true;
+		    break;
+		case 'd':
+		    if (data.depth > 1) {
+			canDownload = true;
+		    }
+		    break;
+		default: break;
+	    }
+
+	    me.lookup('downloadBtn').setDisabled(!canDownload);
+	},
+
+	init: function(view) {
+	    let me = this;
+	    let tree = me.lookup('tree');
+
+	    if (!view['backup-id']) {
+		throw "no backup-id given";
+	    }
+
+	    if (!view['backup-type']) {
+		throw "no backup-id given";
+	    }
+
+	    if (!view['backup-time']) {
+		throw "no backup-id given";
+	    }
+
+	    let store = tree.getStore();
+	    let proxy = store.getProxy();
+
+	    Proxmox.Utils.monStoreErrors(tree, store, true);
+	    proxy.setUrl(`/api2/json/admin/datastore/${view.datastore}/catalog`);
+	    proxy.setExtraParams({
+		'backup-id': view['backup-id'],
+		'backup-type': view['backup-type'],
+		'backup-time': view['backup-time'],
+	    });
+	    store.load(() => {
+		let root = store.getRoot();
+		root.expand(); // always expand invisible root node
+		if (view.archive) {
+		    let child = root.findChild('text', view.archive);
+		    if (child) {
+			child.expand();
+			setTimeout(function() {
+			    tree.setSelection(child);
+			    tree.getView().focusRow(child);
+			}, 10);
+		    }
+		} else if (root.childNodes.length === 1) {
+		    root.firstChild.expand();
+		}
+	    });
+	},
+
+	control: {
+	    'treepanel': {
+		selectionchange: 'fileChanged',
+	    },
+	},
+    },
+
+    layout: 'fit',
+    items: [
+	{
+	    xtype: 'treepanel',
+	    scrollable: true,
+	    rootVisible: false,
+	    reference: 'tree',
+	    store: {
+		autoLoad: false,
+		model: 'proxmox-file-tree',
+		defaultRootId: '/',
+		nodeParam: 'filepath',
+		sorters: 'text',
+		proxy: {
+		    appendId: false,
+		    type: 'proxmox',
+		},
+	    },
+
+	    columns: [
+		{
+		    text: gettext('Name'),
+		    xtype: 'treecolumn',
+		    flex: 1,
+		    dataIndex: 'text',
+		    renderer: Ext.String.htmlEncode,
+		},
+		{
+		    text: gettext('Size'),
+		    dataIndex: 'size',
+		    renderer: value => value === undefined ? '' : Proxmox.Utils.format_size(value),
+		    sorter: {
+			sorterFn: function(a, b) {
+			    let asize = a.data.size || 0;
+			    let bsize = b.data.size || 0;
+
+			    return asize - bsize;
+			},
+		    },
+		},
+		{
+		    text: gettext('Modified'),
+		    dataIndex: 'mtime',
+		    minWidth: 200,
+		},
+		{
+		    text: gettext('Type'),
+		    dataIndex: 'type',
+		    renderer: function(value) {
+			switch (value) {
+			    case 'b': return gettext('Block Device');
+			    case 'c': return gettext('Character Device');
+			    case 'd': return gettext('Directory');
+			    case 'f': return gettext('File');
+			    case 'h': return gettext('Hardlink');
+			    case 'l': return gettext('Softlink');
+			    case 'p': return gettext('Pipe/Fifo');
+			    case 's': return gettext('Socket');
+			    default: return Proxmox.Utils.unknownText;
+			}
+		    },
+		},
+	    ],
+	},
+    ],
+
+    buttons: [
+	{
+	    text: gettext('Download'),
+	    handler: 'downloadFile',
+	    reference: 'downloadBtn',
+	    disabled: true,
+	},
+    ],
+});
-- 
2.20.1





  reply	other threads:[~2021-04-01 15:34 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-01 15:34 [pve-devel] [PATCH 0/3] Move FileBrowser to widget-toolkit Stefan Reiter
2021-04-01 15:34 ` Stefan Reiter [this message]
2021-04-13  6:00   ` [pve-devel] applied: [pbs-devel] [PATCH proxmox-widget-toolkit 1/3] window: add FileBrowser Thomas Lamprecht
2021-04-01 15:34 ` [pve-devel] [PATCH proxmox-widget-toolkit 2/3] FileBrowser: remove PBS dependencies Stefan Reiter
2021-04-13  6:00   ` [pve-devel] applied: [pbs-devel] " Thomas Lamprecht
2021-04-01 15:34 ` [pve-devel] [PATCH proxmox-backup 3/3] use FileBrowser from proxmox-widget-toolkit Stefan Reiter
2021-04-13  7:15   ` [pve-devel] applied: [pbs-devel] " Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210401153444.8711-2-s.reiter@proxmox.com \
    --to=s.reiter@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal