]>
git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/window/FileBrowser.js
1 Ext
.define('proxmox-file-tree', {
2 extend
: 'Ext.data.Model',
4 fields
: ['filepath', 'text', 'type', 'size',
8 if (data
.size
=== undefined) {
10 } else if (data
.type
=== 'd') {
11 let fs
= data
.size
=== 1 ? gettext('{0} item') : gettext('{0} items');
12 return Ext
.String
.format(fs
, data
.size
);
15 return Proxmox
.Utils
.format_size(data
.size
);
21 dateFormat
: 'timestamp',
25 calculate: function(data
) {
28 case 'b': // block device
31 case 'c': // char device
35 icon
= data
.expanded
? 'folder-open-o' : 'folder-o';
37 case 'f': //regular file
46 case 'p': // pipe/fifo
60 return `fa fa-${icon}`;
64 idProperty
: 'filepath',
67 Ext
.define("Proxmox.window.FileBrowser", {
68 extend
: "Ext.window.Window",
76 // the base-URL to get the list of files. required.
79 // the base download URL, e.g., something like '/api2/...'
82 // extra parameters set as proxy paramns and for an actual download request
85 // the file types for which the download button should be enabled
86 downloadableFileTypes
: {
87 'h': true, // hardlinks
88 'f': true, // "normal" files
89 'd': true, // directories
92 // enable tar download, this will add a menu to the
93 // "Download" button when the selection can be downloaded as
97 // prefix to prepend to downloaded file names
102 xclass
: 'Ext.app.ViewController',
104 buildUrl: function(baseurl
, params
) {
105 let url
= new URL(baseurl
, window
.location
.origin
);
106 for (const [key
, value
] of Object
.entries(params
)) {
107 url
.searchParams
.append(key
, value
);
113 downloadTar: function() {
114 this.downloadFile(true);
117 downloadZip: function() {
118 this.downloadFile(false);
121 downloadFile: function(tar
) {
123 let view
= me
.getView();
124 let tree
= me
.lookup('tree');
125 let selection
= tree
.getSelection();
126 if (!selection
|| selection
.length
< 1) return;
128 let data
= selection
[0].data
;
130 let params
= { ...view
.extraParams
};
131 params
.filepath
= data
.filepath
;
133 let atag
= document
.createElement('a');
134 atag
.download
= view
.downloadPrefix
+ data
.text
;
135 if (data
.type
=== 'd') {
138 atag
.download
+= ".tar.zst";
140 atag
.download
+= ".zip";
143 atag
.href
= me
.buildUrl(view
.downloadURL
, params
);
147 fileChanged: function() {
149 let view
= me
.getView();
150 let tree
= me
.lookup('tree');
151 let selection
= tree
.getSelection();
152 if (!selection
|| selection
.length
< 1) return;
154 let data
= selection
[0].data
;
155 let st
= Ext
.String
.format(gettext('Selected "{0}"'), atob(data
.filepath
));
156 view
.lookup('selectText').setText(st
);
158 let canDownload
= view
.downloadURL
&& view
.downloadableFileTypes
[data
.type
];
159 let enableMenu
= view
.enableTar
&& data
.type
=== 'd';
161 let downloadBtn
= view
.lookup('downloadBtn');
162 downloadBtn
.setDisabled(!canDownload
|| enableMenu
);
163 downloadBtn
.setHidden(!canDownload
|| enableMenu
);
165 let menuBtn
= view
.lookup('menuBtn');
166 menuBtn
.setDisabled(!canDownload
|| !enableMenu
);
167 menuBtn
.setHidden(!canDownload
|| !enableMenu
);
170 errorHandler: function(error
, msg
) {
172 if (error
?.status
=== 503) {
175 me
.lookup('downloadBtn').setDisabled(true);
176 me
.lookup('menuBtn').setDisabled(true);
177 if (me
.initialLoadDone
) {
178 Ext
.Msg
.alert(gettext('Error'), msg
);
184 init: function(view
) {
186 let tree
= me
.lookup('tree');
189 throw "no list URL given";
192 let store
= tree
.getStore();
193 let proxy
= store
.getProxy();
195 let errorCallback
= (error
, msg
) => me
.errorHandler(error
, msg
);
196 proxy
.setUrl(view
.listURL
);
197 proxy
.setTimeout(60*1000);
198 proxy
.setExtraParams(view
.extraParams
);
200 tree
.mon(store
, 'beforeload', () => {
201 Proxmox
.Utils
.setErrorMask(tree
, true);
203 tree
.mon(store
, 'load', (treestore
, rec
, success
, operation
, node
) => {
205 Proxmox
.Utils
.setErrorMask(tree
, false);
208 if (!node
.loadCount
) {
209 node
.loadCount
= 0; // ensure its numeric
211 // trigger a reload if we got a 503 answer from the proxy
212 if (operation
?.error
?.status
=== 503 && node
.loadCount
< 10) {
219 let error
= operation
.getError();
220 let msg
= Proxmox
.Utils
.getResponseErrorMessage(error
);
221 if (!errorCallback(error
, msg
)) {
222 Proxmox
.Utils
.setErrorMask(tree
, msg
);
224 Proxmox
.Utils
.setErrorMask(tree
, false);
227 store
.load((rec
, op
, success
) => {
228 let root
= store
.getRoot();
229 root
.expand(); // always expand invisible root node
230 if (view
.archive
=== 'all') {
231 root
.expandChildren(false);
232 } else if (view
.archive
) {
233 let child
= root
.findChild('text', view
.archive
);
236 setTimeout(function() {
237 tree
.setSelection(child
);
238 tree
.getView().focusRow(child
);
241 } else if (root
.childNodes
.length
=== 1) {
242 root
.firstChild
.expand();
244 me
.initialLoadDone
= success
;
250 selectionchange
: 'fileChanged',
264 model
: 'proxmox-file-tree',
266 nodeParam
: 'filepath',
280 text
: gettext('Name'),
284 renderer
: Ext
.String
.htmlEncode
,
287 text
: gettext('Size'),
288 dataIndex
: 'sizedisplay',
290 sorterFn: function(a
, b
) {
291 if (a
.data
.type
=== 'd' && b
.data
.type
!== 'd') {
293 } else if (a
.data
.type
!== 'd' && b
.data
.type
=== 'd') {
297 let asize
= a
.data
.size
|| 0;
298 let bsize
= b
.data
.size
|| 0;
300 return asize
- bsize
;
305 text
: gettext('Modified'),
310 text
: gettext('Type'),
312 renderer: function(value
) {
314 case 'b': return gettext('Block Device');
315 case 'c': return gettext('Character Device');
316 case 'd': return gettext('Directory');
317 case 'f': return gettext('File');
318 case 'h': return gettext('Hardlink');
319 case 'l': return gettext('Softlink');
320 case 'p': return gettext('Pipe/Fifo');
321 case 's': return gettext('Socket');
322 case 'v': return gettext('Virtual');
323 default: return Proxmox
.Utils
.unknownText
;
335 reference
: 'selectText',
338 text
: gettext('Download'),
340 handler
: 'downloadZip',
341 reference
: 'downloadBtn',
346 text
: gettext('Download as'),
348 reference
: 'menuBtn',
352 iconCls
: 'fa fa-fw fa-file-zip-o',
353 text
: gettext('.zip'),
354 handler
: 'downloadZip',
355 reference
: 'downloadZip',
358 iconCls
: 'fa fa-fw fa-archive',
359 text
: gettext('.tar.zst'),
360 handler
: 'downloadTar',
361 reference
: 'downloadTar',