all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pmg-devel] [PATCH pmg-gui v2 0/2] low-hanging improvments for the quarantine interface
@ 2022-10-27 19:12 Stoiko Ivanov
  2022-10-27 19:12 ` [pmg-devel] [PATCH pmg-gui v2 1/2] quarantine: refactor spamquarantine controller Stoiko Ivanov
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Stoiko Ivanov @ 2022-10-27 19:12 UTC (permalink / raw)
  To: pmg-devel

v1->v2:
* dropped already applied patches
* changed the patches, by splitting the refactoring of the spamquarantine
  in a patch of its own, and changing virus and attachmentquarantine in
  the second patch (no functional change intended) - big thanks for the
  suggestion @Thomas!!

gave me also the chance to see the adaptations of the icon-colors for delivery
and delete by Thomas in action - I like it!

original cover-letter for v1:
A few bugzilla entries ask for features in the quarantine interface that
seem quite sensible (e.g. #4137), or are already present in the (by far
more used) spamquarantine, but never made it to the others.

This patchset contains a single small fix, and a refactoring of the
quarantine views to use the same controller.

Would be grateful for feedback


Stoiko Ivanov (2):
  quarantine: refactor spamquarantine controller
  quarantine: use new controller for virus and attachment quarantines

 js/AttachmentQuarantine.js            | 113 +++++-----
 js/Makefile                           |   1 +
 js/SpamQuarantine.js                  | 290 +++++++++-----------------
 js/VirusQuarantine.js                 |  86 ++------
 js/controller/QuarantineController.js | 170 +++++++++++++++
 5 files changed, 335 insertions(+), 325 deletions(-)
 create mode 100644 js/controller/QuarantineController.js

-- 
2.30.2





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

* [pmg-devel] [PATCH pmg-gui v2 1/2] quarantine: refactor spamquarantine controller
  2022-10-27 19:12 [pmg-devel] [PATCH pmg-gui v2 0/2] low-hanging improvments for the quarantine interface Stoiko Ivanov
@ 2022-10-27 19:12 ` Stoiko Ivanov
  2022-10-27 19:12 ` [pmg-devel] [PATCH pmg-gui v2 2/2] quarantine: use new controller for virus and attachment quarantines Stoiko Ivanov
  2022-10-28  9:35 ` [pmg-devel] applied-series: Re: [PATCH pmg-gui v2 0/2] low-hanging improvments for the quarantine interface Thomas Lamprecht
  2 siblings, 0 replies; 4+ messages in thread
From: Stoiko Ivanov @ 2022-10-27 19:12 UTC (permalink / raw)
  To: pmg-devel

over the time the spam quarantine has gained quite a few nice
usability improvments and features, which would be useful in
the virus and attachment quarantines as well - e.g.:

* multi-mail selection
* keyboard actions
* context menu
* download mail as .eml

this patch splits the controller part into a file of its own, while changing
'var' to 'let' and removing the parts only relevant for the spamquarantine
and adapts the current SpamQuarantine.js to use it.

Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
---
 js/Makefile                           |   1 +
 js/SpamQuarantine.js                  | 290 +++++++++-----------------
 js/controller/QuarantineController.js | 170 +++++++++++++++
 3 files changed, 265 insertions(+), 196 deletions(-)
 create mode 100644 js/controller/QuarantineController.js

diff --git a/js/Makefile b/js/Makefile
index b904598..9a2bcf2 100644
--- a/js/Makefile
+++ b/js/Makefile
@@ -19,6 +19,7 @@ JSSRC=							\
 	RuleInfo.js					\
 	RuleEditor.js					\
 	MainView.js					\
+	controller/QuarantineController.js		\
 	QuarantineContextMenu.js			\
 	QuarantineList.js				\
 	SpamInfoGrid.js					\
diff --git a/js/SpamQuarantine.js b/js/SpamQuarantine.js
index 6fe20d7..cf7f181 100644
--- a/js/SpamQuarantine.js
+++ b/js/SpamQuarantine.js
@@ -33,225 +33,123 @@ Ext.define('pmg-spam-list', {
     idProperty: 'id',
 });
 
