public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel
@ 2020-11-09 15:01 Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 01/10] api2/node/tasks: add check_job_store and use it Dominik Csapak
                   ` (10 more replies)
  0 siblings, 11 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

this make 'Datastore' clickable again, and shows an overview
for all datastores, as well as a global sync/verify/acl view

Dominik Csapak (10):
  api2/node/tasks: add check_job_store and use it
  ui: refactor render_estimate
  ui: refactor render_size_usage to Utils
  ui: Utils: add parse_datastore_worker_id
  ui: make Sync/VerifyView and Edit usable without datastore
  ui: TaskSummary: move state/types/titles out of the controller
  ui: TaskSummary: add subPanelModal and datastore parameters
  ui: TaskSummary: handle less defined parameters of tasks
  ui: add Panels necessary for Datastores Overview
  ui: make Datastore clickable again

 src/api2/node/tasks.rs                |  47 ++++--
 www/Makefile                          |   2 +
 www/NavigationTree.js                 |   4 +-
 www/Utils.js                          |  63 +++++++
 www/config/SyncView.js                |   8 +-
 www/config/VerifyView.js              |   8 +-
 www/dashboard/DataStoreStatistics.js  |  20 +--
 www/dashboard/TaskSummary.js          |  90 ++++++----
 www/datastore/DataStoreList.js        | 229 ++++++++++++++++++++++++++
 www/datastore/DataStoreListSummary.js | 138 ++++++++++++++++
 www/datastore/Summary.js              |  13 +-
 www/window/SyncJobEdit.js             |  11 +-
 www/window/VerifyJobEdit.js           |  11 +-
 13 files changed, 552 insertions(+), 92 deletions(-)
 create mode 100644 www/datastore/DataStoreList.js
 create mode 100644 www/datastore/DataStoreListSummary.js

-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 01/10] api2/node/tasks: add check_job_store and use it
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 02/10] ui: refactor render_estimate Dominik Csapak
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

to easily check the store of a worker_id
this fixes the issue that one could not filter by type 'syncjob' and
datastore simultaneously

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/api2/node/tasks.rs | 47 ++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 15 deletions(-)

diff --git a/src/api2/node/tasks.rs b/src/api2/node/tasks.rs
index 4e023fbf..3f06ec70 100644
--- a/src/api2/node/tasks.rs
+++ b/src/api2/node/tasks.rs
@@ -71,6 +71,36 @@ fn check_job_privs(auth_id: &Authid, user_info: &CachedUserInfo, upid: &UPID) ->
     bail!("not a scheduled job task");
 }
 
+// get the store out of the worker_id
+fn check_job_store(upid: &UPID, store: &str) -> bool {
+    match (upid.worker_type.as_str(), &upid.worker_id) {
+        (workertype, Some(workerid)) if workertype.starts_with("verif") => {
+            if let Some(captures) = VERIFICATION_JOB_WORKER_ID_REGEX.captures(&workerid) {
+                if let Some(jobstore) = captures.get(1) {
+                    return store == jobstore.as_str();
+                }
+            } else {
+                return workerid == store;
+            }
+        }
+        ("syncjob", Some(workerid)) => {
+            if let Some(captures) = SYNC_JOB_WORKER_ID_REGEX.captures(&workerid) {
+                if let Some(local_store) = captures.get(3) {
+                    return store == local_store.as_str();
+                }
+            }
+        }
+        ("prune", Some(workerid))
+        | ("backup", Some(workerid))
+        | ("garbage_collection", Some(workerid)) => {
+            return workerid == store || workerid.starts_with(&format!("{}:", store));
+        }
+        _ => {}
+    };
+
+    false
+}
+
 fn check_task_access(auth_id: &Authid, upid: &UPID) -> Result<(), Error> {
     let task_auth_id = &upid.auth_id;
     if auth_id == task_auth_id
@@ -455,21 +485,8 @@ pub fn list_tasks(
         }
 
         if let Some(store) = store {
-            // Note: useful to select all tasks spawned by proxmox-backup-client
-            let worker_id = match &info.upid.worker_id {
-                Some(w) => w,
-                None => return None, // skip
-            };
-
-            if info.upid.worker_type == "backup" || info.upid.worker_type == "restore" ||
-                info.upid.worker_type == "prune"
-            {
-                let prefix = format!("{}:", store);
-                if !worker_id.starts_with(&prefix) { return None; }
-            } else if info.upid.worker_type == "garbage_collection" {
-                if worker_id != store { return None; }
-            } else {
-                return None; // skip
+            if !check_job_store(&info.upid, store) {
+                return None;
             }
         }
 
-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 02/10] ui: refactor render_estimate
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 01/10] api2/node/tasks: add check_job_store and use it Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 03/10] ui: refactor render_size_usage to Utils Dominik Csapak
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/Utils.js                         | 18 ++++++++++++++++++
 www/dashboard/DataStoreStatistics.js | 20 +-------------------
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/www/Utils.js b/www/Utils.js
index 3d370781..3d7e6824 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -167,6 +167,24 @@ Ext.define('PBS.Utils', {
 	return tokenid.match(/^(.+)!([^!]+)$/)[2];
     },
 
+    render_estimate: function(value) {
+	if (!value) {
+	    return gettext('Not enough data');
+	}
+
+	let now = new Date();
+	let estimate = new Date(value*1000);
+
+	let timespan = (estimate - now)/1000;
+
+	if (Number(estimate) <= Number(now) || isNaN(timespan)) {
+	    return gettext('Never');
+	}
+
+	let duration = Proxmox.Utils.format_duration_human(timespan);
+	return Ext.String.format(gettext("in {0}"), duration);
+    },
+
     constructor: function() {
 	var me = this;
 
diff --git a/www/dashboard/DataStoreStatistics.js b/www/dashboard/DataStoreStatistics.js
index 3aaa3c9b..13e1d160 100644
--- a/www/dashboard/DataStoreStatistics.js
+++ b/www/dashboard/DataStoreStatistics.js
@@ -47,24 +47,6 @@ Ext.define('PBS.DatastoreStatistics', {
     controller: {
 	xclass: 'Ext.app.ViewController',
 
-	render_estimate: function(value) {
-	    if (!value) {
-		return gettext('Not enough data');
-	    }
-
-	    let now = new Date();
-	    let estimate = new Date(value*1000);
-
-	    let timespan = (estimate - now)/1000;
-
-	    if (Number(estimate) <= Number(now) || isNaN(timespan)) {
-		return gettext('Never');
-	    }
-
-	    let duration = Proxmox.Utils.format_duration_human(timespan);
-	    return Ext.String.format(gettext("in {0}"), duration);
-	},
-
 	init: function(view) {
 	    Proxmox.Utils.monStoreErrors(view, view.getStore().rstore);
 	},
@@ -111,7 +93,7 @@ Ext.define('PBS.DatastoreStatistics', {
 	    text: gettext('Estimated Full'),
 	    dataIndex: 'estimated-full-date',
 	    sortable: true,
-	    renderer: 'render_estimate',
+	    renderer: PBS.Utils.render_estimate,
 	    flex: 1,
 	    minWidth: 130,
 	    maxWidth: 200,
-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 03/10] ui: refactor render_size_usage to Utils
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 01/10] api2/node/tasks: add check_job_store and use it Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 02/10] ui: refactor render_estimate Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 04/10] ui: Utils: add parse_datastore_worker_id Dominik Csapak
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/Utils.js             |  9 +++++++++
 www/datastore/Summary.js | 13 +------------
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/www/Utils.js b/www/Utils.js
index 3d7e6824..8b87f1bf 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -185,6 +185,15 @@ Ext.define('PBS.Utils', {
 	return Ext.String.format(gettext("in {0}"), duration);
     },
 
+    render_size_usage: function(val, max) {
+	if (max === 0) {
+	    return gettext('N/A');
+	}
+	return (val*100/max).toFixed(2) + '% (' +
+	    Ext.String.format(gettext('{0} of {1}'),
+	    Proxmox.Utils.format_size(val), Proxmox.Utils.format_size(max)) + ')';
+    },
+
     constructor: function() {
 	var me = this;
 
diff --git a/www/datastore/Summary.js b/www/datastore/Summary.js
index 4a89460c..ac3f19e2 100644
--- a/www/datastore/Summary.js
+++ b/www/datastore/Summary.js
@@ -51,18 +51,7 @@ Ext.define('PBS.DataStoreInfo', {
 	    let total = store.getById('total').data.value;
 	    let used = store.getById('used').data.value;
 
-	    let percent = 100*used/total;
-	    if (total === 0) {
-		percent = 0;
-	    }
-	    let used_percent = `${percent.toFixed(2)}%`;
-
-	    let usage = used_percent + ' (' +
-		Ext.String.format(
-		    gettext('{0} of {1}'),
-		    Proxmox.Utils.format_size(used),
-		    Proxmox.Utils.format_size(total),
-		) + ')';
+	    let usage = PBS.Utils.render_size_usage(used, total);
 	    vm.set('usagetext', usage);
 	    vm.set('usage', used/total);
 
-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 04/10] ui: Utils: add parse_datastore_worker_id
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
                   ` (2 preceding siblings ...)
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 03/10] ui: refactor render_size_usage to Utils Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 05/10] ui: make Sync/VerifyView and Edit usable without datastore Dominik Csapak
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

