]> git.proxmox.com Git - pve-manager.git/blobdiff - www/manager6/window/UploadToStorage.js
ui: schedule sim: denote if any simulation was done via empty text
[pve-manager.git] / www / manager6 / window / UploadToStorage.js
index 3c35020a73fc45b3823a0c3043d66e96cd1a8ab0..3c5bba8881b63f66d306c4c1004257b15da97a0f 100644 (file)
 Ext.define('PVE.window.UploadToStorage', {
     extend: 'Ext.window.Window',
     alias: 'widget.pveStorageUpload',
+    mixins: ['Proxmox.Mixin.CBind'],
 
     resizable: false,
-
     modal: true,
 
-    initComponent: function() {
-        var me = this;
+    title: gettext('Upload'),
 
-       if (!me.nodename) {
-           throw "no node name specified";
-       }
-       if (!me.storage) {
-           throw "no storage ID specified";
-       }
+    acceptedExtensions: {
+       iso: ['.img', '.iso'],
+       vztmpl: ['.tar.gz', '.tar.xz', '.tar.zst'],
+    },
 
-       let baseurl = `/nodes/${me.nodename}/storage/${me.storage}/upload`;
+    cbindData: function(initialConfig) {
+       const me = this;
+       const ext = me.acceptedExtensions[me.content] || [];
 
-       let pbar = Ext.create('Ext.ProgressBar', {
-            text: 'Ready',
-           hidden: true,
-       });
+       me.url = `/nodes/${me.nodename}/storage/${me.storage}/upload`;
 
-       let acceptedExtensions = {
-           iso: ".img, .iso",
-           vztmpl: ".tar.gz, .tar.xz",
+       return {
+           extensions: ext.join(', '),
+           filenameRegex: RegExp('^.*(?:' + ext.join('|').replaceAll('.', '\\.') + ')$', 'i'),
        };
+    },
 
-       let defaultContent = me.contents[0] || '';
-
-       let fileField = Ext.create('Ext.form.field.File', {
-           name: 'filename',
-           buttonText: gettext('Select File...'),
-           allowBlank: false,
-           setAccept: function(content) {
-               let acceptString = acceptedExtensions[content] || '';
-               this.fileInputEl.set({
-                   accept: acceptString,
-               });
-           },
-           listeners: {
-               afterrender: function(cmp) {
-                   cmp.setAccept(defaultContent);
-               },
-           },
-       });
+    viewModel: {
+       data: {
+           size: '-',
+           mimetype: '-',
+           filename: '',
+       },
+    },
+
+    controller: {
+       submit: function(button) {
+           const view = this.getView();
+           const form = this.lookup('formPanel').getForm();
+           const abortBtn = this.lookup('abortBtn');
+           const pbar = this.lookup('progressBar');
+
+           const updateProgress = function(per, bytes) {
+               let text = (per * 100).toFixed(2) + '%';
+               if (bytes) {
+                   text += " (" + Proxmox.Utils.format_size(bytes) + ')';
+               }
+               pbar.updateProgress(per, text);
+           };
+
+           const fd = new FormData();
+
+           button.setDisabled(true);
+           abortBtn.setDisabled(false);
+
+           fd.append("content", view.content);
+
+           const fileField = form.findField('file');
+           const file = fileField.fileInputEl.dom.files[0];
+           fileField.setDisabled(true);
+
+           const filenameField = form.findField('filename');
+           const filename = filenameField.getValue();
+           filenameField.setDisabled(true);
+
+           const algorithmField = form.findField('checksum-algorithm');
+           algorithmField.setDisabled(true);
+           if (algorithmField.getValue() !== '__default__') {
+               fd.append("checksum-algorithm", algorithmField.getValue());
+
+               const checksumField = form.findField('checksum');
+               fd.append("checksum", checksumField.getValue()?.trim());
+               checksumField.setDisabled(true);
+           }
 
-       me.formPanel = Ext.create('Ext.form.Panel', {
+           fd.append("filename", file, filename);
+
+           pbar.setVisible(true);
+           updateProgress(0);
+
+           const xhr = new XMLHttpRequest();
+           view.xhr = xhr;
+
+           xhr.addEventListener("load", function(e) {
+               if (xhr.status === 200) {
+                   view.hide();
+
+                   const result = JSON.parse(xhr.response);
+                   const upid = result.data;
+                   Ext.create('Proxmox.window.TaskViewer', {
+                       autoShow: true,
+                       upid: upid,
+                       taskDone: view.taskDone,
+                       listeners: {
+                           destroy: function() {
+                               view.close();
+                           },
+                       },
+                   });
+
+                   return;
+               }
+               const err = Ext.htmlEncode(xhr.statusText);
+               let msg = `${gettext('Error')} ${xhr.status.toString()}: ${err}`;
+               if (xhr.responseText !== "") {
+                   const result = Ext.decode(xhr.responseText);
+                   result.message = msg;
+                   msg = Proxmox.Utils.extractRequestError(result, true);
+               }
+               Ext.Msg.alert(gettext('Error'), msg, btn => view.close());
+           }, false);
+
+           xhr.addEventListener("error", function(e) {
+               const err = e.target.status.toString();
+               const msg = `Error '${err}' occurred while receiving the document.`;
+               Ext.Msg.alert(gettext('Error'), msg, btn => view.close());
+           });
+
+           xhr.upload.addEventListener("progress", function(evt) {
+               if (evt.lengthComputable) {
+                   const percentComplete = evt.loaded / evt.total;
+                   updateProgress(percentComplete, evt.loaded);
+               }
+           }, false);
+
+           xhr.open("POST", `/api2/json${view.url}`, true);
+           xhr.send(fd);
+       },
+
+       validitychange: function(f, valid) {
+           const submitBtn = this.lookup('submitBtn');
+           submitBtn.setDisabled(!valid);
+       },
+
+       fileChange: function(input) {
+           const vm = this.getViewModel();
+           const name = input.value.replace(/^.*(\/|\\)/, '');
+           const fileInput = input.fileInputEl.dom;
+           vm.set('filename', name);
+           vm.set('size', (fileInput.files[0] && Proxmox.Utils.format_size(fileInput.files[0].size)) || '-');
+           vm.set('mimetype', (fileInput.files[0] && fileInput.files[0].type) || '-');
+       },
+
+       hashChange: function(field, value) {
+           const checksum = this.lookup('downloadUrlChecksum');
+           if (value === '__default__') {
+               checksum.setDisabled(true);
+               checksum.setValue("");
+           } else {
+               checksum.setDisabled(false);
+           }
+       },
+    },
+
+    items: [
+       {
+           xtype: 'form',
+           reference: 'formPanel',
            method: 'POST',
            waitMsgTarget: true,
            bodyPadding: 10,
            border: false,
-           width: 300,
+           width: 400,
            fieldDefaults: {
                labelWidth: 100,
                anchor: '100%',
             },
            items: [
                {
-                   xtype: 'pveContentTypeSelector',
-                   cts: me.contents,
-                   fieldLabel: gettext('Content'),
-                   name: 'content',
-                   value: defaultContent,
+                   xtype: 'filefield',
+                   name: 'file',
+                   buttonText: gettext('Select File'),
                    allowBlank: false,
+                   fieldLabel: gettext('File'),
+                   cbind: {
+                       accept: '{extensions}',
+                   },
                    listeners: {
-                       change: function(cmp, newValue, oldValue) {
-                           fileField.setAccept(newValue);
-                       },
+                       change: 'fileChange',
                    },
                },
-               fileField,
-               pbar,
-           ],
-       });
-
-       let form = me.formPanel.getForm();
-
-       let doStandardSubmit = function() {
-           form.submit({
-               url: "/api2/htmljs" + baseurl,
-               waitMsg: gettext('Uploading file...'),
-               success: function(f, action) {
-                   me.close();
+               {
+                   xtype: 'textfield',
+                   name: 'filename',
+                   allowBlank: false,
+                   fieldLabel: gettext('File name'),
+                   bind: {
+                       value: '{filename}',
+                   },
+                   cbind: {
+                       regex: '{filenameRegex}',
+                   },
+                   regexText: gettext('Wrong file extension'),
                },
-               failure: function(f, action) {
-                   var msg = PVE.Utils.extractFormActionError(action);
-                    Ext.Msg.alert(gettext('Error'), msg);
+               {
+                   xtype: 'displayfield',
+                   name: 'size',
+                   fieldLabel: gettext('File size'),
+                   bind: {
+                       value: '{size}',
+                   },
                },
-           });
-       };
-
-       let updateProgress = function(per, bytes) {
-           var text = (per * 100).toFixed(2) + '%';
-           if (bytes) {
-               text += " (" + Proxmox.Utils.format_size(bytes) + ')';
-           }
-           pbar.updateProgress(per, text);
-       };
+               {
+                   xtype: 'displayfield',
+                   name: 'mimetype',
+                   fieldLabel: gettext('MIME type'),
+                   bind: {
+                       value: '{mimetype}',
+                   },
+               },
+               {
+                   xtype: 'pveHashAlgorithmSelector',
+                   name: 'checksum-algorithm',
+                   fieldLabel: gettext('Hash algorithm'),
+                   allowBlank: true,
+                   hasNoneOption: true,
+                   value: '__default__',
+                   listeners: {
+                       change: 'hashChange',
+                   },
+               },
+               {
+                   xtype: 'textfield',
+                   name: 'checksum',
+                   fieldLabel: gettext('Checksum'),
+                   allowBlank: false,
+                   disabled: true,
+                   emptyText: gettext('none'),
+                   reference: 'downloadUrlChecksum',
+               },
+               {
+                   xtype: 'progressbar',
+                   text: 'Ready',
+                   hidden: true,
+                   reference: 'progressBar',
+               },
+               {
+                   xtype: 'hiddenfield',
+                   name: 'content',
+                   cbind: {
+                       value: '{content}',
+                   },
+               },
+           ],
+          listeners: {
+               validitychange: 'validitychange',
+          },
+       },
+    ],
 
-       let abortBtn = Ext.create('Ext.Button', {
+    buttons: [
+       {
+           xtype: 'button',
            text: gettext('Abort'),
+           reference: 'abortBtn',
            disabled: true,
            handler: function() {
-               me.close();
+               const me = this;
+               me.up('pveStorageUpload').close();
            },
-       });
-
-       let submitBtn = Ext.create('Ext.Button', {
+       },
+       {
            text: gettext('Upload'),
+           reference: 'submitBtn',
            disabled: true,
-           handler: function(button) {
-               var fd;
-               try {
-                   fd = new FormData();
-               } catch (err) {
-                   doStandardSubmit();
-                   return;
-               }
+           handler: 'submit',
+       },
+    ],
 
-               button.setDisabled(true);
-               abortBtn.setDisabled(false);
-
-               var field = form.findField('content');
-               fd.append("content", field.getValue());
-               field.setDisabled(true);
-
-               field = form.findField('filename');
-               var file = field.fileInputEl.dom;
-               fd.append("filename", file.files[0]);
-               field.setDisabled(true);
-
-               pbar.setVisible(true);
-               updateProgress(0);
-
-               let xhr = new XMLHttpRequest();
-               me.xhr = xhr;
-
-               xhr.addEventListener("load", function(e) {
-                   if (xhr.status === 200) {
-                       me.close();
-                       return;
-                   }
-                   let err = Ext.htmlEncode(xhr.statusText);
-                   let msg = `${gettext('Error')} ${xhr.status.toString()}: ${err}`;
-                   if (xhr.responseText !== "") {
-                       let result = Ext.decode(xhr.responseText);
-                       result.message = msg;
-                       msg = Proxmox.Utils.extractRequestError(result, true);
-                   }
-                   Ext.Msg.alert(gettext('Error'), msg, btn => me.close());
-               }, false);
-
-               xhr.addEventListener("error", function(e) {
-                   let err = e.target.status.toString();
-                   let msg = `Error '${err}' occurred while receiving the document.`;
-                   Ext.Msg.alert(gettext('Error'), msg, btn => me.close());
-               });
-
-               xhr.upload.addEventListener("progress", function(evt) {
-                   if (evt.lengthComputable) {
-                       let percentComplete = evt.loaded / evt.total;
-                       updateProgress(percentComplete, evt.loaded);
-                   }
-               }, false);
-
-               xhr.open("POST", `/api2/json${baseurl}`, true);
-               xhr.send(fd);
-           },
-       });
-
-       form.on('validitychange', (f, valid) => submitBtn.setDisabled(!valid));
-
-       Ext.apply(me, {
-           title: gettext('Upload'),
-           items: me.formPanel,
-           buttons: [abortBtn, submitBtn],
-           listeners: {
-               close: function() {
-                   if (me.xhr) {
-                       me.xhr.abort();
-                       delete me.xhr;
-                   }
-               },
-           },
-       });
+    listeners: {
+       close: function() {
+           const me = this;
+           if (me.xhr) {
+               me.xhr.abort();
+               delete me.xhr;
+           }
+       },
+    },
+
+    initComponent: function() {
+        const me = this;
+
+       if (!me.nodename) {
+           throw "no node name specified";
+       }
+       if (!me.storage) {
+           throw "no storage ID specified";
+       }
+       if (!me.acceptedExtensions[me.content]) {
+           throw "content type not supported";
+       }
 
         me.callParent();
     },