]> git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/window/FileBrowser.js
d138d1be9fd555e882faa7f126946ea6d4303626
[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 case 'v': // virtual
40 icon = 'cube';
41 break;
42 default:
43 icon = 'file-o';
44 break;
45 }
46
47 return `fa fa-${icon}`;
48 },
49 },
50 ],
51 idProperty: 'filepath',
52 });
53
54 Ext.define("Proxmox.window.FileBrowser", {
55 extend: "Ext.window.Window",
56
57 width: 800,
58 height: 600,
59
60 modal: true,
61
62 config: {
63 // the base-URL to get the list of files. required.
64 listURL: '',
65
66 // the base download URL, e.g., something like '/api2/...'
67 downloadURL: '',
68
69 // extra parameters set as proxy paramns and for an actual download request
70 extraParams: {},
71
72 // the file types for which the download button should be enabled
73 downloadableFileTypes: {
74 'h': true, // hardlinks
75 'f': true, // "normal" files
76 'd': true, // directories
77 },
78 },
79
80 controller: {
81 xclass: 'Ext.app.ViewController',
82
83 buildUrl: function(baseurl, params) {
84 let url = new URL(baseurl, window.location.origin);
85 for (const [key, value] of Object.entries(params)) {
86 url.searchParams.append(key, value);
87 }
88
89 return url.href;
90 },
91
92 downloadFile: function() {
93 let me = this;
94 let view = me.getView();
95 let tree = me.lookup('tree');
96 let selection = tree.getSelection();
97 if (!selection || selection.length < 1) return;
98
99 let data = selection[0].data;
100
101 let atag = document.createElement('a');
102
103 atag.download = data.text;
104 let params = { ...view.extraParams };
105 params.filepath = data.filepath;
106 atag.download = data.text;
107 if (data.type === 'd') {
108 atag.download += ".zip";
109 }
110 atag.href = me.buildUrl(view.downloadURL, params);
111 atag.click();
112 },
113
114 fileChanged: function() {
115 let me = this;
116 let view = me.getView();
117 let tree = me.lookup('tree');
118 let selection = tree.getSelection();
119 if (!selection || selection.length < 1) return;
120
121 let data = selection[0].data;
122 let canDownload = view.downloadURL && view.downloadableFileTypes[data.type];
123 me.lookup('downloadBtn').setDisabled(!canDownload);
124 },
125
126 init: function(view) {
127 let me = this;
128 let tree = me.lookup('tree');
129
130 if (!view.listURL) {
131 throw "no list URL given";
132 }
133
134 let store = tree.getStore();
135 let proxy = store.getProxy();
136
137 Proxmox.Utils.monStoreErrors(tree, store, true);
138 proxy.setUrl(view.listURL);
139 proxy.setExtraParams(view.extraParams);
140 store.load(() => {
141 let root = store.getRoot();
142 root.expand(); // always expand invisible root node
143 if (view.archive) {
144 let child = root.findChild('text', view.archive);
145 if (child) {
146 child.expand();
147 setTimeout(function() {
148 tree.setSelection(child);
149 tree.getView().focusRow(child);
150 }, 10);
151 }
152 } else if (root.childNodes.length === 1) {
153 root.firstChild.expand();
154 }
155 });
156 },
157
158 control: {
159 'treepanel': {
160 selectionchange: 'fileChanged',
161 },
162 },
163 },
164
165 layout: 'fit',
166 items: [
167 {
168 xtype: 'treepanel',
169 scrollable: true,
170 rootVisible: false,
171 reference: 'tree',
172 store: {
173 autoLoad: false,
174 model: 'proxmox-file-tree',
175 defaultRootId: '/',
176 nodeParam: 'filepath',
177 sorters: 'text',
178 proxy: {
179 appendId: false,
180 type: 'proxmox',
181 },
182 },
183
184 columns: [
185 {
186 text: gettext('Name'),
187 xtype: 'treecolumn',
188 flex: 1,
189 dataIndex: 'text',
190 renderer: Ext.String.htmlEncode,
191 },
192 {
193 text: gettext('Size'),
194 dataIndex: 'size',
195 renderer: value => value === undefined ? '' : Proxmox.Utils.format_size(value),
196 sorter: {
197 sorterFn: function(a, b) {
198 let asize = a.data.size || 0;
199 let bsize = b.data.size || 0;
200
201 return asize - bsize;
202 },
203 },
204 },
205 {
206 text: gettext('Modified'),
207 dataIndex: 'mtime',
208 minWidth: 200,
209 },
210 {
211 text: gettext('Type'),
212 dataIndex: 'type',
213 renderer: function(value) {
214 switch (value) {
215 case 'b': return gettext('Block Device');
216 case 'c': return gettext('Character Device');
217 case 'd': return gettext('Directory');
218 case 'f': return gettext('File');
219 case 'h': return gettext('Hardlink');
220 case 'l': return gettext('Softlink');
221 case 'p': return gettext('Pipe/Fifo');
222 case 's': return gettext('Socket');
223 case 'v': return gettext('Virtual');
224 default: return Proxmox.Utils.unknownText;
225 }
226 },
227 },
228 ],
229 },
230 ],
231
232 buttons: [
233 {
234 text: gettext('Download'),
235 handler: 'downloadFile',
236 reference: 'downloadBtn',
237 disabled: true,
238 },
239 ],
240 });