to parse the datastore out of a worker_id
for this we need some regexes that are the same as in the backend

for now we only parse out the datastore, but we can extend this
in the future to parse relevant info (e.g. remote for syncs,
id/type for backups)

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/Utils.js | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/www/Utils.js b/www/Utils.js
index 8b87f1bf..d459eec7 100644
--- a/www/Utils.js
+++ b/www/Utils.js
@@ -159,6 +159,34 @@ Ext.define('PBS.Utils', {
 	return `Datastore ${what} ${id}`;
     },
 
+    parse_datastore_worker_id: function(type, id) {
+	let result;
+	let res;
+	if (type.startsWith('verif')) {
+	    res = PBS.Utils.VERIFICATION_JOB_ID_RE.exec(id);
+	    if (res) {
+		result = res[1];
+	    }
+	} else if (type.startsWith('sync')) {
+	    res = PBS.Utils.SYNC_JOB_ID_RE.exec(id);
+	    if (res) {
+		result = res[3];
+	    }
+	} else if (type === 'backup') {
+	    res = PBS.Utils.BACKUP_JOB_ID_RE.exec(id);
+	    if (res) {
+		result = res[1];
+	    }
+	} else if (type === 'garbage_collection') {
+	    return id;
+	} else if (type === 'prune') {
+	    return id;
+	}
+
+
+	return result;
+    },
+
     extractTokenUser: function(tokenid) {
 	return tokenid.match(/^(.+)!([^!]+)$/)[1];
     },
@@ -197,6 +225,14 @@ Ext.define('PBS.Utils', {
     constructor: function() {
 	var me = this;
 
+	let PROXMOX_SAFE_ID_REGEX = "([A-Za-z0-9_][A-Za-z0-9._-]*)";
+	// only anchored at beginning
+	// only parses datastore for now
+	me.VERIFICATION_JOB_ID_RE = new RegExp("^" + PROXMOX_SAFE_ID_REGEX + ':?');
+	me.SYNC_JOB_ID_RE = new RegExp("^" + PROXMOX_SAFE_ID_REGEX + ':' +
+	    PROXMOX_SAFE_ID_REGEX + ':' + PROXMOX_SAFE_ID_REGEX + ':');
+	me.BACKUP_JOB_ID_RE = new RegExp("^" + PROXMOX_SAFE_ID_REGEX + ':');
+
 	// do whatever you want here
 	Proxmox.Utils.override_task_descriptions({
 	    backup: (type, id) => PBS.Utils.render_datastore_worker_id(id, gettext('Backup')),
-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 05/10] ui: make Sync/VerifyView and Edit usable without datastore
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
                   ` (3 preceding siblings ...)
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 04/10] ui: Utils: add parse_datastore_worker_id Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 06/10] ui: TaskSummary: move state/types/titles out of the controller Dominik Csapak
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

we want to use this panel again for a 'global' overview, without
any datastore preselected, so we have to handle that, and
adding a datastore selector in the editwindow

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/config/SyncView.js      |  8 +++++---
 www/config/VerifyView.js    |  8 +++++---
 www/window/SyncJobEdit.js   | 11 ++++++++---
 www/window/VerifyJobEdit.js | 11 ++++++++---
 4 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/www/config/SyncView.js b/www/config/SyncView.js
index 20fc5e86..24990ff0 100644
--- a/www/config/SyncView.js
+++ b/www/config/SyncView.js
@@ -162,9 +162,11 @@ Ext.define('PBS.config.SyncJobView', {
 	reload: function() { this.getView().getStore().rstore.load(); },
 
 	init: function(view) {
-	    view.getStore().rstore.getProxy().setExtraParams({
-		store: view.datastore,
-	    });
+	    let params = {};
+	    if (view.datastore !== undefined) {
+		params.store = view.datastore;
+	    }
+	    view.getStore().rstore.getProxy().setExtraParams(params);
 	    Proxmox.Utils.monStoreErrors(view, view.getStore().rstore);
 	},
     },
diff --git a/www/config/VerifyView.js b/www/config/VerifyView.js
index da8e9889..8a0ed6d4 100644
--- a/www/config/VerifyView.js
+++ b/www/config/VerifyView.js
@@ -157,9 +157,11 @@ Ext.define('PBS.config.VerifyJobView', {
 	reload: function() { this.getView().getStore().rstore.load(); },
 
 	init: function(view) {
-	    view.getStore().rstore.getProxy().setExtraParams({
-		store: view.datastore,
-	    });
+	    let params = {};
+	    if (view.datastore !== undefined) {
+		params.store = view.datastore;
+	    }
+	    view.getStore().rstore.getProxy().setExtraParams(params);
 	    Proxmox.Utils.monStoreErrors(view, view.getStore().rstore);
 	},
     },
diff --git a/www/window/SyncJobEdit.js b/www/window/SyncJobEdit.js
index 573a4af6..982cec93 100644
--- a/www/window/SyncJobEdit.js
+++ b/www/window/SyncJobEdit.js
@@ -113,6 +113,7 @@ Ext.define('PBS.window.SyncJobEdit', {
 	me.autoLoad = !!id;
 	me.scheduleValue = id ? null : 'hourly';
 	me.authid = id ? null : Proxmox.UserName;
+	me.editDatastore = me.datastore === undefined && me.isCreate;
 	return { };
     },
 
@@ -128,14 +129,18 @@ Ext.define('PBS.window.SyncJobEdit', {
 	},
 	column1: [
 	    {
-		xtype: 'displayfield',
-		name: 'store',
+		xtype: 'pmxDisplayEditField',
 		fieldLabel: gettext('Local Datastore'),
-		allowBlank: false,
+		name: 'store',
 		submitValue: true,
 		cbind: {
+		    editable: '{editDatastore}',
 		    value: '{datastore}',
 		},
+		editConfig: {
+		    xtype: 'pbsDataStoreSelector',
+		    allowBlank: false,
+		},
 	    },
 	    {
 		fieldLabel: gettext('Local Owner'),
diff --git a/www/window/VerifyJobEdit.js b/www/window/VerifyJobEdit.js
index 48a181b6..6153c8e5 100644
--- a/www/window/VerifyJobEdit.js
+++ b/www/window/VerifyJobEdit.js
@@ -24,6 +24,7 @@ Ext.define('PBS.window.VerifyJobEdit', {
 	me.url = id ? `${baseurl}/${id}` : baseurl;
 	me.method = id ? 'PUT' : 'POST';
 	me.autoLoad = !!id;
+	me.editDatastore = me.datastore === undefined && me.isCreate;
 	return { };
     },
 
@@ -45,14 +46,18 @@ Ext.define('PBS.window.VerifyJobEdit', {
 	},
 	column1: [
 	    {
-		xtype: 'displayfield',
+		xtype: 'pmxDisplayEditField',
+		fieldLabel: gettext('Local Datastore'),
 		name: 'store',
-		fieldLabel: gettext('Datastore'),
-		allowBlank: false,
 		submitValue: true,
 		cbind: {
+		    editable: '{editDatastore}',
 		    value: '{datastore}',
 		},
+		editConfig: {
+		    xtype: 'pbsDataStoreSelector',
+		    allowBlank: false,
+		},
 	    },
 	    {
 		xtype: 'pbsCalendarEvent',
-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 06/10] ui: TaskSummary: move state/types/titles out of the controller
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
                   ` (4 preceding siblings ...)
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 05/10] ui: make Sync/VerifyView and Edit usable without datastore Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 07/10] ui: TaskSummary: add subPanelModal and datastore parameters Dominik Csapak
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

it seems that under certain circumstances, extjs does not initialize
or remove the content from objects in controllers

move it to the view, were they always exist

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/dashboard/TaskSummary.js | 58 +++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/www/dashboard/TaskSummary.js b/www/dashboard/TaskSummary.js
index a9ebec07..c70c4118 100644
--- a/www/dashboard/TaskSummary.js
+++ b/www/dashboard/TaskSummary.js
@@ -4,31 +4,32 @@ Ext.define('PBS.TaskSummary', {
 
     title: gettext('Task Summary'),
 
+    states: [
+	"",
+	"error",
+	"warning",
+	"ok",
+    ],
+
+    types: [
+	"backup",
+	"prune",
+	"garbage_collection",
+	"sync",
+	"verify",
+    ],
+
+    titles: {
+	"backup": gettext('Backups'),
+	"prune": gettext('Prunes'),
+	"garbage_collection": gettext('Garbage collections'),
+	"sync": gettext('Syncs'),
+	"verify": gettext('Verify'),
+    },
+
     controller: {
 	xclass: 'Ext.app.ViewController',
 
-	states: [
-	    "",
-	    "error",
-	    "warning",
-	    "ok",
-	],
-
-	types: [
-	    "backup",
-	    "prune",
-	    "garbage_collection",
-	    "sync",
-	    "verify",
-	],
-
-	titles: {
-	    "backup": gettext('Backups'),
-	    "prune": gettext('Prunes'),
-	    "garbage_collection": gettext('Garbage collections'),
-	    "sync": gettext('Syncs'),
-	    "verify": gettext('Verify'),
-	},
 
 	openTaskList: function(grid, td, cellindex, record, tr, rowindex) {
 	    let me = this;
@@ -36,8 +37,8 @@ Ext.define('PBS.TaskSummary', {
 
 	    if (cellindex > 0) {
 		let tasklist = view.tasklist;
-		let state = me.states[cellindex];
-		let type = me.types[rowindex];
+		let state = view.states[cellindex];
+		let type = view.types[rowindex];
 		let filterParam = {
 		    limit: 0,
 		    'statusfilter': state,
@@ -137,7 +138,7 @@ Ext.define('PBS.TaskSummary', {
 		tasklist.cidx = cellindex;
 		tasklist.ridx = rowindex;
 
-		let task = me.titles[type];
+		let task = view.titles[type];
 		let status = "";
 		switch (state) {
 		    case 'ok': status = gettext("OK"); break;
@@ -182,7 +183,8 @@ Ext.define('PBS.TaskSummary', {
 
 	render_count: function(value, md, record, rowindex, colindex) {
 	    let me = this;
-	    let icon = me.render_icon(me.states[colindex], value);
+	    let view = me.getView();
+	    let icon = me.render_icon(view.states[colindex], value);
 	    return `${icon} ${value}`;
 	},
     },
@@ -191,8 +193,8 @@ Ext.define('PBS.TaskSummary', {
 	let me = this;
 	let controller = me.getController();
 	let data = [];
-	controller.types.forEach((type) => {
-	    source[type].type = controller.titles[type];
+	me.types.forEach((type) => {
+	    source[type].type = me.titles[type];
 	    data.push(source[type]);
 	});
 	me.lookup('grid').getStore().setData(data);
-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 07/10] ui: TaskSummary: add subPanelModal and datastore parameters
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
                   ` (5 preceding siblings ...)
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 06/10] ui: TaskSummary: move state/types/titles out of the controller Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 08/10] ui: TaskSummary: handle less defined parameters of tasks Dominik Csapak
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

in preparation for the per-datastore grid

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/dashboard/TaskSummary.js | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/www/dashboard/TaskSummary.js b/www/dashboard/TaskSummary.js
index c70c4118..e4c5378c 100644
--- a/www/dashboard/TaskSummary.js
+++ b/www/dashboard/TaskSummary.js
@@ -27,6 +27,12 @@ Ext.define('PBS.TaskSummary', {
 	"verify": gettext('Verify'),
     },
 
+    // set true to show the onclick panel as modal grid
+    subPanelModal: false,
+
+    // the datastore the onclick panel is filtered by
+    datastore: undefined,
+
     controller: {
 	xclass: 'Ext.app.ViewController',
 
@@ -49,6 +55,10 @@ Ext.define('PBS.TaskSummary', {
 		    filterParam.since = me.since;
 		}
 
+		if (view.datastore) {
+		    filterParam.store = view.datastore;
+		}
+
 		if (record.data[state] === 0) {
 		    return;
 		}
@@ -150,7 +160,13 @@ Ext.define('PBS.TaskSummary', {
 		tasklist.getStore().getProxy().setExtraParams(filterParam);
 		tasklist.getStore().removeAll();
 
-		tasklist.showBy(td, 'bl-tl');
+		if (view.subPanelModal) {
+		    tasklist.modal = true;
+		    tasklist.showBy(Ext.getBody(), 'c-c');
+		} else {
+		    tasklist.modal = false;
+		    tasklist.showBy(td, 'bl-tl');
+		}
 		setTimeout(() => tasklist.getStore().reload(), 10);
 	    }
 	},
-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 08/10] ui: TaskSummary: handle less defined parameters of tasks
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
                   ` (6 preceding siblings ...)
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 07/10] ui: TaskSummary: add subPanelModal and datastore parameters Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 09/10] ui: add Panels necessary for Datastores Overview Dominik Csapak
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

this makes it a little easier to provide good data, without
hardcoding all types in the source object

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/dashboard/TaskSummary.js | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/www/dashboard/TaskSummary.js b/www/dashboard/TaskSummary.js
index e4c5378c..169da2d4 100644
--- a/www/dashboard/TaskSummary.js
+++ b/www/dashboard/TaskSummary.js
@@ -59,7 +59,7 @@ Ext.define('PBS.TaskSummary', {
 		    filterParam.store = view.datastore;
 		}
 
-		if (record.data[state] === 0) {
+		if (record.data[state] === 0 || record.data[state] === undefined) {
 		    return;
 		}
 
@@ -200,8 +200,8 @@ Ext.define('PBS.TaskSummary', {
 	render_count: function(value, md, record, rowindex, colindex) {
 	    let me = this;
 	    let view = me.getView();
-	    let icon = me.render_icon(view.states[colindex], value);
-	    return `${icon} ${value}`;
+	    let icon = me.render_icon(view.states[colindex], value || 0);
+	    return `${icon} ${value || 0}`;
 	},
     },
 
@@ -209,7 +209,17 @@ Ext.define('PBS.TaskSummary', {
 	let me = this;
 	let controller = me.getController();
 	let data = [];
+	if (!source) {
+	    source = {};
+	}
 	me.types.forEach((type) => {
+	    if (!source[type]) {
+		source[type] = {
+		    error: 0,
+		    warning: 0,
+		    ok: 0,
+		};
+	    }
 	    source[type].type = me.titles[type];
 	    data.push(source[type]);
 	});
-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 09/10] ui: add Panels necessary for Datastores Overview
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
                   ` (7 preceding siblings ...)
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 08/10] ui: TaskSummary: handle less defined parameters of tasks Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 10/10] ui: make Datastore clickable again Dominik Csapak
  2020-11-09 17:55 ` [pbs-devel] applied series: [PATCH proxmox-backup 00/10] add Datastore overview panel Thomas Lamprecht
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

a panel for a single datastore that gets updated from an external caller
shows the usage, estimated full date, history and task summary grid

a panel that dynamically generates the panel above for each datastore

and a tabpanel that includes the panel above, as well as a global
syncview, verifiyview and aclview

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/Makefile                          |   2 +
 www/datastore/DataStoreList.js        | 229 ++++++++++++++++++++++++++
 www/datastore/DataStoreListSummary.js | 138 ++++++++++++++++
 3 files changed, 369 insertions(+)
 create mode 100644 www/datastore/DataStoreList.js
 create mode 100644 www/datastore/DataStoreListSummary.js

diff --git a/www/Makefile b/www/Makefile
index f9d8f8e4..192341ec 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -56,6 +56,8 @@ JSSRC=							\
 	datastore/Content.js				\
 	datastore/OptionView.js				\
 	datastore/Panel.js				\
+	datastore/DataStoreListSummary.js		\
+	datastore/DataStoreList.js			\
 	ServerStatus.js					\
 	ServerAdministration.js				\
 	Dashboard.js					\
diff --git a/www/datastore/DataStoreList.js b/www/datastore/DataStoreList.js
new file mode 100644
index 00000000..71dd5fdb
--- /dev/null
+++ b/www/datastore/DataStoreList.js
@@ -0,0 +1,229 @@
+// Overview over all datastores
+Ext.define('PBS.datastore.DataStoreList', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.pbsDataStoreList',
+
+    title: gettext('Summary'),
+
+    scrollable: true,
+
+    bodyPadding: 5,
+    defaults: {
+	xtype: 'pbsDataStoreListSummary',
+	padding: 5,
+    },
+
+    datastores: {},
+    tasks: {},
+
+    updateTasks: function(taskStore, records, success) {
+	let me = this;
+	if (!success) {
+	    return;
+	}
+
+	for (const store of Object.keys(me.tasks)) {
+	    me.tasks[store] = {};
+	}
+
+	records.forEach(record => {
+	    let task = record.data;
+	    if (!task.worker_id) {
+		return;
+	    }
+
+	    let type = task.worker_type;
+	    if (type === 'syncjob') {
+		type = 'sync';
+	    }
+
+	    if (type.startsWith('verif')) {
+		type = 'verify';
+	    }
+
+	    let datastore = PBS.Utils.parse_datastore_worker_id(type, task.worker_id);
+	    if (!datastore) {
+		return;
+	    }
+
+	    if (!me.tasks[datastore]) {
+		me.tasks[datastore] = {};
+	    }
+
+	    if (!me.tasks[datastore][type]) {
+		me.tasks[datastore][type] = {};
+	    }
+
+	    if (me.tasks[datastore][type] && task.status) {
+		let parsed = Proxmox.Utils.parse_task_status(task.status);
+		if (!me.tasks[datastore][type][parsed]) {
+		    me.tasks[datastore][type][parsed] = 0;
+		}
+		me.tasks[datastore][type][parsed]++;
+	    }
+	});
+
+	for (const [store, panel] of Object.entries(me.datastores)) {
+	    panel.setTasks(me.tasks[store], me.since);
+	}
+    },
+
+    updateStores: function(usageStore, records, success) {
+	let me = this;
+	if (!success) {
+	    return;
+	}
+
+	let found = {};
+
+	records.forEach((rec) => {
+	    found[rec.data.store] = true;
+	    me.addSorted(rec.data);
+	});
+
+	for (const [store, panel] of Object.entries(me.datastores)) {
+	    if (!found[store]) {
+		me.remove(panel);
+	    }
+	}
+    },
+
+    addSorted: function(data) {
+	let me = this;
+	let i = 0;
+	let datastores = Object
+	    .keys(me.datastores)
+	    .sort((a, b) => a.localeCompare(b));
+
+	for (const datastore of datastores) {
+	    let result = datastore.localeCompare(data.store);
+	    if (result === 0) {
+		me.datastores[datastore].setStatus(data);
+		return;
+	    } else if (result > 0) {
+		break;
+	    }
+	    i++;
+	}
+
+	me.datastores[data.store] = me.insert(i, {
+	    datastore: data.store,
+	});
+	me.datastores[data.store].setStatus(data);
+	me.datastores[data.store].setTasks(me.tasks[data.store], me.since);
+    },
+
+    initComponent: function() {
+	let me = this;
+	me.items = [];
+	me.datastores = {};
+	// todo make configurable?
+	me.since = (Date.now()/1000 - 30 * 24*3600).toFixed(0);
+
+	me.usageStore = Ext.create('Proxmox.data.UpdateStore', {
+	    storeid: 'datastore-overview-usage',
+	    interval: 5000,
+	    proxy: {
+		type: 'proxmox',
+		url: '/api2/json/status/datastore-usage',
+	    },
+	    listeners: {
+		load: {
+		    fn: me.updateStores,
+		    scope: me,
+		},
+	    },
+	});
+
+	me.taskStore = Ext.create('Proxmox.data.UpdateStore', {
+	    storeid: 'datastore-overview-tasks',
+	    interval: 15000,
+	    model: 'proxmox-tasks',
+	    proxy: {
+		type: 'proxmox',
+		url: '/api2/json/nodes/localhost/tasks',
+		extraParams: {
+		    limit: 0,
+		    since: me.since,
+		},
+	    },
+	    listeners: {
+		load: {
+		    fn: me.updateTasks,
+		    scope: me,
+		},
+	    },
+	});
+
+	me.callParent();
+	Proxmox.Utils.monStoreErrors(me, me.usageStore);
+	Proxmox.Utils.monStoreErrors(me, me.taskStore);
+	me.on('activate', function() {
+	    me.usageStore.startUpdate();
+	    me.taskStore.startUpdate();
+	});
+	me.on('destroy', function() {
+	    me.usageStore.stopUpdate();
+	    me.taskStore.stopUpdate();
+	});
+	me.on('deactivate', function() {
+	    me.usageStore.stopUpdate();
+	    me.taskStore.stopUpdate();
+	});
+    },
+});
+
+Ext.define('PBS.datastore.DataStores', {
+    extend: 'Ext.tab.Panel',
+    alias: 'widget.pbsDataStores',
+
+    title: gettext('Datastores'),
+
+    stateId: 'pbs-datastores-panel',
+    stateful: true,
+
+    stateEvents: ['tabchange'],
+
+    applyState: function(state) {
+	let me = this;
+	if (state.tab !== undefined) {
+	    me.setActiveTab(state.tab);
+	}
+    },
+
+    getState: function() {
+	let me = this;
+	return {
+	    tab: me.getActiveTab().getItemId(),
+	};
+    },
+
+    border: false,
+    defaults: {
+	border: false,
+    },
+
+    items: [
+	{
+	    xtype: 'pbsDataStoreList',
+	    iconCls: 'fa fa-book',
+	},
+
+	{
+	    iconCls: 'fa fa-refresh',
+	    itemId: 'syncjobs',
+	    xtype: 'pbsSyncJobView',
+	},
+	{
+	    iconCls: 'fa fa-check-circle',
+	    itemId: 'verifyjobs',
+	    xtype: 'pbsVerifyJobView',
+	},
+	{
+	    itemId: 'acl',
+	    xtype: 'pbsACLView',
+	    iconCls: 'fa fa-unlock',
+	    aclPath: '/datastore',
+	},
+    ],
+});
diff --git a/www/datastore/DataStoreListSummary.js b/www/datastore/DataStoreListSummary.js
new file mode 100644
index 00000000..a9018a7c
--- /dev/null
+++ b/www/datastore/DataStoreListSummary.js
@@ -0,0 +1,138 @@
+// Summary Panel for a single datastore in overview
+Ext.define('PBS.datastore.DataStoreListSummary', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.pbsDataStoreListSummary',
+    mixins: ['Proxmox.Mixin.CBind'],
+
+    cbind: {
+	title: '{datastore}',
+    },
+    bodyPadding: 10,
+
+    viewModel: {
+	data: {
+	    usage: "N/A",
+	    full: "N/A",
+	    history: [],
+	},
+
+	stores: {
+	    historystore: {
+		data: [],
+	    },
+	},
+    },
+    setTasks: function(taskdata, since) {
+	let me = this;
+	me.down('pbsTaskSummary').updateTasks(taskdata, since);
+    },
+
+    setStatus: function(statusData) {
+	let me = this;
+	let vm = me.getViewModel();
+	vm.set('usagetext', PBS.Utils.render_size_usage(statusData.used, statusData.total));
+	vm.set('usage', statusData.used/statusData.total);
+	let estimate = PBS.Utils.render_estimate(statusData['estimated-full-date']);
+	vm.set('full', estimate);
+	let last = 0;
+	let data = statusData.history.map((val) => {
+	    if (val === null) {
+		val = last;
+	    } else {
+		last = val;
+	    }
+	    return val;
+	});
+	let historyStore = vm.getStore('historystore');
+	historyStore.setData([
+	    {
+		history: data,
+	    },
+	]);
+    },
+
+    items: [
+	{
+	    xtype: 'container',
+	    layout: {
+		type: 'hbox',
+		align: 'stretch',
+	    },
+
+	    defaults: {
+		flex: 1,
+		padding: 5,
+	    },
+
+	    items: [
+		{
+		    xtype: 'pmxInfoWidget',
+		    iconCls: 'fa fa-fw fa-hdd-o',
+		    title: gettext('Usage'),
+		    bind: {
+			data: {
+			    usage: '{usage}',
+			    text: '{usagetext}',
+			},
+		    },
+		},
+		{
+		    xtype: 'pmxInfoWidget',
+		    title: gettext('Estimated Full'),
+		    printBar: false,
+		    bind: {
+			data: {
+			    usage: '0',
+			    text: '{full}',
+			},
+		    },
+		},
+	    ],
+	},
+	{
+	    // we cannot autosize a sparklineline widget,
+	    // abuse a grid with a single column/row to do it for us
+	    xtype: 'grid',
+	    hideHeaders: true,
+	    minHeight: 50,
+	    border: false,
+	    bodyBorder: false,
+	    rowLines: false,
+	    disableSelection: true,
+	    viewConfig: {
+		trackOver: false,
+	    },
+	    bind: {
+		store: '{historystore}',
+	    },
+	    columns: [{
+		xtype: 'widgetcolumn',
+		flex: 1,
+		dataIndex: 'history',
+		widget: {
+		    xtype: 'sparklineline',
+		    bind: '{record.history}',
+		    spotRadius: 0,
+		    fillColor: '#ddd',
+		    lineColor: '#555',
+		    lineWidth: 0,
+		    chartRangeMin: 0,
+		    chartRangeMax: 1,
+		    tipTpl: '{y:number("0.00")*100}%',
+		    height: 40,
+		},
+	    }],
+	},
+	{
+	    xtype: 'pbsTaskSummary',
+	    border: false,
+	    header: false,
+	    subPanelModal: true,
+	    bodyPadding: 0,
+	    minHeight: 0,
+	    cbind: {
+		datastore: '{datastore}',
+	    },
+	},
+    ],
+});
-- 
2.20.1





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

* [pbs-devel] [PATCH proxmox-backup 10/10] ui: make Datastore clickable again
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
                   ` (8 preceding siblings ...)
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 09/10] ui: add Panels necessary for Datastores Overview Dominik Csapak
@ 2020-11-09 15:01 ` Dominik Csapak
  2020-11-09 17:55 ` [pbs-devel] applied series: [PATCH proxmox-backup 00/10] add Datastore overview panel Thomas Lamprecht
  10 siblings, 0 replies; 13+ messages in thread
From: Dominik Csapak @ 2020-11-09 15:01 UTC (permalink / raw)
  To: pbs-devel

by showing the previously added pbsDataStores panel

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 www/NavigationTree.js | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/www/NavigationTree.js b/www/NavigationTree.js
index 09c58938..e0270439 100644
--- a/www/NavigationTree.js
+++ b/www/NavigationTree.js
@@ -87,6 +87,7 @@ Ext.define('PBS.store.NavigationStore', {
 		text: gettext('Datastore'),
 		iconCls: 'fa fa-archive',
 		id: 'datastores',
+		path: 'pbsDataStores',
 		expanded: true,
 		expandable: false,
 		leaf: false,
@@ -174,9 +175,6 @@ Ext.define('PBS.view.main.NavigationTree', {
 
     listeners: {
 	itemclick: function(tl, info) {
-	    if (info.node.data.id === 'datastores') {
-		return false;
-	    }
 	    if (info.node.data.id === 'addbutton') {
 		let me = this;
 		Ext.create('PBS.DataStoreEdit', {
-- 
2.20.1





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

* [pbs-devel] applied series: [PATCH proxmox-backup 00/10] add Datastore overview panel
  2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
                   ` (9 preceding siblings ...)
  2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 10/10] ui: make Datastore clickable again Dominik Csapak
@ 2020-11-09 17:55 ` Thomas Lamprecht
  2020-11-09 18:28   ` Thomas Lamprecht
  10 siblings, 1 reply; 13+ messages in thread
From: Thomas Lamprecht @ 2020-11-09 17:55 UTC (permalink / raw)
  To: Proxmox Backup Server development discussion, Dominik Csapak

On 09.11.20 16:01, Dominik Csapak wrote:
> this make 'Datastore' clickable again, and shows an overview
> for all datastores, as well as a global sync/verify/acl view
> 
> Dominik Csapak (10):
>   api2/node/tasks: add check_job_store and use it
>   ui: refactor render_estimate
>   ui: refactor render_size_usage to Utils
>   ui: Utils: add parse_datastore_worker_id
>   ui: make Sync/VerifyView and Edit usable without datastore
>   ui: TaskSummary: move state/types/titles out of the controller
>   ui: TaskSummary: add subPanelModal and datastore parameters
>   ui: TaskSummary: handle less defined parameters of tasks
>   ui: add Panels necessary for Datastores Overview
>   ui: make Datastore clickable again
> 
>  src/api2/node/tasks.rs                |  47 ++++--
>  www/Makefile                          |   2 +
>  www/NavigationTree.js                 |   4 +-
>  www/Utils.js                          |  63 +++++++
>  www/config/SyncView.js                |   8 +-
>  www/config/VerifyView.js              |   8 +-
>  www/dashboard/DataStoreStatistics.js  |  20 +--
>  www/dashboard/TaskSummary.js          |  90 ++++++----
>  www/datastore/DataStoreList.js        | 229 ++++++++++++++++++++++++++
>  www/datastore/DataStoreListSummary.js | 138 ++++++++++++++++
>  www/datastore/Summary.js              |  13 +-
>  www/window/SyncJobEdit.js             |  11 +-
>  www/window/VerifyJobEdit.js           |  11 +-
>  13 files changed, 552 insertions(+), 92 deletions(-)
>  create mode 100644 www/datastore/DataStoreList.js
>  create mode 100644 www/datastore/DataStoreListSummary.js
> 



applied series, thanks!

Some observations:

* we do not see the datastore in the "all datastore" wide sync/verify job view,
  would be helpful to have here.

* we could use similar graphs like we have for Ceph reads, writes and IOPS in
  PVE? They are IMO quite a bit better looking.

* I'd enable "trackOver" for the task summary element, it makes it easier to
  relate to different rows, especially if the distance between columns is such
  wide.

* Maybe using a gauge for the usage and putting it besides the task summary
  element could be better use of space? E.g., a POC here:
  1080p: https://lamprecht.org/dump/scrots/pbs-ds-summary/poc-summary-1080p-2020-11-09_18.46.03.png
   720p: https://lamprecht.org/dump/scrots/pbs-ds-summary/poc-summary-720p-2020-11-09_18.46.03.png


changes of my hacky, not cleaned up, POC below.

----8<----
diff --git a/www/dashboard/TaskSummary.js b/www/dashboard/TaskSummary.js
index 15db49cd..09ee9fd0 100644
--- a/www/dashboard/TaskSummary.js
+++ b/www/dashboard/TaskSummary.js
@@ -246,7 +246,7 @@ Ext.define('PBS.TaskSummary', {
 	    rowLines: false,
 	    viewConfig: {
 		stripeRows: false,
-		trackOver: false,
+		trackOver: true,
 	    },
 	    scrollable: false,
 	    disableSelection: true,
diff --git a/www/datastore/DataStoreListSummary.js b/www/datastore/DataStoreListSummary.js
index 2322e62b..8724d220 100644
--- a/www/datastore/DataStoreListSummary.js
+++ b/www/datastore/DataStoreListSummary.js
@@ -9,6 +9,9 @@ Ext.define('PBS.datastore.DataStoreListSummary', {
     },
     bodyPadding: 10,
 
+    controller: {
+	xclass: 'Ext.app.ViewController',
+    },
     viewModel: {
 	data: {
 	    usage: "N/A",
@@ -31,7 +34,17 @@ Ext.define('PBS.datastore.DataStoreListSummary', {
 	let me = this;
 	let vm = me.getViewModel();
 	vm.set('usagetext', PBS.Utils.render_size_usage(statusData.used, statusData.total));
-	vm.set('usage', statusData.used/statusData.total);
+
+	let usage = statusData.used/statusData.total;
+	vm.set('usage', usage);
+
+	let usagePanel = me.lookup('usage');
+	let usagetext = Ext.String.format(gettext('{0} of {1}'),
+	    Proxmox.Utils.format_size(statusData.used),
+	    Proxmox.Utils.format_size(statusData.total)
+	);
+	usagePanel.updateValue(usage, usagetext);
+
 	let estimate = PBS.Utils.render_estimate(statusData['estimated-full-date']);
 	vm.set('full', estimate);
 	let last = 0;
@@ -60,26 +73,20 @@ Ext.define('PBS.datastore.DataStoreListSummary', {
 	    },
 
 	    defaults: {
-		flex: 1,
 		padding: 5,
 	    },
 
 	    items: [
 		{
-		    xtype: 'pmxInfoWidget',
-		    iconCls: 'fa fa-fw fa-hdd-o',
-		    title: gettext('Usage'),
-		    bind: {
-			data: {
-			    usage: '{usage}',
-			    text: '{usagetext}',
-			},
-		    },
+		    xtype: 'panel',
+		    border: false,
+		    flex: 1,
 		},
 		{
 		    xtype: 'pmxInfoWidget',
 		    iconCls: 'fa fa-fw fa-line-chart',
 		    title: gettext('Estimated Full'),
+		    width: 230,
 		    printBar: false,
 		    bind: {
 			data: {
@@ -125,15 +132,54 @@ Ext.define('PBS.datastore.DataStoreListSummary', {
 	    }],
 	},
 	{
-	    xtype: 'pbsTaskSummary',
-	    border: false,
-	    header: false,
-	    subPanelModal: true,
-	    bodyPadding: 0,
-	    minHeight: 0,
-	    cbind: {
-		datastore: '{datastore}',
+	    xtype: 'container',
+	    layout: {
+		type: 'hbox',
+		align: 'stretch',
 	    },
+
+	    defaults: {
+		padding: 5,
+	    },
+
+	    items: [
+		{
+		    xtype: 'proxmoxGauge',
+		    flex: 1,
+		    reference: 'usage',
+		},
+		{
+		    xtype: 'container',
+		    flex: 2,
+		    layout: {
+			type: 'vbox',
+			align: 'stretch',
+		    },
+
+		    defaults: {
+			padding: 5,
+		    },
+
+		    items: [
+			{
+			    xtype: 'label',
+			    text: 'Task Summary (last 30 days)',
+			},
+			{
+			    xtype: 'pbsTaskSummary',
+			    border: false,
+			    header: false,
+			    subPanelModal: true,
+			    flex: 2,
+			    bodyPadding: 0,
+			    minHeight: 0,
+			    cbind: {
+				datastore: '{datastore}',
+			    },
+			},
+		    ],
+		},
+	    ],
 	},
     ],
 });





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

* Re: [pbs-devel] applied series: [PATCH proxmox-backup 00/10] add Datastore overview panel
  2020-11-09 17:55 ` [pbs-devel] applied series: [PATCH proxmox-backup 00/10] add Datastore overview panel Thomas Lamprecht
@ 2020-11-09 18:28   ` Thomas Lamprecht
  0 siblings, 0 replies; 13+ messages in thread
From: Thomas Lamprecht @ 2020-11-09 18:28 UTC (permalink / raw)
  To: Proxmox Backup Server development discussion, Dominik Csapak

On 09.11.20 18:55, Thomas Lamprecht wrote:
> * Maybe using a gauge for the usage and putting it besides the task summary
>   element could be better use of space? E.g., a POC here:
>   1080p: https://lamprecht.org/dump/scrots/pbs-ds-summary/poc-summary-1080p-2020-11-09_18.46.03.png
>    720p: https://lamprecht.org/dump/scrots/pbs-ds-summary/poc-summary-720p-2020-11-09_18.46.03.png
> 
> 
> changes of my hacky, not cleaned up, POC below.

FYI: After a quick talk with Martin I applied a slightly cleaned up version of
the POC below, he shared the opinion that the usage is more visible/easier to
parse as a gauge.





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

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

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-09 15:01 [pbs-devel] [PATCH proxmox-backup 00/10] add Datastore overview panel Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 01/10] api2/node/tasks: add check_job_store and use it Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 02/10] ui: refactor render_estimate Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 03/10] ui: refactor render_size_usage to Utils Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 04/10] ui: Utils: add parse_datastore_worker_id Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 05/10] ui: make Sync/VerifyView and Edit usable without datastore Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 06/10] ui: TaskSummary: move state/types/titles out of the controller Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 07/10] ui: TaskSummary: add subPanelModal and datastore parameters Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 08/10] ui: TaskSummary: handle less defined parameters of tasks Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 09/10] ui: add Panels necessary for Datastores Overview Dominik Csapak
2020-11-09 15:01 ` [pbs-devel] [PATCH proxmox-backup 10/10] ui: make Datastore clickable again Dominik Csapak
2020-11-09 17:55 ` [pbs-devel] applied series: [PATCH proxmox-backup 00/10] add Datastore overview panel Thomas Lamprecht
2020-11-09 18:28   ` Thomas Lamprecht

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