diff --git a/src/NagScreen/patches/01-proxmoxlib-js-nagscreen.patch b/src/NagScreen/patches/01-proxmoxlib-js-nagscreen.patch
new file mode 100644
index 0000000..e69de29
diff --git a/src/PVENodeInfo/patches/01-nodes-pm-sensors.patch b/src/PVENodeInfo/patches/01-nodes-pm-sensors.patch
new file mode 100644
index 0000000..272e6f8
--- /dev/null
+++ b/src/PVENodeInfo/patches/01-nodes-pm-sensors.patch
@@ -0,0 +1,15 @@
+--- usr/share/perl5/PVE/API2/Nodes.pm 2026-05-24 02:05:58.000000000 +0200
++++ /usr/share/perl5/PVE/API2/Nodes.pm 2026-06-08 20:38:56.988900119 +0200
+@@ -536,6 +536,12 @@
+
+ $res->{pveversion} = PVE::pvecfg::package() . "/" . PVE::pvecfg::version_text();
+
++ # Collect sensor data from PveMod_SensorInfo
++ use PVE::API2::PVEMod_SensorInfo;
++ $res->{PveMod_JsonSensorInfo} = PVE::API2::PVEMod_SensorInfo::get_sensors_info();
++ $res->{PveMod_Version} = PVE::API2::PVEMod_SensorInfo::get_pve_mod_version();
++ $res->{PveMod_upsInfo} = PVE::API2::PVEMod_SensorInfo::get_ups_info();
++ $res->{PveMod_systemInfo} = PVE::API2::PVEMod_SensorInfo::get_system_info();
+ my $dinfo = df('/', 1); # output is bytes
+
+ $res->{rootfs} = {
diff --git a/src/PVENodeInfo/patches/02-nodes-pm-GPU-RRD-history.patch b/src/PVENodeInfo/patches/02-nodes-pm-GPU-RRD-history.patch
new file mode 100644
index 0000000..e69de29
diff --git a/src/PVENodeInfo/patches/03-pvemanager-js-sensors.patch b/src/PVENodeInfo/patches/03-pvemanager-js-sensors.patch
new file mode 100644
index 0000000..0252331
--- /dev/null
+++ b/src/PVENodeInfo/patches/03-pvemanager-js-sensors.patch
@@ -0,0 +1,1013 @@
+--- usr/share/pve-manager/js/pvemanagerlib.js 2026-05-24 02:05:58.000000000 +0200
++++ /usr/share/pve-manager/js/pvemanagerlib.js 2026-06-07 15:44:28.581927600 +0200
+@@ -50737,175 +50737,181 @@
+ me.reload();
+ },
+ });
+-Ext.define('PVE.node.StatusView', {
+- extend: 'Proxmox.panel.StatusView',
+- alias: 'widget.pveNodeStatus',
+-
+- height: 350,
+- bodyPadding: '15 5 15 5',
+-
+- layout: {
+- type: 'table',
+- columns: 2,
+- tableAttrs: {
+- style: {
+- width: '100%',
+- },
+- },
+- },
+-
+- defaults: {
+- xtype: 'pmxInfoWidget',
+- padding: '0 10 5 10',
+- },
+-
+- items: [
+- {
+- itemId: 'cpu',
+- iconCls: 'fa fa-fw pmx-itype-icon-processor pmx-icon',
+- title: gettext('CPU usage'),
+- valueField: 'cpu',
+- maxField: 'cpuinfo',
+- renderer: Proxmox.Utils.render_node_cpu_usage,
+- },
+- {
+- itemId: 'wait',
+- iconCls: 'fa fa-fw fa-clock-o',
+- title: gettext('IO delay'),
+- valueField: 'wait',
+- rowspan: 2,
+- },
+- {
+- itemId: 'load',
+- iconCls: 'fa fa-fw fa-tasks',
+- title: gettext('Load average'),
+- printBar: false,
+- textField: 'loadavg',
+- },
+- {
+- xtype: 'box',
+- colspan: 2,
+- padding: '0 0 20 0',
+- },
+- {
+- iconCls: 'fa fa-fw pmx-itype-icon-memory pmx-icon',
+- itemId: 'memory',
+- title: gettext('RAM usage'),
+- valueField: 'memory',
+- maxField: 'memory',
+- warningThreshold: 0.9,
+- criticalThreshold: 0.975,
+- // TODO: split out ARC usage
+- renderer: Proxmox.Utils.render_node_size_usage,
+- },
+- {
+- itemId: 'ksm',
+- printBar: false,
+- title: gettext('KSM sharing'),
+- textField: 'ksm',
+- renderer: (record) => Proxmox.Utils.render_size(record.shared),
+- padding: '0 10 10 10',
+- },
+- {
+- iconCls: 'fa fa-fw fa-hdd-o',
+- itemId: 'rootfs',
+- title: '/ ' + gettext('HD space'),
+- valueField: 'rootfs',
+- maxField: 'rootfs',
+- renderer: Proxmox.Utils.render_node_size_usage,
+- },
+- {
+- iconCls: 'fa fa-fw fa-refresh',
+- itemId: 'swap',
+- printSize: true,
+- title: gettext('SWAP usage'),
+- valueField: 'swap',
+- maxField: 'swap',
+- renderer: Proxmox.Utils.render_node_size_usage,
+- },
+- {
+- xtype: 'box',
+- colspan: 2,
+- padding: '0 0 20 0',
+- },
+- {
+- itemId: 'cpus',
+- colspan: 2,
+- printBar: false,
+- title: gettext('CPU(s)'),
+- textField: 'cpuinfo',
+- renderer: Proxmox.Utils.render_cpu_model,
+- value: '',
+- },
+- {
+- colspan: 2,
+- title: gettext('Kernel Version'),
+- printBar: false,
+- // TODO: remove with next major and only use newish current-kernel textfield
+- multiField: true,
+- //textField: 'current-kernel',
+- renderer: ({ data }) => {
+- if (!data['current-kernel']) {
+- return data.kversion;
+- }
+- let kernel = data['current-kernel'];
+- let buildDate = kernel.version.match(/\((.+)\)\s*$/)?.[1] ?? 'unknown';
+- return `${kernel.sysname} ${kernel.release} (${buildDate})`;
+- },
+- value: '',
+- },
+- {
+- colspan: 2,
+- title: gettext('Boot Mode'),
+- printBar: false,
+- textField: 'boot-info',
+- renderer: (boot) => {
+- if (boot.mode === 'legacy-bios') {
+- return 'Legacy BIOS';
+- } else if (boot.mode === 'efi') {
+- return `EFI${boot.secureboot ? ' (Secure Boot)' : ''}`;
+- }
+- return Proxmox.Utils.unknownText;
+- },
+- value: '',
+- },
+- {
+- itemId: 'version',
+- colspan: 2,
+- printBar: false,
+- title: gettext('Manager Version'),
+- textField: 'pveversion',
+- value: '',
+- },
+- ],
+-
+- updateTitle: function () {
+- var me = this;
+- var uptime = Proxmox.Utils.render_uptime(me.getRecordValue('uptime'));
+- me.setTitle(me.pveSelNode.data.node + ' (' + gettext('Uptime') + ': ' + uptime + ')');
+- },
+-
+- initComponent: function () {
+- let me = this;
+-
+- let stateProvider = Ext.state.Manager.getProvider();
+- let repoLink = stateProvider.encodeHToken({
+- view: 'server',
+- rid: `node/${me.pveSelNode.data.node}`,
+- ltab: 'tasks',
+- nodetab: 'aptrepositories',
+- });
+-
+- me.items.push({
+- xtype: 'pmxNodeInfoRepoStatus',
+- itemId: 'repositoryStatus',
+- product: 'Proxmox VE',
+- repoLink: `#${repoLink}`,
+- });
+-
+- me.callParent();
+- },
++// Load custom PVE.node.StatusView from external module
++Ext.Loader.loadScript({
++ url: '/pve2/js/PveMod_PveNodeStatusView.js',
++ onLoad: function() { },
++ onError: function() { console.error('Failed to load PveMod_PveNodeStatusView.js'); }
+ });
++// Ext.define('PVE.node.StatusView', {
++// extend: 'Proxmox.panel.StatusView',
++// alias: 'widget.pveNodeStatus',
++//
++// height: 350,
++// bodyPadding: '15 5 15 5',
++//
++// layout: {
++// type: 'table',
++// columns: 2,
++// tableAttrs: {
++// style: {
++// width: '100%',
++// },
++// },
++// },
++//
++// defaults: {
++// xtype: 'pmxInfoWidget',
++// padding: '0 10 5 10',
++// },
++//
++// items: [
++// {
++// itemId: 'cpu',
++// iconCls: 'fa fa-fw pmx-itype-icon-processor pmx-icon',
++// title: gettext('CPU usage'),
++// valueField: 'cpu',
++// maxField: 'cpuinfo',
++// renderer: Proxmox.Utils.render_node_cpu_usage,
++// },
++// {
++// itemId: 'wait',
++// iconCls: 'fa fa-fw fa-clock-o',
++// title: gettext('IO delay'),
++// valueField: 'wait',
++// rowspan: 2,
++// },
++// {
++// itemId: 'load',
++// iconCls: 'fa fa-fw fa-tasks',
++// title: gettext('Load average'),
++// printBar: false,
++// textField: 'loadavg',
++// },
++// {
++// xtype: 'box',
++// colspan: 2,
++// padding: '0 0 20 0',
++// },
++// {
++// iconCls: 'fa fa-fw pmx-itype-icon-memory pmx-icon',
++// itemId: 'memory',
++// title: gettext('RAM usage'),
++// valueField: 'memory',
++// maxField: 'memory',
++// warningThreshold: 0.9,
++// criticalThreshold: 0.975,
++// // TODO: split out ARC usage
++// renderer: Proxmox.Utils.render_node_size_usage,
++// },
++// {
++// itemId: 'ksm',
++// printBar: false,
++// title: gettext('KSM sharing'),
++// textField: 'ksm',
++// renderer: (record) => Proxmox.Utils.render_size(record.shared),
++// padding: '0 10 10 10',
++// },
++// {
++// iconCls: 'fa fa-fw fa-hdd-o',
++// itemId: 'rootfs',
++// title: '/ ' + gettext('HD space'),
++// valueField: 'rootfs',
++// maxField: 'rootfs',
++// renderer: Proxmox.Utils.render_node_size_usage,
++// },
++// {
++// iconCls: 'fa fa-fw fa-refresh',
++// itemId: 'swap',
++// printSize: true,
++// title: gettext('SWAP usage'),
++// valueField: 'swap',
++// maxField: 'swap',
++// renderer: Proxmox.Utils.render_node_size_usage,
++// },
++// {
++// xtype: 'box',
++// colspan: 2,
++// padding: '0 0 20 0',
++// },
++// {
++// itemId: 'cpus',
++// colspan: 2,
++// printBar: false,
++// title: gettext('CPU(s)'),
++// textField: 'cpuinfo',
++// renderer: Proxmox.Utils.render_cpu_model,
++// value: '',
++// },
++// {
++// colspan: 2,
++// title: gettext('Kernel Version'),
++// printBar: false,
++// // TODO: remove with next major and only use newish current-kernel textfield
++// multiField: true,
++// //textField: 'current-kernel',
++// renderer: ({ data }) => {
++// if (!data['current-kernel']) {
++// return data.kversion;
++// }
++// let kernel = data['current-kernel'];
++// let buildDate = kernel.version.match(/\((.+)\)\s*$/)?.[1] ?? 'unknown';
++// return `${kernel.sysname} ${kernel.release} (${buildDate})`;
++// },
++// value: '',
++// },
++// {
++// colspan: 2,
++// title: gettext('Boot Mode'),
++// printBar: false,
++// textField: 'boot-info',
++// renderer: (boot) => {
++// if (boot.mode === 'legacy-bios') {
++// return 'Legacy BIOS';
++// } else if (boot.mode === 'efi') {
++// return `EFI${boot.secureboot ? ' (Secure Boot)' : ''}`;
++// }
++// return Proxmox.Utils.unknownText;
++// },
++// value: '',
++// },
++// {
++// itemId: 'version',
++// colspan: 2,
++// printBar: false,
++// title: gettext('Manager Version'),
++// textField: 'pveversion',
++// value: '',
++// },
++// ],
++//
++// updateTitle: function () {
++// var me = this;
++// var uptime = Proxmox.Utils.render_uptime(me.getRecordValue('uptime'));
++// me.setTitle(me.pveSelNode.data.node + ' (' + gettext('Uptime') + ': ' + uptime + ')');
++// },
++//
++// initComponent: function () {
++// let me = this;
++//
++// let stateProvider = Ext.state.Manager.getProvider();
++// let repoLink = stateProvider.encodeHToken({
++// view: 'server',
++// rid: `node/${me.pveSelNode.data.node}`,
++// ltab: 'tasks',
++// nodetab: 'aptrepositories',
++// });
++//
++// me.items.push({
++// xtype: 'pmxNodeInfoRepoStatus',
++// itemId: 'repositoryStatus',
++// product: 'Proxmox VE',
++// repoLink: `#${repoLink}`,
++// });
++//
++// me.callParent();
++// },
++// });
+ Ext.define('PVE.node.SubscriptionKeyEdit', {
+ extend: 'Proxmox.window.Edit',
+
+@@ -51112,333 +51118,333 @@
+ me.callParent();
+ },
+ });
+-Ext.define('PVE.node.Summary', {
+- extend: 'Ext.panel.Panel',
+- alias: 'widget.pveNodeSummary',
+-
+- scrollable: true,
+- bodyPadding: 5,
+-
+- showVersions: function () {
+- var me = this;
+-
+- // Note: we use simply text/html here, because ExtJS grid has problems
+- // with cut&paste
+-
+- var nodename = me.pveSelNode.data.node;
+-
+- var view = Ext.createWidget('component', {
+- autoScroll: true,
+- id: 'pkgversions',
+- padding: 5,
+- style: {
+- 'white-space': 'pre',
+- 'font-family': 'monospace',
+- },
+- });
+-
+- var win = Ext.create('Ext.window.Window', {
+- title: gettext('Package versions'),
+- width: 600,
+- height: 600,
+- layout: 'fit',
+- modal: true,
+- items: [view],
+- buttons: [
+- {
+- xtype: 'button',
+- iconCls: 'fa fa-clipboard',
+- handler: function (button) {
+- window
+- .getSelection()
+- .selectAllChildren(document.getElementById('pkgversions'));
+- document.execCommand('copy');
+- },
+- text: gettext('Copy'),
+- },
+- {
+- text: gettext('Ok'),
+- handler: function () {
+- this.up('window').close();
+- },
+- },
+- ],
+- });
+-
+- Proxmox.Utils.API2Request({
+- waitMsgTarget: me,
+- url: `/nodes/${nodename}/apt/versions`,
+- method: 'GET',
+- failure: function (response, opts) {
+- win.close();
+- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+- },
+- success: function (response, opts) {
+- win.show();
+- let text = '';
+- Ext.Array.each(response.result.data, function (rec) {
+- let version = 'not correctly installed';
+- let pkg = rec.Package;
+- if (rec.OldVersion && rec.CurrentState === 'Installed') {
+- version = rec.OldVersion;
+- }
+- if (rec.RunningKernel) {
+- text += `${pkg}: ${version} (running kernel: ${rec.RunningKernel})\n`;
+- } else if (rec.ManagerVersion) {
+- text += `${pkg}: ${version} (running version: ${rec.ManagerVersion})\n`;
+- } else {
+- text += `${pkg}: ${version}\n`;
+- }
+- });
+-
+- view.update(Ext.htmlEncode(text));
+- },
+- });
+- },
+-
+- updateRepositoryStatus: function () {
+- let me = this;
+- let repoStatus = me.nodeStatus.down('#repositoryStatus');
+-
+- let nodename = me.pveSelNode.data.node;
+-
+- Proxmox.Utils.API2Request({
+- url: `/nodes/${nodename}/apt/repositories`,
+- method: 'GET',
+- failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+- success: (response) =>
+- repoStatus.setRepositoryInfo(response.result.data['standard-repos']),
+- });
+-
+- Proxmox.Utils.API2Request({
+- url: `/nodes/${nodename}/subscription`,
+- method: 'GET',
+- failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+- success: function (response, opts) {
+- const res = response.result;
+- const subscription = res?.data?.status.toLowerCase() === 'active';
+- repoStatus.setSubscriptionStatus(subscription);
+- },
+- });
+- },
+-
+- initComponent: function () {
+- var me = this;
+-
+- var nodename = me.pveSelNode.data.node;
+- if (!nodename) {
+- throw 'no node name specified';
+- }
+-
+- if (!me.statusStore) {
+- throw 'no status storage specified';
+- }
+-
+- var rstore = me.statusStore;
+-
+- var version_btn = new Ext.Button({
+- text: gettext('Package versions'),
+- handler: function () {
+- Proxmox.Utils.checked_command(function () {
+- me.showVersions();
+- });
+- },
+- });
+-
+- var rrdstore = Ext.create('Proxmox.data.RRDStore', {
+- rrdurl: '/api2/json/nodes/' + nodename + '/rrddata',
+- model: 'pve-rrd-node',
+- });
+-
+- let nodeStatus = Ext.create('PVE.node.StatusView', {
+- xtype: 'pveNodeStatus',
+- rstore: rstore,
+- width: 770,
+- pveSelNode: me.pveSelNode,
+- });
+-
+- Ext.apply(me, {
+- tbar: [version_btn, '->', { xtype: 'proxmoxRRDTypeSelector' }],
+- nodeStatus: nodeStatus,
+- items: [
+- {
+- xtype: 'container',
+- itemId: 'itemcontainer',
+- layout: 'column',
+- minWidth: 700,
+- defaults: {
+- minHeight: 360,
+- padding: 5,
+- columnWidth: 1,
+- },
+- items: [
+- nodeStatus,
+- {
+- xtype: 'proxmoxRRDChart',
+- title: gettext('CPU Usage'),
+- fields: ['cpu', 'iowait'],
+- fieldTitles: [gettext('CPU usage'), gettext('IO delay')],
+- unit: 'percent',
+- store: rrdstore,
+- },
+- {
+- xtype: 'proxmoxRRDChart',
+- title: gettext('Server Load'),
+- fields: ['loadavg'],
+- fieldTitles: [gettext('Load average')],
+- store: rrdstore,
+- },
+- {
+- xtype: 'proxmoxRRDChart',
+- title: gettext('Memory usage'),
+- fields: [
+- {
+- yField: 'memtotal',
+- title: gettext('Total'),
+- tooltip: {
+- trackMouse: true,
+- renderer: function (toolTip, record, item) {
+- let value = record.get('memtotal');
+-
+- if (value === null) {
+- toolTip.setHtml(gettext('No Data'));
+- } else {
+- let total = Proxmox.Utils.format_size(value);
+- let time = new Date(record.get('time'));
+-
+- let avail = record.get('memavailable');
+- let availText = '';
+- if (Ext.isNumeric(avail)) {
+- let v = Proxmox.Utils.format_size(avail);
+- availText = ` (${gettext('Available')}: ${v})`;
+- }
+-
+- toolTip.setHtml(
+- `${gettext('Total')}: ${total}${availText}
${time}`,
+- );
+- }
+- },
+- },
+- },
+- {
+- yField: 'memused',
+- title: gettext('Used'),
+- tooltip: {
+- trackMouse: true,
+- renderer: function (toolTip, record, item) {
+- let value = record.get('memused');
+-
+- if (value === null) {
+- toolTip.setHtml(gettext('No Data'));
+- } else {
+- let total = Proxmox.Utils.format_size(value);
+- let time = new Date(record.get('time'));
+-
+- let arc = record.get('arcsize');
+- let arcText = '';
+- if (Ext.isNumeric(arc) && arc > 1024 * 1024) {
+- let v = Proxmox.Utils.format_size(value - arc);
+- arcText = ` (${gettext('Without ZFS ARC')}: ${v})`;
+- }
+-
+- toolTip.setHtml(
+- `${gettext('Used')}: ${total}${arcText}
${time}`,
+- );
+- }
+- },
+- },
+- },
+- 'arcsize',
+- {
+- type: 'line',
+- fill: false,
+- yField: 'memavailable',
+- title: gettext('Available'),
+- style: {
+- lineWidth: 2.5,
+- opacity: 1,
+- },
+- },
+- ],
+- fieldTitles: [
+- gettext('Total'),
+- gettext('Used'),
+- gettext('ZFS ARC'),
+- gettext('Available'),
+- ],
+- colors: ['#94ae0a', '#115fa6', '#24AD9A', '#bbde0d'],
+- unit: 'bytes',
+- powerOfTwo: true,
+- store: rrdstore,
+- },
+- {
+- xtype: 'proxmoxRRDChart',
+- title: gettext('Network Traffic'),
+- fields: ['netin', 'netout'],
+- fieldTitles: [gettext('Incoming'), gettext('Outgoing')],
+- store: rrdstore,
+- },
+- {
+- xtype: 'proxmoxRRDChart',
+- title: gettext('CPU Pressure Stall'),
+- fieldTitles: ['Some'],
+- fields: ['pressurecpusome'],
+- colors: ['#FFD13E', '#A61120'],
+- store: rrdstore,
+- unit: 'percent',
+- },
+- {
+- xtype: 'proxmoxRRDChart',
+- title: gettext('IO Pressure Stall'),
+- fieldTitles: ['Some', 'Full'],
+- fields: ['pressureiosome', 'pressureiofull'],
+- colors: ['#FFD13E', '#A61120'],
+- store: rrdstore,
+- unit: 'percent',
+- },
+- {
+- xtype: 'proxmoxRRDChart',
+- title: gettext('Memory Pressure Stall'),
+- fieldTitles: ['Some', 'Full'],
+- fields: ['pressurememorysome', 'pressurememoryfull'],
+- colors: ['#FFD13E', '#A61120'],
+- store: rrdstore,
+- unit: 'percent',
+- },
+- ],
+- listeners: {
+- resize: function (panel) {
+- Proxmox.Utils.updateColumns(panel);
+- },
+- },
+- },
+- ],
+- listeners: {
+- activate: function () {
+- rstore.setInterval(1000);
+- rstore.startUpdate(); // just to be sure
+- rrdstore.startUpdate();
+- },
+- destroy: function () {
+- rstore.setInterval(5000); // don't stop it, it's not ours!
+- rrdstore.stopUpdate();
+- },
+- },
+- });
+-
+- me.updateRepositoryStatus();
+-
+- me.callParent();
+-
+- let sp = Ext.state.Manager.getProvider();
+- me.mon(sp, 'statechange', function (provider, key, value) {
+- if (key !== 'summarycolumns') {
+- return;
+- }
+- Proxmox.Utils.updateColumns(me.getComponent('itemcontainer'));
+- });
+- },
+-});
++// Ext.define('PVE.node.Summary', {
++// extend: 'Ext.panel.Panel',
++// alias: 'widget.pveNodeSummary',
++//
++// scrollable: true,
++// bodyPadding: 5,
++//
++// showVersions: function () {
++// var me = this;
++//
++// // Note: we use simply text/html here, because ExtJS grid has problems
++// // with cut&paste
++//
++// var nodename = me.pveSelNode.data.node;
++//
++// var view = Ext.createWidget('component', {
++// autoScroll: true,
++// id: 'pkgversions',
++// padding: 5,
++// style: {
++// 'white-space': 'pre',
++// 'font-family': 'monospace',
++// },
++// });
++//
++// var win = Ext.create('Ext.window.Window', {
++// title: gettext('Package versions'),
++// width: 600,
++// height: 600,
++// layout: 'fit',
++// modal: true,
++// items: [view],
++// buttons: [
++// {
++// xtype: 'button',
++// iconCls: 'fa fa-clipboard',
++// handler: function (button) {
++// window
++// .getSelection()
++// .selectAllChildren(document.getElementById('pkgversions'));
++// document.execCommand('copy');
++// },
++// text: gettext('Copy'),
++// },
++// {
++// text: gettext('Ok'),
++// handler: function () {
++// this.up('window').close();
++// },
++// },
++// ],
++// });
++//
++// Proxmox.Utils.API2Request({
++// waitMsgTarget: me,
++// url: `/nodes/${nodename}/apt/versions`,
++// method: 'GET',
++// failure: function (response, opts) {
++// win.close();
++// Ext.Msg.alert(gettext('Error'), response.htmlStatus);
++// },
++// success: function (response, opts) {
++// win.show();
++// let text = '';
++// Ext.Array.each(response.result.data, function (rec) {
++// let version = 'not correctly installed';
++// let pkg = rec.Package;
++// if (rec.OldVersion && rec.CurrentState === 'Installed') {
++// version = rec.OldVersion;
++// }
++// if (rec.RunningKernel) {
++// text += `${pkg}: ${version} (running kernel: ${rec.RunningKernel})\n`;
++// } else if (rec.ManagerVersion) {
++// text += `${pkg}: ${version} (running version: ${rec.ManagerVersion})\n`;
++// } else {
++// text += `${pkg}: ${version}\n`;
++// }
++// });
++//
++// view.update(Ext.htmlEncode(text));
++// },
++// });
++// },
++//
++// updateRepositoryStatus: function () {
++// let me = this;
++// let repoStatus = me.nodeStatus.down('#repositoryStatus');
++//
++// let nodename = me.pveSelNode.data.node;
++//
++// Proxmox.Utils.API2Request({
++// url: `/nodes/${nodename}/apt/repositories`,
++// method: 'GET',
++// failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
++// success: (response) =>
++// repoStatus.setRepositoryInfo(response.result.data['standard-repos']),
++// });
++//
++// Proxmox.Utils.API2Request({
++// url: `/nodes/${nodename}/subscription`,
++// method: 'GET',
++// failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
++// success: function (response, opts) {
++// const res = response.result;
++// const subscription = res?.data?.status.toLowerCase() === 'active';
++// repoStatus.setSubscriptionStatus(subscription);
++// },
++// });
++// },
++//
++// initComponent: function () {
++// var me = this;
++//
++// var nodename = me.pveSelNode.data.node;
++// if (!nodename) {
++// throw 'no node name specified';
++// }
++//
++// if (!me.statusStore) {
++// throw 'no status storage specified';
++// }
++//
++// var rstore = me.statusStore;
++//
++// var version_btn = new Ext.Button({
++// text: gettext('Package versions'),
++// handler: function () {
++// Proxmox.Utils.checked_command(function () {
++// me.showVersions();
++// });
++// },
++// });
++//
++// var rrdstore = Ext.create('Proxmox.data.RRDStore', {
++// rrdurl: '/api2/json/nodes/' + nodename + '/rrddata',
++// model: 'pve-rrd-node',
++// });
++//
++// let nodeStatus = Ext.create('PVE.node.StatusView', {
++// xtype: 'pveNodeStatus',
++// rstore: rstore,
++// width: 770,
++// pveSelNode: me.pveSelNode,
++// });
++//
++// Ext.apply(me, {
++// tbar: [version_btn, '->', { xtype: 'proxmoxRRDTypeSelector' }],
++// nodeStatus: nodeStatus,
++// items: [
++// {
++// xtype: 'container',
++// itemId: 'itemcontainer',
++// layout: 'column',
++// minWidth: 700,
++// defaults: {
++// minHeight: 360,
++// padding: 5,
++// columnWidth: 1,
++// },
++// items: [
++// nodeStatus,
++// {
++// xtype: 'proxmoxRRDChart',
++// title: gettext('CPU Usage'),
++// fields: ['cpu', 'iowait'],
++// fieldTitles: [gettext('CPU usage'), gettext('IO delay')],
++// unit: 'percent',
++// store: rrdstore,
++// },
++// {
++// xtype: 'proxmoxRRDChart',
++// title: gettext('Server Load'),
++// fields: ['loadavg'],
++// fieldTitles: [gettext('Load average')],
++// store: rrdstore,
++// },
++// {
++// xtype: 'proxmoxRRDChart',
++// title: gettext('Memory usage'),
++// fields: [
++// {
++// yField: 'memtotal',
++// title: gettext('Total'),
++// tooltip: {
++// trackMouse: true,
++// renderer: function (toolTip, record, item) {
++// let value = record.get('memtotal');
++//
++// if (value === null) {
++// toolTip.setHtml(gettext('No Data'));
++// } else {
++// let total = Proxmox.Utils.format_size(value);
++// let time = new Date(record.get('time'));
++//
++// let avail = record.get('memavailable');
++// let availText = '';
++// if (Ext.isNumeric(avail)) {
++// let v = Proxmox.Utils.format_size(avail);
++// availText = ` (${gettext('Available')}: ${v})`;
++// }
++//
++// toolTip.setHtml(
++// `${gettext('Total')}: ${total}${availText}
${time}`,
++// );
++// }
++// },
++// },
++// },
++// {
++// yField: 'memused',
++// title: gettext('Used'),
++// tooltip: {
++// trackMouse: true,
++// renderer: function (toolTip, record, item) {
++// let value = record.get('memused');
++//
++// if (value === null) {
++// toolTip.setHtml(gettext('No Data'));
++// } else {
++// let total = Proxmox.Utils.format_size(value);
++// let time = new Date(record.get('time'));
++//
++// let arc = record.get('arcsize');
++// let arcText = '';
++// if (Ext.isNumeric(arc) && arc > 1024 * 1024) {
++// let v = Proxmox.Utils.format_size(value - arc);
++// arcText = ` (${gettext('Without ZFS ARC')}: ${v})`;
++// }
++//
++// toolTip.setHtml(
++// `${gettext('Used')}: ${total}${arcText}
${time}`,
++// );
++// }
++// },
++// },
++// },
++// 'arcsize',
++// {
++// type: 'line',
++// fill: false,
++// yField: 'memavailable',
++// title: gettext('Available'),
++// style: {
++// lineWidth: 2.5,
++// opacity: 1,
++// },
++// },
++// ],
++// fieldTitles: [
++// gettext('Total'),
++// gettext('Used'),
++// gettext('ZFS ARC'),
++// gettext('Available'),
++// ],
++// colors: ['#94ae0a', '#115fa6', '#24AD9A', '#bbde0d'],
++// unit: 'bytes',
++// powerOfTwo: true,
++// store: rrdstore,
++// },
++// {
++// xtype: 'proxmoxRRDChart',
++// title: gettext('Network Traffic'),
++// fields: ['netin', 'netout'],
++// fieldTitles: [gettext('Incoming'), gettext('Outgoing')],
++// store: rrdstore,
++// },
++// {
++// xtype: 'proxmoxRRDChart',
++// title: gettext('CPU Pressure Stall'),
++// fieldTitles: ['Some'],
++// fields: ['pressurecpusome'],
++// colors: ['#FFD13E', '#A61120'],
++// store: rrdstore,
++// unit: 'percent',
++// },
++// {
++// xtype: 'proxmoxRRDChart',
++// title: gettext('IO Pressure Stall'),
++// fieldTitles: ['Some', 'Full'],
++// fields: ['pressureiosome', 'pressureiofull'],
++// colors: ['#FFD13E', '#A61120'],
++// store: rrdstore,
++// unit: 'percent',
++// },
++// {
++// xtype: 'proxmoxRRDChart',
++// title: gettext('Memory Pressure Stall'),
++// fieldTitles: ['Some', 'Full'],
++// fields: ['pressurememorysome', 'pressurememoryfull'],
++// colors: ['#FFD13E', '#A61120'],
++// store: rrdstore,
++// unit: 'percent',
++// },
++// ],
++// listeners: {
++// resize: function (panel) {
++// Proxmox.Utils.updateColumns(panel);
++// },
++// },
++// },
++// ],
++// listeners: {
++// activate: function () {
++// rstore.setInterval(1000);
++// rstore.startUpdate(); // just to be sure
++// rrdstore.startUpdate();
++// },
++// destroy: function () {
++// rstore.setInterval(5000); // don't stop it, it's not ours!
++// rrdstore.stopUpdate();
++// },
++// },
++// });
++//
++// me.updateRepositoryStatus();
++//
++// me.callParent();
++//
++// let sp = Ext.state.Manager.getProvider();
++// me.mon(sp, 'statechange', function (provider, key, value) {
++// if (key !== 'summarycolumns') {
++// return;
++// }
++// Proxmox.Utils.updateColumns(me.getComponent('itemcontainer'));
++// });
++// },
++// });
+ Ext.define('PVE.node.CreateZFS', {
+ extend: 'Proxmox.window.Edit',
+ xtype: 'pveCreateZFS',