]>
git.proxmox.com Git - proxmox-widget-toolkit.git/blob - src/node/APTRepositories.js
1 Ext
.define('apt-repolist', {
2 extend
: 'Ext.data.Model',
18 Ext
.define('Proxmox.node.APTRepositoriesErrors', {
19 extend
: 'Ext.grid.GridPanel',
21 xtype
: 'proxmoxNodeAPTRepositoriesErrors',
23 title
: gettext('Errors'),
29 getRowClass
: () => 'proxmox-invalid-row',
34 header
: gettext('File'),
36 renderer
: value
=> `<i class='pve-grid-fa fa fa-fw fa-exclamation-triangle'></i>${value}`,
40 header
: gettext('Error'),
47 Ext
.define('Proxmox.node.APTRepositoriesGrid', {
48 extend
: 'Ext.grid.GridPanel',
49 xtype
: 'proxmoxNodeAPTRepositoriesGrid',
51 title
: gettext('APT Repositories'),
55 text
: gettext('Reload'),
56 iconCls
: 'fa fa-refresh',
59 me
.up('proxmoxNodeAPTRepositories').reload();
72 xtype
: 'proxmoxButton',
73 text
: gettext('Enable') + '/' + gettext('Disable'),
75 handler: function(button
, event
, record
) {
77 let panel
= me
.up('proxmoxNodeAPTRepositories');
80 path
: record
.data
.Path
,
81 index
: record
.data
.Index
,
82 enabled
: record
.data
.Enabled
? 0 : 1, // invert
85 if (panel
.digest
!== undefined) {
86 params
.digest
= panel
.digest
;
89 Proxmox
.Utils
.API2Request({
90 url
: `/nodes/${panel.nodename}/apt/repositories`,
93 failure: function(response
, opts
) {
94 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
97 success: function(response
, opts
) {
105 sortableColumns
: false,
109 header
: gettext('Official'),
110 dataIndex
: 'OfficialHost',
111 renderer: function(value
, cell
, record
) {
112 let icon
= (cls
) => `<i class="fa fa-fw ${cls}"></i>`;
114 const enabled
= record
.data
.Enabled
;
116 if (value
=== undefined || value
=== null) {
117 return icon('fa-question-circle-o');
120 return icon('fa-times ' + (enabled
? 'critical' : 'faded'));
122 return icon('fa-check ' + (enabled
? 'good' : 'faded'));
127 header
: gettext('Enabled'),
128 dataIndex
: 'Enabled',
129 renderer
: Proxmox
.Utils
.format_enabled_toggle
,
133 header
: gettext('Types'),
135 renderer: function(types
, cell
, record
) {
136 return types
.join(' ');
141 header
: gettext('URIs'),
143 renderer: function(uris
, cell
, record
) {
144 return uris
.join(' ');
149 header
: gettext('Suites'),
151 renderer: function(suites
, cell
, record
) {
152 return suites
.join(' ');
157 header
: gettext('Components'),
158 dataIndex
: 'Components',
159 renderer: function(components
, cell
, record
) {
160 return components
.join(' ');
165 header
: gettext('Options'),
166 dataIndex
: 'Options',
167 renderer: function(options
, cell
, record
) {
172 let filetype
= record
.data
.FileType
;
175 options
.forEach(function(option
) {
176 let key
= option
.Key
;
177 if (filetype
=== 'list') {
178 let values
= option
.Values
.join(',');
179 text
+= `${key}=${values} `;
180 } else if (filetype
=== 'sources') {
181 let values
= option
.Values
.join(' ');
182 text
+= `${key}: ${values}<br>`;
184 throw "unkown file type";
192 header
: gettext('Comment'),
193 dataIndex
: 'Comment',
198 addAdditionalInfos: function(gridData
, infos
) {
202 let officialHosts
= {};
204 let addLine = function(obj
, key
, line
) {
213 for (const info
of infos
) {
214 const key
= `${info.path}:${info.index}`;
215 if (info
.kind
=== 'warning' ||
216 (info
.kind
=== 'ignore-pre-upgrade-warning' && !me
.majorUpgradeAllowed
)
218 addLine(warnings
, key
, gettext('Warning') + ": " + info
.message
);
219 } else if (info
.kind
=== 'badge' && info
.message
=== 'official host name') {
220 officialHosts
[key
] = true;
224 gridData
.forEach(function(record
) {
225 const key
= `${record.Path}:${record.Index}`;
226 record
.OfficialHost
= !!officialHosts
[key
];
229 me
.rowBodyFeature
.getAdditionalData = function(innerData
, rowIndex
, record
, orig
) {
230 let headerCt
= this.view
.headerCt
;
231 let colspan
= headerCt
.getColumnCount();
233 const key
= `${innerData.Path}:${innerData.Index}`;
234 const warning_text
= warnings
[key
];
237 rowBody
: '<div style="color: red; white-space: pre-line">' +
238 Ext
.String
.htmlEncode(warning_text
) + '</div>',
239 rowBodyCls
: warning_text
? '' : Ext
.baseCSSPrefix
+ 'grid-row-body-hidden',
240 rowBodyColspan
: colspan
,
245 initComponent: function() {
249 throw "no node name specified";
252 let store
= Ext
.create('Ext.data.Store', {
253 model
: 'apt-repolist',
263 let rowBodyFeature
= Ext
.create('Ext.grid.feature.RowBody', {});
265 let groupingFeature
= Ext
.create('Ext.grid.feature.Grouping', {
266 groupHeaderTpl
: '{[ "File: " + values.name ]} ({rows.length} ' +
267 'repositor{[values.rows.length > 1 ? "ies" : "y"]})',
268 enableGroupingMenu
: false,
271 let sm
= Ext
.create('Ext.selection.RowModel', {});
276 rowBodyFeature
: rowBodyFeature
,
277 features
: [groupingFeature
, rowBodyFeature
],
284 Ext
.define('Proxmox.node.APTRepositories', {
285 extend
: 'Ext.panel.Panel',
286 xtype
: 'proxmoxNodeAPTRepositories',
287 mixins
: ['Proxmox.Mixin.CBind'],
294 subscriptionActive
: '',
295 noSubscriptionRepo
: '',
299 noErrors
: (get) => get('errorCount') === 0,
300 mainWarning: function(get) {
301 // Not yet initialized
302 if (get('subscriptionActive') === '' ||
303 get('enterpriseRepo') === '') {
307 let withStyle
= (msg
) => "<div style='color:red;'><i class='fa fa-fw " +
308 "fa-exclamation-triangle'></i>" + gettext('Warning') + ': ' + msg
+ "</div>";
310 if (!get('subscriptionActive') && get('enterpriseRepo')) {
311 return withStyle(gettext('The enterprise repository is ' +
312 'enabled, but there is no active subscription!'));
315 if (get('noSubscriptionRepo')) {
316 return withStyle(gettext('The no-subscription repository is ' +
317 'not recommended for production use!'));
320 if (!get('enterpriseRepo') && !get('noSubscriptionRepo')) {
321 return withStyle(gettext('No Proxmox repository is enabled!'));
331 title
: gettext('Warning'),
332 name
: 'repositoriesMainWarning',
335 title
: '{mainWarning}',
336 hidden
: '{!mainWarning}',
340 xtype
: 'proxmoxNodeAPTRepositoriesErrors',
341 name
: 'repositoriesErrors',
344 hidden
: '{noErrors}',
348 xtype
: 'proxmoxNodeAPTRepositoriesGrid',
349 name
: 'repositoriesGrid',
351 nodename
: '{nodename}',
353 majorUpgradeAllowed
: false, // TODO get release information from an API call?
357 check_subscription: function() {
359 let vm
= me
.getViewModel();
361 Proxmox
.Utils
.API2Request({
362 url
: `/nodes/${me.nodename}/subscription`,
364 failure
: (response
, opts
) => Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
),
365 success: function(response
, opts
) {
366 const res
= response
.result
;
367 const subscription
= !(!res
|| !res
.data
|| res
.data
.status
.toLowerCase() !== 'active');
368 vm
.set('subscriptionActive', subscription
);
373 updateStandardRepos: function(standardRepos
) {
375 let vm
= me
.getViewModel();
377 let menu
= me
.down('#addMenu');
380 for (const standardRepo
of standardRepos
) {
381 const handle
= standardRepo
.handle
;
382 const status
= standardRepo
.status
;
384 if (handle
=== "enterprise") {
385 vm
.set('enterpriseRepo', status
);
386 } else if (handle
=== "no-subscription") {
387 vm
.set('noSubscriptionRepo', status
);
390 let status_text
= '';
391 if (status
!== undefined && status
!== null) {
392 status_text
= Ext
.String
.format(
394 gettext('configured'),
395 status
? gettext('enabled') : gettext('disabled'),
400 text
: standardRepo
.name
+ status_text
,
401 disabled
: status
!== undefined && status
!== null,
403 handler: function(menuItem
) {
405 handle
: menuItem
.repoHandle
,
408 if (me
.digest
!== undefined) {
409 params
.digest
= me
.digest
;
412 Proxmox
.Utils
.API2Request({
413 url
: `/nodes/${me.nodename}/apt/repositories`,
416 failure: function(response
, opts
) {
417 Ext
.Msg
.alert(gettext('Error'), response
.htmlStatus
);
420 success: function(response
, opts
) {
431 let vm
= me
.getViewModel();
432 let repoGrid
= me
.down('proxmoxNodeAPTRepositoriesGrid');
433 let errorGrid
= me
.down('proxmoxNodeAPTRepositoriesErrors');
435 me
.store
.load(function(records
, operation
, success
) {
440 if (success
&& records
.length
> 0) {
441 let data
= records
[0].data
;
442 let files
= data
.files
;
443 errors
= data
.errors
;
444 digest
= data
.digest
;
446 files
.forEach(function(file
) {
447 for (let n
= 0; n
< file
.repositories
.length
; n
++) {
448 let repo
= file
.repositories
[n
];
449 repo
.Path
= file
.path
;
455 repoGrid
.addAdditionalInfos(gridData
, data
.infos
);
456 repoGrid
.store
.loadData(gridData
);
458 me
.updateStandardRepos(data
['standard-repos']);
463 vm
.set('errorCount', errors
.length
);
464 errorGrid
.store
.loadData(errors
);
467 me
.check_subscription();
471 activate: function() {
477 initComponent: function() {
481 throw "no node name specified";
484 let store
= Ext
.create('Ext.data.Store', {
487 url
: `/api2/json/nodes/${me.nodename}/apt/repositories`,
491 Ext
.apply(me
, { store
: store
});
493 Proxmox
.Utils
.monStoreErrors(me
, me
.store
, true);