]>
git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/window/FileBrowser.js
1 Ext
.define('proxmox-file-tree', {
2 extend
: 'Ext.data.Model',
5 'filepath', 'text', 'type', 'size',
9 if (data
.size
=== undefined) {
11 } else if (data
.type
=== 'd') {
12 let fs
= data
.size
=== 1 ? gettext('{0} item') : gettext('{0} items');
13 return Ext
.String
.format(fs
, data
.size
);
16 return Proxmox
.Utils
.format_size(data
.size
);
22 dateFormat
: 'timestamp',
26 calculate: function(data
) {
27 let icon
= Proxmox
.Schema
.pxarFileTypes
[data
.type
]?.icon
?? 'file-o';
28 if (data
.expanded
&& data
.type
=== 'd') {
29 icon
= 'folder-open-o';
31 return `fa fa-${icon}`;
35 idProperty
: 'filepath',
38 Ext
.define("Proxmox.window.FileBrowser", {
39 extend
: "Ext.window.Window",
47 // the base-URL to get the list of files. required.
50 // the base download URL, e.g., something like '/api2/...'
53 // extra parameters set as proxy paramns and for an actual download request
56 // the file types for which the download button should be enabled
57 downloadableFileTypes
: {
58 'h': true, // hardlinks
59 'f': true, // "normal" files
60 'd': true, // directories
63 // enable tar download, this will add a menu to the "Download" button when the selection
64 // can be downloaded as `.tar` files
67 // prefix to prepend to downloaded file names
72 xclass
: 'Ext.app.ViewController',
74 buildUrl: function(baseurl
, params
) {
75 let url
= new URL(baseurl
, window
.location
.origin
);
76 for (const [key
, value
] of Object
.entries(params
)) {
77 url
.searchParams
.append(key
, value
);
83 downloadTar: function() {
84 this.downloadFile(true);
87 downloadZip: function() {
88 this.downloadFile(false);
91 downloadFile: function(tar
) {
93 let view
= me
.getView();
94 let tree
= me
.lookup('tree');
95 let selection
= tree
.getSelection();
96 if (!selection
|| selection
.length
< 1) return;
98 let data
= selection
[0].data
;
100 let params
= { ...view
.extraParams
};
101 params
.filepath
= data
.filepath
;
103 let atag
= document
.createElement('a');
104 atag
.download
= view
.downloadPrefix
+ data
.text
;
105 if (data
.type
=== 'd') {
108 atag
.download
+= ".tar.zst";
110 atag
.download
+= ".zip";
113 atag
.href
= me
.buildUrl(view
.downloadURL
, params
);
117 fileChanged: function() {
119 let view
= me
.getView();
120 let tree
= me
.lookup('tree');
121 let selection
= tree
.getSelection();
122 if (!selection
|| selection
.length
< 1) return;
124 let data
= selection
[0].data
;
125 let st
= Ext
.String
.format(gettext('Selected "{0}"'), atob(data
.filepath
));
126 view
.lookup('selectText').setText(st
);
128 let canDownload
= view
.downloadURL
&& view
.downloadableFileTypes
[data
.type
];
129 let enableMenu
= view
.enableTar
&& data
.type
=== 'd';
131 let downloadBtn
= view
.lookup('downloadBtn');
132 downloadBtn
.setDisabled(!canDownload
|| enableMenu
);
133 downloadBtn
.setHidden(canDownload
&& enableMenu
);
134 let typeLabel
= Proxmox
.Schema
.pxarFileTypes
[data
.type
]?.label
?? Proxmox
.Utils
.unknownText
;
135 let ttip
= Ext
.String
.format(
136 gettext('File of type {0} cannot be downloaded directly, download a parent directory instead.'),
139 if (!canDownload
) { // ensure tooltip gets shown
140 downloadBtn
.setStyle({ pointerEvents
: 'all' });
142 downloadBtn
.setTooltip(canDownload
? null : ttip
);
144 let menuBtn
= view
.lookup('menuBtn');
145 menuBtn
.setDisabled(!canDownload
|| !enableMenu
);
146 menuBtn
.setHidden(!canDownload
|| !enableMenu
);
149 errorHandler: function(error
, msg
) {
151 if (error
?.status
=== 503) {
154 me
.lookup('downloadBtn').setDisabled(true);
155 me
.lookup('menuBtn').setDisabled(true);
156 if (me
.initialLoadDone
) {
157 Ext
.Msg
.alert(gettext('Error'), msg
);
163 init: function(view
) {
165 let tree
= me
.lookup('tree');
168 throw "no list URL given";
171 let store
= tree
.getStore();
172 let proxy
= store
.getProxy();
174 let errorCallback
= (error
, msg
) => me
.errorHandler(error
, msg
);
175 proxy
.setUrl(view
.listURL
);
176 proxy
.setTimeout(60*1000);
177 proxy
.setExtraParams(view
.extraParams
);
179 tree
.mon(store
, 'beforeload', () => {
180 Proxmox
.Utils
.setErrorMask(tree
, true);
182 tree
.mon(store
, 'load', (treestore
, rec
, success
, operation
, node
) => {
184 Proxmox
.Utils
.setErrorMask(tree
, false);
187 if (!node
.loadCount
) {
188 node
.loadCount
= 0; // ensure its numeric
190 // trigger a reload if we got a 503 answer from the proxy
191 if (operation
?.error
?.status
=== 503 && node
.loadCount
< 10) {
198 let error
= operation
.getError();
199 let msg
= Proxmox
.Utils
.getResponseErrorMessage(error
);
200 if (!errorCallback(error
, msg
)) {
201 Proxmox
.Utils
.setErrorMask(tree
, msg
);
203 Proxmox
.Utils
.setErrorMask(tree
, false);
206 store
.load((rec
, op
, success
) => {
207 let root
= store
.getRoot();
208 root
.expand(); // always expand invisible root node
209 if (view
.archive
=== 'all') {
210 root
.expandChildren(false);
211 } else if (view
.archive
) {
212 let child
= root
.findChild('text', view
.archive
);
215 setTimeout(function() {
216 tree
.setSelection(child
);
217 tree
.getView().focusRow(child
);
220 } else if (root
.childNodes
.length
=== 1) {
221 root
.firstChild
.expand();
223 me
.initialLoadDone
= success
;
229 selectionchange
: 'fileChanged',
243 model
: 'proxmox-file-tree',
245 nodeParam
: 'filepath',
259 text
: gettext('Name'),
263 renderer
: Ext
.String
.htmlEncode
,
266 text
: gettext('Size'),
267 dataIndex
: 'sizedisplay',
270 sorterFn: function(a
, b
) {
271 if (a
.data
.type
=== 'd' && b
.data
.type
!== 'd') {
273 } else if (a
.data
.type
!== 'd' && b
.data
.type
=== 'd') {
277 let asize
= a
.data
.size
|| 0;
278 let bsize
= b
.data
.size
|| 0;
280 return asize
- bsize
;
285 text
: gettext('Modified'),
290 text
: gettext('Type'),
292 renderer
: (v
) => Proxmox
.Schema
.pxarFileTypes
[v
]?.label
?? Proxmox
.Utils
.unknownText
,
302 reference
: 'selectText',
305 text
: gettext('Download'),
307 handler
: 'downloadZip',
308 reference
: 'downloadBtn',
313 text
: gettext('Download as'),
315 reference
: 'menuBtn',
319 iconCls
: 'fa fa-fw fa-file-zip-o',
320 text
: gettext('.zip'),
321 handler
: 'downloadZip',
322 reference
: 'downloadZip',
325 iconCls
: 'fa fa-fw fa-archive',
326 text
: gettext('.tar.zst'),
327 handler
: 'downloadTar',
328 reference
: 'downloadTar',