-Ext.define('PMG.SpamQuarantine', {
-    extend: 'Ext.container.Container',
-    xtype: 'pmgSpamQuarantine',
-
-    border: false,
-    layout: { type: 'border' },
+Ext.define('PMG.SpamQuarantineController', {
+    extend: 'PMG.controller.QuarantineController',
+    xtype: 'pmgSpamQuarantineController',
+    alias: 'controller.spamquarantine',
 
-    defaults: { border: false },
+    updatePreview: function(raw, rec) {
+	let me = this;
+	me.lookupReference('spam').setDisabled(false);
 
-    // from mail link
-    cselect: undefined,
+	me.callParent(arguments);
+    },
 
-    viewModel: {
-	parent: null,
-	data: {
-	    mailid: '',
-	},
-	formulas: {
-	    downloadMailURL: get => '/api2/json/quarantine/download?mailid=' + encodeURIComponent(get('mailid')),
-	},
+    multiSelect: function(selection) {
+	let me = this;
+	let spam = me.lookupReference('spam');
+	spam.setDisabled(true);
+	spam.setPressed(false);
+	me.lookupReference('spaminfo').setVisible(false);
+	me.callParent(selection);
     },
-    controller: {
 
-	xclass: 'Ext.app.ViewController',
+    onSelectMail: function() {
+	let me = this;
+	let list = me.lookupReference('list');
+	let selection = list.selModel.getSelection();
+	if (selection.length <= 1) {
+	    let rec = selection[0] || {};
+	    me.lookupReference('spaminfo').setID(rec);
+	}
+	me.callParent();
+    },
 
-	updatePreview: function(raw, rec) {
-	    var preview = this.lookupReference('preview');
 
-	    if (!rec || !rec.data || !rec.data.id) {
-		preview.update('');
-		preview.setDisabled(true);
-		return;
-	    }
+    toggleSpamInfo: function(btn) {
+	var grid = this.lookupReference('spaminfo');
+	grid.setVisible(!grid.isVisible());
+    },
 
-	    let url = `/api2/htmlmail/quarantine/content?id=${rec.data.id}`;
-	    if (raw) {
-		url += '&raw=1';
-	    }
-	    preview.setDisabled(false);
-	    this.lookupReference('raw').setDisabled(false);
-	    this.lookupReference('spam').setDisabled(false);
-	    this.lookupReference('download').setDisabled(false);
-	    preview.update("<iframe frameborder=0 width=100% height=100% sandbox='allow-same-origin' src='" + url +"'></iframe>");
-	},
+    openContextMenu: function(table, record, tr, index, event) {
+	event.stopEvent();
+	let me = this;
+	let list = me.lookup('list');
+	Ext.create('PMG.menu.SpamContextMenu', {
+	    callback: action => me.doAction(action, list.getSelection()),
+	}).showAt(event.getXY());
+    },
 
-	multiSelect: function(selection) {
-	    var preview = this.lookupReference('preview');
-	    var raw = this.lookupReference('raw');
-	    var spam = this.lookupReference('spam');
-	    var spaminfo = this.lookupReference('spaminfo');
-	    var mailinfo = this.lookupReference('mailinfo');
-	    var download = this.lookupReference('download');
+    keyPress: function(table, record, item, index, event) {
+	var me = this;
+	var list = me.lookup('list');
+	var key = event.getKey();
+	var action = '';
+	switch (key) {
+	    case event.DELETE:
+	    case 127:
+		action = 'delete';
+		break;
+	    case Ext.event.Event.D:
+	    case Ext.event.Event.D + 32:
+		action = 'deliver';
+		break;
+	    case Ext.event.Event.W:
+	    case Ext.event.Event.W + 32:
+		action = 'whitelist';
+		break;
+	    case Ext.event.Event.B:
+	    case Ext.event.Event.B + 32:
+		action = 'blacklist';
+		break;
+	}
 
-	    preview.setDisabled(false);
-	    preview.update(`<h3 style="padding-left:5px;">${gettext('Multiple E-Mails selected')} (${selection.length})</h3>`);
-	    raw.setDisabled(true);
-	    spam.setDisabled(true);
-	    spam.setPressed(false);
-	    spaminfo.setVisible(false);
-	    mailinfo.setVisible(false);
-	    download.setDisabled(true);
-	},
+	if (action !== '') {
+	    me.doAction(action, list.getSelection());
+	}
+    },
 
-	toggleRaw: function(button) {
-	    var me = this;
-	    var list = me.lookupReference('list');
-	    var rec = list.selModel.getSelection()[0];
-	    me.lookupReference('mailinfo').setVisible(me.raw);
-	    me.raw = !me.raw;
-	    me.updatePreview(me.raw, rec);
-	},
+    init: function(view) {
+	this.lookup('list').cselect = view.cselect;
+    },
 
-	btnHandler: function(button, e) {
-	    var me = this;
-	    var action = button.reference;
-	    var list = this.lookupReference('list');
-	    var selected = list.getSelection();
-	    me.doAction(action, selected);
+    control: {
+	'button[reference=raw]': {
+	    click: 'toggleRaw',
 	},
-
-	doAction: function(action, selected) {
-	    if (!selected.length) {
-		return;
-	    }
-
-	    var list = this.lookupReference('list');
-
-	    if (selected.length > 1) {
-		let idlist = selected.map(item => item.data.id);
-		Ext.Msg.confirm(
-		    gettext('Confirm'),
-		    Ext.String.format(
-			gettext("Action '{0}' for '{1}' items"),
-			action, selected.length,
-		    ),
-		    async function(button) {
-			if (button !== 'yes') {
-			    return;
-			}
-
-			list.mask(gettext('Processing...'), 'x-mask-loading');
-
-			const sliceSize = 2500, maxInFlight = 2;
-			let batches = [], batchCount = Math.ceil(selected.length / sliceSize);
-			for (let i = 0; i * sliceSize < selected.length; i++) {
-			    let sliceStart = i * sliceSize;
-			    let sliceEnd = Math.min(sliceStart + sliceSize, selected.length);
-			    batches.push(
-				PMG.Async.doQAction(
-				    action,
-				    idlist.slice(sliceStart, sliceEnd),
-				    i + 1,
-				    batchCount,
-				),
-			    );
-			    if (batches.length >= maxInFlight) {
-				await Promise.allSettled(batches); // eslint-disable-line no-await-in-loop
-				batches = [];
-			    }
-			}
-			await Promise.allSettled(batches); // await possible remaining ones
-			list.unmask();
-			// below can be slow, we could remove directly from the in-memory store, but
-			// with lots of elements and some failures we could be quite out of sync?
-			list.getController().load();
-		    },
-		);
-		return;
-	    }
-
-	    PMG.Utils.doQuarantineAction(action, selected[0].data.id, function() {
-		let listController = list.getController();
-		listController.allowPositionSave = false;
-		// success -> remove directly to avoid slow store reload for a single-element action
-		list.getStore().remove(selected[0]);
-		listController.restoreSavedSelection();
-		listController.allowPositionSave = true;
-	    });
+	'button[reference=spam]': {
+	    click: 'toggleSpamInfo',
 	},
-
-	onSelectMail: function() {
-	    var me = this;
-	    var list = this.lookupReference('list');
-	    var selection = list.selModel.getSelection();
-	    if (selection.length > 1) {
-		me.multiSelect(selection);
-		return;
-	    }
-
-	    var rec = selection[0] || {};
-
-	    me.getViewModel().set('mailid', rec.data ? rec.data.id : '');
-	    me.updatePreview(me.raw || false, rec);
-	    me.lookupReference('spaminfo').setID(rec);
-	    me.lookupReference('mailinfo').setVisible(!!rec.data && !me.raw);
-	    me.lookupReference('mailinfo').update(rec.data);
+	'pmgQuarantineList': {
+	    selectionChange: 'onSelectMail',
+	    itemkeypress: 'keyPress',
+	    rowcontextmenu: 'openContextMenu',
 	},
+    },
+});
 
-	toggleSpamInfo: function(btn) {
-	    var grid = this.lookupReference('spaminfo');
-	    grid.setVisible(!grid.isVisible());
-	},
+Ext.define('PMG.SpamQuarantine', {
+    extend: 'Ext.container.Container',
+    xtype: 'pmgSpamQuarantine',
 
-	openContextMenu: function(table, record, tr, index, event) {
-	    event.stopEvent();
-	    let me = this;
-	    let list = me.lookup('list');
-	    Ext.create('PMG.menu.SpamContextMenu', {
-		callback: action => me.doAction(action, list.getSelection()),
-	    }).showAt(event.getXY());
-	},
+    border: false,
+    layout: { type: 'border' },
 
-	keyPress: function(table, record, item, index, event) {
-	    var me = this;
-	    var list = me.lookup('list');
-	    var key = event.getKey();
-	    var action = '';
-	    switch (key) {
-		case event.DELETE:
-		case 127:
-		    action = 'delete';
-		    break;
-		case Ext.event.Event.D:
-		case Ext.event.Event.D + 32:
-		    action = 'deliver';
-		    break;
-		case Ext.event.Event.W:
-		case Ext.event.Event.W + 32:
-		    action = 'whitelist';
-		    break;
-		case Ext.event.Event.B:
-		case Ext.event.Event.B + 32:
-		    action = 'blacklist';
-		    break;
-	    }
+    defaults: { border: false },
 
-	    if (action !== '') {
-		me.doAction(action, list.getSelection());
-	    }
-	},
+    // from mail link
+    cselect: undefined,
 
-	init: function(view) {
-	    this.lookup('list').cselect = view.cselect;
+    viewModel: {
+	parent: null,
+	data: {
+	    mailid: '',
 	},
-
-	control: {
-	    'button[reference=raw]': {
-		click: 'toggleRaw',
-	    },
-	    'button[reference=spam]': {
-		click: 'toggleSpamInfo',
-	    },
-	    'pmgQuarantineList': {
-		selectionChange: 'onSelectMail',
-		itemkeypress: 'keyPress',
-		rowcontextmenu: 'openContextMenu',
-	    },
+	formulas: {
+	    downloadMailURL: get => '/api2/json/quarantine/download?mailid=' + encodeURIComponent(get('mailid')),
 	},
     },
+    controller: 'spamquarantine',
 
     items: [
 	{
diff --git a/js/controller/QuarantineController.js b/js/controller/QuarantineController.js
new file mode 100644
index 0000000..dfe2915
--- /dev/null
+++ b/js/controller/QuarantineController.js
@@ -0,0 +1,170 @@
+Ext.define('PMG.controller.QuarantineController', {
+    extend: 'Ext.app.ViewController',
+    xtype: 'controller.Quarantine',
+    alias: 'controller.quarantine',
+
+    updatePreview: function(raw, rec) {
+	let preview = this.lookupReference('preview');
+
+	if (!rec || !rec.data || !rec.data.id) {
+	    preview.update('');
+	    preview.setDisabled(true);
+	    return;
+	}
+
+	let url = `/api2/htmlmail/quarantine/content?id=${rec.data.id}`;
+	if (raw) {
+	    url += '&raw=1';
+	}
+	preview.setDisabled(false);
+	this.lookupReference('raw').setDisabled(false);
+	this.lookupReference('download').setDisabled(false);
+	preview.update("<iframe frameborder=0 width=100% height=100% sandbox='allow-same-origin' src='" + url +"'></iframe>");
+    },
+
+    multiSelect: function(selection) {
+	let me = this;
+	me.lookupReference('raw').setDisabled(true);
+	me.lookupReference('download').setDisabled(true);
+	me.lookupReference('mailinfo').setVisible(false);
+
+	let preview = me.lookupReference('preview');
+	preview.setDisabled(false);
+	preview.update(`<h3 style="padding-left:5px;">${gettext('Multiple E-Mails selected')} (${selection.length})</h3>`);
+    },
+
+    toggleRaw: function(button) {
+	let me = this;
+	let list = me.lookupReference('list');
+	let rec = list.selModel.getSelection()[0];
+	me.lookupReference('mailinfo').setVisible(me.raw);
+	me.raw = !me.raw;
+	me.updatePreview(me.raw, rec);
+    },
+
+    btnHandler: function(button, e) {
+	let me = this;
+	let action = button.reference;
+	let list = me.lookupReference('list');
+	let selected = list.getSelection();
+	me.doAction(action, selected);
+    },
+
+    doAction: function(action, selected) {
+	if (!selected.length) {
+	    return;
+	}
+
+	let list = this.lookupReference('list');
+
+	if (selected.length > 1) {
+	    let idlist = selected.map(item => item.data.id);
+	    Ext.Msg.confirm(
+		gettext('Confirm'),
+		Ext.String.format(
+		    gettext("Action '{0}' for '{1}' items"),
+		    action, selected.length,
+		),
+		async function(button) {
+		    if (button !== 'yes') {
+			return;
+		    }
+
+		    list.mask(gettext('Processing...'), 'x-mask-loading');
+
+		    const sliceSize = 2500, maxInFlight = 2;
+		    let batches = [], batchCount = Math.ceil(selected.length / sliceSize);
+		    for (let i = 0; i * sliceSize < selected.length; i++) {
+			let sliceStart = i * sliceSize;
+			let sliceEnd = Math.min(sliceStart + sliceSize, selected.length);
+			batches.push(
+			    PMG.Async.doQAction(
+				action,
+				idlist.slice(sliceStart, sliceEnd),
+				i + 1,
+				batchCount,
+			    ),
+			);
+			if (batches.length >= maxInFlight) {
+			    await Promise.allSettled(batches); // eslint-disable-line no-await-in-loop
+			    batches = [];
+			}
+		    }
+		    await Promise.allSettled(batches); // await possible remaining ones
+		    list.unmask();
+		    // below can be slow, we could remove directly from the in-memory store, but
+		    // with lots of elements and some failures we could be quite out of sync?
+		    list.getController().load();
+		},
+	    );
+	    return;
+	}
+
+	PMG.Utils.doQuarantineAction(action, selected[0].data.id, function() {
+	    let listController = list.getController();
+	    listController.allowPositionSave = false;
+	    // success -> remove directly to avoid slow store reload for a single-element action
+	    list.getStore().remove(selected[0]);
+	    listController.restoreSavedSelection();
+	    listController.allowPositionSave = true;
+	});
+    },
+
+    onSelectMail: function() {
+	let me = this;
+	let list = this.lookupReference('list');
+	let selection = list.selModel.getSelection();
+	if (selection.length > 1) {
+	    me.multiSelect(selection);
+	    return;
+	}
+
+	let rec = selection[0] || {};
+
+	me.getViewModel().set('mailid', rec.data ? rec.data.id : '');
+	me.updatePreview(me.raw || false, rec);
+	me.lookupReference('mailinfo').setVisible(!!rec.data && !me.raw);
+	me.lookupReference('mailinfo').update(rec.data);
+    },
+
+    openContextMenu: function(table, record, tr, index, event) {
+	event.stopEvent();
+	let me = this;
+	let list = me.lookup('list');
+	Ext.create('PMG.menu.QuarantineContextMenu', {
+	    callback: action => me.doAction(action, list.getSelection()),
+	}).showAt(event.getXY());
+    },
+
+    keyPress: function(table, record, item, index, event) {
+	let me = this;
+	let list = me.lookup('list');
+	let key = event.getKey();
+	let action = '';
+	switch (key) {
+	    case event.DELETE:
+	    case 127:
+		action = 'delete';
+		break;
+	    case Ext.event.Event.D:
+	    case Ext.event.Event.D + 32:
+		action = 'deliver';
+		break;
+	}
+
+	if (action !== '') {
+	    me.doAction(action, list.getSelection());
+	}
+    },
+
+    control: {
+	'button[reference=raw]': {
+	    click: 'toggleRaw',
+	},
+	'pmgQuarantineList': {
+	    selectionChange: 'onSelectMail',
+	    itemkeypress: 'keyPress',
+	    rowcontextmenu: 'openContextMenu',
+	},
+    },
+});
-- 
2.30.2





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

* [pmg-devel] [PATCH pmg-gui v2 2/2] quarantine: use new controller for virus and attachment quarantines
  2022-10-27 19:12 [pmg-devel] [PATCH pmg-gui v2 0/2] low-hanging improvments for the quarantine interface Stoiko Ivanov
  2022-10-27 19:12 ` [pmg-devel] [PATCH pmg-gui v2 1/2] quarantine: refactor spamquarantine controller Stoiko Ivanov
@ 2022-10-27 19:12 ` Stoiko Ivanov
  2022-10-28  9:35 ` [pmg-devel] applied-series: Re: [PATCH pmg-gui v2 0/2] low-hanging improvments for the quarantine interface Thomas Lamprecht
  2 siblings, 0 replies; 4+ messages in thread
From: Stoiko Ivanov @ 2022-10-27 19:12 UTC (permalink / raw)
  To: pmg-devel

fixes #1674 (the comment about multiselect for the virus quarantine)
fixes #3947 (multiselect for attachment quarantine)

Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
---
 js/AttachmentQuarantine.js | 113 ++++++++++++++++---------------------
 js/VirusQuarantine.js      |  86 +++++++---------------------
 2 files changed, 70 insertions(+), 129 deletions(-)

diff --git a/js/AttachmentQuarantine.js b/js/AttachmentQuarantine.js
index 1e56420..8abfcad 100644
--- a/js/AttachmentQuarantine.js
+++ b/js/AttachmentQuarantine.js
@@ -18,87 +18,59 @@ Ext.define('pmg-attachment-list', {
     idProperty: 'id',
 });
 
-Ext.define('PMG.AttachmentQuarantine', {
-    extend: 'Ext.container.Container',
-    xtype: 'pmgAttachmentQuarantine',
-
-    border: false,
-    layout: { type: 'border' },
-
-    defaults: { border: false },
-
-    controller: {
-
-	xclass: 'Ext.app.ViewController',
-
-	updatePreview: function(raw, rec) {
-	    var preview = this.lookupReference('preview');
+Ext.define('PMG.AttachmentQuarantineController', {
+    extend: 'PMG.controller.QuarantineController',
+    alias: 'controller.attachmentquarantine',
+    xtype: 'pmgAttachmentQuarantineController',
+
+    onSelectMail: function() {
+	let me = this;
+	let list = this.lookupReference('list');
+	let selection = list.selModel.getSelection();
+	if (selection.length <= 1) {
+	    let rec = selection[0] || {};
+	    me.lookup('attachmentlist').setID(rec);
+	}
 
-	    if (!rec || !rec.data || !rec.data.id) {
-		preview.update('');
-		preview.setDisabled(true);
-		return;
-	    }
+	me.callParent();
+    },
 
-	    let url = `/api2/htmlmail/quarantine/content?id=${rec.data.id}`;
-	    if (raw) {
-		url += '&raw=1';
-	    }
-	    preview.setDisabled(false);
-	    preview.update("<iframe frameborder=0 width=100% height=100% sandbox='allow-same-origin' src='" + url +"'></iframe>");
+    control: {
+	'button[reference=raw]': {
+	    click: 'toggleRaw',
 	},
-
-	toggleRaw: function(button) {
-	    var me = this;
-	    var list = this.lookupReference('list');
-	    var rec = list.getSelection()[0] || {};
-	    me.lookup('mailinfo').setVisible(me.raw);
-	    me.raw = !me.raw;
-	    me.updatePreview(me.raw, rec);
+	'pmgQuarantineList': {
+	    selectionChange: 'onSelectMail',
 	},
+    },
 
-	btnHandler: function(button, e) {
-	    var list = this.lookupReference('list');
-	    var selected = list.getSelection();
-	    if (!selected.length) {
-		return;
-	    }
+});
 
-	    var action = button.reference;
+Ext.define('PMG.AttachmentQuarantine', {
+    extend: 'Ext.container.Container',
+    xtype: 'pmgAttachmentQuarantine',
 
-	    PMG.Utils.doQuarantineAction(action, selected[0].data.id, function() {
-		list.getController().load();
-	    });
-	},
+    border: false,
+    layout: { type: 'border' },
 
-	onSelectMail: function() {
-	    let me = this;
-	    let list = me.lookup('list');
-	    let rec = list.getSelection()[0] || {};
-	    let mailinfo = me.lookup('mailinfo');
+    defaults: { border: false },
 
-	    me.updatePreview(me.raw || false, rec);
-	    me.lookup('attachmentlist').setID(rec);
-	    mailinfo.setVisible(!!rec.data && !me.raw);
-	    mailinfo.update(rec.data);
+    viewModel: {
+	parent: null,
+	data: {
+	    mailid: '',
 	},
-
-	control: {
-	    'button[reference=raw]': {
-		click: 'toggleRaw',
-	    },
-	    'pmgQuarantineList': {
-		selectionChange: 'onSelectMail',
-	    },
+	formulas: {
+	    downloadMailURL: get => '/api2/json/quarantine/download?mailid=' + encodeURIComponent(get('mailid')),
 	},
-
     },
-
+    controller: 'attachmentquarantine',
     items: [
 	{
 	    title: gettext('Attachment Quarantine'),
 	    xtype: 'pmgQuarantineList',
 	    emptyText: gettext('No data in database'),
+	    selModel: 'checkboxmodel',
 	    emailSelection: false,
 	    reference: 'list',
 	    region: 'west',
@@ -163,6 +135,19 @@ Ext.define('PMG.AttachmentQuarantine', {
 			    iconCls: 'fa fa-file-code-o',
 			},
 			'->',
+			{
+			    xtype: 'button',
+			    reference: 'download',
+			    text: gettext('Download'),
+			    setDownload: function(id) {
+				this.el.dom.download = id + ".eml";
+			    },
+			    bind: {
+				href: '{downloadMailURL}',
+				download: '{mailid}',
+			    },
+			    iconCls: 'fa fa-download',
+			},
 			{
 			    reference: 'deliver',
 			    text: gettext('Deliver'),
diff --git a/js/VirusQuarantine.js b/js/VirusQuarantine.js
index 4c1d0ba..47e055c 100644
--- a/js/VirusQuarantine.js
+++ b/js/VirusQuarantine.js
@@ -28,80 +28,23 @@ Ext.define('PMG.VirusQuarantine', {
 
     defaults: { border: false },
 
-    controller: {
-
-	xclass: 'Ext.app.ViewController',
-
-	updatePreview: function(raw) {
-	    var list = this.lookupReference('list');
-	    var rec = list.selModel.getSelection()[0];
-	    var preview = this.lookupReference('preview');
-
-	    if (!rec || !rec.data || !rec.data.id) {
-		preview.update('');
-		preview.setDisabled(true);
-		return;
-	    }
-
-	    let url = `/api2/htmlmail/quarantine/content?id=${rec.data.id}`;
-	    if (raw) {
-		url += '&raw=1';
-	    }
-	    preview.setDisabled(false);
-	    preview.update("<iframe frameborder=0 width=100% height=100% sandbox='allow-same-origin' src='" + url +"'></iframe>");
-	},
-
-	toggleRaw: function(button) {
-	    var me = this;
-	    me.lookup('mailinfo').setVisible(me.raw);
-	    me.raw = !me.raw;
-	    me.updatePreview(me.raw);
+    viewModel: {
+	parent: null,
+	data: {
+	    mailid: '',
 	},
-
-	btnHandler: function(button, e) {
-	    var list = this.lookupReference('list');
-	    var selected = list.getSelection();
-	    if (!selected.length) {
-		return;
-	    }
-
-	    var action = button.reference;
-
-	    PMG.Utils.doQuarantineAction(action, selected[0].data.id, function() {
-		list.getController().load();
-	    });
+	formulas: {
+	    downloadMailURL: get => '/api2/json/quarantine/download?mailid=' + encodeURIComponent(get('mailid')),
 	},
-
-	onSelectMail: function() {
-	    var me = this;
-	    me.updatePreview(me.raw || false);
-	    let mailinfo = me.lookup('mailinfo');
-	    let list = me.lookup('list');
-	    let selection = list.getSelection();
-	    if (selection.length < 1) {
-		mailinfo.setVisible(false);
-		return;
-	    }
-	    mailinfo.setVisible(!me.raw);
-	    mailinfo.update(selection[0].data);
-	},
-
-	control: {
-	    'button[reference=raw]': {
-		click: 'toggleRaw',
-	    },
-	    'pmgQuarantineList': {
-		selectionChange: 'onSelectMail',
-	    },
-	},
-
     },
+    controller: 'quarantine',
 
     items: [
 	{
 	    title: gettext('Virus Quarantine'),
 	    xtype: 'pmgQuarantineList',
 	    emptyText: gettext('No data in database'),
+	    selModel: 'checkboxmodel',
 	    emailSelection: false,
 	    reference: 'list',
 	    region: 'west',
@@ -172,6 +115,19 @@ Ext.define('PMG.VirusQuarantine', {
 			    iconCls: 'fa fa-file-code-o',
 			},
 			'->',
+			{
+			    xtype: 'button',
+			    reference: 'download',
+			    text: gettext('Download'),
+			    setDownload: function(id) {
+				this.el.dom.download = id + ".eml";
+			    },
+			    bind: {
+				href: '{downloadMailURL}',
+				download: '{mailid}',
+			    },
+			    iconCls: 'fa fa-download',
+			},
 			{
 			    reference: 'deliver',
 			    text: gettext('Deliver'),
-- 
2.30.2





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

* [pmg-devel] applied-series: Re: [PATCH pmg-gui v2 0/2] low-hanging improvments for the quarantine interface
  2022-10-27 19:12 [pmg-devel] [PATCH pmg-gui v2 0/2] low-hanging improvments for the quarantine interface Stoiko Ivanov
  2022-10-27 19:12 ` [pmg-devel] [PATCH pmg-gui v2 1/2] quarantine: refactor spamquarantine controller Stoiko Ivanov
  2022-10-27 19:12 ` [pmg-devel] [PATCH pmg-gui v2 2/2] quarantine: use new controller for virus and attachment quarantines Stoiko Ivanov
@ 2022-10-28  9:35 ` Thomas Lamprecht
  2 siblings, 0 replies; 4+ messages in thread
From: Thomas Lamprecht @ 2022-10-28  9:35 UTC (permalink / raw)
  To: Stoiko Ivanov, pmg-devel

On 27/10/2022 21:12, Stoiko Ivanov wrote:
> v1->v2:
> * dropped already applied patches
> * changed the patches, by splitting the refactoring of the spamquarantine
>   in a patch of its own, and changing virus and attachmentquarantine in
>   the second patch (no functional change intended) - big thanks for the
>   suggestion @Thomas!!
> 
> gave me also the chance to see the adaptations of the icon-colors for delivery
> and delete by Thomas in action - I like it!
> 
> original cover-letter for v1:
> A few bugzilla entries ask for features in the quarantine interface that
> seem quite sensible (e.g. #4137), or are already present in the (by far
> more used) spamquarantine, but never made it to the others.
> 
> This patchset contains a single small fix, and a refactoring of the
> quarantine views to use the same controller.
> 
> Would be grateful for feedback
> 
> 
> Stoiko Ivanov (2):
>   quarantine: refactor spamquarantine controller
>   quarantine: use new controller for virus and attachment quarantines
> 
>  js/AttachmentQuarantine.js            | 113 +++++-----
>  js/Makefile                           |   1 +
>  js/SpamQuarantine.js                  | 290 +++++++++-----------------
>  js/VirusQuarantine.js                 |  86 ++------
>  js/controller/QuarantineController.js | 170 +++++++++++++++
>  5 files changed, 335 insertions(+), 325 deletions(-)
>  create mode 100644 js/controller/QuarantineController.js
> 


applied series, many thanks!




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

end of thread, other threads:[~2022-10-28  9:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-27 19:12 [pmg-devel] [PATCH pmg-gui v2 0/2] low-hanging improvments for the quarantine interface Stoiko Ivanov
2022-10-27 19:12 ` [pmg-devel] [PATCH pmg-gui v2 1/2] quarantine: refactor spamquarantine controller Stoiko Ivanov
2022-10-27 19:12 ` [pmg-devel] [PATCH pmg-gui v2 2/2] quarantine: use new controller for virus and attachment quarantines Stoiko Ivanov
2022-10-28  9:35 ` [pmg-devel] applied-series: Re: [PATCH pmg-gui v2 0/2] low-hanging improvments for the quarantine interface Thomas Lamprecht

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal