]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/storage/ContentView.js
update shipped appliance info index
[pve-manager.git] / www / manager6 / storage / ContentView.js
CommitLineData
4a580e60
DM
1Ext.define('PVE.storage.ContentView', {
2 extend: 'Ext.grid.GridPanel',
3
3f90858a 4 alias: 'widget.pveStorageContentView',
4a580e60 5
62580ab8
TL
6 itemdblclick: Ext.emptyFn,
7
c90539de
DC
8 viewConfig: {
9 trackOver: false,
1d8306e4 10 loadMask: false,
c90539de 11 },
1d8306e4 12 initComponent: function() {
4a580e60
DM
13 var me = this;
14
dbeddeb3
FE
15 if (!me.nodename) {
16 me.nodename = me.pveSelNode.data.node;
17 if (!me.nodename) {
18 throw "no node name specified";
19 }
4a580e60 20 }
1d8306e4 21 const nodename = me.nodename;
4a580e60 22
dbeddeb3
FE
23 if (!me.storage) {
24 me.storage = me.pveSelNode.data.storage;
25 if (!me.storage) {
26 throw "no storage ID specified";
27 }
4a580e60 28 }
1d8306e4 29 const storage = me.storage;
4a580e60 30
e8b422bc
FE
31 var content = me.content;
32 if (!content) {
33 throw "no content type specified";
34 }
35
1d8306e4
TL
36 const baseurl = `/nodes/${nodename}/storage/${storage}/content`;
37 let store = me.store = Ext.create('Ext.data.Store', {
4a580e60 38 model: 'pve-storage-content',
4a580e60 39 proxy: {
56a353b9 40 type: 'proxmox',
e8b422bc
FE
41 url: '/api2/json' + baseurl,
42 extraParams: {
43 content: content,
44 },
4a580e60 45 },
177de3de
DC
46 sorters: {
47 property: 'volid',
392e3cf1 48 direction: 'ASC',
1d8306e4 49 },
4a580e60
DM
50 });
51
dbeddeb3
FE
52 if (!me.sm) {
53 me.sm = Ext.create('Ext.selection.RowModel', {});
54 }
1d8306e4 55 let sm = me.sm;
4a580e60 56
1d8306e4 57 let reload = () => store.load();
4a580e60 58
e7ade592 59 Proxmox.Utils.monStoreErrors(me, store);
4a580e60 60
3dd9c5c8 61 let tbar = me.tbar ? [...me.tbar] : [];
8798c35b 62 if (me.useUploadButton) {
3dd9c5c8 63 tbar.unshift(
af3c0a92
LS
64 {
65 xtype: 'button',
66 text: gettext('Upload'),
67 disabled: !me.enableUploadButton,
68 handler: function() {
26bfeca1 69 Ext.create('PVE.window.UploadToStorage', {
af3c0a92
LS
70 nodename: nodename,
71 storage: storage,
f9f45aac 72 content: content,
af3c0a92
LS
73 autoShow: true,
74 taskDone: () => reload(),
75 });
76 },
77 },
78 {
79 xtype: 'button',
80 text: gettext('Download from URL'),
81 disabled: !me.enableDownloadUrlButton,
82 handler: function() {
01366f9e 83 Ext.create('PVE.window.DownloadUrlToStorage', {
af3c0a92
LS
84 nodename: nodename,
85 storage: storage,
86 content: content,
87 autoShow: true,
88 taskDone: () => reload(),
89 });
90 },
91 },
92 '-',
93 );
8798c35b 94 }
f5e17f15 95 if (!me.useCustomRemoveButton) {
3dd9c5c8 96 tbar.push({
af3c0a92
LS
97 xtype: 'proxmoxStdRemoveButton',
98 selModel: sm,
2b289547 99 enableFn: rec => !rec?.data?.protected,
af3c0a92
LS
100 delay: 5,
101 callback: () => reload(),
102 baseurl: baseurl + '/',
103 });
f5e17f15 104 }
3dd9c5c8 105 tbar.push(
9ce0c258 106 '->',
1d8306e4
TL
107 gettext('Search') + ':',
108 ' ',
9ce0c258
FE
109 {
110 xtype: 'textfield',
111 width: 200,
112 enableKeyEvents: true,
5a912de3 113 emptyText: content === 'backup' ? gettext('Name, Format, Notes') : gettext('Name, Format'),
9ce0c258 114 listeners: {
c8a71b9e
TL
115 keyup: {
116 buffer: 500,
117 fn: function(field) {
5a912de3 118 let needle = field.getValue().toLocaleLowerCase();
c8a71b9e
TL
119 store.clearFilter(true);
120 store.filter([
121 {
5a912de3
TL
122 filterFn: ({ data }) =>
123 data.text?.toLocaleLowerCase().includes(needle) ||
124 data.notes?.toLocaleLowerCase().includes(needle),
c8a71b9e
TL
125 },
126 ]);
127 },
128 },
129 change: function(field, newValue, oldValue) {
130 if (newValue !== this.originalValue) {
131 this.triggers.clear.setVisible(true);
132 }
133 },
134 },
135 triggers: {
136 clear: {
137 cls: 'pmx-clear-trigger',
138 weight: -1,
139 hidden: true,
140 handler: function() {
141 this.triggers.clear.setVisible(false);
142 this.setValue(this.originalValue);
143 store.clearFilter();
144 },
145 },
146 },
147 },
9ce0c258
FE
148 );
149
6ecc7420 150 let availableColumns = {
7ef0f4c3
FE
151 'name': {
152 header: gettext('Name'),
153 flex: 2,
154 sortable: true,
155 renderer: PVE.Utils.render_storage_content,
1d8306e4 156 dataIndex: 'text',
7ef0f4c3 157 },
ef402242
DC
158 'notes': {
159 header: gettext('Notes'),
7ef0f4c3
FE
160 flex: 1,
161 renderer: Ext.htmlEncode,
ef402242 162 dataIndex: 'notes',
7ef0f4c3 163 },
61cf2658 164 'protected': {
528c24b5
TL
165 header: `<i class="fa fa-shield"></i>`,
166 tooltip: gettext('Protected'),
167 width: 30,
168 renderer: v => v ? `<i data-qtip="${gettext('Protected')}" class="fa fa-shield"></i>` : '',
bc54c473 169 sorter: (a, b) => (b.data.protected || 0) - (a.data.protected || 0),
61cf2658
FE
170 dataIndex: 'protected',
171 },
7ef0f4c3
FE
172 'date': {
173 header: gettext('Date'),
174 width: 150,
1d8306e4 175 dataIndex: 'vdate',
7ef0f4c3
FE
176 },
177 'format': {
178 header: gettext('Format'),
179 width: 100,
1d8306e4 180 dataIndex: 'format',
7ef0f4c3
FE
181 },
182 'size': {
183 header: gettext('Size'),
184 width: 100,
185 renderer: Proxmox.Utils.format_size,
1d8306e4 186 dataIndex: 'size',
7ef0f4c3
FE
187 },
188 };
189
c0eadd55
FE
190 let showColumns = me.showColumns || ['name', 'date', 'format', 'size'];
191
192 Object.keys(availableColumns).forEach(function(key) {
193 if (!showColumns.includes(key)) {
194 delete availableColumns[key];
195 }
196 });
197
ebea3f45
TL
198 if (me.extraColumns && typeof me.extraColumns === 'object') {
199 Object.assign(availableColumns, me.extraColumns);
200 }
6ecc7420 201 const columns = Object.values(availableColumns);
7ef0f4c3 202
9ce0c258 203 Ext.apply(me, {
1826922d 204 store,
9ce0c258 205 selModel: sm,
3dd9c5c8 206 tbar,
1826922d 207 columns,
4a580e60 208 listeners: {
1d8306e4 209 activate: reload,
62580ab8 210 itemdblclick: (view, record) => me.itemdblclick(view, record),
1d8306e4 211 },
4a580e60
DM
212 });
213
214 me.callParent();
1d8306e4 215 },
4a580e60 216}, function() {
4a580e60
DM
217 Ext.define('pve-storage-content', {
218 extend: 'Ext.data.Model',
177de3de
DC
219 fields: [
220 'volid', 'content', 'format', 'size', 'used', 'vmid',
ef402242 221 'channel', 'id', 'lun', 'notes', 'verification',
177de3de
DC
222 {
223 name: 'text',
4a580e60 224 convert: function(value, record) {
86cc7049
DC
225 // check for volid, because if you click on a grouping header,
226 // it calls convert (but with an empty volid)
227 if (value || record.data.volid === null) {
4a580e60
DM
228 return value;
229 }
230 return PVE.Utils.render_storage_content(value, {}, record);
1d8306e4 231 },
12d50fcd
TL
232 },
233 {
234 name: 'vdate',
235 convert: function(value, record) {
236 // check for volid, because if you click on a grouping header,
237 // it calls convert (but with an empty volid)
238 if (value || record.data.volid === null) {
239 return value;
240 }
241 let t = record.data.content;
242 if (t === "backup") {
243 let v = record.data.volid;
244 let match = v.match(/(\d{4}_\d{2}_\d{2})-(\d{2}_\d{2}_\d{2})/);
245 if (match) {
a4a86fe9 246 let date = match[1].replace(/_/g, '-');
12d50fcd
TL
247 let time = match[2].replace(/_/g, ':');
248 return date + " " + time;
249 }
250 }
a4a86fe9
DM
251 if (record.data.ctime) {
252 let ctime = new Date(record.data.ctime * 1000);
1d8306e4 253 return Ext.Date.format(ctime, 'Y-m-d H:i:s');
a4a86fe9 254 }
12d50fcd 255 return '';
1d8306e4 256 },
12d50fcd 257 },
4a580e60 258 ],
1d8306e4 259 idProperty: 'volid',
4a580e60 260 });
4a580e60 261});