]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/window/FileBrowser.js
window: add FileBrowser
[proxmox-widget-toolkit.git] / src / window / FileBrowser.js
1 Ext.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
51 Ext.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;
83 let params = {
84 'backup-id': view['backup-id'],
85 'backup-type': view['backup-type'],
86 'backup-time': view['backup-time'],
87 };
88 params.filepath = data.filepath;
89 atag.download = data.text;
90 if (data.type === 'd') {
91 atag.download += ".zip";
92 }
93 atag.href = me
94 .buildUrl(`/api2/json/admin/datastore/${view.datastore}/pxar-file-download`, params);
95 atag.click();
96 },
97
98 fileChanged: function() {
99 let me = this;
100 let tree = me.lookup('tree');
101 let selection = tree.getSelection();
102 if (!selection || selection.length < 1) return;
103
104 let data = selection[0].data;
105
106 let canDownload = false;
107 switch (data.type) {
108 case 'h':
109 case 'f':
110 canDownload = true;
111 break;
112 case 'd':
113 if (data.depth > 1) {
114 canDownload = true;
115 }
116 break;
117 default: break;
118 }
119
120 me.lookup('downloadBtn').setDisabled(!canDownload);
121 },
122
123 init: function(view) {
124 let me = this;
125 let tree = me.lookup('tree');
126
127 if (!view['backup-id']) {
128 throw "no backup-id given";
129 }
130
131 if (!view['backup-type']) {
132 throw "no backup-id given";
133 }
134
135 if (!view['backup-time']) {
136 throw "no backup-id given";
137 }
138
139 let store = tree.getStore();
140 let proxy = store.getProxy();
141
142 Proxmox.Utils.monStoreErrors(tree, store, true);
143 proxy.setUrl(`/api2/json/admin/datastore/${view.datastore}/catalog`);
144 proxy.setExtraParams({
145 'backup-id': view['backup-id'],
146 'backup-type': view['backup-type'],
147 'backup-time': view['backup-time'],
148 });
149 store.load(() => {
150 let root = store.getRoot();
151 root.expand(); // always expand invisible root node
152 if (view.archive) {
153 let child = root.findChild('text', view.archive);
154 if (child) {
155 child.expand();
156 setTimeout(function() {
157 tree.setSelection(child);
158 tree.getView().focusRow(child);
159 }, 10);
160 }
161 } else if (root.childNodes.length === 1) {
162 root.firstChild.expand();
163 }
164 });
165 },
166
167 control: {
168 'treepanel': {
169 selectionchange: 'fileChanged',
170 },
171 },
172 },
173
174 layout: 'fit',
175 items: [
176 {
177 xtype: 'treepanel',
178 scrollable: true,
179 rootVisible: false,
180 reference: 'tree',
181 store: {
182 autoLoad: false,
183 model: 'proxmox-file-tree',
184 defaultRootId: '/',
185 nodeParam: 'filepath',
186 sorters: 'text',
187 proxy: {
188 appendId: false,
189 type: 'proxmox',
190 },
191 },
192
193 columns: [
194 {
195 text: gettext('Name'),
196 xtype: 'treecolumn',
197 flex: 1,
198 dataIndex: 'text',
199 renderer: Ext.String.htmlEncode,
200 },
201 {
202 text: gettext('Size'),
203 dataIndex: 'size',
204 renderer: value => value === undefined ? '' : Proxmox.Utils.format_size(value),
205 sorter: {
206 sorterFn: function(a, b) {
207 let asize = a.data.size || 0;
208 let bsize = b.data.size || 0;
209
210 return asize - bsize;
211 },
212 },
213 },
214 {
215 text: gettext('Modified'),
216 dataIndex: 'mtime',
217 minWidth: 200,
218 },
219 {
220 text: gettext('Type'),
221 dataIndex: 'type',
222 renderer: function(value) {
223 switch (value) {
224 case 'b': return gettext('Block Device');
225 case 'c': return gettext('Character Device');
226 case 'd': return gettext('Directory');
227 case 'f': return gettext('File');
228 case 'h': return gettext('Hardlink');
229 case 'l': return gettext('Softlink');
230 case 'p': return gettext('Pipe/Fifo');
231 case 's': return gettext('Socket');
232 default: return Proxmox.Utils.unknownText;
233 }
234 },
235 },
236 ],
237 },
238 ],
239
240 buttons: [
241 {
242 text: gettext('Download'),
243 handler: 'downloadFile',
244 reference: 'downloadBtn',
245 disabled: true,
246 },
247 ],
248 });