]> git.proxmox.com Git - proxmox-backup.git/blob - www/window/FileBrowser.js
api2/admin/datastore: accept "/" as path for root
[proxmox-backup.git] / www / window / FileBrowser.js
1 Ext.define('pbs-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("PBS.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 if (!view.datastore) {
140 throw "no datastore given";
141 }
142
143 let store = tree.getStore();
144 let proxy = store.getProxy();
145
146 Proxmox.Utils.monStoreErrors(tree, store, true);
147 proxy.setUrl(`/api2/json/admin/datastore/${view.datastore}/catalog`);
148 proxy.setExtraParams({
149 'backup-id': view['backup-id'],
150 'backup-type': view['backup-type'],
151 'backup-time': view['backup-time'],
152 });
153 store.load(() => {
154 let root = store.getRoot();
155 root.expand(); // always expand invisible root node
156 if (view.archive) {
157 let child = root.findChild('text', view.archive);
158 if (child) {
159 child.expand();
160 setTimeout(function() {
161 tree.setSelection(child);
162 tree.getView().focusRow(child);
163 }, 10);
164 }
165 } else if (root.childNodes.length === 1) {
166 root.firstChild.expand();
167 }
168 });
169 },
170
171 control: {
172 'treepanel': {
173 selectionchange: 'fileChanged',
174 },
175 },
176 },
177
178 layout: 'fit',
179 items: [
180 {
181 xtype: 'treepanel',
182 scrollable: true,
183 rootVisible: false,
184 reference: 'tree',
185 store: {
186 autoLoad: false,
187 model: 'pbs-file-tree',
188 defaultRootId: '/',
189 nodeParam: 'filepath',
190 sorters: 'text',
191 proxy: {
192 appendId: false,
193 type: 'proxmox',
194 },
195 },
196
197 columns: [
198 {
199 text: gettext('Name'),
200 xtype: 'treecolumn',
201 flex: 1,
202 dataIndex: 'text',
203 renderer: Ext.String.htmlEncode,
204 },
205 {
206 text: gettext('Size'),
207 dataIndex: 'size',
208 renderer: value => value === undefined ? '' : Proxmox.Utils.format_size(value),
209 sorter: {
210 sorterFn: function(a, b) {
211 let asize = a.data.size || 0;
212 let bsize = b.data.size || 0;
213
214 return asize - bsize;
215 },
216 },
217 },
218 {
219 text: gettext('Modified'),
220 dataIndex: 'mtime',
221 minWidth: 200,
222 },
223 {
224 text: gettext('Type'),
225 dataIndex: 'type',
226 renderer: function(value) {
227 switch (value) {
228 case 'b': return gettext('Block Device');
229 case 'c': return gettext('Character Device');
230 case 'd': return gettext('Directory');
231 case 'f': return gettext('File');
232 case 'h': return gettext('Hardlink');
233 case 'l': return gettext('Softlink');
234 case 'p': return gettext('Pipe/Fifo');
235 case 's': return gettext('Socket');
236 default: return Proxmox.Utils.unknownText;
237 }
238 },
239 },
240 ],
241 },
242 ],
243
244 buttons: [
245 {
246 text: gettext('Download'),
247 handler: 'downloadFile',
248 reference: 'downloadBtn',
249 disabled: true,
250 },
251 ],
252 });