]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/storage/ContentView.js
3a19012d4025cb8bfaeca38673e8072087275059
[pve-manager.git] / www / manager6 / storage / ContentView.js
1 Ext.define('PVE.storage.ContentView', {
2 extend: 'Ext.grid.GridPanel',
3
4 alias: 'widget.pveStorageContentView',
5
6 viewConfig: {
7 trackOver: false,
8 loadMask: false,
9 },
10 initComponent: function() {
11 var me = this;
12
13 if (!me.nodename) {
14 me.nodename = me.pveSelNode.data.node;
15 if (!me.nodename) {
16 throw "no node name specified";
17 }
18 }
19 const nodename = me.nodename;
20
21 if (!me.storage) {
22 me.storage = me.pveSelNode.data.storage;
23 if (!me.storage) {
24 throw "no storage ID specified";
25 }
26 }
27 const storage = me.storage;
28
29 var content = me.content;
30 if (!content) {
31 throw "no content type specified";
32 }
33
34 const baseurl = `/nodes/${nodename}/storage/${storage}/content`;
35 let store = me.store = Ext.create('Ext.data.Store', {
36 model: 'pve-storage-content',
37 proxy: {
38 type: 'proxmox',
39 url: '/api2/json' + baseurl,
40 extraParams: {
41 content: content,
42 },
43 },
44 sorters: {
45 property: 'volid',
46 order: 'DESC',
47 },
48 });
49
50 if (!me.sm) {
51 me.sm = Ext.create('Ext.selection.RowModel', {});
52 }
53 let sm = me.sm;
54
55 let reload = () => store.load();
56
57 Proxmox.Utils.monStoreErrors(me, store);
58
59 if (!me.tbar) {
60 me.tbar = [];
61 }
62 if (me.useUploadButton) {
63 me.tbar.unshift(
64 {
65 xtype: 'button',
66 text: gettext('Upload'),
67 disabled: !me.enableUploadButton,
68 handler: function() {
69 Ext.create('PVE.window.UploadToStorage', {
70 nodename: nodename,
71 storage: storage,
72 content: content,
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() {
83 Ext.create('PVE.window.DownloadUrlToStorage', {
84 nodename: nodename,
85 storage: storage,
86 content: content,
87 autoShow: true,
88 taskDone: () => reload(),
89 });
90 },
91 },
92 '-',
93 );
94 }
95 if (!me.useCustomRemoveButton) {
96 me.tbar.push({
97 xtype: 'proxmoxStdRemoveButton',
98 selModel: sm,
99 enableFn: rec => !rec?.data?.protected,
100 delay: 5,
101 callback: () => reload(),
102 baseurl: baseurl + '/',
103 });
104 }
105 me.tbar.push(
106 '->',
107 gettext('Search') + ':',
108 ' ',
109 {
110 xtype: 'textfield',
111 width: 200,
112 enableKeyEvents: true,
113 emptyText: gettext('Name, Format'),
114 listeners: {
115 keyup: {
116 buffer: 500,
117 fn: function(field) {
118 store.clearFilter(true);
119 store.filter([
120 {
121 property: 'text',
122 value: field.getValue(),
123 anyMatch: true,
124 caseSensitive: false,
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 },
148 );
149
150 let availableColumns = {
151 'name': {
152 header: gettext('Name'),
153 flex: 2,
154 sortable: true,
155 renderer: PVE.Utils.render_storage_content,
156 dataIndex: 'text',
157 },
158 'notes': {
159 header: gettext('Notes'),
160 flex: 1,
161 renderer: Ext.htmlEncode,
162 dataIndex: 'notes',
163 },
164 'protected': {
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>` : '',
169 sorter: (a, b) => (b.data.protected || 0) - (a.data.protected || 0),
170 dataIndex: 'protected',
171 },
172 'date': {
173 header: gettext('Date'),
174 width: 150,
175 dataIndex: 'vdate',
176 },
177 'format': {
178 header: gettext('Format'),
179 width: 100,
180 dataIndex: 'format',
181 },
182 'size': {
183 header: gettext('Size'),
184 width: 100,
185 renderer: Proxmox.Utils.format_size,
186 dataIndex: 'size',
187 },
188 };
189
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
198 if (me.extraColumns && typeof me.extraColumns === 'object') {
199 Object.assign(availableColumns, me.extraColumns);
200 }
201 const columns = Object.values(availableColumns);
202
203 Ext.apply(me, {
204 store: store,
205 selModel: sm,
206 tbar: me.tbar,
207 columns: columns,
208 listeners: {
209 activate: reload,
210 },
211 });
212
213 me.callParent();
214 },
215 }, function() {
216 Ext.define('pve-storage-content', {
217 extend: 'Ext.data.Model',
218 fields: [
219 'volid', 'content', 'format', 'size', 'used', 'vmid',
220 'channel', 'id', 'lun', 'notes', 'verification',
221 {
222 name: 'text',
223 convert: function(value, record) {
224 // check for volid, because if you click on a grouping header,
225 // it calls convert (but with an empty volid)
226 if (value || record.data.volid === null) {
227 return value;
228 }
229 return PVE.Utils.render_storage_content(value, {}, record);
230 },
231 },
232 {
233 name: 'vdate',
234 convert: function(value, record) {
235 // check for volid, because if you click on a grouping header,
236 // it calls convert (but with an empty volid)
237 if (value || record.data.volid === null) {
238 return value;
239 }
240 let t = record.data.content;
241 if (t === "backup") {
242 let v = record.data.volid;
243 let match = v.match(/(\d{4}_\d{2}_\d{2})-(\d{2}_\d{2}_\d{2})/);
244 if (match) {
245 let date = match[1].replace(/_/g, '-');
246 let time = match[2].replace(/_/g, ':');
247 return date + " " + time;
248 }
249 }
250 if (record.data.ctime) {
251 let ctime = new Date(record.data.ctime * 1000);
252 return Ext.Date.format(ctime, 'Y-m-d H:i:s');
253 }
254 return '';
255 },
256 },
257 ],
258 idProperty: 'volid',
259 });
260 });