]> git.proxmox.com Git - proxmox-backup.git/blob - www/DataStoreContent.js
8099c99c408533b5b6605f19cd816d1e2d1a0e1c
[proxmox-backup.git] / www / DataStoreContent.js
1 Ext.define('pbs-data-store-snapshots', {
2 extend: 'Ext.data.Model',
3 fields: [
4 'backup-type',
5 'backup-id',
6 {
7 name: 'backup-time',
8 type: 'date',
9 dateFormat: 'timestamp'
10 },
11 'files',
12 'owner',
13 { name: 'size', type: 'int' },
14 ]
15 });
16
17 Ext.define('PBS.DataStoreContent', {
18 extend: 'Ext.tree.Panel',
19 alias: 'widget.pbsDataStoreContent',
20
21 rootVisible: false,
22
23 title: gettext('Content'),
24
25 controller: {
26 xclass: 'Ext.app.ViewController',
27
28 init: function(view) {
29 if (!view.datastore) {
30 throw "no datastore specified";
31 }
32
33 this.store = Ext.create('Ext.data.Store', {
34 model: 'pbs-data-store-snapshots',
35 sorters: 'backup-group',
36 groupField: 'backup-group',
37 });
38 this.store.on('load', this.onLoad, this);
39
40 Proxmox.Utils.monStoreErrors(view, view.store, true);
41 this.reload(); // initial load
42 },
43
44 reload: function() {
45 let view = this.getView();
46
47 if (!view.store || !this.store) {
48 console.warn('cannot reload, no store(s)');
49 return;
50 }
51
52 let url = `/api2/json/admin/datastore/${view.datastore}/snapshots`;
53 this.store.setProxy({
54 type: 'proxmox',
55 url: url
56 });
57
58 this.store.load();
59 },
60
61 getRecordGroups: function(records) {
62 let groups = {};
63
64 for (const item of records) {
65 var btype = item.data["backup-type"];
66 let group = btype + "/" + item.data["backup-id"];
67
68 if (groups[group] !== undefined) {
69 continue;
70 }
71
72 var cls = '';
73 if (btype === 'vm') {
74 cls = 'fa-desktop';
75 } else if (btype === 'ct') {
76 cls = 'fa-cube';
77 } else if (btype === 'host') {
78 cls = 'fa-building';
79 } else {
80 console.warn(`got unkown backup-type '${btype}'`);
81 continue; // FIXME: auto render? what do?
82 }
83
84 groups[group] = {
85 text: group,
86 leaf: false,
87 iconCls: "fa " + cls,
88 expanded: false,
89 backup_type: item.data["backup-type"],
90 backup_id: item.data["backup-id"],
91 children: []
92 };
93 }
94
95 return groups;
96 },
97
98 onLoad: function(store, records, success) {
99 let view = this.getView();
100
101 if (!success) {
102 return;
103 }
104
105 let groups = this.getRecordGroups(records);
106
107 for (const item of records) {
108 let group = item.data["backup-type"] + "/" + item.data["backup-id"];
109 let children = groups[group].children;
110
111 let data = item.data;
112
113 data.text = group + '/' + PBS.Utils.render_datetime_utc(data["backup-time"]);
114 data.leaf = true;
115 data.cls = 'no-leaf-icons';
116
117 children.push(data);
118 }
119
120 let children = [];
121 for (const [_key, group] of Object.entries(groups)) {
122 let last_backup = 0;
123 for (const item of group.children) {
124 if (item["backup-time"] > last_backup) {
125 last_backup = item["backup-time"];
126 group["backup-time"] = last_backup;
127 group.files = item.files;
128 group.size = item.size;
129 group.owner = item.owner;
130 }
131 }
132 group.count = group.children.length;
133 children.push(group);
134 }
135
136 view.setRootNode({
137 expanded: true,
138 children: children
139 });
140 },
141
142 onPrune: function() {
143 var view = this.getView();
144
145 let rec = view.selModel.getSelection()[0];
146 if (!(rec && rec.data)) return;
147 let data = rec.data;
148 if (data.leaf) return;
149
150 if (!view.datastore) return;
151
152 let win = Ext.create('PBS.DataStorePrune', {
153 datastore: view.datastore,
154 backup_type: data.backup_type,
155 backup_id: data.backup_id,
156 });
157 win.on('destroy', this.reload, this);
158 win.show();
159 }
160 },
161
162 columns: [
163 {
164 xtype: 'treecolumn',
165 header: gettext("Backup Group"),
166 dataIndex: 'text',
167 flex: 1
168 },
169 {
170 xtype: 'datecolumn',
171 header: gettext('Backup Time'),
172 sortable: true,
173 dataIndex: 'backup-time',
174 format: 'Y-m-d H:i:s',
175 width: 150
176 },
177 {
178 header: gettext("Size"),
179 sortable: true,
180 dataIndex: 'size',
181 renderer: Proxmox.Utils.format_size,
182 },
183 {
184 xtype: 'numbercolumn',
185 format: '0',
186 header: gettext("Count"),
187 sortable: true,
188 dataIndex: 'count',
189 },
190 {
191 header: gettext("Owner"),
192 sortable: true,
193 dataIndex: 'owner',
194 },
195 {
196 header: gettext("Files"),
197 sortable: false,
198 dataIndex: 'files',
199 flex: 2
200 },
201 ],
202
203 tbar: [
204 {
205 text: gettext('Reload'),
206 iconCls: 'fa fa-refresh',
207 handler: 'reload',
208 },
209 {
210 xtype: 'proxmoxButton',
211 text: gettext('Prune'),
212 disabled: true,
213 enableFn: function(record) { return !record.data.leaf; },
214 handler: 'onPrune',
215 }
216 ],
217 });