* [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