]> git.proxmox.com Git - proxmox-widget-toolkit.git/blame - src/window/FileBrowser.js
FileBrowser: allow downloading root folder and simplify code
[proxmox-widget-toolkit.git] / src / window / FileBrowser.js
CommitLineData
09195cb6
SR
1Ext.define('proxmox-file-tree', {
2 extend: 'Ext.data.Model',
3
4 fields: ['filepath', 'text', 'type', 'size',
5 {
6 name: 'mtime',
7 type: 'date',
8 dateFormat: 'timestamp',
9 },
10 {
11 name: 'iconCls',
12 calculate: function(data) {
13 let icon = 'file-o';
14 switch (data.type) {
15 case 'b': // block device
16 icon = 'cube';
17 break;
18 case 'c': // char device
19 icon = 'tty';
20 break;
21 case 'd':
22 icon = data.expanded ? 'folder-open-o' : 'folder-o';
23 break;
24 case 'f': //regular file
25 icon = 'file-text-o';
26 break;
27 case 'h': // hardlink
28 icon = 'file-o';
29 break;
30 case 'l': // softlink
31 icon = 'link';
32 break;
33 case 'p': // pipe/fifo
34 icon = 'exchange';
35 break;
36 case 's': // socket
37 icon = 'plug';
38 break;
39 default:
40 icon = 'file-o';
41 break;
42 }
43
44 return `fa fa-${icon}`;
45 },
46 },
47 ],
48 idProperty: 'filepath',
49});
50
51Ext.define("Proxmox.window.FileBrowser", {
52 extend: "Ext.window.Window",
53
54 width: 800,
55 height: 600,
56
57 modal: true,
58
59 controller: {
60 xclass: 'Ext.app.ViewController',
61
62 buildUrl: function(baseurl, params) {
63 let url = new URL(baseurl, window.location.origin);
64 for (const [key, value] of Object.entries(params)) {
65 url.searchParams.append(key, value);
66 }
67
68 return url.href;
69 },
70
71 downloadFile: function() {
72 let me = this;
73 let view = me.getView();
74 let tree = me.lookup('tree');
75 let selection = tree.getSelection();
76 if (!selection || selection.length < 1) return;
77
78 let data = selection[0].data;
79
80 let atag = document.createElement('a');
81
82 atag.download = data.text;
68b29ade 83 let params = { ...view.extraParams };
09195cb6
SR
84 params.filepath = data.filepath;
85 atag.download = data.text;
86 if (data.type === 'd') {
87 atag.download += ".zip";
88 }
68b29ade 89 atag.href = me.buildUrl(view.downloadUrl, params);
09195cb6
SR
90 atag.click();
91 },
92
93 fileChanged: function() {
94 let me = this;
68b29ade 95 let view = me.getView();
09195cb6
SR
96 let tree = me.lookup('tree');
97 let selection = tree.getSelection();
98 if (!selection || selection.length < 1) return;
99
100 let data = selection[0].data;
2a778ef9 101 let canDownload = view.downloadUrl && ['h', 'f', 'd'].indexOf(data.type) !== -1;
09195cb6
SR
102 me.lookup('downloadBtn').setDisabled(!canDownload);
103 },
104
105 init: function(view) {
106 let me = this;
107 let tree = me.lookup('tree');
108
68b29ade
SR
109 if (!view.listUrl) {
110 throw "no list URL given";
09195cb6
SR
111 }
112
113 let store = tree.getStore();
114 let proxy = store.getProxy();
115
116 Proxmox.Utils.monStoreErrors(tree, store, true);
68b29ade
SR
117 proxy.setUrl(view.listUrl);
118 proxy.setExtraParams(view.extraParams);
09195cb6
SR
119 store.load(() => {
120 let root = store.getRoot();
121 root.expand(); // always expand invisible root node
122 if (view.archive) {
123 let child = root.findChild('text', view.archive);
124 if (child) {
125 child.expand();
126 setTimeout(function() {
127 tree.setSelection(child);
128 tree.getView().focusRow(child);
129 }, 10);
130 }
131 } else if (root.childNodes.length === 1) {
132 root.firstChild.expand();
133 }
134 });
135 },
136
137 control: {
138 'treepanel': {
139 selectionchange: 'fileChanged',
140 },
141 },
142 },
143
144 layout: 'fit',
145 items: [
146 {
147 xtype: 'treepanel',
148 scrollable: true,
149 rootVisible: false,
150 reference: 'tree',
151 store: {
152 autoLoad: false,
153 model: 'proxmox-file-tree',
154 defaultRootId: '/',
155 nodeParam: 'filepath',
156 sorters: 'text',
157 proxy: {
158 appendId: false,
159 type: 'proxmox',
160 },
161 },
162
163 columns: [
164 {
165 text: gettext('Name'),
166 xtype: 'treecolumn',
167 flex: 1,
168 dataIndex: 'text',
169 renderer: Ext.String.htmlEncode,
170 },
171 {
172 text: gettext('Size'),
173 dataIndex: 'size',
174 renderer: value => value === undefined ? '' : Proxmox.Utils.format_size(value),
175 sorter: {
176 sorterFn: function(a, b) {
177 let asize = a.data.size || 0;
178 let bsize = b.data.size || 0;
179
180 return asize - bsize;
181 },
182 },
183 },
184 {
185 text: gettext('Modified'),
186 dataIndex: 'mtime',
187 minWidth: 200,
188 },
189 {
190 text: gettext('Type'),
191 dataIndex: 'type',
192 renderer: function(value) {
193 switch (value) {
194 case 'b': return gettext('Block Device');
195 case 'c': return gettext('Character Device');
196 case 'd': return gettext('Directory');
197 case 'f': return gettext('File');
198 case 'h': return gettext('Hardlink');
199 case 'l': return gettext('Softlink');
200 case 'p': return gettext('Pipe/Fifo');
201 case 's': return gettext('Socket');
202 default: return Proxmox.Utils.unknownText;
203 }
204 },
205 },
206 ],
207 },
208 ],
209
210 buttons: [
211 {
212 text: gettext('Download'),
213 handler: 'downloadFile',
214 reference: 'downloadBtn',
215 disabled: true,
216 },
217 ],
218});