ui: tape: rework BackupOverview
instead of grouping by tape (which is rarely interesting), group by pool -> group -> id -> mediaset this way a user looking for a backup of specific vm can do just that we may want to have an additional view here were we list all snapshots included in the selected media-set ? Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
f806c0effa
commit
631e550920
@ -260,6 +260,15 @@ Ext.define('PBS.Utils', {
|
||||
return dedup;
|
||||
},
|
||||
|
||||
parse_snapshot_id: function(snapshot) {
|
||||
if (!snapshot) {
|
||||
return [undefined, undefined, undefined];
|
||||
}
|
||||
let [_match, type, group, id] = /^([^/]+)\/([^/]+)\/(.+)$/.exec(snapshot);
|
||||
|
||||
return [type, group, id];
|
||||
},
|
||||
|
||||
get_type_icon_cls: function(btype) {
|
||||
var cls = '';
|
||||
if (btype.startsWith('vm')) {
|
||||
|
@ -16,6 +16,90 @@ Ext.define('PBS.TapeManagement.BackupOverview', {
|
||||
}).show();
|
||||
},
|
||||
|
||||
restore: function(button, record) {
|
||||
let me = this;
|
||||
let view = me.getView();
|
||||
let selection = view.getSelection();
|
||||
if (!selection || selection.length < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mediaset = selection[0].data.text;
|
||||
let uuid = selection[0].data.uuid;
|
||||
Ext.create('PBS.TapeManagement.TapeRestoreWindow', {
|
||||
mediaset,
|
||||
uuid,
|
||||
listeners: {
|
||||
destroy: function() {
|
||||
me.reload();
|
||||
},
|
||||
},
|
||||
}).show();
|
||||
},
|
||||
|
||||
loadContent: async function() {
|
||||
let content_response = await PBS.Async.api2({
|
||||
url: '/api2/extjs/tape/media/content',
|
||||
});
|
||||
let data = {};
|
||||
|
||||
for (const entry of content_response.result.data) {
|
||||
let pool = entry.pool;
|
||||
let [type, group_id, id] = PBS.Utils.parse_snapshot_id(entry.snapshot);
|
||||
let group = `${type}/${group_id}`;
|
||||
let media_set = entry['media-set-name'];
|
||||
let uuid = entry['media-set-uuid'];
|
||||
let ctime = entry['media-set-ctime'];
|
||||
if (data[pool] === undefined) {
|
||||
data[pool] = {};
|
||||
}
|
||||
|
||||
if (data[pool][group] === undefined) {
|
||||
data[pool][group] = {};
|
||||
}
|
||||
|
||||
if (data[pool][group][id] === undefined) {
|
||||
data[pool][group][id] = [];
|
||||
}
|
||||
data[pool][group][id].push({
|
||||
text: media_set,
|
||||
uuid,
|
||||
ctime,
|
||||
leaf: true,
|
||||
});
|
||||
}
|
||||
|
||||
let list = [];
|
||||
|
||||
for (const [pool, groups] of Object.entries(data)) {
|
||||
let pool_entry = {
|
||||
text: pool,
|
||||
leaf: false,
|
||||
children: [],
|
||||
};
|
||||
for (const [group, ids] of Object.entries(groups)) {
|
||||
let group_entry = {
|
||||
text: group,
|
||||
iconCls: "fa " + PBS.Utils.get_type_icon_cls(group),
|
||||
leaf: false,
|
||||
children: [],
|
||||
};
|
||||
for (const [id, media_sets] of Object.entries(ids)) {
|
||||
let id_entry = {
|
||||
text: `${group}/${id}`,
|
||||
leaf: false,
|
||||
children: media_sets,
|
||||
};
|
||||
group_entry.children.push(id_entry);
|
||||
}
|
||||
pool_entry.children.push(group_entry);
|
||||
}
|
||||
list.push(pool_entry);
|
||||
}
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
reload: async function() {
|
||||
let me = this;
|
||||
let view = me.getView();
|
||||
@ -23,43 +107,7 @@ Ext.define('PBS.TapeManagement.BackupOverview', {
|
||||
Proxmox.Utils.setErrorMask(view, true);
|
||||
|
||||
try {
|
||||
let list_response = await PBS.Async.api2({
|
||||
url: '/api2/extjs/tape/media/list',
|
||||
});
|
||||
let list = list_response.result.data.sort(
|
||||
(a, b) => a['label-text'].localeCompare(b['label-text']),
|
||||
);
|
||||
|
||||
let content = {};
|
||||
|
||||
let content_response = await PBS.Async.api2({
|
||||
url: '/api2/extjs/tape/media/content',
|
||||
});
|
||||
|
||||
let content_list = content_response.result.data.sort(
|
||||
(a, b) => a.snapshot.localeCompare(b.snapshot),
|
||||
);
|
||||
|
||||
for (let entry of content_list) {
|
||||
let tape = entry['label-text'];
|
||||
entry['label-text'] = entry.snapshot;
|
||||
entry.leaf = true;
|
||||
if (content[tape] === undefined) {
|
||||
content[tape] = [entry];
|
||||
} else {
|
||||
content[tape].push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
for (let child of list) {
|
||||
let tape = child['label-text'];
|
||||
if (content[tape]) {
|
||||
child.children = content[tape];
|
||||
child.leaf = false;
|
||||
} else {
|
||||
child.leaf = true;
|
||||
}
|
||||
}
|
||||
let list = await me.loadContent();
|
||||
|
||||
view.setRootNode({
|
||||
expanded: true,
|
||||
@ -78,8 +126,14 @@ Ext.define('PBS.TapeManagement.BackupOverview', {
|
||||
},
|
||||
|
||||
store: {
|
||||
sorters: 'label-text',
|
||||
data: [],
|
||||
sorters: function(a, b) {
|
||||
if (a.data.leaf && b.data.leaf) {
|
||||
return a.data.ctime - b.data.ctime;
|
||||
} else {
|
||||
return a.data.text.localeCompare(b.data.text);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
rootVisible: false,
|
||||
@ -99,50 +153,15 @@ Ext.define('PBS.TapeManagement.BackupOverview', {
|
||||
columns: [
|
||||
{
|
||||
xtype: 'treecolumn',
|
||||
text: gettext('Tape/Backup'),
|
||||
dataIndex: 'label-text',
|
||||
text: gettext('Pool/Group/Snapshot/Media Set'),
|
||||
dataIndex: 'text',
|
||||
sortable: false,
|
||||
flex: 3,
|
||||
},
|
||||
{
|
||||
text: gettext('Location'),
|
||||
dataIndex: 'location',
|
||||
flex: 1,
|
||||
renderer: function(value) {
|
||||
if (!value) {
|
||||
return "";
|
||||
}
|
||||
let result;
|
||||
if ((result = /^online-(.+)$/.exec(value)) !== null) {
|
||||
return Ext.htmlEncode(result[1]);
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
},
|
||||
{
|
||||
text: gettext('Status'),
|
||||
dataIndex: 'status',
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
text: gettext('Media Set'),
|
||||
dataIndex: 'media-set-name',
|
||||
flex: 2,
|
||||
},
|
||||
{
|
||||
text: gettext('Pool'),
|
||||
dataIndex: 'pool',
|
||||
flex: 1,
|
||||
},
|
||||
{
|
||||
text: gettext('Sequence Nr.'),
|
||||
dataIndex: 'seq-nr',
|
||||
flex: 0.5,
|
||||
},
|
||||
{
|
||||
text: gettext('Backup Time'),
|
||||
dataIndex: 'backup-time',
|
||||
renderer: (time) => time !== undefined ? new Date(time*1000) : "",
|
||||
text: gettext('Media Set UUID'),
|
||||
dataIndex: 'uuid',
|
||||
sortable: false,
|
||||
flex: 1,
|
||||
},
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user