public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type
@ 2020-09-02 11:03 Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 01/14] config panel: allow new nodes to be added later Fabian Ebner
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

The goal of doing this is to have more flexibility/cleaner code for
content-type-dependent features in the content view. Now only buttons
that are useful for each content type are displayed. And it might make
sense to display different columns for different content types, e.g.
'parent' for cloned VM/CT images. The mechanism introduced in this series
(patch #13) is not used yet, suggestions for which columns to use for
which types are welcome.

API calls might be faster if only one type of content is requested.
The obvious drawback is that there is no view with all contents anymore.

The last patch is not directly related, but introduces the prune window
for backups, essentially copied over from the PBS code.

@Thomas: Hope this is not too far from what you had in mind.
Of course I can rebase the prune window patch on current master if prefer.

Fabian Ebner (14):
  config panel: allow new nodes to be added later
  storage panel/browser: use insertNodes function
  use separate view for each content type
  remove the now unneccessary grouping
  content view: allow specifying title bar elements for init
  turn nodename,storage,sm into object variables
  add upload button conditionally
  create and use TemplateView
  create and use BackupView
  get rid of unneccessary enableFn's
  create ImageView and use it for VM and CT images
  simplify reload call
  content view: allow specifying which columns to show on init
  backup view: add prune window

 www/manager6/Makefile                |   4 +
 www/manager6/panel/ConfigPanel.js    |  93 ++---
 www/manager6/storage/BackupView.js   |  96 ++++++
 www/manager6/storage/Browser.js      |  89 ++++-
 www/manager6/storage/ContentView.js  | 497 +++++----------------------
 www/manager6/storage/ImageView.js    |  74 ++++
 www/manager6/storage/TemplateView.js | 212 ++++++++++++
 www/manager6/window/Prune.js         | 230 +++++++++++++
 8 files changed, 836 insertions(+), 459 deletions(-)
 create mode 100644 www/manager6/storage/BackupView.js
 create mode 100644 www/manager6/storage/ImageView.js
 create mode 100644 www/manager6/storage/TemplateView.js
 create mode 100644 www/manager6/window/Prune.js

-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 01/14] config panel: allow new nodes to be added later
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 02/14] storage panel/browser: use insertNodes function Fabian Ebner
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

in preparation for dynamically loading nodes for content-type-specific views.

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/panel/ConfigPanel.js | 93 +++++++++++++++++--------------
 1 file changed, 50 insertions(+), 43 deletions(-)

diff --git a/www/manager6/panel/ConfigPanel.js b/www/manager6/panel/ConfigPanel.js
index 4356c24e..fabf9108 100644
--- a/www/manager6/panel/ConfigPanel.js
+++ b/www/manager6/panel/ConfigPanel.js
@@ -227,48 +227,7 @@ Ext.define('PVE.panel.Config', {
 	    }
 	});
 	var root = me.store.getRoot();
-	me.items.forEach(function(item){
-	    var treeitem = Ext.create('Ext.data.TreeModel',{
-		id: item.itemId,
-		text: item.title,
-		iconCls: item.iconCls,
-		leaf: true,
-		expanded: item.expandedOnInit
-	    });
-	    item.header = false;
-	    if (me.savedItems[item.itemId] !== undefined) {
-		throw "itemId already exists, please use another";
-	    }
-	    me.savedItems[item.itemId] = item;
-
-	    var group;
-	    var curnode = root;
-
-	    // get/create the group items
-	    while (Ext.isArray(item.groups) && item.groups.length > 0) {
-		group = item.groups.shift();
-
-		var child = curnode.findChild('id', group);
-		if (child === null) {
-		    // did not find the group item
-		    // so add it where we are
-		    break;
-		}
-		curnode = child;
-	    }
-
-	    // insert the item
-
-	    // lets see if it already exists
-	    var node = curnode.findChild('id', item.itemId);
-
-	    if (node === null) {
-		curnode.appendChild(treeitem);
-	    } else {
-		// should not happen!
-		throw "id already exists";
-	    }
-	});
+	me.insertNodes(me.items);
 
 	delete me.items;
 	me.defaults = me.defaults || {};
@@ -310,5 +269,53 @@ Ext.define('PVE.panel.Config', {
 	if (stateid) {
 	    me.mon(me.sp, 'statechange', statechange);
 	}
-    }
+    },
+
+    insertNodes: function(items) {
+	var me = this;
+	var root = me.store.getRoot();
+
+	items.forEach(function(item) {
+	    var treeitem = Ext.create('Ext.data.TreeModel',{
+		id: item.itemId,
+		text: item.title,
+		iconCls: item.iconCls,
+		leaf: true,
+		expanded: item.expandedOnInit
+	    });
+	    item.header = false;
+	    if (me.savedItems[item.itemId] !== undefined) {
+		throw "itemId already exists, please use another";
+	    }
+	    me.savedItems[item.itemId] = item;
+
+	    var group;
+	    var curnode = root;
+
+	    // get/create the group items
+	    while (Ext.isArray(item.groups) && item.groups.length > 0) {
+		group = item.groups.shift();
+
+		var child = curnode.findChild('id', group);
+		if (child === null) {
+		    // did not find the group item
+		    // so add it where we are
+		    break;
+		}
+		curnode = child;
+	    }
+
+	    // insert the item
+
+	    // lets see if it already exists
+	    var node = curnode.findChild('id', item.itemId);
+
+	    if (node === null) {
+		curnode.appendChild(treeitem);
+	    } else {
+		// should not happen!
+		throw "id already exists";
+	    }
+	});
+    },
 });
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 02/14] storage panel/browser: use insertNodes function
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 01/14] config panel: allow new nodes to be added later Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 03/14] use separate view for each content type Fabian Ebner
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

in preparation for dynamically loading nodes for content-type-specific views.

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/storage/Browser.js | 35 +++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/www/manager6/storage/Browser.js b/www/manager6/storage/Browser.js
index e93aa8de..7537bdf1 100644
--- a/www/manager6/storage/Browser.js
+++ b/www/manager6/storage/Browser.js
@@ -35,27 +35,32 @@ Ext.define('PVE.storage.Browser', {
 	    hstateid: 'storagetab'
 	});
 
+	// call here, so there is a root for insertNodes()
+	me.callParent();
+
 	if (caps.storage['Datastore.Allocate'] ||
 	    caps.storage['Datastore.AllocateSpace'] ||
 	    caps.storage['Datastore.Audit']) {
-	    me.items.push({
-		xtype: 'pveStorageContentView',
-		title: gettext('Content'),
-		iconCls: 'fa fa-th',
-		itemId: 'content'
-	    });
+	    me.insertNodes([
+		{
+		    xtype: 'pveStorageContentView',
+		    title: gettext('Content'),
+		    iconCls: 'fa fa-th',
+		    itemId: 'content'
+		},
+	    ]);
 	}
 
 	if (caps.storage['Permissions.Modify']) {
-	    me.items.push({
-		xtype: 'pveACLView',
-		title: gettext('Permissions'),
-		iconCls: 'fa fa-unlock',
-		itemId: 'permissions',
-		path: '/storage/' + storeid
-	    });
+	    me.insertNodes([
+		{
+		    xtype: 'pveACLView',
+		    title: gettext('Permissions'),
+		    iconCls: 'fa fa-unlock',
+		    itemId: 'permissions',
+		    path: '/storage/' + storeid
+		},
+	    ]);
 	}
-
-	me.callParent();
    }
 });
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 03/14] use separate view for each content type
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 01/14] config panel: allow new nodes to be added later Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 02/14] storage panel/browser: use insertNodes function Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 04/14] remove the now unneccessary grouping Fabian Ebner
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

Organized as separate "if"s to allow changing properties easily later.

statusStore is not needed anymore, now there is a single fixed content type,
and the template and upload button are disabled depending on that type.

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---

Hope I didn't miss an easier existing mechanism to accomplish that.
Note that the available contents are loaded only once, if we would
want to update it periodically, we'd need to add something like
removeNodes for the configPanel AFAICT

 www/manager6/storage/Browser.js     | 71 ++++++++++++++++++++++++++---
 www/manager6/storage/ContentView.js | 57 ++++++-----------------
 2 files changed, 78 insertions(+), 50 deletions(-)

