]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/storage/ContentView.js
1 Ext
.define('PVE.grid.TemplateSelector', {
2 extend
: 'Ext.grid.GridPanel',
4 alias
: 'widget.pveTemplateSelector',
7 stateId
: 'grid-template-selector',
11 initComponent : function() {
15 throw "no node name specified";
18 var baseurl
= "/nodes/" + me
.nodename
+ "/aplinfo";
19 var store
= new Ext
.data
.Store({
21 groupField
: 'section',
24 url
: '/api2/json' + baseurl
28 var sm
= Ext
.create('Ext.selection.RowModel', {});
30 var groupingFeature
= Ext
.create('Ext.grid.feature.Grouping',{
31 groupHeaderTpl
: '{[ "Section: " + values.name ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
34 var reload = function() {
38 Proxmox
.Utils
.monStoreErrors(me
, store
);
49 enableKeyEvents
: true,
52 keyup: function(field
) {
53 var value
= field
.getValue().toLowerCase();
54 store
.clearFilter(true);
55 store
.filterBy(function(rec
) {
56 return (rec
.data
['package'].toLowerCase().indexOf(value
) !== -1)
57 || (rec
.data
.headline
.toLowerCase().indexOf(value
) !== -1);
63 features
: [ groupingFeature
],
66 header
: gettext('Type'),
71 header
: gettext('Package'),
76 header
: gettext('Version'),
81 header
: gettext('Description'),
83 renderer
: Ext
.String
.htmlEncode
,
97 Ext
.define('pve-aplinfo', {
98 extend
: 'Ext.data.Model',
100 'template', 'type', 'package', 'version', 'headline', 'infopage',
101 'description', 'os', 'section'
103 idProperty
: 'template'
108 Ext
.define('PVE.storage.TemplateDownload', {
109 extend
: 'Ext.window.Window',
110 alias
: 'widget.pveTemplateDownload',
113 title
: gettext('Templates'),
117 initComponent : function() {
118 /*jslint confusion: true */
121 var grid
= Ext
.create('PVE.grid.TemplateSelector', {
124 nodename
: me
.nodename
127 var sm
= grid
.getSelectionModel();
129 var submitBtn
= Ext
.create('Proxmox.button.Button', {
130 text
: gettext('Download'),
133 handler: function(button
, event
, rec
) {
134 Proxmox
.Utils
.API2Request({
135 url
: '/nodes/' + me
.nodename
+ '/aplinfo',
138 template
: rec
.data
.template
141 failure: function (response
, opts
) {
142 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
144 success: function(response
, options
) {
145 var upid
= response
.result
.data
;
147 Ext
.create('Proxmox.window.TaskViewer', {
150 destroy
: me
.reloadGrid
162 buttons
: [ submitBtn
]
169 Ext
.define('PVE.storage.Upload', {
170 extend
: 'Ext.window.Window',
171 alias
: 'widget.pveStorageUpload',
177 initComponent : function() {
178 /*jslint confusion: true */
184 throw "no node name specified";
188 throw "no storage ID specified";
191 var baseurl
= "/nodes/" + me
.nodename
+ "/storage/" + me
.storage
+ "/upload";
193 var pbar
= Ext
.create('Ext.ProgressBar', {
198 me
.formPanel
= Ext
.create('Ext.form.Panel', {
210 xtype
: 'pveContentTypeSelector',
212 fieldLabel
: gettext('Content'),
214 value
: me
.contents
[0] || '',
220 buttonText
: gettext('Select File...'),
223 afterrender: function(cmp
) {
224 cmp
.fileInputEl
.set({
234 var form
= me
.formPanel
.getForm();
236 var doStandardSubmit = function() {
238 url
: "/api2/htmljs" + baseurl
,
239 waitMsg
: gettext('Uploading file...'),
240 success: function(f
, action
) {
243 failure: function(f
, action
) {
244 var msg
= PVE
.Utils
.extractFormActionError(action
);
245 Ext
.Msg
.alert(gettext('Error'), msg
);
250 var updateProgress = function(per
, bytes
) {
251 var text
= (per
* 100).toFixed(2) + '%';
253 text
+= " (" + Proxmox
.Utils
.format_size(bytes
) + ')';
255 pbar
.updateProgress(per
, text
);
258 var abortBtn
= Ext
.create('Ext.Button', {
259 text
: gettext('Abort'),
261 handler: function() {
266 var submitBtn
= Ext
.create('Ext.Button', {
267 text
: gettext('Upload'),
269 handler: function(button
) {
278 button
.setDisabled(true);
279 abortBtn
.setDisabled(false);
281 var field
= form
.findField('content');
282 fd
.append("content", field
.getValue());
283 field
.setDisabled(true);
285 field
= form
.findField('filename');
286 var file
= field
.fileInputEl
.dom
;
287 fd
.append("filename", file
.files
[0]);
288 field
.setDisabled(true);
290 pbar
.setVisible(true);
293 xhr
= new XMLHttpRequest();
295 xhr
.addEventListener("load", function(e
) {
296 if (xhr
.status
== 200) {
299 var msg
= gettext('Error') + " " + xhr
.status
.toString() + ": " + Ext
.htmlEncode(xhr
.statusText
);
300 if (xhr
.responseText
!== "") {
301 var result
= Ext
.decode(xhr
.responseText
);
302 result
.message
= msg
;
303 msg
= Proxmox
.Utils
.extractRequestError(result
, true);
305 Ext
.Msg
.alert(gettext('Error'), msg
, function(btn
) {
311 xhr
.addEventListener("error", function(e
) {
312 var msg
= "Error " + e
.target
.status
.toString() + " occurred while receiving the document.";
313 Ext
.Msg
.alert(gettext('Error'), msg
, function(btn
) {
318 xhr
.upload
.addEventListener("progress", function(evt
) {
319 if (evt
.lengthComputable
) {
320 var percentComplete
= evt
.loaded
/ evt
.total
;
321 updateProgress(percentComplete
, evt
.loaded
);
325 xhr
.open("POST", "/api2/json" + baseurl
, true);
330 form
.on('validitychange', function(f
, valid
) {
331 submitBtn
.setDisabled(!valid
);
335 title
: gettext('Upload'),
337 buttons
: [ abortBtn
, submitBtn
],
351 Ext
.define('PVE.storage.ContentView', {
352 extend
: 'Ext.grid.GridPanel',
354 alias
: 'widget.pveStorageContentView',
357 stateId
: 'grid-storage-content',
365 groupHeaderTpl
: '{name} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
368 initComponent : function() {
371 var nodename
= me
.pveSelNode
.data
.node
;
373 throw "no node name specified";
376 var storage
= me
.pveSelNode
.data
.storage
;
378 throw "no storage ID specified";
381 var baseurl
= "/nodes/" + nodename
+ "/storage/" + storage
+ "/content";
382 var store
= Ext
.create('Ext.data.Store',{
383 model
: 'pve-storage-content',
384 groupField
: 'content',
387 url
: '/api2/json' + baseurl
395 var sm
= Ext
.create('Ext.selection.RowModel', {});
397 var reload = function() {
399 me
.statusStore
.load();
402 Proxmox
.Utils
.monStoreErrors(me
, store
);
404 var templateButton
= Ext
.create('Proxmox.button.Button',{
406 text
: gettext('Templates'),
407 handler: function() {
408 var win
= Ext
.create('PVE.storage.TemplateDownload', {
417 var uploadButton
= Ext
.create('Proxmox.button.Button', {
418 contents
: ['iso','vztmpl'],
419 text
: gettext('Upload'),
420 handler: function() {
422 var win
= Ext
.create('PVE.storage.Upload', {
425 contents
: me
.contents
428 win
.on('destroy', reload
);
432 var imageRemoveButton
;
433 var removeButton
= Ext
.create('Proxmox.button.StdRemoveButton',{
436 enableFn: function(rec
) {
437 if (rec
&& rec
.data
.content
!== 'images') {
438 imageRemoveButton
.setVisible(false);
439 removeButton
.setVisible(true);
444 callback: function() {
447 baseurl
: baseurl
+ '/'
450 imageRemoveButton
= Ext
.create('Proxmox.button.Button',{
453 text
: gettext('Remove'),
454 enableFn: function(rec
) {
455 if (rec
&& rec
.data
.content
=== 'images') {
456 removeButton
.setVisible(false);
457 imageRemoveButton
.setVisible(true);
462 handler: function(btn
, event
, rec
) {
465 var url
= baseurl
+ '/' + rec
.data
.volid
;
466 var vmid
= rec
.data
.vmid
;
468 var store
= PVE
.data
.ResourceStore
;
470 if (vmid
&& store
.findVMID(vmid
)) {
471 var guest_node
= store
.guestNode(vmid
);
472 var storage_path
= 'storage/' + nodename
+ '/' + storage
;
474 // allow to delete local backed images if a VMID exists on another node.
475 if (store
.storageIsShared(storage_path
) || guest_node
== nodename
) {
476 var msg
= Ext
.String
.format(
477 gettext("Cannot remove image, a guest with VMID '{0}' exists!"), vmid
);
478 msg
+= '<br />' + gettext("You can delete the image from the guest's hardware pane");
481 title
: gettext('Cannot remove disk image.'),
488 var win
= Ext
.create('PVE.window.SafeDestroy', {
489 title
: Ext
.String
.format(gettext("Destroy '{0}'"), rec
.data
.volid
),
492 item
: { type
: 'Image', id
: vmid
}
494 win
.on('destroy', function() {
495 me
.statusStore
= Ext
.create('Proxmox.data.ObjectStore', {
496 url
: '/api2/json/nodes/' + nodename
+ '/storage/' + storage
+ '/status'
504 me
.statusStore
= Ext
.create('Proxmox.data.ObjectStore', {
505 url
: '/api2/json/nodes/' + nodename
+ '/storage/' + storage
+ '/status'
513 xtype
: 'proxmoxButton',
514 text
: gettext('Restore'),
517 enableFn: function(rec
) {
518 return rec
&& rec
.data
.content
=== 'backup';
520 handler: function(b
, e
, rec
) {
522 if (PVE
.Utils
.volume_is_qemu_backup(rec
.data
.volid
, rec
.data
.format
)) {
524 } else if (PVE
.Utils
.volume_is_lxc_backup(rec
.data
.volid
, rec
.data
.format
)) {
530 var win
= Ext
.create('PVE.window.Restore', {
532 volid
: rec
.data
.volid
,
533 volidText
: PVE
.Utils
.render_storage_content(rec
.data
.volid
, {}, rec
),
537 win
.on('destroy', reload
);
545 xtype
: 'proxmoxButton',
546 text
: gettext('Show Configuration'),
549 enableFn: function(rec
) {
550 return rec
&& rec
.data
.content
=== 'backup';
552 handler: function(b
,e
,rec
) {
553 var win
= Ext
.create('PVE.window.BackupConfig', {
554 volume
: rec
.data
.volid
,
555 pveSelNode
: me
.pveSelNode
562 gettext('Search') + ':', ' ',
566 enableKeyEvents
: true,
569 keyup: function(field
) {
570 store
.clearFilter(true);
574 value
: field
.getValue(),
585 header
: gettext('Name'),
588 renderer
: PVE
.Utils
.render_storage_content
,
592 header
: gettext('Date'),
597 header
: gettext('Format'),
602 header
: gettext('Type'),
604 dataIndex
: 'content',
605 renderer
: PVE
.Utils
.format_content_types
608 header
: gettext('Size'),
610 renderer
: Proxmox
.Utils
.format_size
,
621 // disable the buttons/restrict the upload window
622 // if templates or uploads are not allowed
623 me
.mon(me
.statusStore
, 'load', function(s
, records
, success
) {
624 var availcontent
= [];
625 Ext
.Array
.each(records
, function(item
){
626 if (item
.id
=== 'content') {
627 availcontent
= item
.data
.value
.split(',');
634 Ext
.Array
.each(availcontent
, function(content
) {
635 if (content
=== 'vztmpl') {
638 } else if (content
=== 'iso') {
644 if (templ
!== upload
) {
645 uploadButton
.contents
= cts
;
648 templateButton
.setDisabled(!templ
);
649 uploadButton
.setDisabled(!upload
&& !templ
);
654 Ext
.define('pve-storage-content', {
655 extend
: 'Ext.data.Model',
657 'volid', 'content', 'format', 'size', 'used', 'vmid',
658 'channel', 'id', 'lun',
661 convert: function(value
, record
) {
662 // check for volid, because if you click on a grouping header,
663 // it calls convert (but with an empty volid)
664 if (value
|| record
.data
.volid
=== null) {
667 return PVE
.Utils
.render_storage_content(value
, {}, record
);
672 convert: function(value
, record
) {
673 // check for volid, because if you click on a grouping header,
674 // it calls convert (but with an empty volid)
675 if (value
|| record
.data
.volid
=== null) {
678 let t
= record
.data
.content
;
679 if (t
=== "backup") {
680 let v
= record
.data
.volid
;
681 let match
= v
.match(/(\d{4}_\d{2}_\d{2})-(\d{2}_\d{2}_\d{2})/);
683 let date
= match
[1].replace(/_
/g
, '.');
684 let time
= match
[2].replace(/_
/g
, ':');
685 return date
+ " " + time
;