diff --git a/www/manager6/storage/Browser.js b/www/manager6/storage/Browser.js
index 7537bdf1..e3822d5b 100644
--- a/www/manager6/storage/Browser.js
+++ b/www/manager6/storage/Browser.js
@@ -41,14 +41,71 @@ Ext.define('PVE.storage.Browser', {
 	if (caps.storage['Datastore.Allocate'] ||
 	    caps.storage['Datastore.AllocateSpace'] ||
 	    caps.storage['Datastore.Audit']) {
-	    me.insertNodes([
-		{
-		    xtype: 'pveStorageContentView',
-		    title: gettext('Content'),
-		    iconCls: 'fa fa-th',
-		    itemId: 'content'
+
+	    Proxmox.Utils.API2Request({
+		url: "/nodes/" + nodename + "/storage/" + storeid + "/status",
+		method: 'GET',
+		success: function(response, opts) {
+		    var contents = response.result.data.content.split(',');
+		    var items = [];
+
+		    if (contents.includes('backup')) {
+			items.push({
+			    xtype: 'pveStorageContentView',
+			    title: PVE.Utils.contentTypes['backup'],
+			    iconCls: 'fa fa-th',
+			    itemId: 'contentBackup',
+			    content: 'backup',
+			});
+		    }
+		    if (contents.includes('images')) {
+			items.push({
+			    xtype: 'pveStorageContentView',
+			    title: PVE.Utils.contentTypes['images'],
+			    iconCls: 'fa fa-th',
+			    itemId: 'contentImages',
+			    content: 'images',
+			});
+		    }
+		    if (contents.includes('iso')) {
+			items.push({
+			    xtype: 'pveStorageContentView',
+			    title: PVE.Utils.contentTypes['iso'],
+			    iconCls: 'fa fa-th',
+			    itemId: 'contentIso',
+			    content: 'iso',
+			});
+		    }
+		    if (contents.includes('rootdir')) {
+			items.push({
+			    xtype: 'pveStorageContentView',
+			    title: PVE.Utils.contentTypes['rootdir'],
+			    iconCls: 'fa fa-th',
+			    itemId: 'contentRootdir',
+			    content: 'rootdir',
+			});
+		    }
+		    if (contents.includes('snippets')) {
+			items.push({
+			    xtype: 'pveStorageContentView',
+			    title: PVE.Utils.contentTypes['snippets'],
+			    iconCls: 'fa fa-th',
+			    itemId: 'contentSnippets',
+			    content: 'snippets',
+			});
+		    }
+		    if (contents.includes('vztmpl')) {
+			items.push({
+			    xtype: 'pveStorageContentView',
+			    title: PVE.Utils.contentTypes['vztmpl'],
+			    iconCls: 'fa fa-th',
+			    itemId: 'contentVztmpl',
+			    content: 'vztmpl',
+			});
+		    }
+		    me.insertNodes(items);
 		},
-	    ]);
+	    });
 	}
 
 	if (caps.storage['Permissions.Modify']) {
diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index 194ad42e..c067d3e0 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -376,13 +376,18 @@ Ext.define('PVE.storage.ContentView', {
 	    throw "no storage ID specified";
 	}
 
+	var content = me.content;
+	if (!content) {
+	    throw "no content type specified";
+	}
+
 	var baseurl = "/nodes/" + nodename + "/storage/" + storage + "/content";
 	var store = Ext.create('Ext.data.Store',{
 	    model: 'pve-storage-content',
 	    groupField: 'content',
 	    proxy: {
                 type: 'proxmox',
-		url: '/api2/json' + baseurl
+		url: '/api2/json' + baseurl + '?content=' + content,
 	    },
 	    sorters: {
 		property: 'volid',
@@ -394,7 +399,6 @@ Ext.define('PVE.storage.ContentView', {
 
 	var reload = function() {
 	    store.load();
-	    me.statusStore.load();
 	};
 
 	Proxmox.Utils.monStoreErrors(me, store);
@@ -411,6 +415,9 @@ Ext.define('PVE.storage.ContentView', {
 		win.show();
 	    }
 	});
+	if (content !== 'vztmpl') {
+	    templateButton.setDisabled(true);
+	}
 
 	var uploadButton = Ext.create('Proxmox.button.Button', {
 	    contents : ['iso','vztmpl'],
@@ -426,6 +433,11 @@ Ext.define('PVE.storage.ContentView', {
 		win.on('destroy', reload);
 	    }
 	});
+	if (content === 'iso' || content === 'vztmpl') {
+	    uploadButton.contents = [content];
+	} else {
+	    uploadButton.setDisabled(true);
+	}
 
 	var imageRemoveButton;
 	var removeButton = Ext.create('Proxmox.button.StdRemoveButton',{
@@ -460,8 +472,6 @@ Ext.define('PVE.storage.ContentView', {
 		return false;
 	    },
 	    handler: function(btn, event, rec) {
-		me = this;
-
 		var url = baseurl + '/' + rec.data.volid;
 		var vmid = rec.data.vmid;
 
@@ -492,19 +502,11 @@ Ext.define('PVE.storage.ContentView', {
 		    item: { type: 'Image', id: vmid }
 		}).show();
 		win.on('destroy', function() {
-		    me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
-			url: '/api2/json/nodes/' + nodename + '/storage/' + storage + '/status'
-		    });
 		    reload();
-
 		});
 	    }
 	});
 
-	me.statusStore = Ext.create('Proxmox.data.ObjectStore', {
-	    url: '/api2/json/nodes/' + nodename + '/storage/' + storage + '/status'
-	});
-
 	Ext.apply(me, {
 	    store: store,
 	    selModel: sm,
@@ -617,37 +619,6 @@ Ext.define('PVE.storage.ContentView', {
 	});
 
 	me.callParent();
-
-	// disable the buttons/restrict the upload window
-	// if templates or uploads are not allowed
-	me.mon(me.statusStore, 'load', function(s, records, success) {
-	    var availcontent = [];
-	    Ext.Array.each(records, function(item){
-		if (item.id === 'content') {
-		    availcontent = item.data.value.split(',');
-		}
-	    });
-	    var templ = false;
-	    var upload = false;
-	    var cts = [];
-
-	    Ext.Array.each(availcontent, function(content) {
-		if (content === 'vztmpl') {
-		    templ = true;
-		    cts.push('vztmpl');
-		} else if (content === 'iso') {
-		    upload = true;
-		    cts.push('iso');
-		}
-	    });
-
-	    if (templ !== upload) {
-		uploadButton.contents = cts;
-	    }
-
-	    templateButton.setDisabled(!templ);
-	    uploadButton.setDisabled(!upload && !templ);
-	});
     }
 }, function() {
 
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 04/14] remove the now unneccessary grouping
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (2 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 03/14] use separate view for each content type Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 05/14] content view: allow specifying title bar elements for init Fabian Ebner
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

since there are no grouping headers anymore, the situation
with the empty volid shouldn't happen anymore.

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/storage/ContentView.js | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index c067d3e0..2c320bec 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -357,12 +357,6 @@ Ext.define('PVE.storage.ContentView', {
 	trackOver: false,
 	loadMask: false
     },
-    features: [
-	{
-	    ftype: 'grouping',
-	    groupHeaderTpl: '{name} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
-	}
-    ],
     initComponent : function() {
 	var me = this;
 
@@ -630,9 +624,7 @@ Ext.define('PVE.storage.ContentView', {
 	    {
 		name: 'text',
 		convert: function(value, record) {
-		    // check for volid, because if you click on a grouping header,
-		    // it calls convert (but with an empty volid)
-		    if (value || record.data.volid === null) {
+		    if (value) {
 			return value;
 		    }
 		    return PVE.Utils.render_storage_content(value, {}, record);
@@ -641,9 +633,7 @@ Ext.define('PVE.storage.ContentView', {
 	    {
 		name: 'vdate',
 		convert: function(value, record) {
-		    // check for volid, because if you click on a grouping header,
-		    // it calls convert (but with an empty volid)
-		    if (value || record.data.volid === null) {
+		    if (value) {
 			return value;
 		    }
 		    let t = record.data.content;
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 05/14] content view: allow specifying title bar elements for init
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (3 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 04/14] remove the now unneccessary grouping Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 06/14] turn nodename, storage, sm into object variables Fabian Ebner
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

in preparation to create derived classes.

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---

use --color-moved=zebra --color-moved-ws=ignore-all-space --patience
to make patch more readable

 www/manager6/storage/ContentView.js | 145 ++++++++++++++--------------
 1 file changed, 75 insertions(+), 70 deletions(-)

diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index 2c320bec..45e40074 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -501,81 +501,86 @@ Ext.define('PVE.storage.ContentView', {
 	    }
 	});
 
-	Ext.apply(me, {
-	    store: store,
-	    selModel: sm,
-	    tbar: [
-		{
-		    xtype: 'proxmoxButton',
-		    text: gettext('Restore'),
-		    selModel: sm,
-		    disabled: true,
-		    enableFn: function(rec) {
-			return rec && rec.data.content === 'backup';
-		    },
-		    handler: function(b, e, rec) {
-			var vmtype;
-			if (PVE.Utils.volume_is_qemu_backup(rec.data.volid, rec.data.format)) {
-			    vmtype = 'qemu';
-			} else if (PVE.Utils.volume_is_lxc_backup(rec.data.volid, rec.data.format)) {
-			    vmtype = 'lxc';
-			} else {
-			    return;
-			}
-
-			var win = Ext.create('PVE.window.Restore', {
-			    nodename: nodename,
-			    volid: rec.data.volid,
-			    volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
-			    vmtype: vmtype
-			});
-			win.show();
-			win.on('destroy', reload);
-		    }
+	if (!me.tbar) {
+	    me.tbar = [];
+	}
+	me.tbar.push(
+	    {
+		xtype: 'proxmoxButton',
+		text: gettext('Restore'),
+		selModel: sm,
+		disabled: true,
+		enableFn: function(rec) {
+		    return rec && rec.data.content === 'backup';
 		},
-		removeButton,
-		imageRemoveButton,
-		templateButton,
-		uploadButton,
-		{
-		    xtype: 'proxmoxButton',
-		    text: gettext('Show Configuration'),
-		    disabled: true,
-		    selModel: sm,
-		    enableFn: function(rec) {
-			return rec && rec.data.content === 'backup';
-		    },
-		    handler: function(b,e,rec) {
-			var win = Ext.create('PVE.window.BackupConfig', {
-			    volume: rec.data.volid,
-			    pveSelNode: me.pveSelNode
-			});
-
-			win.show();
+		handler: function(b, e, rec) {
+		    var vmtype;
+		    if (PVE.Utils.volume_is_qemu_backup(rec.data.volid, rec.data.format)) {
+			vmtype = 'qemu';
+		    } else if (PVE.Utils.volume_is_lxc_backup(rec.data.volid, rec.data.format)) {
+			vmtype = 'lxc';
+		    } else {
+			return;
 		    }
+
+		    var win = Ext.create('PVE.window.Restore', {
+			nodename: nodename,
+			volid: rec.data.volid,
+			volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
+			vmtype: vmtype
+		    });
+		    win.show();
+		    win.on('destroy', reload);
+		}
+	    },
+	    removeButton,
+	    imageRemoveButton,
+	    templateButton,
+	    uploadButton,
+	    {
+		xtype: 'proxmoxButton',
+		text: gettext('Show Configuration'),
+		disabled: true,
+		selModel: sm,
+		enableFn: function(rec) {
+		    return rec && rec.data.content === 'backup';
 		},
-		'->',
-		gettext('Search') + ':', ' ',
-		{
-		    xtype: 'textfield',
-		    width: 200,
-		    enableKeyEvents: true,
-		    listeners: {
-			buffer: 500,
-			keyup: function(field) {
-			    store.clearFilter(true);
-			    store.filter([
-				{
-				    property: 'text',
-				    value: field.getValue(),
-				    anyMatch: true,
-				    caseSensitive: false
-				}
-			    ]);
-			}
+		handler: function(b,e,rec) {
+		    var win = Ext.create('PVE.window.BackupConfig', {
+			volume: rec.data.volid,
+			pveSelNode: me.pveSelNode
+		    });
+
+		    win.show();
+		}
+	    },
+	    '->',
+	    gettext('Search') + ':', ' ',
+	    {
+		xtype: 'textfield',
+		width: 200,
+		enableKeyEvents: true,
+		listeners: {
+		    buffer: 500,
+		    keyup: function(field) {
+			store.clearFilter(true);
+			store.filter([
+			    {
+				property: 'text',
+				value: field.getValue(),
+				anyMatch: true,
+				caseSensitive: false
+			    }
+			]);
 		    }
 		}
-	    ],
+	    }
+	);
+
+	Ext.apply(me, {
+	    store: store,
+	    selModel: sm,
+	    tbar: me.tbar,
 	    columns: [
 		{
 		    header: gettext('Name'),
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 06/14] turn nodename, storage, sm into object variables
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (4 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 05/14] content view: allow specifying title bar elements for init Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 07/14] add upload button conditionally Fabian Ebner
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

so they can be used and specified in derived classes.

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/storage/ContentView.js | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index 45e40074..e7c3bc70 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -360,15 +360,21 @@ Ext.define('PVE.storage.ContentView', {
     initComponent : function() {
 	var me = this;
 
-	var nodename = me.pveSelNode.data.node;
-	if (!nodename) {
-	    throw "no node name specified";
+	if (!me.nodename) {
+	    me.nodename = me.pveSelNode.data.node;
+	    if (!me.nodename) {
+		throw "no node name specified";
+	    }
 	}
+	var nodename = me.nodename;
 
-	var storage = me.pveSelNode.data.storage;
-	if (!storage) {
-	    throw "no storage ID specified";
+	if (!me.storage) {
+	    me.storage = me.pveSelNode.data.storage;
+	    if (!me.storage) {
+		throw "no storage ID specified";
+	    }
 	}
+	var storage = me.storage;
 
 	var content = me.content;
 	if (!content) {
@@ -376,7 +382,7 @@ Ext.define('PVE.storage.ContentView', {
 	}
 
 	var baseurl = "/nodes/" + nodename + "/storage/" + storage + "/content";
-	var store = Ext.create('Ext.data.Store',{
+	var store = me.store = Ext.create('Ext.data.Store', {
 	    model: 'pve-storage-content',
 	    groupField: 'content',
 	    proxy: {
@@ -389,7 +395,10 @@ Ext.define('PVE.storage.ContentView', {
 	    }
 	});
 
-	var sm = Ext.create('Ext.selection.RowModel', {});
+	if (!me.sm) {
+	    me.sm = Ext.create('Ext.selection.RowModel', {});
+	}
+	var sm = me.sm;
 
 	var reload = function() {
 	    store.load();
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 07/14] add upload button conditionally
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (5 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 06/14] turn nodename, storage, sm into object variables Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 08/14] create and use template view Fabian Ebner
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/storage/Browser.js     |  2 ++
 www/manager6/storage/ContentView.js | 13 ++++---------
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/www/manager6/storage/Browser.js b/www/manager6/storage/Browser.js
index e3822d5b..3e87fcd4 100644
--- a/www/manager6/storage/Browser.js
+++ b/www/manager6/storage/Browser.js
@@ -74,6 +74,7 @@ Ext.define('PVE.storage.Browser', {
 			    iconCls: 'fa fa-th',
 			    itemId: 'contentIso',
 			    content: 'iso',
+			    useUploadButton: true,
 			});
 		    }
 		    if (contents.includes('rootdir')) {
@@ -101,6 +102,7 @@ Ext.define('PVE.storage.Browser', {
 			    iconCls: 'fa fa-th',
 			    itemId: 'contentVztmpl',
 			    content: 'vztmpl',
+			    useUploadButton: true,
 			});
 		    }
 		    me.insertNodes(items);
diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index e7c3bc70..acd34f20 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -423,24 +423,17 @@ Ext.define('PVE.storage.ContentView', {
 	}
 
 	var uploadButton = Ext.create('Proxmox.button.Button', {
-	    contents : ['iso','vztmpl'],
 	    text: gettext('Upload'),
 	    handler: function() {
-		var me = this;
 		var win = Ext.create('PVE.storage.Upload', {
 		    nodename: nodename,
 		    storage: storage,
-		    contents: me.contents
+		    contents: [content],
 		});
 		win.show();
 		win.on('destroy', reload);
 	    }
 	});
-	if (content === 'iso' || content === 'vztmpl') {
-	    uploadButton.contents = [content];
-	} else {
-	    uploadButton.setDisabled(true);
-	}
 
 	var imageRemoveButton;
 	var removeButton = Ext.create('Proxmox.button.StdRemoveButton',{
@@ -513,6 +506,9 @@ Ext.define('PVE.storage.ContentView', {
 	if (!me.tbar) {
 	    me.tbar = [];
 	}
+	if (me.useUploadButton) {
+	    me.tbar.push(uploadButton);
+	}
 	me.tbar.push(
 	    {
 		xtype: 'proxmoxButton',
@@ -545,7 +541,6 @@ Ext.define('PVE.storage.ContentView', {
 	    removeButton,
 	    imageRemoveButton,
 	    templateButton,
-	    uploadButton,
 	    {
 		xtype: 'proxmoxButton',
 		text: gettext('Show Configuration'),
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 08/14] create and use template view
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (6 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 07/14] add upload button conditionally Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 09/14] create and use backup view Fabian Ebner
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/Makefile                |   1 +
 www/manager6/storage/Browser.js      |   4 +-
 www/manager6/storage/ContentView.js  | 184 -----------------------
 www/manager6/storage/TemplateView.js | 212 +++++++++++++++++++++++++++
 4 files changed, 214 insertions(+), 187 deletions(-)
 create mode 100644 www/manager6/storage/TemplateView.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 4288acdd..cece0aae 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -232,6 +232,7 @@ JSSRC= 							\
 	storage/RBDEdit.js				\
 	storage/StatusView.js				\
 	storage/Summary.js				\
+	storage/TemplateView.js				\
 	storage/ZFSEdit.js				\
 	storage/ZFSPoolEdit.js				\
 	tree/ResourceTree.js				\
diff --git a/www/manager6/storage/Browser.js b/www/manager6/storage/Browser.js
index 3e87fcd4..4393558c 100644
--- a/www/manager6/storage/Browser.js
+++ b/www/manager6/storage/Browser.js
@@ -97,12 +97,10 @@ Ext.define('PVE.storage.Browser', {
 		    }
 		    if (contents.includes('vztmpl')) {
 			items.push({
-			    xtype: 'pveStorageContentView',
+			    xtype: 'pveStorageTemplateView',
 			    title: PVE.Utils.contentTypes['vztmpl'],
 			    iconCls: 'fa fa-th',
 			    itemId: 'contentVztmpl',
-			    content: 'vztmpl',
-			    useUploadButton: true,
 			});
 		    }
 		    me.insertNodes(items);
diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index acd34f20..03b595f8 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -1,170 +1,3 @@
-Ext.define('PVE.grid.TemplateSelector', {
-    extend: 'Ext.grid.GridPanel',
-
-    alias: 'widget.pveTemplateSelector',
-
-    stateful: true,
-    stateId: 'grid-template-selector',
-    viewConfig: {
-	trackOver: false
-    },
-    initComponent : function() {
-	var me = this;
-
-	if (!me.nodename) {
-	    throw "no node name specified";
-	}
-
-	var baseurl = "/nodes/" + me.nodename + "/aplinfo";
-	var store = new Ext.data.Store({
-	    model: 'pve-aplinfo',
-	    groupField: 'section',
-	    proxy: {
-                type: 'proxmox',
-		url: '/api2/json' + baseurl
-	    }
-	});
-
-	var sm = Ext.create('Ext.selection.RowModel', {});
-
-	var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
-            groupHeaderTpl: '{[ "Section: " + values.name ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
-	});
-
-	var reload = function() {
-	    store.load();
-	};
-
-	Proxmox.Utils.monStoreErrors(me, store);
-
-	Ext.apply(me, {
-	    store: store,
-	    selModel: sm,
-	    tbar: [
-		'->',
-		gettext('Search'),
-		{
-		    xtype: 'textfield',
-		    width: 200,
-		    enableKeyEvents: true,
-		    listeners: {
-			buffer: 500,
-			keyup: function(field) {
-			    var value = field.getValue().toLowerCase();
-			    store.clearFilter(true);
-			    store.filterBy(function(rec) {
-				return (rec.data['package'].toLowerCase().indexOf(value) !== -1)
-				|| (rec.data.headline.toLowerCase().indexOf(value) !== -1);
-			    });
-			}
-		    }
-		}
-	    ],
-	    features: [ groupingFeature ],
-	    columns: [
-		{
-		    header: gettext('Type'),
-		    width: 80,
-		    dataIndex: 'type'
-		},
-		{
-		    header: gettext('Package'),
-		    flex: 1,
-		    dataIndex: 'package'
-		},
-		{
-		    header: gettext('Version'),
-		    width: 80,
-		    dataIndex: 'version'
-		},
-		{
-		    header: gettext('Description'),
-		    flex: 1.5,
-		    renderer: Ext.String.htmlEncode,
-		    dataIndex: 'headline'
-		}
-	    ],
-	    listeners: {
-		afterRender: reload
-	    }
-	});
-
-	me.callParent();
-    }
-
-}, function() {
-
-    Ext.define('pve-aplinfo', {
-	extend: 'Ext.data.Model',
-	fields: [
-	    'template', 'type', 'package', 'version', 'headline', 'infopage',
-	    'description', 'os', 'section'
-	],
-	idProperty: 'template'
-    });
-
-});
-
-Ext.define('PVE.storage.TemplateDownload', {
-    extend: 'Ext.window.Window',
-    alias: 'widget.pveTemplateDownload',
-
-    modal: true,
-    title: gettext('Templates'),
-    layout: 'fit',
-    width: 900,
-    height: 600,
-    initComponent : function() {
-        var me = this;
-
-	var grid = Ext.create('PVE.grid.TemplateSelector', {
-	    border: false,
-	    scrollable: true,
-	    nodename: me.nodename
-	});
-
-	var sm = grid.getSelectionModel();
-
-	var submitBtn = Ext.create('Proxmox.button.Button', {
-	    text: gettext('Download'),
-	    disabled: true,
-	    selModel: sm,
-	    handler: function(button, event, rec) {
-		Proxmox.Utils.API2Request({
-		    url: '/nodes/' + me.nodename + '/aplinfo',
-		    params: {
-			storage: me.storage,
-			template: rec.data.template
-		    },
-		    method: 'POST',
-		    failure: function (response, opts) {
-			Ext.Msg.alert(gettext('Error'), response.htmlStatus);
-		    },
-		    success: function(response, options) {
-			var upid = response.result.data;
-
-			Ext.create('Proxmox.window.TaskViewer', {
-			    upid: upid,
-			    listeners: {
-				destroy: me.reloadGrid
-			    }
-			}).show();
-
-			me.close();
-		    }
-		});
-	    }
-	});
-
-        Ext.apply(me, {
-	    items: grid,
-	    buttons: [ submitBtn ]
-	});
-
-	me.callParent();
-    }
-});
-
 Ext.define('PVE.storage.Upload', {
     extend: 'Ext.window.Window',
     alias: 'widget.pveStorageUpload',
@@ -406,22 +239,6 @@ Ext.define('PVE.storage.ContentView', {
 
 	Proxmox.Utils.monStoreErrors(me, store);
 
-	var templateButton = Ext.create('Proxmox.button.Button',{
-	    itemId: 'tmpl-btn',
-	    text: gettext('Templates'),
-	    handler: function() {
-		var win = Ext.create('PVE.storage.TemplateDownload', {
-		    nodename: nodename,
-		    storage: storage,
-		    reloadGrid: reload
-		});
-		win.show();
-	    }
-	});
-	if (content !== 'vztmpl') {
-	    templateButton.setDisabled(true);
-	}
-
 	var uploadButton = Ext.create('Proxmox.button.Button', {
 	    text: gettext('Upload'),
 	    handler: function() {
@@ -540,7 +357,6 @@ Ext.define('PVE.storage.ContentView', {
 	    },
 	    removeButton,
 	    imageRemoveButton,
-	    templateButton,
 	    {
 		xtype: 'proxmoxButton',
 		text: gettext('Show Configuration'),
diff --git a/www/manager6/storage/TemplateView.js b/www/manager6/storage/TemplateView.js
new file mode 100644
index 00000000..f7b5efe8
--- /dev/null
+++ b/www/manager6/storage/TemplateView.js
@@ -0,0 +1,212 @@
+Ext.define('PVE.grid.TemplateSelector', {
+    extend: 'Ext.grid.GridPanel',
+
+    alias: 'widget.pveTemplateSelector',
+
+    stateful: true,
+    stateId: 'grid-template-selector',
+    viewConfig: {
+	trackOver: false
+    },
+    initComponent : function() {
+	var me = this;
+
+	if (!me.nodename) {
+	    throw "no node name specified";
+	}
+
+	var baseurl = "/nodes/" + me.nodename + "/aplinfo";
+	var store = new Ext.data.Store({
+	    model: 'pve-aplinfo',
+	    groupField: 'section',
+	    proxy: {
+                type: 'proxmox',
+		url: '/api2/json' + baseurl
+	    }
+	});
+
+	var sm = Ext.create('Ext.selection.RowModel', {});
+
+	var groupingFeature = Ext.create('Ext.grid.feature.Grouping',{
+            groupHeaderTpl: '{[ "Section: " + values.name ]} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
+	});
+
+	var reload = function() {
+	    store.load();
+	};
+
+	Proxmox.Utils.monStoreErrors(me, store);
+
+	Ext.apply(me, {
+	    store: store,
+	    selModel: sm,
+	    tbar: [
+		'->',
+		gettext('Search'),
+		{
+		    xtype: 'textfield',
+		    width: 200,
+		    enableKeyEvents: true,
+		    listeners: {
+			buffer: 500,
+			keyup: function(field) {
+			    var value = field.getValue().toLowerCase();
+			    store.clearFilter(true);
+			    store.filterBy(function(rec) {
+				return (rec.data['package'].toLowerCase().indexOf(value) !== -1)
+				|| (rec.data.headline.toLowerCase().indexOf(value) !== -1);
+			    });
+			}
+		    }
+		}
+	    ],
+	    features: [ groupingFeature ],
+	    columns: [
+		{
+		    header: gettext('Type'),
+		    width: 80,
+		    dataIndex: 'type'
+		},
+		{
+		    header: gettext('Package'),
+		    flex: 1,
+		    dataIndex: 'package'
+		},
+		{
+		    header: gettext('Version'),
+		    width: 80,
+		    dataIndex: 'version'
+		},
+		{
+		    header: gettext('Description'),
+		    flex: 1.5,
+		    renderer: Ext.String.htmlEncode,
+		    dataIndex: 'headline'
+		}
+	    ],
+	    listeners: {
+		afterRender: reload
+	    }
+	});
+
+	me.callParent();
+    }
+
+}, function() {
+
+    Ext.define('pve-aplinfo', {
+	extend: 'Ext.data.Model',
+	fields: [
+	    'template', 'type', 'package', 'version', 'headline', 'infopage',
+	    'description', 'os', 'section'
+	],
+	idProperty: 'template'
+    });
+
+});
+
+Ext.define('PVE.storage.TemplateDownload', {
+    extend: 'Ext.window.Window',
+    alias: 'widget.pveTemplateDownload',
+
+    modal: true,
+    title: gettext('Templates'),
+    layout: 'fit',
+    width: 900,
+    height: 600,
+    initComponent : function() {
+        var me = this;
+
+	var grid = Ext.create('PVE.grid.TemplateSelector', {
+	    border: false,
+	    scrollable: true,
+	    nodename: me.nodename
+	});
+
+	var sm = grid.getSelectionModel();
+
+	var submitBtn = Ext.create('Proxmox.button.Button', {
+	    text: gettext('Download'),
+	    disabled: true,
+	    selModel: sm,
+	    handler: function(button, event, rec) {
+		Proxmox.Utils.API2Request({
+		    url: '/nodes/' + me.nodename + '/aplinfo',
+		    params: {
+			storage: me.storage,
+			template: rec.data.template
+		    },
+		    method: 'POST',
+		    failure: function (response, opts) {
+			Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+		    },
+		    success: function(response, options) {
+			var upid = response.result.data;
+
+			Ext.create('Proxmox.window.TaskViewer', {
+			    upid: upid,
+			    listeners: {
+				destroy: me.reloadGrid
+			    }
+			}).show();
+
+			me.close();
+		    }
+		});
+	    }
+	});
+
+        Ext.apply(me, {
+	    items: grid,
+	    buttons: [ submitBtn ]
+	});
+
+	me.callParent();
+    }
+});
+
+Ext.define('PVE.storage.TemplateView', {
+    extend: 'PVE.storage.ContentView',
+
+    alias: 'widget.pveStorageTemplateView',
+
+    initComponent: function() {
+	var me = this;
+
+	var nodename = me.nodename = me.pveSelNode.data.node;
+	if (!nodename) {
+	    throw "no node name specified";
+	}
+
+	var storage = me.storage = me.pveSelNode.data.storage;
+	if (!storage) {
+	    throw "no storage ID specified";
+	}
+
+	me.content = 'vztmpl';
+
+	var sm = me.sm = Ext.create('Ext.selection.RowModel', {});
+
+	var reload = function() {
+	    me.store.load();
+	}
+
+	var templateButton = Ext.create('Proxmox.button.Button',{
+	    itemId: 'tmpl-btn',
+	    text: gettext('Templates'),
+	    handler: function() {
+		var win = Ext.create('PVE.storage.TemplateDownload', {
+		    nodename: nodename,
+		    storage: storage,
+		    reloadGrid: reload
+		});
+		win.show();
+	    }
+	});
+
+	me.tbar = [ templateButton ];
+	me.useUploadButton = true;
+
+	me.callParent();
+    },
+});
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 09/14] create and use backup view
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (7 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 08/14] create and use template view Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 10/14] get rid of unneccessary enableFns Fabian Ebner
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/Makefile               |  1 +
 www/manager6/storage/BackupView.js  | 77 +++++++++++++++++++++++++++++
 www/manager6/storage/Browser.js     |  3 +-
 www/manager6/storage/ContentView.js | 45 -----------------
 4 files changed, 79 insertions(+), 47 deletions(-)
 create mode 100644 www/manager6/storage/BackupView.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index cece0aae..26c91bef 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -217,6 +217,7 @@ JSSRC= 							\
 	sdn/zones/SimpleEdit.js				\
 	sdn/zones/VlanEdit.js				\
 	sdn/zones/VxlanEdit.js				\
+	storage/BackupView.js				\
 	storage/Base.js					\
 	storage/Browser.js				\
 	storage/CIFSEdit.js				\
diff --git a/www/manager6/storage/BackupView.js b/www/manager6/storage/BackupView.js
new file mode 100644
index 00000000..ea195e43
--- /dev/null
+++ b/www/manager6/storage/BackupView.js
@@ -0,0 +1,77 @@
+Ext.define('PVE.storage.BackupView', {
+    extend: 'PVE.storage.ContentView',
+
+    alias: 'widget.pveStorageBackupView',
+
+    initComponent: function() {
+	var me = this;
+
+	var nodename = me.nodename = me.pveSelNode.data.node;
+	if (!nodename) {
+	    throw "no node name specified";
+	}
+
+	var storage = me.storage = me.pveSelNode.data.storage;
+	if (!storage) {
+	    throw "no storage ID specified";
+	}
+
+	me.content = 'backup';
+
+	var sm = me.sm = Ext.create('Ext.selection.RowModel', {});
+
+	var reload = function() {
+	    me.store.load();
+	};
+
+	me.tbar = [
+	    {
+		xtype: 'proxmoxButton',
+		text: gettext('Restore'),
+		selModel: sm,
+		disabled: true,
+		enableFn: function(rec) {
+		    return rec && rec.data.content === 'backup';
+		},
+		handler: function(b, e, rec) {
+		    var vmtype;
+		    if (PVE.Utils.volume_is_qemu_backup(rec.data.volid, rec.data.format)) {
+			vmtype = 'qemu';
+		    } else if (PVE.Utils.volume_is_lxc_backup(rec.data.volid, rec.data.format)) {
+			vmtype = 'lxc';
+		    } else {
+			return;
+		    }
+
+		    var win = Ext.create('PVE.window.Restore', {
+			nodename: nodename,
+			volid: rec.data.volid,
+			volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
+			vmtype: vmtype
+		    });
+		    win.show();
+		    win.on('destroy', reload);
+		}
+	    },
+	    {
+		xtype: 'proxmoxButton',
+		text: gettext('Show Configuration'),
+		disabled: true,
+		selModel: sm,
+		enableFn: function(rec) {
+		    return rec && rec.data.content === 'backup';
+		},
+		handler: function(b,e,rec) {
+		    var win = Ext.create('PVE.window.BackupConfig', {
+			volume: rec.data.volid,
+			pveSelNode: me.pveSelNode
+		    });
+
+		    win.show();
+		}
+	    },
+	];
+
+	me.callParent();
+    },
+});
diff --git a/www/manager6/storage/Browser.js b/www/manager6/storage/Browser.js
index 4393558c..4536392c 100644
--- a/www/manager6/storage/Browser.js
+++ b/www/manager6/storage/Browser.js
@@ -51,11 +51,10 @@ Ext.define('PVE.storage.Browser', {
 
 		    if (contents.includes('backup')) {
 			items.push({
-			    xtype: 'pveStorageContentView',
+			    xtype: 'pveStorageBackupView',
 			    title: PVE.Utils.contentTypes['backup'],
 			    iconCls: 'fa fa-th',
 			    itemId: 'contentBackup',
-			    content: 'backup',
 			});
 		    }
 		    if (contents.includes('images')) {
diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index 03b595f8..c78ac398 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -327,53 +327,8 @@ Ext.define('PVE.storage.ContentView', {
 	    me.tbar.push(uploadButton);
 	}
 	me.tbar.push(
-	    {
-		xtype: 'proxmoxButton',
-		text: gettext('Restore'),
-		selModel: sm,
-		disabled: true,
-		enableFn: function(rec) {
-		    return rec && rec.data.content === 'backup';
-		},
-		handler: function(b, e, rec) {
-		    var vmtype;
-		    if (PVE.Utils.volume_is_qemu_backup(rec.data.volid, rec.data.format)) {
-			vmtype = 'qemu';
-		    } else if (PVE.Utils.volume_is_lxc_backup(rec.data.volid, rec.data.format)) {
-			vmtype = 'lxc';
-		    } else {
-			return;
-		    }
-
-		    var win = Ext.create('PVE.window.Restore', {
-			nodename: nodename,
-			volid: rec.data.volid,
-			volidText: PVE.Utils.render_storage_content(rec.data.volid, {}, rec),
-			vmtype: vmtype
-		    });
-		    win.show();
-		    win.on('destroy', reload);
-		}
-	    },
 	    removeButton,
 	    imageRemoveButton,
-	    {
-		xtype: 'proxmoxButton',
-		text: gettext('Show Configuration'),
-		disabled: true,
-		selModel: sm,
-		enableFn: function(rec) {
-		    return rec && rec.data.content === 'backup';
-		},
-		handler: function(b,e,rec) {
-		    var win = Ext.create('PVE.window.BackupConfig', {
-			volume: rec.data.volid,
-			pveSelNode: me.pveSelNode
-		    });
-
-		    win.show();
-		}
-	    },
 	    '->',
 	    gettext('Search') + ':', ' ',
 	    {
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 10/14] get rid of unneccessary enableFns
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (8 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 09/14] create and use backup view Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 11/14] create ImageView and use it for VM and CT images Fabian Ebner
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

There's only backups in this view.

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/storage/BackupView.js | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/www/manager6/storage/BackupView.js b/www/manager6/storage/BackupView.js
index ea195e43..8c1e2ed6 100644
--- a/www/manager6/storage/BackupView.js
+++ b/www/manager6/storage/BackupView.js
@@ -30,9 +30,6 @@ Ext.define('PVE.storage.BackupView', {
 		text: gettext('Restore'),
 		selModel: sm,
 		disabled: true,
-		enableFn: function(rec) {
-		    return rec && rec.data.content === 'backup';
-		},
 		handler: function(b, e, rec) {
 		    var vmtype;
 		    if (PVE.Utils.volume_is_qemu_backup(rec.data.volid, rec.data.format)) {
@@ -58,9 +55,6 @@ Ext.define('PVE.storage.BackupView', {
 		text: gettext('Show Configuration'),
 		disabled: true,
 		selModel: sm,
-		enableFn: function(rec) {
-		    return rec && rec.data.content === 'backup';
-		},
 		handler: function(b,e,rec) {
 		    var win = Ext.create('PVE.window.BackupConfig', {
 			volume: rec.data.volid,
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 11/14] create ImageView and use it for VM and CT images
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (9 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 10/14] get rid of unneccessary enableFns Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 12/14] simplify reload call Fabian Ebner
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

The enableFns that were responsible for switching
between the image remove button and the standard remove button
are not needed anymore.

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---

use --color-moved=zebra --color-moved-ws=ignore-all-space for
better readability.

 www/manager6/Makefile               |  1 +
 www/manager6/storage/Browser.js     |  4 +-
 www/manager6/storage/ContentView.js | 64 ++----------------------
 www/manager6/storage/ImageView.js   | 76 +++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+), 63 deletions(-)
 create mode 100644 www/manager6/storage/ImageView.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 26c91bef..4b9dcf58 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -225,6 +225,7 @@ JSSRC= 							\
 	storage/ContentView.js				\
 	storage/DirEdit.js				\
 	storage/GlusterFsEdit.js			\
+	storage/ImageView.js				\
 	storage/IScsiEdit.js				\
 	storage/LVMEdit.js				\
 	storage/LvmThinEdit.js				\
diff --git a/www/manager6/storage/Browser.js b/www/manager6/storage/Browser.js
index 4536392c..f0d81418 100644
--- a/www/manager6/storage/Browser.js
+++ b/www/manager6/storage/Browser.js
@@ -59,7 +59,7 @@ Ext.define('PVE.storage.Browser', {
 		    }
 		    if (contents.includes('images')) {
 			items.push({
-			    xtype: 'pveStorageContentView',
+			    xtype: 'pveStorageImageView',
 			    title: PVE.Utils.contentTypes['images'],
 			    iconCls: 'fa fa-th',
 			    itemId: 'contentImages',
@@ -78,7 +78,7 @@ Ext.define('PVE.storage.Browser', {
 		    }
 		    if (contents.includes('rootdir')) {
 			items.push({
-			    xtype: 'pveStorageContentView',
+			    xtype: 'pveStorageImageView',
 			    title: PVE.Utils.contentTypes['rootdir'],
 			    iconCls: 'fa fa-th',
 			    itemId: 'contentRootdir',
diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index c78ac398..f9e28b97 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -252,83 +252,25 @@ Ext.define('PVE.storage.ContentView', {
 	    }
 	});
 
-	var imageRemoveButton;
 	var removeButton = Ext.create('Proxmox.button.StdRemoveButton',{
 	    selModel: sm,
 	    delay: 5,
-	    enableFn: function(rec) {
-		if (rec && rec.data.content !== 'images' &&
-			   rec.data.content !== 'rootdir') {
-		    imageRemoveButton.setVisible(false);
-		    removeButton.setVisible(true);
-		    return true;
-		}
-		return false;
-	    },
 	    callback: function() {
 		reload();
 	    },
 	    baseurl: baseurl + '/'
 	});
 
-	imageRemoveButton = Ext.create('Proxmox.button.Button',{
-	    selModel: sm,
-	    hidden: true,
-	    text: gettext('Remove'),
-	    enableFn: function(rec) {
-		if (rec && (rec.data.content === 'images' ||
-			    rec.data.content === 'rootdir')) {
-		    removeButton.setVisible(false);
-		    imageRemoveButton.setVisible(true);
-		    return true;
-		}
-		return false;
-	    },
-	    handler: function(btn, event, rec) {
-		var url = baseurl + '/' + rec.data.volid;
-		var vmid = rec.data.vmid;
-
-		var store = PVE.data.ResourceStore;
-
-		if (vmid && store.findVMID(vmid)) {
-		    var guest_node = store.guestNode(vmid);
-		    var storage_path = 'storage/' + nodename + '/' + storage;
-
-		    // allow to delete local backed images if a VMID exists on another node.
-		    if (store.storageIsShared(storage_path) || guest_node == nodename) {
-			var msg = Ext.String.format(
-			    gettext("Cannot remove image, a guest with VMID '{0}' exists!"), vmid);
-			msg += '<br />' + gettext("You can delete the image from the guest's hardware pane");
-
-			Ext.Msg.show({
-			    title: gettext('Cannot remove disk image.'),
-			    icon: Ext.Msg.ERROR,
-			    msg: msg
-			});
-			return;
-		    }
-		}
-		var win = Ext.create('PVE.window.SafeDestroy', {
-		    title: Ext.String.format(gettext("Destroy '{0}'"), rec.data.volid),
-		    showProgress: true,
-		    url: url,
-		    item: { type: 'Image', id: vmid }
-		}).show();
-		win.on('destroy', function() {
-		    reload();
-		});
-	    }
-	});
-
 	if (!me.tbar) {
 	    me.tbar = [];
 	}
 	if (me.useUploadButton) {
 	    me.tbar.push(uploadButton);
 	}
+	if (!me.useCustomRemoveButton) {
+	    me.tbar.push(removeButton);
+	}
 	me.tbar.push(
-	    removeButton,
-	    imageRemoveButton,
 	    '->',
 	    gettext('Search') + ':', ' ',
 	    {
diff --git a/www/manager6/storage/ImageView.js b/www/manager6/storage/ImageView.js
new file mode 100644
index 00000000..97dae567
--- /dev/null
+++ b/www/manager6/storage/ImageView.js
@@ -0,0 +1,76 @@
+Ext.define('PVE.storage.ImageView', {
+    extend: 'PVE.storage.ContentView',
+
+    alias: 'widget.pveStorageImageView',
+
+    initComponent: function() {
+	var me = this;
+
+	var nodename = me.nodename = me.pveSelNode.data.node;
+	if (!me.nodename) {
+	    throw "no node name specified";
+	}
+
+	var storage = me.storage = me.pveSelNode.data.storage;
+	if (!me.storage) {
+	    throw "no storage ID specified";
+	}
+
+	if (!me.content || (me.content !== 'images' && me.content !== 'rootdir')) {
+	    throw "content needs to be either 'images' or 'rootdir'";
+	}
+
+	var sm = me.sm = Ext.create('Ext.selection.RowModel', {});
+
+	var reload = function() {
+	    me.store.load();
+	}
+
+	me.tbar = [
+	    {
+		xtype: 'proxmoxButton',
+		selModel: sm,
+		text: gettext('Remove'),
+		disabled: true,
+		handler: function(btn, event, rec) {
+		    var url = "/nodes/" + nodename + "/storage/" + storage +
+			      "/content" + '/' + rec.data.volid;
+		    var vmid = rec.data.vmid;
+
+		    var store = PVE.data.ResourceStore;
+
+		    if (vmid && store.findVMID(vmid)) {
+			var guest_node = store.guestNode(vmid);
+			var storage_path = 'storage/' + nodename + '/' + storage;
+
+			// allow to delete local backed images if a VMID exists on another node.
+			if (store.storageIsShared(storage_path) || guest_node == nodename) {
+			    var msg = Ext.String.format(
+				gettext("Cannot remove image, a guest with VMID '{0}' exists!"), vmid);
+			    msg += '<br />' + gettext("You can delete the image from the guest's hardware pane");
+
+			    Ext.Msg.show({
+				title: gettext('Cannot remove disk image.'),
+				icon: Ext.Msg.ERROR,
+				msg: msg
+			    });
+			    return;
+			}
+		    }
+		    var win = Ext.create('PVE.window.SafeDestroy', {
+			title: Ext.String.format(gettext("Destroy '{0}'"), rec.data.volid),
+			showProgress: true,
+			url: url,
+			item: { type: 'Image', id: vmid }
+		    }).show();
+		    win.on('destroy', function() {
+			reload();
+		    });
+		}
+	    },
+	];
+	me.useCustomRemoveButton = true;
+
+	me.callParent();
+    },
+});
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 12/14] simplify reload call
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (10 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 11/14] create ImageView and use it for VM and CT images Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [RFC manager 13/14] content view: allow specifying which columns to show on init Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 14/14] backup view: add prune window Fabian Ebner
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/storage/ImageView.js | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/www/manager6/storage/ImageView.js b/www/manager6/storage/ImageView.js
index 97dae567..d9f19035 100644
--- a/www/manager6/storage/ImageView.js
+++ b/www/manager6/storage/ImageView.js
@@ -63,9 +63,7 @@ Ext.define('PVE.storage.ImageView', {
 			url: url,
 			item: { type: 'Image', id: vmid }
 		    }).show();
-		    win.on('destroy', function() {
-			reload();
-		    });
+		    win.on('destroy', reload);
 		}
 	    },
 	];
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [RFC manager 13/14] content view: allow specifying which columns to show on init
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (11 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 12/14] simplify reload call Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  2020-09-02 11:03 ` [pve-devel] [PATCH manager 14/14] backup view: add prune window Fabian Ebner
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

depending on the content type we might want to show different
information, e.g. parent for cloned VM/CT images

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/storage/ContentView.js | 72 ++++++++++++++++-------------
 1 file changed, 41 insertions(+), 31 deletions(-)

diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index f9e28b97..ddbce259 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -294,41 +294,51 @@ Ext.define('PVE.storage.ContentView', {
 	    }
 	);
 
+	var availableColumns = {
+	    'name': {
+		header: gettext('Name'),
+		flex: 1,
+		sortable: true,
+		renderer: PVE.Utils.render_storage_content,
+		dataIndex: 'text'
+	    },
+	    'date': {
+		header: gettext('Date'),
+		width: 150,
+		dataIndex: 'vdate'
+	    },
+	    'format': {
+		header: gettext('Format'),
+		width: 100,
+		dataIndex: 'format'
+	    },
+	    'type': {
+		header: gettext('Type'),
+		width: 100,
+		dataIndex: 'content',
+		renderer: PVE.Utils.format_content_types
+	    },
+	    'size': {
+		header: gettext('Size'),
+		width: 100,
+		renderer: Proxmox.Utils.format_size,
+		dataIndex: 'size'
+	    },
+	};
+
+	if (!me.showColumns) {
+	    me.showColumns = ['name', 'date', 'format', 'type', 'size'];
+	}
+	var columns = [];
+	me.showColumns.forEach(function(datum) {
+	    columns.push(availableColumns[datum]);
+	});
+
 	Ext.apply(me, {
 	    store: store,
 	    selModel: sm,
 	    tbar: me.tbar,
-	    columns: [
-		{
-		    header: gettext('Name'),
-		    flex: 1,
-		    sortable: true,
-		    renderer: PVE.Utils.render_storage_content,
-		    dataIndex: 'text'
-		},
-		{
-		    header: gettext('Date'),
-		    width: 150,
-		    dataIndex: 'vdate'
-		},
-		{
-		    header: gettext('Format'),
-		    width: 100,
-		    dataIndex: 'format'
-		},
-		{
-		    header: gettext('Type'),
-		    width: 100,
-		    dataIndex: 'content',
-		    renderer: PVE.Utils.format_content_types
-		},
-		{
-		    header: gettext('Size'),
-		    width: 100,
-		    renderer: Proxmox.Utils.format_size,
-		    dataIndex: 'size'
-		}
-	    ],
+	    columns: columns,
 	    listeners: {
 		activate: reload
 	    }
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [pve-devel] [PATCH manager 14/14] backup view: add prune window
  2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
                   ` (12 preceding siblings ...)
  2020-09-02 11:03 ` [pve-devel] [RFC manager 13/14] content view: allow specifying which columns to show on init Fabian Ebner
@ 2020-09-02 11:03 ` Fabian Ebner
  13 siblings, 0 replies; 15+ messages in thread
From: Fabian Ebner @ 2020-09-02 11:03 UTC (permalink / raw)
  To: pve-devel

adapted from PBS. Main differences are:
1. keep-last defaults to 1 to avoid error on load
2. keep options are loaded from the storage configuration if there are any
3. API has GET/DELETE distinction instead of 'dry-run'
4. API expects a single property string for the prune options

Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
---
 www/manager6/Makefile              |   1 +
 www/manager6/storage/BackupView.js |  25 ++++
 www/manager6/window/Prune.js       | 230 +++++++++++++++++++++++++++++
 3 files changed, 256 insertions(+)
 create mode 100644 www/manager6/window/Prune.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 4b9dcf58..b34bb41d 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -249,6 +249,7 @@ JSSRC= 							\
 	window/LoginWindow.js				\
 	window/Migrate.js				\
 	window/NotesEdit.js				\
+	window/Prune.js					\
 	window/Restore.js				\
 	window/SafeDestroy.js				\
 	window/Settings.js				\
diff --git a/www/manager6/storage/BackupView.js b/www/manager6/storage/BackupView.js
index 8c1e2ed6..6bf26167 100644
--- a/www/manager6/storage/BackupView.js
+++ b/www/manager6/storage/BackupView.js
@@ -64,6 +64,31 @@ Ext.define('PVE.storage.BackupView', {
 		    win.show();
 		}
 	    },
+	    {
+		xtype: 'proxmoxButton',
+		text: gettext('Prune'),
+		selModel: sm,
+		disabled: true,
+		handler: function(b, e, rec) {
+		    var backup_type;
+		    if (PVE.Utils.volume_is_qemu_backup(rec.data.volid, rec.data.format)) {
+			backup_type = 'qemu';
+		    } else if (PVE.Utils.volume_is_lxc_backup(rec.data.volid, rec.data.format)) {
+			backup_type = 'lxc';
+		    } else {
+			return;
+		    }
+
+		    var win = Ext.create('PVE.window.Prune', {
+			nodename: nodename,
+			storage: storage,
+			backup_id: rec.data.vmid,
+			backup_type: backup_type,
+		    });
+		    win.show();
+		    win.on('destroy', reload);
+		},
+	    },
 	];
 
 	me.callParent();
diff --git a/www/manager6/window/Prune.js b/www/manager6/window/Prune.js
new file mode 100644
index 00000000..4c90f87a
--- /dev/null
+++ b/www/manager6/window/Prune.js
@@ -0,0 +1,230 @@
+Ext.define('pve-prune-list', {
+    extend: 'Ext.data.Model',
+    fields: [
+	'backup-type',
+	'backup-id',
+	{
+	    name: 'ctime',
+	    type: 'date',
+	    dateFormat: 'timestamp',
+	},
+    ],
+});
+
+Ext.define('PVE.PruneInputPanel', {
+    extend: 'Proxmox.panel.InputPanel',
+    alias: 'widget.pvePruneInputPanel',
+    mixins: ['Proxmox.Mixin.CBind'],
+
+    onGetValues: function(values) {
+	var me = this;
+
+	// the API expects a single prune-backups property string
+	let prune_opts = PVE.Parser.printPropertyString(values);
+	values = {};
+	values["prune-backups"] = prune_opts;
+	values.type = me.backup_type;
+	values.vmid = me.backup_id;
+
+	return values;
+    },
+
+    controller: {
+	xclass: 'Ext.app.ViewController',
+
+	init: function(view) {
+	    if (!view.url) {
+		throw "no url specified";
+	    }
+	    if (!view.backup_type) {
+		throw "no backup_type specified";
+	    }
+	    if (!view.backup_id) {
+		throw "no backup_id specified";
+	    }
+
+	    this.reload(); // initial load
+	},
+
+	reload: function() {
+	    var view = this.getView();
+
+	    let params = view.getValues();
+
+	    Proxmox.Utils.API2Request({
+		url: view.url,
+		method: "GET",
+		params: params,
+		callback: function() {
+		    return; // for easy breakpoint setting
+		},
+		failure: function(response, opts) {
+		    Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+		},
+		success: function(response, options) {
+		    var data = response.result.data;
+		    view.prune_store.setData(data);
+		},
+	    });
+	},
+
+	control: {
+	    field: { change: 'reload' },
+	},
+    },
+
+    column1: [
+	{
+	    xtype: 'proxmoxintegerfield',
+	    name: 'keep-last',
+	    allowBlank: true,
+	    fieldLabel: gettext('keep-last'),
+	    value: 1,
+	    minValue: 1,
+	},
+	{
+	    xtype: 'proxmoxintegerfield',
+	    name: 'keep-hourly',
+	    allowBlank: true,
+	    fieldLabel: gettext('keep-hourly'),
+	    minValue: 1,
+	},
+	{
+	    xtype: 'proxmoxintegerfield',
+	    name: 'keep-daily',
+	    allowBlank: true,
+	    fieldLabel: gettext('keep-daily'),
+	    minValue: 1,
+	},
+	{
+	    xtype: 'proxmoxintegerfield',
+	    name: 'keep-weekly',
+	    allowBlank: true,
+	    fieldLabel: gettext('keep-weekly'),
+	    minValue: 1,
+	},
+	{
+	    xtype: 'proxmoxintegerfield',
+	    name: 'keep-monthly',
+	    allowBlank: true,
+	    fieldLabel: gettext('keep-monthly'),
+	    minValue: 1,
+	},
+	{
+	    xtype: 'proxmoxintegerfield',
+	    name: 'keep-yearly',
+	    allowBlank: true,
+	    fieldLabel: gettext('keep-yearly'),
+	    minValue: 1,
+	},
+    ],
+
+    initComponent: function() {
+        var me = this;
+
+	me.prune_store = Ext.create('Ext.data.Store', {
+	    model: 'pve-prune-list',
+	    sorters: { property: 'ctime', direction: 'DESC' },
+	});
+
+	Proxmox.Utils.API2Request({
+	    url: "/storage",
+	    method: 'GET',
+	    success: function(response, opts) {
+		let scfg = response.result.data.find(x => x.storage === me.storage);
+		if (!scfg || !scfg["prune-backups"]) {
+		    return;
+		}
+		let prune_opts = PVE.Parser.parsePropertyString(scfg["prune-backups"]);
+		me.setValues(prune_opts);
+	    },
+	});
+
+	me.column2 = [
+	    {
+		xtype: 'grid',
+		height: 200,
+		store: me.prune_store,
+		columns: [
+		    {
+			header: gettext('Backup Time'),
+			sortable: true,
+			dataIndex: 'ctime',
+			renderer: function(value, metaData, record) {
+			    let text = Ext.Date.format(value, 'Y-m-d H:i:s');
+			    if (record.data.mark === 'remove') {
+				return '<div style="text-decoration: line-through;">'+ text +'</div>';
+			    } else {
+				return text;
+			    }
+			},
+			flex: 1,
+		    },
+		    {
+			text: "keep",
+			dataIndex: 'mark',
+		    },
+		],
+	    },
+	];
+
+	me.callParent();
+    },
+});
+
+Ext.define('PVE.window.Prune', {
+    extend: 'Proxmox.window.Edit',
+
+    method: 'DELETE',
+    submitText: gettext("Prune"),
+
+    isCreate: true,
+
+    initComponent: function() {
+        var me = this;
+
+	if (!me.nodename) {
+	    throw "no nodename specified";
+	}
+	if (!me.storage) {
+	    throw "no storage specified";
+	}
+	if (!me.backup_type) {
+	    throw "no backup_type specified";
+	}
+	if (!me.backup_id) {
+	    throw "no backup_id specified";
+	}
+
+	let backup_type_str;
+	if (me.backup_type === 'qemu') {
+	    backup_type_str = 'VM';
+	} else if (me.backup_type === 'lxc') {
+	    backup_type_str = 'CT';
+	} else {
+	    throw "unknown backup type";
+	}
+	let backup_group_str = backup_type_str + '/' + me.backup_id;
+	let title = Ext.String.format(
+	    gettext("Prune Backups for '{0}' on Storage '{1}'"),
+	    backup_group_str,
+	    me.storage,
+	);
+
+	Ext.apply(me, {
+	    url: '/api2/extjs/nodes/' + me.nodename + '/storage/' + me.storage + "/prunebackups",
+	    title: title,
+	    items: [
+		{
+		    xtype: 'pvePruneInputPanel',
+		    url: '/api2/extjs/nodes/' + me.nodename + '/storage/' + me.storage + "/prunebackups",
+		    backup_type: me.backup_type,
+		    backup_id: me.backup_id,
+		    storage: me.storage,
+		},
+	    ],
+	});
+
+	me.callParent();
+    },
+});
-- 
2.20.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-09-02 11:04 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-02 11:03 [pve-devel] [PATCH-SERIES/RFC manager 00/14] split up content view into a view for each type Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 01/14] config panel: allow new nodes to be added later Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 02/14] storage panel/browser: use insertNodes function Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 03/14] use separate view for each content type Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 04/14] remove the now unneccessary grouping Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 05/14] content view: allow specifying title bar elements for init Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 06/14] turn nodename, storage, sm into object variables Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 07/14] add upload button conditionally Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 08/14] create and use template view Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 09/14] create and use backup view Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 10/14] get rid of unneccessary enableFns Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 11/14] create ImageView and use it for VM and CT images Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 12/14] simplify reload call Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [RFC manager 13/14] content view: allow specifying which columns to show on init Fabian Ebner
2020-09-02 11:03 ` [pve-devel] [PATCH manager 14/14] backup view: add prune window Fabian Ebner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal