From 59ccfd0c966ecd6c0113dbe62444357c87da1f36 Mon Sep 17 00:00:00 2001 From: Denys Butenko Date: Mon, 20 May 2024 14:18:53 +0700 Subject: [PATCH] NAS-128451 / 24.10 / Port WidgetSysInfoComponent to new dashboard (#10047) * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard * NAS-128451: Port WidgetSysInfoComponent to new dashboard --- src/app/constants/server-series.constant.ts | 67 ++++++++ src/app/constants/time.constant.ts | 2 + src/app/core/core-components.module.ts | 3 - .../core/pipes/format-datetime.pipe.spec.ts | 9 + src/app/core/pipes/format-datetime.pipe.ts | 3 + src/app/interfaces/system-info.interface.ts | 1 + .../ix-cell-relative-date.component.spec.ts | 3 +- src/app/modules/jobs/store/job.selectors.ts | 12 +- .../widget-sys-info.component.spec.ts | 2 + .../widget-sys-info.component.ts | 13 +- .../dashboard-old/dashboard-old.module.ts | 6 +- src/app/pages/dashboard/dashboard.module.ts | 7 + .../dashboard/services/dashboard.store.ts | 4 +- .../services/demo-widgets.constant.ts | 12 ++ .../services/widget-resources.service.ts | 27 ++- .../dashboard/types/widget-category.enum.ts | 2 + .../pages/dashboard/types/widget.interface.ts | 2 + .../dashboard/widgets/all-widgets.constant.ts | 6 + .../product-image.component.html | 36 ++++ .../product-image.component.scss | 37 ++++ .../product-image.component.spec.ts | 108 ++++++++++++ .../product-image/product-image.component.ts | 50 ++++++ .../system/common}/uptime.pipe.spec.ts | 0 .../widgets/system/common}/uptime.pipe.ts | 1 + .../system/common/widget-sys-info.scss | 119 +++++++++++++ .../common/widget-sys-info.utils.spec.ts | 59 +++++++ .../system/common/widget-sys-info.utils.ts | 52 ++++++ .../widget-sys-info-active.component.html | 139 +++++++++++++++ .../widget-sys-info-active.component.spec.ts | 147 ++++++++++++++++ .../widget-sys-info-active.component.ts | 53 ++++++ .../widget-sys-info-active.definition.ts | 13 ++ .../widget-sys-info-passive.component.html | 136 +++++++++++++++ .../widget-sys-info-passive.component.spec.ts | 158 ++++++++++++++++++ .../widget-sys-info-passive.component.ts | 77 +++++++++ .../widget-sys-info-passive.definition.ts | 13 ++ .../components/report/report.component.ts | 11 +- .../support-card/support-card.component.ts | 17 +- src/app/services/product-image.service.ts | 100 ----------- src/app/store/ha-info/ha-info.selectors.ts | 5 + .../store/system-info/system-info.actions.ts | 6 + .../store/system-info/system-info.effects.ts | 14 ++ .../store/system-info/system-info.reducer.ts | 5 + .../system-info/system-info.selectors.ts | 16 ++ src/assets/i18n/af.json | 6 + src/assets/i18n/ar.json | 6 + src/assets/i18n/ast.json | 6 + src/assets/i18n/az.json | 6 + src/assets/i18n/be.json | 6 + src/assets/i18n/bg.json | 6 + src/assets/i18n/bn.json | 6 + src/assets/i18n/br.json | 6 + src/assets/i18n/bs.json | 6 + src/assets/i18n/ca.json | 6 + src/assets/i18n/cs.json | 6 + src/assets/i18n/cy.json | 6 + src/assets/i18n/da.json | 6 + src/assets/i18n/de.json | 6 + src/assets/i18n/dsb.json | 6 + src/assets/i18n/el.json | 6 + src/assets/i18n/en-au.json | 6 + src/assets/i18n/en-gb.json | 6 + src/assets/i18n/en.json | 6 + src/assets/i18n/eo.json | 6 + src/assets/i18n/es-ar.json | 6 + src/assets/i18n/es-co.json | 6 + src/assets/i18n/es-mx.json | 6 + src/assets/i18n/es-ni.json | 6 + src/assets/i18n/es-ve.json | 6 + src/assets/i18n/es.json | 6 + src/assets/i18n/et.json | 6 + src/assets/i18n/eu.json | 6 + src/assets/i18n/fa.json | 6 + src/assets/i18n/fi.json | 6 + src/assets/i18n/fr.json | 6 + src/assets/i18n/fy.json | 6 + src/assets/i18n/ga.json | 6 + src/assets/i18n/gd.json | 6 + src/assets/i18n/gl.json | 6 + src/assets/i18n/he.json | 6 + src/assets/i18n/hi.json | 6 + src/assets/i18n/hr.json | 6 + src/assets/i18n/hsb.json | 6 + src/assets/i18n/hu.json | 6 + src/assets/i18n/ia.json | 6 + src/assets/i18n/id.json | 6 + src/assets/i18n/io.json | 6 + src/assets/i18n/is.json | 6 + src/assets/i18n/it.json | 6 + src/assets/i18n/ja.json | 6 + src/assets/i18n/ka.json | 6 + src/assets/i18n/kk.json | 6 + src/assets/i18n/km.json | 6 + src/assets/i18n/kn.json | 6 + src/assets/i18n/ko.json | 6 + src/assets/i18n/lb.json | 6 + src/assets/i18n/lt.json | 6 + src/assets/i18n/lv.json | 6 + src/assets/i18n/mk.json | 6 + src/assets/i18n/ml.json | 6 + src/assets/i18n/mn.json | 6 + src/assets/i18n/mr.json | 6 + src/assets/i18n/my.json | 6 + src/assets/i18n/nb.json | 6 + src/assets/i18n/ne.json | 6 + src/assets/i18n/nl.json | 6 + src/assets/i18n/nn.json | 6 + src/assets/i18n/os.json | 6 + src/assets/i18n/pa.json | 6 + src/assets/i18n/pl.json | 6 + src/assets/i18n/pt-br.json | 6 + src/assets/i18n/pt.json | 6 + src/assets/i18n/ro.json | 6 + src/assets/i18n/ru.json | 6 + src/assets/i18n/sk.json | 6 + src/assets/i18n/sl.json | 6 + src/assets/i18n/sq.json | 6 + src/assets/i18n/sr-latn.json | 6 + src/assets/i18n/sr.json | 6 + src/assets/i18n/strings.json | 6 + src/assets/i18n/sv.json | 6 + src/assets/i18n/sw.json | 6 + src/assets/i18n/ta.json | 6 + src/assets/i18n/te.json | 6 + src/assets/i18n/th.json | 6 + src/assets/i18n/tr.json | 6 + src/assets/i18n/tt.json | 6 + src/assets/i18n/udm.json | 6 + src/assets/i18n/uk.json | 6 + src/assets/i18n/vi.json | 6 + src/assets/i18n/zh-hans.json | 6 + src/assets/i18n/zh-hant.json | 6 + tsconfig.strictNullChecks.json | 12 +- 132 files changed, 1952 insertions(+), 141 deletions(-) create mode 100644 src/app/constants/server-series.constant.ts create mode 100644 src/app/constants/time.constant.ts create mode 100644 src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.html create mode 100644 src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.scss create mode 100644 src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.spec.ts create mode 100644 src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.ts rename src/app/{core/pipes => pages/dashboard/widgets/system/common}/uptime.pipe.spec.ts (100%) rename src/app/{core/pipes => pages/dashboard/widgets/system/common}/uptime.pipe.ts (98%) create mode 100644 src/app/pages/dashboard/widgets/system/common/widget-sys-info.scss create mode 100644 src/app/pages/dashboard/widgets/system/common/widget-sys-info.utils.spec.ts create mode 100644 src/app/pages/dashboard/widgets/system/common/widget-sys-info.utils.ts create mode 100644 src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.html create mode 100644 src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.spec.ts create mode 100644 src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.ts create mode 100644 src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.definition.ts create mode 100644 src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.html create mode 100644 src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.spec.ts create mode 100644 src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.ts create mode 100644 src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.definition.ts delete mode 100644 src/app/services/product-image.service.ts diff --git a/src/app/constants/server-series.constant.ts b/src/app/constants/server-series.constant.ts new file mode 100644 index 00000000000..1fc317d6d8f --- /dev/null +++ b/src/app/constants/server-series.constant.ts @@ -0,0 +1,67 @@ +interface MiniSeries { + pathImg: string; + images: string[]; + isRackmount: boolean; +} + +export const serverSeries = [ + 'H10', + 'M30', + 'M40', + 'M50', + 'M60', + 'X10', + 'X20', + 'Z20', + 'Z30', + 'Z35', + 'Z50', + 'R10', + 'R20', + 'R30', + 'R40', + 'R50', + 'F60', + 'F100', + 'F130', +]; + +export const miniSeries: Record = { + mini: { + pathImg: 'freenas_mini_cropped.png', + images: [ + 'FREENAS-MINI-2.0', + 'FREENAS-MINI-3.0-E', + 'FREENAS-MINI-3.0-E+', + 'TRUENAS-MINI-3.0-E', + 'TRUENAS-MINI-3.0-E+', + ], + isRackmount: false, + }, + miniX: { + pathImg: 'freenas_mini_x_cropped.png', + images: [ + 'FREENAS-MINI-3.0-X', + 'FREENAS-MINI-3.0-X+', + 'TRUENAS-MINI-3.0-X', + 'TRUENAS-MINI-3.0-X+', + ], + isRackmount: false, + }, + miniXL: { + pathImg: 'freenas_mini_xl_cropped.png', + images: [ + 'FREENAS-MINI-XL', + 'FREENAS-MINI-3.0-XL+', + 'TRUENAS-MINI-3.0-XL+', + ], + isRackmount: false, + }, + miniR: { + pathImg: 'servers/MINI-R.png', + images: [ + 'TRUENAS-MINI-R', + ], + isRackmount: true, + }, +}; diff --git a/src/app/constants/time.constant.ts b/src/app/constants/time.constant.ts new file mode 100644 index 00000000000..5f3543576b2 --- /dev/null +++ b/src/app/constants/time.constant.ts @@ -0,0 +1,2 @@ +export const oneHourMillis = 60 * 60 * 1000; +export const oneDayMillis = 24 * oneHourMillis; diff --git a/src/app/core/core-components.module.ts b/src/app/core/core-components.module.ts index 269559ece89..4511eb7e296 100644 --- a/src/app/core/core-components.module.ts +++ b/src/app/core/core-components.module.ts @@ -17,7 +17,6 @@ import { TextLimiterDirective } from 'app/core/components/directives/text-limite import { FormatDateTimePipe } from 'app/core/pipes/format-datetime.pipe'; import { MapValuePipe } from 'app/core/pipes/map-value.pipe'; import { ScheduleToCrontabPipe } from 'app/core/pipes/schedule-to-crontab.pipe'; -import { UptimePipe } from 'app/core/pipes/uptime.pipe'; import { YesNoPipe } from 'app/core/pipes/yes-no.pipe'; import { CommonDirectivesModule } from 'app/directives/common/common-directives.module'; import { IxIconModule } from 'app/modules/ix-icon/ix-icon.module'; @@ -54,7 +53,6 @@ import { CleanLinkPipe } from './pipes/clean-link.pipe'; CleanLinkPipe, ScheduleToCrontabPipe, DragHandleComponent, - UptimePipe, ], exports: [ TextLimiterTooltipComponent, @@ -72,7 +70,6 @@ import { CleanLinkPipe } from './pipes/clean-link.pipe'; YesNoPipe, CleanLinkPipe, ScheduleToCrontabPipe, - UptimePipe, ], providers: [ StorageService, diff --git a/src/app/core/pipes/format-datetime.pipe.spec.ts b/src/app/core/pipes/format-datetime.pipe.spec.ts index 6f4ed0e521b..f70505bd9c2 100644 --- a/src/app/core/pipes/format-datetime.pipe.spec.ts +++ b/src/app/core/pipes/format-datetime.pipe.spec.ts @@ -52,4 +52,13 @@ describe('FormatDateTimePipe', () => { }); expect(spectator.element).toHaveExactText('2023-06-20 06:55:04'); }); + + it('omits date format if empty string is passed', () => { + spectator = createPipe('{{ inputValue | formatDateTime:" ":"HH:mm" }}', { + hostProps: { + inputValue, + }, + }); + expect(spectator.element).toHaveExactText('15:03'); + }); }); diff --git a/src/app/core/pipes/format-datetime.pipe.ts b/src/app/core/pipes/format-datetime.pipe.ts index 5968852428f..5aaac96ce31 100644 --- a/src/app/core/pipes/format-datetime.pipe.ts +++ b/src/app/core/pipes/format-datetime.pipe.ts @@ -83,6 +83,9 @@ export class FormatDateTimePipe implements PipeTransform { if (this.timeFormat) { this.timeFormat = this.timeFormat.replace(' A', ' aa'); } + if (this.dateFormat === ' ') { + return format(localDate, this.timeFormat); + } return format(localDate, `${this.dateFormat} ${this.timeFormat}`); } catch { return 'Invalid date'; diff --git a/src/app/interfaces/system-info.interface.ts b/src/app/interfaces/system-info.interface.ts index 8576360ba34..4945e6f9ff6 100644 --- a/src/app/interfaces/system-info.interface.ts +++ b/src/app/interfaces/system-info.interface.ts @@ -2,6 +2,7 @@ import { Codename } from 'app/enums/codename.enum'; import { LicenseFeature } from 'app/enums/license-feature.enum'; import { ApiDate, ApiTimestamp } from 'app/interfaces/api-date.interface'; +// TODO: Split mixed interface for system.info and webui.main.dashboard.sys_info export interface SystemInfo { platform: string; boottime: ApiTimestamp; diff --git a/src/app/modules/ix-table/components/ix-table-body/cells/ix-cell-relative-date/ix-cell-relative-date.component.spec.ts b/src/app/modules/ix-table/components/ix-table-body/cells/ix-cell-relative-date/ix-cell-relative-date.component.spec.ts index 3f6302af044..0704fc23746 100644 --- a/src/app/modules/ix-table/components/ix-table-body/cells/ix-cell-relative-date/ix-cell-relative-date.component.spec.ts +++ b/src/app/modules/ix-table/components/ix-table-body/cells/ix-cell-relative-date/ix-cell-relative-date.component.spec.ts @@ -2,6 +2,7 @@ import { Spectator } from '@ngneat/spectator'; import { createComponentFactory, mockProvider } from '@ngneat/spectator/jest'; import { Store } from '@ngrx/store'; import { of } from 'rxjs'; +import { oneDayMillis } from 'app/constants/time.constant'; import { FakeFormatDateTimePipe } from 'app/core/testing/classes/fake-format-datetime.pipe'; import { IxCellRelativeDateComponent } from 'app/modules/ix-table/components/ix-table-body/cells/ix-cell-relative-date/ix-cell-relative-date.component'; import { IxTableModule } from 'app/modules/ix-table/ix-table.module'; @@ -26,7 +27,7 @@ describe('IxCellRelativeDateComponent', () => { beforeEach(() => { spectator = createComponent(); spectator.component.propertyName = 'dateField'; - spectator.component.setRow({ dateField: new Date(new Date().getTime() - (24 * 60 * 60 * 10000)) }); + spectator.component.setRow({ dateField: new Date(new Date().getTime() - (oneDayMillis * 10)) }); spectator.component.rowTestId = () => ''; spectator.detectChanges(); }); diff --git a/src/app/modules/jobs/store/job.selectors.ts b/src/app/modules/jobs/store/job.selectors.ts index 22606a8f9ee..54388d5dee2 100644 --- a/src/app/modules/jobs/store/job.selectors.ts +++ b/src/app/modules/jobs/store/job.selectors.ts @@ -77,5 +77,15 @@ export const selectJobsPanelSlice = createSelector( export const selectUpdateJob = createSelector( selectRunningJobs, - (jobs) => jobs.filter((job) => job.method === 'update.update' || job.method === 'failover.upgrade'), + (jobs: Job[]) => jobs.filter((job) => job.method === 'update.update' || job.method === 'failover.upgrade'), +); + +export const selectUpdateJobForActiveNode = createSelector( + selectRunningJobs, + (jobs: Job[]) => jobs.find((job) => job.method === 'update.update'), +); + +export const selectUpdateJobForPassiveNode = createSelector( + selectRunningJobs, + (jobs: Job[]) => jobs.find((job) => job.method === 'failover.upgrade'), ); diff --git a/src/app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component.spec.ts b/src/app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component.spec.ts index e24f5249a0e..d4447389fe4 100644 --- a/src/app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component.spec.ts +++ b/src/app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component.spec.ts @@ -19,6 +19,7 @@ import { SystemUpdateStatus } from 'app/enums/system-update.enum'; import { SystemInfo, SystemLicense } from 'app/interfaces/system-info.interface'; import { SystemUpdate } from 'app/interfaces/system-update.interface'; import { IxIconComponent } from 'app/modules/ix-icon/ix-icon.component'; +import { UptimePipe } from 'app/pages/dashboard/widgets/system/common/uptime.pipe'; import { SimpleFailoverBtnComponent } from 'app/pages/dashboard-old/components/widget-sys-info/simple-failover-btn.component'; import { WidgetSysInfoComponent } from 'app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component'; import { SystemGeneralService } from 'app/services/system-general.service'; @@ -75,6 +76,7 @@ describe('WidgetSysInfoComponent', () => { imports: [ MatGridListModule, ImgFallbackModule, + UptimePipe, ], declarations: [ MockComponent(DragHandleComponent), diff --git a/src/app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component.ts b/src/app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component.ts index 1eba6fde3fc..03614221b4a 100644 --- a/src/app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component.ts +++ b/src/app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component.ts @@ -9,6 +9,7 @@ import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { filter, map, take } from 'rxjs/operators'; +import { oneDayMillis } from 'app/constants/time.constant'; import { JobState } from 'app/enums/job-state.enum'; import { ProductEnclosure } from 'app/enums/product-enclosure.enum'; import { SystemUpdateStatus } from 'app/enums/system-update.enum'; @@ -20,8 +21,8 @@ import { DialogService, } from 'app/modules/dialog/dialog.service'; import { AppLoaderService } from 'app/modules/loader/app-loader.service'; +import { getMiniImagePath, getServerProduct } from 'app/pages/dashboard/widgets/system/common/widget-sys-info.utils'; import { WidgetComponent } from 'app/pages/dashboard-old/components/widget/widget.component'; -import { ProductImageService } from 'app/services/product-image.service'; import { SystemGeneralService } from 'app/services/system-general.service'; import { ThemeService } from 'app/services/theme/theme.service'; import { WebSocketService } from 'app/services/ws.service'; @@ -97,7 +98,6 @@ export class WidgetSysInfoComponent extends WidgetComponent implements OnInit, O public loader: AppLoaderService, public dialogService: DialogService, private store$: Store, - private productImgServ: ProductImageService, private ws: WebSocketService, private cdr: ChangeDetectorRef, private breakpointObserver: BreakpointObserver, @@ -224,9 +224,9 @@ export class WidgetSysInfoComponent extends WidgetComponent implements OnInit, O } else if (this.systemInfo.platform.includes('CERTIFIED')) { this.certified = true; } else { - const product = this.productImgServ.getServerProduct(this.systemInfo.platform); + const product = getServerProduct(this.systemInfo.platform); this.productImage = product ? `/servers/${product}.png` : 'ix-original.svg'; - this.productModel = product || ''; + this.productModel = product; this.productEnclosure = ProductEnclosure.Rackmount; } @@ -241,7 +241,7 @@ export class WidgetSysInfoComponent extends WidgetComponent implements OnInit, O this.certified = true; return; } - this.productImage = this.productImgServ.getMiniImagePath(sysProduct) || ''; + this.productImage = getMiniImagePath(sysProduct); } goToEnclosure(): void { @@ -255,10 +255,9 @@ export class WidgetSysInfoComponent extends WidgetComponent implements OnInit, O * limit the check to once a day */ private checkForUpdate(): void { - const oneDay = 24 * 60 * 60 * 1000; if ( sessionStorage.updateLastChecked - && Number(sessionStorage.updateLastChecked) + oneDay > Date.now() + && Number(sessionStorage.updateLastChecked) + oneDayMillis > Date.now() ) { this.updateAvailable = sessionStorage.updateAvailable === 'true'; return; diff --git a/src/app/pages/dashboard-old/dashboard-old.module.ts b/src/app/pages/dashboard-old/dashboard-old.module.ts index 4455700923b..0c95b9823bd 100644 --- a/src/app/pages/dashboard-old/dashboard-old.module.ts +++ b/src/app/pages/dashboard-old/dashboard-old.module.ts @@ -28,6 +28,7 @@ import { IxIconModule } from 'app/modules/ix-icon/ix-icon.module'; import { IxTableModule } from 'app/modules/ix-table/ix-table.module'; import { LayoutModule } from 'app/modules/layout/layout.module'; import { TestIdModule } from 'app/modules/test-id/test-id.module'; +import { UptimePipe } from 'app/pages/dashboard/widgets/system/common/uptime.pipe'; import { DashboardComponent } from 'app/pages/dashboard-old/components/dashboard/dashboard.component'; import { DashboardFormComponent } from 'app/pages/dashboard-old/components/dashboard-form/dashboard-form.component'; import { WidgetBackupComponent } from 'app/pages/dashboard-old/components/widget-backup/widget-backup.component'; @@ -40,9 +41,7 @@ import { WidgetNicComponent } from 'app/pages/dashboard-old/components/widget-ni import { WidgetPoolComponent } from 'app/pages/dashboard-old/components/widget-pool/widget-pool.component'; import { WidgetPoolWrapperComponent } from 'app/pages/dashboard-old/components/widget-pool-wrapper/widget-pool-wrapper.component'; import { WidgetStorageComponent } from 'app/pages/dashboard-old/components/widget-storage/widget-storage.component'; -import { - SimpleFailoverBtnComponent, -} from 'app/pages/dashboard-old/components/widget-sys-info/simple-failover-btn.component'; +import { SimpleFailoverBtnComponent } from 'app/pages/dashboard-old/components/widget-sys-info/simple-failover-btn.component'; import { WidgetSysInfoComponent } from 'app/pages/dashboard-old/components/widget-sys-info/widget-sys-info.component'; import { routing } from 'app/pages/dashboard-old/dashboard-old.routing'; import { DashboardStorageStore } from 'app/pages/dashboard-old/store/dashboard-storage-store.service'; @@ -80,6 +79,7 @@ import { ResourcesUsageStore } from 'app/pages/dashboard-old/store/resources-usa IxTableModule, EmptyComponent, InterfaceStatusIconComponent, + UptimePipe, ], declarations: [ DashboardComponent, diff --git a/src/app/pages/dashboard/dashboard.module.ts b/src/app/pages/dashboard/dashboard.module.ts index 8f4b3b820bc..b34879dc40b 100644 --- a/src/app/pages/dashboard/dashboard.module.ts +++ b/src/app/pages/dashboard/dashboard.module.ts @@ -10,6 +10,7 @@ import { MatListModule } from '@angular/material/list'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; import { BaseChartDirective } from 'ng2-charts'; +import { ImgFallbackModule } from 'ngx-img-fallback'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { CoreComponents } from 'app/core/core-components.module'; import { CommonDirectivesModule } from 'app/directives/common/common-directives.module'; @@ -43,10 +44,13 @@ import { BackupTaskActionsComponent } from 'app/pages/dashboard/widgets/backup/w import { BackupTaskEmptyComponent } from 'app/pages/dashboard/widgets/backup/widget-backup/backup-task-empty/backup-task-empty.component'; import { BackupTaskTileComponent } from 'app/pages/dashboard/widgets/backup/widget-backup/backup-task-tile/backup-task-tile.component'; import { WidgetDatapointComponent } from 'app/pages/dashboard/widgets/common/widget-datapoint/widget-datapoint.component'; +import { ProductImageComponent } from 'app/pages/dashboard/widgets/system/common/product-image/product-image.component'; +import { UptimePipe } from 'app/pages/dashboard/widgets/system/common/uptime.pipe'; @NgModule({ declarations: [ DashboardComponent, + ProductImageComponent, WidgetGroupComponent, WidgetErrorComponent, WidgetGroupFormComponent, @@ -64,6 +68,7 @@ import { WidgetDatapointComponent } from 'app/pages/dashboard/widgets/common/wid WidgetResourcesService, ], imports: [ + CoreComponents, IxFormsModule, ReactiveFormsModule, TranslateModule, @@ -98,9 +103,11 @@ import { WidgetDatapointComponent } from 'app/pages/dashboard/widgets/common/wid ChartsModule, MatListModule, EmptyComponent, + ImgFallbackModule, ChartsModule, InterfaceStatusIconComponent, IxFileSizeModule, + UptimePipe, ], }) export class DashboardModule { diff --git a/src/app/pages/dashboard/services/dashboard.store.ts b/src/app/pages/dashboard/services/dashboard.store.ts index 09be33d0d86..ad9742556fa 100644 --- a/src/app/pages/dashboard/services/dashboard.store.ts +++ b/src/app/pages/dashboard/services/dashboard.store.ts @@ -113,16 +113,16 @@ export class DashboardStore extends ComponentStore { private getWidgetTypeFromOldDashboard(name: WidgetName): WidgetType { const unknownWidgetType = name as unknown as WidgetType; - // TODO: we have some widgets that are not yet implemented for the new dashboard switch (name) { case WidgetName.Help: return WidgetType.Help; case WidgetName.Memory: return WidgetType.Memory; case WidgetName.Interface: return WidgetType.InterfaceIp; + case WidgetName.SystemInformation: return WidgetType.SystemInfoActive; + case WidgetName.SystemInformationStandby: return WidgetType.SystemInfoPassive; case WidgetName.Network: return WidgetType.Network; case WidgetName.Backup: return WidgetType.BackupTasks; case WidgetName.Cpu: return WidgetType.Cpu; - case WidgetName.SystemInformation: return unknownWidgetType; case WidgetName.Storage: return unknownWidgetType; case WidgetName.Pool: return unknownWidgetType; default: return unknownWidgetType; diff --git a/src/app/pages/dashboard/services/demo-widgets.constant.ts b/src/app/pages/dashboard/services/demo-widgets.constant.ts index 26e1520021c..151f8188a8f 100644 --- a/src/app/pages/dashboard/services/demo-widgets.constant.ts +++ b/src/app/pages/dashboard/services/demo-widgets.constant.ts @@ -2,6 +2,18 @@ import { WidgetGroup, WidgetGroupLayout } from 'app/pages/dashboard/types/widget import { Widget, WidgetType } from 'app/pages/dashboard/types/widget.interface'; export const demoWidgets: WidgetGroup[] = [ + { + layout: WidgetGroupLayout.Full, + slots: [ + { type: WidgetType.SystemInfoActive }, + ], + }, + { + layout: WidgetGroupLayout.Full, + slots: [ + { type: WidgetType.SystemInfoPassive }, + ], + }, { layout: WidgetGroupLayout.Full, slots: [ diff --git a/src/app/pages/dashboard/services/widget-resources.service.ts b/src/app/pages/dashboard/services/widget-resources.service.ts index 20820bb50e7..e9a2516d2c6 100644 --- a/src/app/pages/dashboard/services/widget-resources.service.ts +++ b/src/app/pages/dashboard/services/widget-resources.service.ts @@ -1,11 +1,16 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { sub } from 'date-fns'; -import { Observable, timer, forkJoin } from 'rxjs'; +import { + Observable, Subject, forkJoin, + timer, +} from 'rxjs'; import { combineLatestWith, - map, shareReplay, switchMap, + debounceTime, + map, repeat, shareReplay, switchMap, } from 'rxjs/operators'; +import { SystemUpdateStatus } from 'app/enums/system-update.enum'; import { toLoadingState } from 'app/helpers/operators/to-loading-state.helper'; import { ReportingData } from 'app/interfaces/reporting.interface'; import { WebSocketService } from 'app/services/ws.service'; @@ -26,6 +31,8 @@ import { waitForSystemInfo } from 'app/store/system-info/system-info.selectors'; export class WidgetResourcesService { // TODO: nosub is emitted for some reason readonly realtimeUpdates$ = this.ws.subscribe('reporting.realtime'); + readonly fiveSecondsRefreshInteval$ = timer(0, 5000); + private readonly triggerRefreshSystemInfo$ = new Subject(); readonly backups$ = forkJoin([ this.ws.call('replication.query'), @@ -36,6 +43,8 @@ export class WidgetResourcesService { ); readonly systemInfo$ = this.ws.call('webui.main.dashboard.sys_info').pipe( + repeat({ delay: () => this.triggerRefreshSystemInfo$ }), + debounceTime(300), toLoadingState(), shareReplay({ bufferSize: 1, refCount: true }), ); @@ -45,12 +54,18 @@ export class WidgetResourcesService { shareReplay({ bufferSize: 1, refCount: true }), ); + readonly updateAvailable$ = this.ws.call('update.check_available').pipe( + map((update) => update.status === SystemUpdateStatus.Available), + toLoadingState(), + shareReplay({ refCount: false, bufferSize: 1 }), + ); + readonly serverTime$ = this.store$.pipe( waitForSystemInfo, map((systemInfo) => new Date(systemInfo.datetime.$date)), - combineLatestWith(timer(0, 10000)), + combineLatestWith(this.fiveSecondsRefreshInteval$), map(([serverTime]) => { - serverTime.setSeconds(serverTime.getSeconds() + 10000 / 1000); + serverTime.setSeconds(serverTime.getSeconds() + 5); return serverTime; }), ); @@ -74,4 +89,8 @@ export class WidgetResourcesService { private ws: WebSocketService, private store$: Store, ) {} + + refreshSystemInfo(): void { + this.triggerRefreshSystemInfo$.next(); + } } diff --git a/src/app/pages/dashboard/types/widget-category.enum.ts b/src/app/pages/dashboard/types/widget-category.enum.ts index 34ea73ffd59..6520dd84fe8 100644 --- a/src/app/pages/dashboard/types/widget-category.enum.ts +++ b/src/app/pages/dashboard/types/widget-category.enum.ts @@ -7,6 +7,7 @@ export enum WidgetCategory { Cpu = 'cpu', Memory = 'memory', Storage = 'storage', + SystemInfo = 'system-information', BackupTasks = 'backup-tasks', } @@ -17,5 +18,6 @@ export const widgetCategoryLabels = new Map([ [WidgetCategory.Cpu, T('CPU')], [WidgetCategory.Memory, T('Memory')], [WidgetCategory.Storage, T('Storage')], + [WidgetCategory.SystemInfo, T('System Information')], [WidgetCategory.BackupTasks, T('Backup Tasks')], ]); diff --git a/src/app/pages/dashboard/types/widget.interface.ts b/src/app/pages/dashboard/types/widget.interface.ts index 071ff0c4ad2..ff179edaa7a 100644 --- a/src/app/pages/dashboard/types/widget.interface.ts +++ b/src/app/pages/dashboard/types/widget.interface.ts @@ -13,6 +13,8 @@ export enum WidgetType { Network = 'network', BackupTasks = 'backup-tasks', Cpu = 'cpu', + SystemInfoActive = 'system-info-active', + SystemInfoPassive = 'system-info-passive', } export enum SlotSize { diff --git a/src/app/pages/dashboard/widgets/all-widgets.constant.ts b/src/app/pages/dashboard/widgets/all-widgets.constant.ts index 74b8f9a9934..1da6cff2db1 100644 --- a/src/app/pages/dashboard/widgets/all-widgets.constant.ts +++ b/src/app/pages/dashboard/widgets/all-widgets.constant.ts @@ -8,6 +8,8 @@ import { interfaceIpWidget, } from 'app/pages/dashboard/widgets/network/widget-interface-ip/widget-interface-ip.definition'; import { networkWidget } from 'app/pages/dashboard/widgets/network/widget-network/widget-network.definition'; +import { systemInfoActiveWidget } from 'app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.definition'; +import { systemInfoPassiveWidget } from 'app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.definition'; export const widgetComponents = [ hostnameWidget.component, @@ -18,6 +20,8 @@ export const widgetComponents = [ networkWidget.component, backupTasksWidget.component, cpuWidget.component, + systemInfoActiveWidget.component, + systemInfoPassiveWidget.component, ]; export const widgetRegistry = { @@ -28,4 +32,6 @@ export const widgetRegistry = { [WidgetType.Network]: networkWidget, [WidgetType.BackupTasks]: backupTasksWidget, [WidgetType.Cpu]: cpuWidget, + [WidgetType.SystemInfoActive]: systemInfoActiveWidget, + [WidgetType.SystemInfoPassive]: systemInfoPassiveWidget, }; diff --git a/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.html b/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.html new file mode 100644 index 00000000000..e6a6e9fa4ac --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.html @@ -0,0 +1,36 @@ +
+ + + +
+ +
+ () + ({{ 'Unsupported Hardware' | translate }}) +
+ + + + + + + + diff --git a/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.scss b/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.scss new file mode 100644 index 00000000000..93a2b2a9ef2 --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.scss @@ -0,0 +1,37 @@ +:host { + align-items: center; + display: flex; + flex: 1; + flex-direction: column; + gap: 12px; + justify-content: center; + + .product-image-placeholder { + display: flex; + min-height: 100px; + min-width: 150px; + place-content: center; + place-items: center; + + ix-icon { + flex: 0 0 auto; + max-height: 150px; + max-width: 150px; + } + + img { + height: auto; + max-width: 80%; + + &.clickable { + cursor: pointer; + } + } + } + + .product-image-text { + align-items: center; + display: inline-flex; + min-height: 24px; + } +} diff --git a/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.spec.ts b/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.spec.ts new file mode 100644 index 00000000000..475c7dd90fe --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.spec.ts @@ -0,0 +1,108 @@ +import { HarnessLoader } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { MatIconTestingModule } from '@angular/material/icon/testing'; +import { Router } from '@angular/router'; +import { Spectator } from '@ngneat/spectator'; +import { createComponentFactory, mockProvider } from '@ngneat/spectator/jest'; +import { IxIconHarness } from 'app/modules/ix-icon/ix-icon.harness'; +import { ProductImageComponent } from 'app/pages/dashboard/widgets/system/common/product-image/product-image.component'; + +describe('ProductImageComponent', () => { + let spectator: Spectator; + let loader: HarnessLoader; + + const createComponent = createComponentFactory({ + component: ProductImageComponent, + imports: [MatIconTestingModule], + declarations: [], + providers: [mockProvider(Router)], + }); + + describe('Generic', () => { + it('should display "Unsupported Hardware" for Generic platform', async () => { + spectator = createComponent({ + props: { + systemProduct: 'Standard PC (Q35 + ICH9, 2009)', + isEnterprise: true, + hasEnclosureSupport: false, + isHaLicensed: false, + isIxHardware: false, + }, + }); + + loader = TestbedHarnessEnvironment.loader(spectator.fixture); + const icon = await loader.getHarness(IxIconHarness); + + expect(spectator.query('img')).not.toExist(); + expect(await icon.getName()).toBe('logo_truenas_scale_mark'); + expect(spectator.query('.product-image-text')).toHaveExactText('(Unsupported Hardware)'); + }); + + it('should display logo for certified platform', async () => { + spectator = createComponent({ + props: { + systemProduct: 'Generic-CERTIFIED', + isEnterprise: false, + hasEnclosureSupport: false, + isHaLicensed: false, + isIxHardware: false, + }, + }); + + loader = TestbedHarnessEnvironment.loader(spectator.fixture); + const icon = await loader.getHarness(IxIconHarness); + + expect(spectator.query('img')).not.toExist(); + expect(await icon.getName()).toBe('logo_freenas_certified'); + expect(spectator.query('.product-image-text')).not.toHaveExactText('(Unsupported Hardware)'); + }); + }); + + describe('iX Hardware', () => { + it('should display image for M40 platform', () => { + spectator = createComponent({ + props: { + systemProduct: 'TRUENAS-M40-HA', + isEnterprise: true, + hasEnclosureSupport: true, + isHaLicensed: true, + isIxHardware: true, + }, + }); + + const image = spectator.query('img'); + + expect(image).toHaveId('M40'); + expect(image).toHaveAttribute('src', 'assets/images/servers/M40.png'); + + expect(spectator.query('.product-image-text')).not.toHaveExactText('(Unsupported Hardware)'); + + expect(image).toHaveClass('clickable'); + spectator.click('img'); + expect(spectator.inject(Router).navigate).toHaveBeenCalledWith(['/system/oldviewenclosure']); + }); + + it('should display image for F60 platform', () => { + spectator = createComponent({ + props: { + systemProduct: 'TRUENAS-F60-HA', + isEnterprise: true, + hasEnclosureSupport: true, + isHaLicensed: true, + isIxHardware: true, + }, + }); + + const image = spectator.query('img'); + + expect(image).toHaveId('F60'); + expect(image).toHaveAttribute('src', 'assets/images/servers/F60.png'); + + expect(spectator.query('.product-image-text')).not.toHaveExactText('(Unsupported Hardware)'); + + expect(image).toHaveClass('clickable'); + spectator.click('img'); + expect(spectator.inject(Router).navigate).toHaveBeenCalledWith(['/system/oldviewenclosure']); + }); + }); +}); diff --git a/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.ts b/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.ts new file mode 100644 index 00000000000..f4aff5eb1ac --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/common/product-image/product-image.component.ts @@ -0,0 +1,50 @@ +import { + Component, ChangeDetectionStrategy, input, + computed, + HostBinding, +} from '@angular/core'; +import { Router } from '@angular/router'; +import { getProductEnclosure, getProductImage, getServerProduct } from 'app/pages/dashboard/widgets/system/common/widget-sys-info.utils'; + +@Component({ + selector: 'ix-product-image', + templateUrl: './product-image.component.html', + styleUrls: ['./product-image.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ProductImageComponent { + @HostBinding('class.ix-logo') get isIxLogo(): boolean { + return this.productImage().includes('ix-original.svg'); + } + @HostBinding('class.truenas') + isEnterprise = input.required(); + systemProduct = input.required(); + hasEnclosureSupport = input.required(); + isHaLicensed = input.required(); + isIxHardware = input.required(); + + isCertified = computed(() => this.systemProduct()?.includes('CERTIFIED')); + product = computed(() => getServerProduct(this.systemProduct())); + productImage = computed(() => getProductImage(this.systemProduct())); + productEnclosure = computed(() => { + if (!this.hasEnclosureSupport() || !this.systemProduct()) { + return null; + } + return getProductEnclosure(this.systemProduct()); + }); + isUnsupportedHardware = computed(() => { + const isEnterprise = this.isEnterprise(); + const isIxHardware = this.isIxHardware(); + const isHaLicensed = this.isHaLicensed(); + return isEnterprise && !isIxHardware && !isHaLicensed; + }); + + constructor(private router: Router) { } + + goToEnclosure(): void { + if (!this.hasEnclosureSupport()) { + return; + } + this.router.navigate(['/system/oldviewenclosure']); + } +} diff --git a/src/app/core/pipes/uptime.pipe.spec.ts b/src/app/pages/dashboard/widgets/system/common/uptime.pipe.spec.ts similarity index 100% rename from src/app/core/pipes/uptime.pipe.spec.ts rename to src/app/pages/dashboard/widgets/system/common/uptime.pipe.spec.ts diff --git a/src/app/core/pipes/uptime.pipe.ts b/src/app/pages/dashboard/widgets/system/common/uptime.pipe.ts similarity index 98% rename from src/app/core/pipes/uptime.pipe.ts rename to src/app/pages/dashboard/widgets/system/common/uptime.pipe.ts index 41fbf97bf11..dd3e1b6f86a 100644 --- a/src/app/core/pipes/uptime.pipe.ts +++ b/src/app/pages/dashboard/widgets/system/common/uptime.pipe.ts @@ -3,6 +3,7 @@ import { TranslateService } from '@ngx-translate/core'; @Pipe({ name: 'uptime', + standalone: true, }) export class UptimePipe implements PipeTransform { constructor(private translate: TranslateService) {} diff --git a/src/app/pages/dashboard/widgets/system/common/widget-sys-info.scss b/src/app/pages/dashboard/widgets/system/common/widget-sys-info.scss new file mode 100644 index 00000000000..63e18693785 --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/common/widget-sys-info.scss @@ -0,0 +1,119 @@ +@import 'scss-imports/cssvars'; + +.card { + box-sizing: border-box; + display: flex; + flex-direction: column; + height: 100%; +} + +.card-content { + display: flex; + flex-direction: row; + height: 100%; + padding-bottom: 0; + padding-right: 0; + + .container { + padding: 0; + } +} + +.header { + display: flex; + justify-content: space-between; + + h3 { + font-size: 24px; + + small { + align-items: baseline; + display: inline-flex; + font-size: 75%; + font-weight: 600; + margin-left: 4px; + opacity: 0.5; + text-transform: lowercase; + } + } +} + +.copy-version { + align-items: center; + display: flex; + flex: 1; + margin-right: -29px; + min-width: 0; + + .copy-version-text { + display: inline-flex; + flex: 1; + max-width: 78%; + min-width: 0; + + span { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } +} + +::ng-deep mat-list-item .mat-mdc-list-item-unscoped-content { + gap: 8px; +} + +.container { + display: flex; + flex-grow: 1; + overflow: hidden; +} + +.content-left { + display: flex; + flex: 1 0 40%; + flex-direction: column; + max-width: 40%; +} + +.content-right { + flex: 1 0 60%; + max-width: 60%; + padding: 0; + + .header { + padding: 16px; + } +} + +.product-logo-container { + min-height: 87px; + padding: 16px 32px; +} + +.card-action-container { + align-items: center; + display: flex; + justify-content: center; + padding: 16px 32px 32px; +} + +.overview { + padding-left: 16px; + padding-right: 16px; +} + +ix-product-image.passive { + opacity: 0.5; +} + +.image-loader { + height: 150px; + margin: auto; + width: 150px; +} + +.inline-loader { + display: inline-flex; + flex: 1; +} diff --git a/src/app/pages/dashboard/widgets/system/common/widget-sys-info.utils.spec.ts b/src/app/pages/dashboard/widgets/system/common/widget-sys-info.utils.spec.ts new file mode 100644 index 00000000000..0c139f137e2 --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/common/widget-sys-info.utils.spec.ts @@ -0,0 +1,59 @@ +import { Codename } from 'app/enums/codename.enum'; +import { + getMiniImagePath, getProductEnclosure, getProductImage, getServerProduct, getSystemVersion, + isRackmount, +} from 'app/pages/dashboard/widgets/system/common/widget-sys-info.utils'; + +describe('getSystemVersion', () => { + it('should return the correct system version when valid input is provided', () => { + expect(getSystemVersion('TrueNAS-SCALE-24.10.0-MASTER-20240301-233006', Codename.ElectricEel)).toBe( + 'ElectricEel-24.10.0-MASTER-20240301-233006', + ); + }); + + it('should initial version if second argument is skipped', () => { + expect(getSystemVersion('TrueNAS-SCALE-24.10.0-MASTER-20240301-233006')).toBe( + 'TrueNAS-SCALE-24.10.0-MASTER-20240301-233006', + ); + }); +}); + +describe('getServerProduct', () => { + it('should return the correct image path for provided product', () => { + expect(getServerProduct('TRUENAS-M40-HA')).toBe('M40'); + expect(getServerProduct('TRUENAS-F130-HA')).toBe('F130'); + expect(getServerProduct('TRUENAS-MINI-R')).toBeUndefined(); + expect(getServerProduct('TRUENAS-MINI-3.0-XL+')).toBeUndefined(); + expect(getServerProduct('FREENAS-MINI-XL')).toBeUndefined(); + }); +}); + +describe('getProductImage', () => { + it('should return the correct image path for provided product', () => { + expect(getProductImage('TRUENAS-M40-HA')).toBe('assets/images/servers/M40.png'); + expect(getProductImage('TRUENAS-MINI-R')).toBe('assets/images/servers/MINI-R.png'); + expect(getProductImage('FREENAS-MINI-XL')).toBe('assets/images/freenas_mini_xl_cropped.png'); + }); +}); + +describe('getMiniImagePath', () => { + it('should return the correct image path for provided product', () => { + expect(getMiniImagePath('TRUENAS-M40-HA')).toBeUndefined(); + expect(getMiniImagePath('TRUENAS-MINI-R')).toBe('servers/MINI-R.png'); + expect(getMiniImagePath('FREENAS-MINI-XL')).toBe('freenas_mini_xl_cropped.png'); + }); +}); + +describe('getProductEnclosure', () => { + it('should return the correct product enclosure for provided product', () => { + expect(getProductEnclosure('TRUENAS-M40-HA')).toBe('rackmount'); + expect(getProductEnclosure('FREENAS-MINI-XL')).toBe('tower'); + }); +}); + +describe('isRackmount', () => { + it('should return the correct image path for provided product', () => { + expect(isRackmount('FREENAS-MINI-XL')).toBeFalsy(); + expect(isRackmount('TRUENAS-MINI-R')).toBeTruthy(); + }); +}); diff --git a/src/app/pages/dashboard/widgets/system/common/widget-sys-info.utils.ts b/src/app/pages/dashboard/widgets/system/common/widget-sys-info.utils.ts new file mode 100644 index 00000000000..b5c2187f303 --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/common/widget-sys-info.utils.ts @@ -0,0 +1,52 @@ +import { miniSeries, serverSeries } from 'app/constants/server-series.constant'; +import { Codename } from 'app/enums/codename.enum'; +import { ProductEnclosure } from 'app/enums/product-enclosure.enum'; + +export function getServerProduct(systemProduct: string): string { + return serverSeries.find((series) => systemProduct?.includes(series)); +} + +export function getMiniImagePath(systemProduct: string): string { + return Object.values(miniSeries).find((series) => series.images.includes(systemProduct))?.pathImg; +} + +export function getProductImage(systemProduct: string): string { + if (!systemProduct) { + return ''; + } + + let product: string; + + if (systemProduct.includes('MINI')) { + product = getMiniImagePath(systemProduct); + } else { + product = getServerProduct(systemProduct) ? `servers/${getServerProduct(systemProduct)}.png` : 'ix-original.svg'; + } + + return product ? `assets/images/${product}` : ''; +} + +export function isRackmount(systemProduct: string): boolean { + if (systemProduct.includes('MINI')) { + return !!Object.values(miniSeries)?.find((mini) => mini.images.includes(systemProduct))?.isRackmount; + } + + return !!serverSeries.find((name) => systemProduct === name); +} + +export function getProductEnclosure(systemProduct: string): ProductEnclosure { + if (!systemProduct) { + return null; + } + if (systemProduct.includes('MINI')) { + return ProductEnclosure.Tower; + } + return ProductEnclosure.Rackmount; +} + +export function getSystemVersion(version: string, codename?: Codename): string { + if (codename) { + return version.replace('TrueNAS-SCALE', codename); + } + return version; +} diff --git a/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.html b/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.html new file mode 100644 index 00000000000..e561088e5e2 --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.html @@ -0,0 +1,139 @@ + + +
+
+
+ +
+ + + {{ 'Active' | translate }} + + +
+ + + +
+
+ +
+
+

{{ 'System Information' | translate }}

+ + +
+ +
+ {{ 'Overview' | translate }} +
+ + + + {{ 'Platform' | translate }}: + + + {{ systemInfo().platform }} + + + {{ 'Generic' }} + + + + + {{ 'Version' | translate }}: +
+
+ + {{ version() }} + +
+ +
+
+ + + {{ 'License' | translate }}: + + + {{ + '{license} contract, expires {date}' | translate: + { + license: systemInfo().license.contract_type | titlecase, + date: systemInfo().license.contract_end.$value, + } + }} + + + {{ 'No License' | translate }} + + + + + + {{ 'System Serial' | translate }}: + + {{ systemInfo().system_serial }} + + + + + {{ 'Hostname' | translate }}: + + {{ systemInfo().hostname }} + + + + + {{ 'Uptime' | translate }}: + + {{ uptime() | uptime: (datetime() | formatDateTime:' ':'HH:mm') }} + + +
+
+
+
+
+ + + + diff --git a/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.spec.ts b/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.spec.ts new file mode 100644 index 00000000000..6dcde551ccb --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.spec.ts @@ -0,0 +1,147 @@ +import { HarnessLoader, parallel } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { MatIconTestingModule } from '@angular/material/icon/testing'; +import { MatListModule } from '@angular/material/list'; +import { MatListItemHarness } from '@angular/material/list/testing'; +import { Spectator } from '@ngneat/spectator'; +import { createComponentFactory, mockProvider } from '@ngneat/spectator/jest'; +import { provideMockStore } from '@ngrx/store/testing'; +import { MockComponent } from 'ng-mocks'; +import { NgxSkeletonLoaderComponent } from 'ngx-skeleton-loader'; +import { BehaviorSubject, of } from 'rxjs'; +import { FakeFormatDateTimePipe } from 'app/core/testing/classes/fake-format-datetime.pipe'; +import { mockAuth } from 'app/core/testing/utils/mock-auth.utils'; +import { Codename } from 'app/enums/codename.enum'; +import { ProductType } from 'app/enums/product-type.enum'; +import { LoadingState } from 'app/helpers/operators/to-loading-state.helper'; +import { SystemLicense, SystemInfo } from 'app/interfaces/system-info.interface'; +import { selectUpdateJobForActiveNode } from 'app/modules/jobs/store/job.selectors'; +import { WidgetResourcesService } from 'app/pages/dashboard/services/widget-resources.service'; +import { SlotSize } from 'app/pages/dashboard/types/widget.interface'; +import { ProductImageComponent } from 'app/pages/dashboard/widgets/system/common/product-image/product-image.component'; +import { UptimePipe } from 'app/pages/dashboard/widgets/system/common/uptime.pipe'; +import { WidgetSysInfoActiveComponent } from 'app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component'; +import { selectIsHaLicensed, selectIsHaEnabled } from 'app/store/ha-info/ha-info.selectors'; +import { + selectIsIxHardware, selectProductType, + selectIsEnterprise, + selectEnclosureSupport, +} from 'app/store/system-info/system-info.selectors'; + +describe('WidgetSysInfoActiveComponent', () => { + let spectator: Spectator; + let loader: HarnessLoader; + const fiveSecondsRefreshInteval$ = new BehaviorSubject(0); + + const systemInfo = { + platform: 'TRUENAS-M40-HA', + version: 'TrueNAS-SCALE-24.10.0-MASTER-20240301-233006', + codename: Codename.ElectricEel, + license: { + contract_type: 'BEST', + contract_end: { + $type: 'date', + $value: '2025-01-01', + }, + } as SystemLicense, + system_serial: 'AA-00001', + hostname: 'test-hostname-a', + uptime_seconds: 83532.938532175, + datetime: { + $date: 1710491651000, + }, + } as SystemInfo; + + const createComponent = createComponentFactory({ + component: WidgetSysInfoActiveComponent, + imports: [ + MatListModule, + MatIconTestingModule, + UptimePipe, + ], + declarations: [ + MockComponent(ProductImageComponent), + MockComponent(NgxSkeletonLoaderComponent), + FakeFormatDateTimePipe, + ], + providers: [ + mockAuth(), + mockProvider(WidgetResourcesService, { + systemInfo$: of({ + isLoading: false, + error: null, + value: systemInfo, + } as LoadingState), + updateAvailable$: of(true), + fiveSecondsRefreshInteval$, + }), + provideMockStore({ + selectors: [ + { + selector: selectProductType, + value: ProductType.ScaleEnterprise, + }, + { + selector: selectIsEnterprise, + value: true, + }, + { + selector: selectEnclosureSupport, + value: true, + }, + { + selector: selectIsIxHardware, + value: true, + }, + { + selector: selectIsHaLicensed, + value: true, + }, + { + selector: selectIsHaEnabled, + value: true, + }, + { + selector: selectUpdateJobForActiveNode, + value: null, + }, + ], + }), + ], + }); + + beforeEach(() => { + spectator = createComponent({ + props: { + size: SlotSize.Full, + }, + }); + loader = TestbedHarnessEnvironment.loader(spectator.fixture); + }); + + it('checks title', () => { + expect(spectator.query('.header h3')).toHaveText('System Information'); + }); + + it('checks system info rows', async () => { + const matListItems = await loader.getAllHarnesses(MatListItemHarness); + const items = await parallel(() => matListItems.map((item) => item.getFullText())); + expect(items).toEqual([ + 'Platform: TRUENAS-M40-HA', + 'Version: ElectricEel-24.10.0-MASTER-20240301-233006', + 'License: Best contract, expires 2025-01-01', + 'System Serial: AA-00001', + 'Hostname: test-hostname-a', + 'Uptime: 23 hours 12 minutes as of 2024-03-15 10:34:11', + ]); + }); + + it('checks uptime and datetime changed over the time', async () => { + fiveSecondsRefreshInteval$.next(12); + + const uptime = await loader.getHarness(MatListItemHarness.with({ text: /Uptime:/ })); + expect(await uptime.getFullText()).toBe('Uptime: 23 hours 13 minutes as of 2024-03-15 10:35:11'); + }); + + // TODO: Add more tests +}); diff --git a/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.ts b/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.ts new file mode 100644 index 00000000000..f4454f44f0c --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component.ts @@ -0,0 +1,53 @@ +import { + Component, ChangeDetectionStrategy, input, + computed, +} from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { Store } from '@ngrx/store'; +import { filter, map } from 'rxjs'; +import { selectUpdateJobForActiveNode } from 'app/modules/jobs/store/job.selectors'; +import { WidgetResourcesService } from 'app/pages/dashboard/services/widget-resources.service'; +import { SlotSize } from 'app/pages/dashboard/types/widget.interface'; +import { getSystemVersion } from 'app/pages/dashboard/widgets/system/common/widget-sys-info.utils'; +import { AppState } from 'app/store'; +import { selectIsHaLicensed } from 'app/store/ha-info/ha-info.selectors'; +import { + selectEnclosureSupport, selectIsEnterprise, selectIsIxHardware, +} from 'app/store/system-info/system-info.selectors'; + +@Component({ + selector: 'ix-widget-sys-info-active', + templateUrl: './widget-sys-info-active.component.html', + styleUrls: ['../common/widget-sys-info.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class WidgetSysInfoActiveComponent { + size = input.required(); + + isIxHardware = toSignal(this.store$.select(selectIsIxHardware)); + isEnterprise = toSignal(this.store$.select(selectIsEnterprise)); + isHaLicensed = toSignal(this.store$.select(selectIsHaLicensed)); + hasEnclosureSupport = toSignal(this.store$.select(selectEnclosureSupport)); + isUpdateRunning = toSignal(this.store$.select(selectUpdateJobForActiveNode)); + + updateAvailable = toSignal(this.resources.updateAvailable$); + systemInfo = toSignal(this.resources.systemInfo$.pipe( + filter((state) => !state.isLoading), + map((state) => state.value), + )); + elapsedSeconds = toSignal(this.resources.fiveSecondsRefreshInteval$.pipe( + map((iteration) => (iteration ? iteration * 5 : 0)), + )); + + version = computed(() => getSystemVersion(this.systemInfo().version, this.systemInfo().codename)); + uptime = computed(() => this.systemInfo().uptime_seconds + this.elapsedSeconds()); + datetime = computed(() => this.systemInfo().datetime.$date + (this.elapsedSeconds() * 1000)); + isLoaded = computed(() => this.systemInfo()); + + constructor( + private resources: WidgetResourcesService, + private store$: Store, + ) { + this.resources.refreshSystemInfo(); + } +} diff --git a/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.definition.ts b/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.definition.ts new file mode 100644 index 00000000000..ce057502c6f --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.definition.ts @@ -0,0 +1,13 @@ +import { marker as T } from '@biesbjerg/ngx-translate-extract-marker'; +import { WidgetCategory } from 'app/pages/dashboard/types/widget-category.enum'; +import { dashboardWidget } from 'app/pages/dashboard/types/widget-component.interface'; +import { SlotSize } from 'app/pages/dashboard/types/widget.interface'; +import { WidgetSysInfoActiveComponent } from 'app/pages/dashboard/widgets/system/widget-sys-info-active/widget-sys-info-active.component'; + +export const systemInfoActiveWidget = dashboardWidget({ + name: T('System Information Active Node'), + supportedSizes: [SlotSize.Full], + category: WidgetCategory.SystemInfo, + component: WidgetSysInfoActiveComponent, + settingsComponent: null, +}); diff --git a/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.html b/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.html new file mode 100644 index 00000000000..3026eb35e3c --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.html @@ -0,0 +1,136 @@ + + +
+
+
+ +
+ + + {{ 'Standby' | translate }} + + +
+ + + + + +
+
+ +
+
+

{{ 'System Information' | translate }} {{ 'standby' | translate }}

+
+ +
+ {{ 'Overview' | translate }} +
+ + + + {{ 'Platform' | translate }}: + + + {{ systemInfo().platform }} + + + {{ 'Generic' }} + + + + + {{ 'Version' | translate }}: +
+
+ + {{ version() }} + +
+ +
+
+ + + {{ 'License' | translate }}: + + + {{ + '{license} contract, expires {date}' | translate: + { + license: systemInfo().license.contract_type | titlecase, + date: systemInfo().license.contract_end.$value, + } + }} + + + {{ 'No License' | translate }} + + + + + + {{ 'System Serial' | translate }}: + + {{ systemInfo().system_serial }} + + + + + {{ 'Hostname' | translate }}: + + {{ systemInfo().hostname }} + + + + + {{ 'Uptime' | translate }}: + + {{ uptime() | uptime: (datetime() | formatDateTime:' ':'HH:mm') }} + + +
+
+
+
+
+ + + + diff --git a/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.spec.ts b/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.spec.ts new file mode 100644 index 00000000000..e49a8c0b62e --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.spec.ts @@ -0,0 +1,158 @@ +import { HarnessLoader, parallel } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { MatIconTestingModule } from '@angular/material/icon/testing'; +import { MatListModule } from '@angular/material/list'; +import { MatListItemHarness } from '@angular/material/list/testing'; +import { Router } from '@angular/router'; +import { Spectator } from '@ngneat/spectator'; +import { createComponentFactory, mockProvider } from '@ngneat/spectator/jest'; +import { provideMockStore } from '@ngrx/store/testing'; +import { MockComponent } from 'ng-mocks'; +import { NgxSkeletonLoaderComponent } from 'ngx-skeleton-loader'; +import { BehaviorSubject, of } from 'rxjs'; +import { FakeFormatDateTimePipe } from 'app/core/testing/classes/fake-format-datetime.pipe'; +import { mockAuth } from 'app/core/testing/utils/mock-auth.utils'; +import { Codename } from 'app/enums/codename.enum'; +import { ProductType } from 'app/enums/product-type.enum'; +import { LoadingState } from 'app/helpers/operators/to-loading-state.helper'; +import { SystemLicense, SystemInfo } from 'app/interfaces/system-info.interface'; +import { DialogService } from 'app/modules/dialog/dialog.service'; +import { selectUpdateJobForPassiveNode } from 'app/modules/jobs/store/job.selectors'; +import { WidgetResourcesService } from 'app/pages/dashboard/services/widget-resources.service'; +import { SlotSize } from 'app/pages/dashboard/types/widget.interface'; +import { ProductImageComponent } from 'app/pages/dashboard/widgets/system/common/product-image/product-image.component'; +import { UptimePipe } from 'app/pages/dashboard/widgets/system/common/uptime.pipe'; +import { WidgetSysInfoPassiveComponent } from 'app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component'; +import { selectCanFailover, selectIsHaEnabled, selectIsHaLicensed } from 'app/store/ha-info/ha-info.selectors'; +import { + selectIsIxHardware, + selectProductType, + selectIsEnterprise, + selectEnclosureSupport, +} from 'app/store/system-info/system-info.selectors'; + +describe('WidgetSysInfoPassiveComponent', () => { + let spectator: Spectator; + let loader: HarnessLoader; + const fiveSecondsRefreshInteval$ = new BehaviorSubject(0); + + const systemInfo = { + remote_info: { + platform: 'TRUENAS-M40-HA', + version: 'TrueNAS-SCALE-24.10.0-MASTER-20240301-233006', + codename: Codename.ElectricEel, + license: { + contract_type: 'BEST', + contract_end: { + $type: 'date', + $value: '2025-01-01', + }, + } as SystemLicense, + system_serial: 'AA-00002', + hostname: 'test-hostname-b', + uptime_seconds: 77.915545062, + datetime: { + $date: 1710491651000, + }, + } as SystemInfo, + } as SystemInfo; + + const createComponent = createComponentFactory({ + component: WidgetSysInfoPassiveComponent, + imports: [ + MatListModule, + MatIconTestingModule, + UptimePipe, + ], + declarations: [ + MockComponent(ProductImageComponent), + MockComponent(NgxSkeletonLoaderComponent), + FakeFormatDateTimePipe, + ], + providers: [ + mockAuth(), + mockProvider(DialogService), + mockProvider(Router), + mockProvider(WidgetResourcesService, { + systemInfo$: of({ + isLoading: false, + error: null, + value: systemInfo, + } as LoadingState), + updateAvailable$: of(true), + fiveSecondsRefreshInteval$, + }), + provideMockStore({ + selectors: [ + { + selector: selectProductType, + value: ProductType.ScaleEnterprise, + }, + { + selector: selectIsEnterprise, + value: true, + }, + { + selector: selectEnclosureSupport, + value: true, + }, + { + selector: selectIsIxHardware, + value: true, + }, + { + selector: selectIsHaLicensed, + value: true, + }, + { + selector: selectIsHaEnabled, + value: true, + }, + { + selector: selectCanFailover, + value: true, + }, + { + selector: selectUpdateJobForPassiveNode, + value: null, + }, + ], + }), + ], + }); + + beforeEach(() => { + spectator = createComponent({ + props: { + size: SlotSize.Full, + }, + }); + loader = TestbedHarnessEnvironment.loader(spectator.fixture); + }); + + it('checks title', () => { + expect(spectator.query('.header h3')).toHaveText('System Information standby'); + }); + + it('checks system info rows', async () => { + const matListItems = await loader.getAllHarnesses(MatListItemHarness); + const items = await parallel(() => matListItems.map((item) => item.getFullText())); + expect(items).toEqual([ + 'Platform: TRUENAS-M40-HA', + 'Version: ElectricEel-24.10.0-MASTER-20240301-233006', + 'License: Best contract, expires 2025-01-01', + 'System Serial: AA-00002', + 'Hostname: test-hostname-b', + 'Uptime: 1 minute 17 seconds as of 2024-03-15 10:34:11', + ]); + }); + + it('checks uptime and datetime changed over the time', async () => { + fiveSecondsRefreshInteval$.next(12); + + const uptime = await loader.getHarness(MatListItemHarness.with({ text: /Uptime:/ })); + expect(await uptime.getFullText()).toBe('Uptime: 2 minutes 17 seconds as of 2024-03-15 10:35:11'); + }); + + // TODO: Add more tests +}); diff --git a/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.ts b/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.ts new file mode 100644 index 00000000000..4f701154de0 --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component.ts @@ -0,0 +1,77 @@ +import { + ChangeDetectionStrategy, Component, computed, input, +} from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { Router } from '@angular/router'; +import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; +import { Store } from '@ngrx/store'; +import { filter, map } from 'rxjs'; +import { Role } from 'app/enums/role.enum'; +import { helptextSystemFailover } from 'app/helptext/system/failover'; +import { DialogService } from 'app/modules/dialog/dialog.service'; +import { selectUpdateJobForPassiveNode } from 'app/modules/jobs/store/job.selectors'; +import { WidgetResourcesService } from 'app/pages/dashboard/services/widget-resources.service'; +import { SlotSize } from 'app/pages/dashboard/types/widget.interface'; +import { getSystemVersion } from 'app/pages/dashboard/widgets/system/common/widget-sys-info.utils'; +import { AppState } from 'app/store'; +import { selectCanFailover, selectIsHaEnabled, selectIsHaLicensed } from 'app/store/ha-info/ha-info.selectors'; +import { + selectIsIxHardware, selectIsEnterprise, selectEnclosureSupport, +} from 'app/store/system-info/system-info.selectors'; + +@UntilDestroy() +@Component({ + selector: 'ix-widget-sys-info-passive', + templateUrl: './widget-sys-info-passive.component.html', + styleUrls: ['../common/widget-sys-info.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class WidgetSysInfoPassiveComponent { + size = input.required(); + + protected readonly isDisabled$ = this.store$.select(selectCanFailover).pipe(map((canFailover) => !canFailover)); + protected readonly requiredRoles = [Role.FailoverWrite]; + + isIxHardware = toSignal(this.store$.select(selectIsIxHardware)); + isEnterprise = toSignal(this.store$.select(selectIsEnterprise)); + isHaLicensed = toSignal(this.store$.select(selectIsHaLicensed)); + isHaEnabled = toSignal(this.store$.select(selectIsHaEnabled)); + hasEnclosureSupport = toSignal(this.store$.select(selectEnclosureSupport)); + isUpdateRunning = toSignal(this.store$.select(selectUpdateJobForPassiveNode)); + + updateAvailable = toSignal(this.resources.updateAvailable$); + systemInfo = toSignal(this.resources.systemInfo$.pipe( + filter((state) => !state.isLoading), + map((state) => state.value.remote_info), + )); + elapsedSeconds = toSignal(this.resources.fiveSecondsRefreshInteval$.pipe( + map((iteration) => (iteration ? iteration * 5 : 0)), + )); + + version = computed(() => getSystemVersion(this.systemInfo().version, this.systemInfo().codename)); + uptime = computed(() => this.systemInfo().uptime_seconds + this.elapsedSeconds()); + datetime = computed(() => this.systemInfo().datetime.$date + (this.elapsedSeconds() * 1000)); + isLoaded = computed(() => this.systemInfo()); + + constructor( + private resources: WidgetResourcesService, + private dialog: DialogService, + private store$: Store, + private router: Router, + ) { + this.resources.refreshSystemInfo(); + } + + openDialog(): void { + this.dialog.confirm({ + title: helptextSystemFailover.dialog_initiate_failover_title, + message: helptextSystemFailover.dialog_initiate_failover_message, + buttonText: helptextSystemFailover.dialog_initiate_action, + }).pipe( + filter(Boolean), + untilDestroyed(this), + ).subscribe(() => { + this.router.navigate(['/others/failover'], { skipLocationChange: true }); + }); + } +} diff --git a/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.definition.ts b/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.definition.ts new file mode 100644 index 00000000000..65363269f63 --- /dev/null +++ b/src/app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.definition.ts @@ -0,0 +1,13 @@ +import { marker as T } from '@biesbjerg/ngx-translate-extract-marker'; +import { WidgetCategory } from 'app/pages/dashboard/types/widget-category.enum'; +import { dashboardWidget } from 'app/pages/dashboard/types/widget-component.interface'; +import { SlotSize } from 'app/pages/dashboard/types/widget.interface'; +import { WidgetSysInfoPassiveComponent } from 'app/pages/dashboard/widgets/system/widget-sys-info-passive/widget-sys-info-passive.component'; + +export const systemInfoPassiveWidget = dashboardWidget({ + name: T('System Information Standby Node'), + supportedSizes: [SlotSize.Full], + category: WidgetCategory.SystemInfo, + component: WidgetSysInfoPassiveComponent, + settingsComponent: null, +}); diff --git a/src/app/pages/reports-dashboard/components/report/report.component.ts b/src/app/pages/reports-dashboard/components/report/report.component.ts index f7e72020425..e7592f12763 100644 --- a/src/app/pages/reports-dashboard/components/report/report.component.ts +++ b/src/app/pages/reports-dashboard/components/report/report.component.ts @@ -19,6 +19,7 @@ import { import { delay, distinctUntilChanged, filter, skipWhile, throttleTime, } from 'rxjs/operators'; +import { oneDayMillis, oneHourMillis } from 'app/constants/time.constant'; import { toggleMenuDuration } from 'app/constants/toggle-menu-duration'; import { FormatDateTimePipe } from 'app/core/pipes/format-datetime.pipe'; import { EmptyType } from 'app/enums/empty-type.enum'; @@ -493,15 +494,15 @@ export class ReportComponent extends WidgetComponent implements OnInit, OnChange private getHalfPeriodMilliseconds(): number { switch (this.currentZoomLevel) { case ReportZoomLevel.Hour: - return (1 * 60 * 60 * 1000) / 2; + return (1 * oneHourMillis) / 2; case ReportZoomLevel.Day: - return (1 * 24 * 60 * 60 * 1000) / 2; + return (1 * oneDayMillis) / 2; case ReportZoomLevel.Week: - return (7 * 24 * 60 * 60 * 1000) / 2; + return (7 * oneDayMillis) / 2; case ReportZoomLevel.Month: - return (30 * 24 * 60 * 60 * 1000) / 2; + return (30 * oneDayMillis) / 2; case ReportZoomLevel.HalfYear: - return (365 * 24 * 60 * 60 * 1000) / 2; + return (365 * oneDayMillis) / 2; default: return 0; } diff --git a/src/app/pages/system/general-settings/support/support-card/support-card.component.ts b/src/app/pages/system/general-settings/support/support-card/support-card.component.ts index da2c147a32f..d83f4b10de1 100644 --- a/src/app/pages/system/general-settings/support/support-card/support-card.component.ts +++ b/src/app/pages/system/general-settings/support/support-card/support-card.component.ts @@ -10,6 +10,7 @@ import _ from 'lodash'; import { Observable, of, switchMap } from 'rxjs'; import { filter, tap } from 'rxjs/operators'; import { GiB } from 'app/constants/bytes.constant'; +import { oneDayMillis } from 'app/constants/time.constant'; import { Role } from 'app/enums/role.enum'; import { helptextSystemSupport as helptext } from 'app/helptext/system/support'; import { DialogService } from 'app/modules/dialog/dialog.service'; @@ -17,6 +18,7 @@ import { FeedbackDialogComponent } from 'app/modules/feedback/components/feedbac import { FeedbackType } from 'app/modules/feedback/interfaces/feedback.interface'; import { AppLoaderService } from 'app/modules/loader/app-loader.service'; import { SnackbarService } from 'app/modules/snackbar/services/snackbar.service'; +import { getMiniImagePath, getServerProduct, isRackmount } from 'app/pages/dashboard/widgets/system/common/widget-sys-info.utils'; import { LicenseComponent } from 'app/pages/system/general-settings/support/license/license.component'; import { LicenseInfoInSupport } from 'app/pages/system/general-settings/support/license-info-in-support.interface'; import { ProactiveComponent } from 'app/pages/system/general-settings/support/proactive/proactive.component'; @@ -28,7 +30,6 @@ import { supportCardElements } from 'app/pages/system/general-settings/support/s import { SystemInfoInSupport } from 'app/pages/system/general-settings/support/system-info-in-support.interface'; import { ErrorHandlerService } from 'app/services/error-handler.service'; import { IxSlideInService } from 'app/services/ix-slide-in.service'; -import { ProductImageService } from 'app/services/product-image.service'; import { WebSocketService } from 'app/services/ws.service'; import { AppState } from 'app/store'; import { waitForSystemInfo } from 'app/store/system-info/system-info.selectors'; @@ -68,7 +69,6 @@ export class SupportCardComponent implements OnInit { private store$: Store, private snackbar: SnackbarService, private translate: TranslateService, - private productImageService: ProductImageService, private cdr: ChangeDetectorRef, private errorHandler: ErrorHandlerService, ) {} @@ -78,8 +78,8 @@ export class SupportCardComponent implements OnInit { this.systemInfo = { ...systemInfo }; this.systemInfo.memory = (systemInfo.physmem / GiB).toFixed(0) + ' GiB'; if (systemInfo.system_product?.includes('MINI')) { - const getImage = this.productImageService.getMiniImagePath(systemInfo.system_product); - if (this.productImageService.isRackmount(systemInfo.system_product)) { + const getImage = getMiniImagePath(systemInfo.system_product); + if (isRackmount(systemInfo.system_product)) { this.isProductImageRack = true; this.extraMargin = true; } else { @@ -130,16 +130,15 @@ export class SupportCardComponent implements OnInit { } daysTillExpiration(now: Date, then: Date): number { - const oneDay = 24 * 60 * 60 * 1000; // milliseconds in a day - return Math.round((then.getTime() - now.getTime()) / (oneDay)); + return Math.round((then.getTime() - now.getTime()) / (oneDayMillis)); } getServerImage(sysProduct: string): void { - const imagePath = this.productImageService.getServerProduct(sysProduct); + const product = getServerProduct(sysProduct); - if (imagePath) { + if (product) { this.isProductImageRack = true; - this.productImage = `/servers/${imagePath}.png`; + this.productImage = `/servers/${product}.png`; } else { this.productImage = 'ix-original-cropped.png'; this.isProductImageRack = false; diff --git a/src/app/services/product-image.service.ts b/src/app/services/product-image.service.ts deleted file mode 100644 index 9a757617f0a..00000000000 --- a/src/app/services/product-image.service.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Injectable } from '@angular/core'; - -interface MiniSeries { - pathImg: string; - images: string[]; - isRackmount: boolean; -} - -@Injectable({ providedIn: 'root' }) -export class ProductImageService { - private miniSeries: Record = { - mini: { - pathImg: 'freenas_mini_cropped.png', - images: [ - 'FREENAS-MINI-2.0', - 'FREENAS-MINI-3.0-E', - 'FREENAS-MINI-3.0-E+', - 'TRUENAS-MINI-3.0-E', - 'TRUENAS-MINI-3.0-E+', - ], - isRackmount: false, - }, - miniX: { - pathImg: 'freenas_mini_x_cropped.png', - images: [ - 'FREENAS-MINI-3.0-X', - 'FREENAS-MINI-3.0-X+', - 'TRUENAS-MINI-3.0-X', - 'TRUENAS-MINI-3.0-X+', - ], - isRackmount: false, - }, - miniXL: { - pathImg: 'freenas_mini_xl_cropped.png', - images: [ - 'FREENAS-MINI-XL', - 'FREENAS-MINI-3.0-XL+', - 'TRUENAS-MINI-3.0-XL+', - ], - isRackmount: false, - }, - miniR: { - pathImg: 'servers/MINI-R.png', - images: [ - 'TRUENAS-MINI-R', - ], - isRackmount: true, - }, - }; - private serverSeries = [ - 'H10', - 'M30', - 'M40', - 'M50', - 'M60', - 'X10', - 'X20', - 'Z20', - 'Z30', - 'Z35', - 'Z50', - 'R10', - 'R20', - 'R30', - 'R40', - 'R50', - 'F60', - 'F100', - 'F130', - ]; - - getMiniImagePath(sysProd: string): string { - const product = Object.values(this.miniSeries).find((mini) => mini.images.includes(sysProd)); - if (!product) { - return null; - } - - return product.pathImg; - } - - getServerProduct(sysProd: string): string { - for (const series of this.serverSeries) { - if (sysProd.includes(series)) { - return series; - } - } - return null; - } - - isRackmount(sysProd: string): boolean { - let result = null; - if (sysProd.includes('MINI')) { - result = !!Object.values(this.miniSeries).find((mini) => mini.images.includes(sysProd)).isRackmount; - } else { - result = !!this.serverSeries.find((name: string) => sysProd === name); - } - - return result; - } -} diff --git a/src/app/store/ha-info/ha-info.selectors.ts b/src/app/store/ha-info/ha-info.selectors.ts index eb4476267fa..24537c9bd76 100644 --- a/src/app/store/ha-info/ha-info.selectors.ts +++ b/src/app/store/ha-info/ha-info.selectors.ts @@ -16,6 +16,11 @@ export const selectIsHaLicensed = createSelector( (state) => state.isHaLicensed, ); +export const selectIsHaEnabled = createSelector( + selectHaStatus, + (state) => state.hasHa, +); + export const selectIsUpgradePending = createSelector( selectHaInfoState, (state) => state.isUpgradePending, diff --git a/src/app/store/system-info/system-info.actions.ts b/src/app/store/system-info/system-info.actions.ts index 596b6549e12..a8baec01c78 100644 --- a/src/app/store/system-info/system-info.actions.ts +++ b/src/app/store/system-info/system-info.actions.ts @@ -1,4 +1,5 @@ import { createAction, props } from '@ngrx/store'; +import { ProductType } from 'app/enums/product-type.enum'; import { SystemFeatures } from 'app/interfaces/events/sys-info-event.interface'; import { SystemInfo } from 'app/interfaces/system-info.interface'; @@ -22,6 +23,11 @@ export const systemIsStableLoaded = createAction( props<{ systemIsStable: boolean }>(), ); +export const productTypeLoaded = createAction( + '[System Info API] Product Type Loaded', + props<{ productType: ProductType }>(), +); + export const ixHardwareLoaded = createAction( '[System Info API] System is IxHardware Loaded', props<{ isIxHardware: boolean }>(), diff --git a/src/app/store/system-info/system-info.effects.ts b/src/app/store/system-info/system-info.effects.ts index c6092c7b95f..74f0c397806 100644 --- a/src/app/store/system-info/system-info.effects.ts +++ b/src/app/store/system-info/system-info.effects.ts @@ -9,6 +9,7 @@ import { WebSocketService } from 'app/services/ws.service'; import { adminUiInitialized } from 'app/store/admin-panel/admin.actions'; import { ixHardwareLoaded, + productTypeLoaded, systemFeaturesLoaded, systemHostIdLoaded, systemInfoLoaded, systemInfoUpdated, systemIsStableLoaded, } from 'app/store/system-info/system-info.actions'; @@ -95,6 +96,19 @@ export class SystemInfoEffects { }), )); + loadProductType = createEffect(() => this.actions$.pipe( + ofType(adminUiInitialized), + mergeMap(() => { + return this.ws.call('system.product_type').pipe( + map((productType) => productTypeLoaded({ productType })), + catchError((error) => { + console.error(error); + return of(productTypeLoaded({ productType: null })); + }), + ); + }), + )); + constructor( private actions$: Actions, private ws: WebSocketService, diff --git a/src/app/store/system-info/system-info.reducer.ts b/src/app/store/system-info/system-info.reducer.ts index dcdf8387a17..b2c055c93ec 100644 --- a/src/app/store/system-info/system-info.reducer.ts +++ b/src/app/store/system-info/system-info.reducer.ts @@ -1,8 +1,10 @@ import { createReducer, on } from '@ngrx/store'; +import { ProductType } from 'app/enums/product-type.enum'; import { SystemFeatures } from 'app/interfaces/events/sys-info-event.interface'; import { SystemInfo } from 'app/interfaces/system-info.interface'; import { ixHardwareLoaded, systemFeaturesLoaded, systemHostIdLoaded, systemInfoLoaded, systemIsStableLoaded, + productTypeLoaded, } from 'app/store/system-info/system-info.actions'; export interface SystemInfoState { @@ -10,6 +12,7 @@ export interface SystemInfoState { systemFeatures: SystemFeatures; systemHostId: string; systemIsStable: boolean; + productType: ProductType; isIxHardware: boolean; } @@ -17,6 +20,7 @@ const initialState: SystemInfoState = { systemInfo: null, systemFeatures: null, systemHostId: null, + productType: null, systemIsStable: false, isIxHardware: false, }; @@ -27,5 +31,6 @@ export const systemInfoReducer = createReducer( on(systemFeaturesLoaded, (state, { systemFeatures }) => ({ ...state, systemFeatures })), on(systemHostIdLoaded, (state, { systemHostId }) => ({ ...state, systemHostId })), on(systemIsStableLoaded, (state, { systemIsStable }) => ({ ...state, systemIsStable })), + on(productTypeLoaded, (state, { productType }) => ({ ...state, productType })), on(ixHardwareLoaded, (state, { isIxHardware }) => ({ ...state, isIxHardware })), ); diff --git a/src/app/store/system-info/system-info.selectors.ts b/src/app/store/system-info/system-info.selectors.ts index 8b29ba40eb7..608593e19fc 100644 --- a/src/app/store/system-info/system-info.selectors.ts +++ b/src/app/store/system-info/system-info.selectors.ts @@ -1,4 +1,5 @@ import { createFeatureSelector, createSelector } from '@ngrx/store'; +import { ProductType } from 'app/enums/product-type.enum'; import { selectNotNull } from 'app/helpers/operators/select-not-null.helper'; import { SystemInfoState } from 'app/store/system-info/system-info.reducer'; @@ -16,6 +17,11 @@ export const selectSystemFeatures = createSelector( (state) => state.systemFeatures, ); +export const selectEnclosureSupport = createSelector( + selectSystemFeatures, + (features) => features.enclosure, +); + export const selectSystemHostId = createSelector( selectSystemInfoState, (state) => state.systemHostId, @@ -26,6 +32,16 @@ export const selectIsIxHardware = createSelector( (state) => state.isIxHardware, ); +export const selectProductType = createSelector( + selectSystemInfoState, + (state) => state.productType, +); + +export const selectIsEnterprise = createSelector( + selectProductType, + (productType) => productType === ProductType.ScaleEnterprise, +); + export const waitForSystemInfo = selectNotNull(selectSystemInfo); export const waitForSystemFeatures = selectNotNull(selectSystemFeatures); diff --git a/src/assets/i18n/af.json b/src/assets/i18n/af.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/af.json +++ b/src/assets/i18n/af.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ar.json b/src/assets/i18n/ar.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ar.json +++ b/src/assets/i18n/ar.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ast.json b/src/assets/i18n/ast.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ast.json +++ b/src/assets/i18n/ast.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/az.json b/src/assets/i18n/az.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/az.json +++ b/src/assets/i18n/az.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/be.json b/src/assets/i18n/be.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/be.json +++ b/src/assets/i18n/be.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/bg.json b/src/assets/i18n/bg.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/bg.json +++ b/src/assets/i18n/bg.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/bn.json b/src/assets/i18n/bn.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/bn.json +++ b/src/assets/i18n/bn.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/br.json b/src/assets/i18n/br.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/br.json +++ b/src/assets/i18n/br.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/bs.json b/src/assets/i18n/bs.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/bs.json +++ b/src/assets/i18n/bs.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ca.json b/src/assets/i18n/ca.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ca.json +++ b/src/assets/i18n/ca.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/cs.json b/src/assets/i18n/cs.json index 64d22f4bb54..f879753f4a7 100644 --- a/src/assets/i18n/cs.json +++ b/src/assets/i18n/cs.json @@ -1611,6 +1611,7 @@ "Guide": "", "HA Disabled": "", "HA Enabled": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled.": "", @@ -2237,6 +2238,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3410,6 +3412,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4122,6 +4127,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/cy.json b/src/assets/i18n/cy.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/cy.json +++ b/src/assets/i18n/cy.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/da.json b/src/assets/i18n/da.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/da.json +++ b/src/assets/i18n/da.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 8aab72e6c11..d12b65c8713 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -1291,6 +1291,7 @@ "Groups could not be loaded": "", "Groups that can log in using password": "", "Guide": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is in a faulted state": "", @@ -1855,6 +1856,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Pods Found": "", "No Pools Found": "", "No Propagate Inherit": "", @@ -2785,6 +2787,9 @@ "System Data Pool": "", "System Dataset": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -3374,6 +3379,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/dsb.json b/src/assets/i18n/dsb.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/dsb.json +++ b/src/assets/i18n/dsb.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/el.json b/src/assets/i18n/el.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/el.json +++ b/src/assets/i18n/el.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/en-au.json b/src/assets/i18n/en-au.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/en-au.json +++ b/src/assets/i18n/en-au.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/en-gb.json b/src/assets/i18n/en-gb.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/en-gb.json +++ b/src/assets/i18n/en-gb.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/eo.json b/src/assets/i18n/eo.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/eo.json +++ b/src/assets/i18n/eo.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/es-ar.json b/src/assets/i18n/es-ar.json index 8df40f3fbce..4c19a64d1f8 100644 --- a/src/assets/i18n/es-ar.json +++ b/src/assets/i18n/es-ar.json @@ -689,6 +689,7 @@ "Groups": "", "Groups could not be loaded": "", "Groups that can log in using password": "", + "HA is Disabled": "", "HA is disabled": "", "HA is reconnecting": "", "HEX": "", @@ -1046,6 +1047,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Pods Found": "", "No Pools Found": "", "No Propagate Inherit": "", @@ -1704,6 +1706,9 @@ "System Data Pool": "", "System Dataset": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Widgets": "", @@ -2109,6 +2114,7 @@ "pigz (all rounder)": "", "plzip (best compression)": "", "readonly": "", + "standby": "", "to another TrueNAS": "", "to cloud": "", "vdev": "", diff --git a/src/assets/i18n/es-co.json b/src/assets/i18n/es-co.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/es-co.json +++ b/src/assets/i18n/es-co.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/es-mx.json b/src/assets/i18n/es-mx.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/es-mx.json +++ b/src/assets/i18n/es-mx.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/es-ni.json b/src/assets/i18n/es-ni.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/es-ni.json +++ b/src/assets/i18n/es-ni.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/es-ve.json b/src/assets/i18n/es-ve.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/es-ve.json +++ b/src/assets/i18n/es-ve.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index 6c9f5e2ea36..3c012a1825e 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -1680,6 +1680,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2358,6 +2359,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3614,6 +3616,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4333,6 +4338,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/et.json b/src/assets/i18n/et.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/et.json +++ b/src/assets/i18n/et.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/eu.json b/src/assets/i18n/eu.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/eu.json +++ b/src/assets/i18n/eu.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/fa.json b/src/assets/i18n/fa.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/fa.json +++ b/src/assets/i18n/fa.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/fi.json b/src/assets/i18n/fi.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/fi.json +++ b/src/assets/i18n/fi.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index e170d364a01..9fb3d0a1768 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -138,6 +138,7 @@ "Group Read": "", "Group Write": "", "Groups": "", + "HA is Disabled": "", "HTTP": "", "Has Allow List": "", "Highlighted path is {node}. Press 'Space' to {expand}. Press 'Enter' to {select}.": "", @@ -239,6 +240,7 @@ "New Privilege": "", "New View Enclosure": "", "No Enclosure Dispersal Strategy": "", + "No License": "", "No available licensed Expansion Shelves ": "", "No logs available": "", "No results found in {section}": "", @@ -413,6 +415,9 @@ "System Audit Read": "", "System Audit Write": "", "System Data Pool": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "Table Actions of Expandable Table": "", "Task Details for {task}": "", "Task Settings": "", @@ -469,6 +474,7 @@ "owner@": "", "pCloud": "", "readonly": "", + "standby": "", "to cloud": "", "{catalog} Catalog": "", "{checked} exporter: {name}": "", diff --git a/src/assets/i18n/fy.json b/src/assets/i18n/fy.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/fy.json +++ b/src/assets/i18n/fy.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ga.json b/src/assets/i18n/ga.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ga.json +++ b/src/assets/i18n/ga.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/gd.json b/src/assets/i18n/gd.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/gd.json +++ b/src/assets/i18n/gd.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/gl.json b/src/assets/i18n/gl.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/gl.json +++ b/src/assets/i18n/gl.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/he.json b/src/assets/i18n/he.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/he.json +++ b/src/assets/i18n/he.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/hi.json b/src/assets/i18n/hi.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/hi.json +++ b/src/assets/i18n/hi.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/hr.json b/src/assets/i18n/hr.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/hr.json +++ b/src/assets/i18n/hr.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/hsb.json b/src/assets/i18n/hsb.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/hsb.json +++ b/src/assets/i18n/hsb.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/hu.json b/src/assets/i18n/hu.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/hu.json +++ b/src/assets/i18n/hu.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ia.json b/src/assets/i18n/ia.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ia.json +++ b/src/assets/i18n/ia.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/id.json b/src/assets/i18n/id.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/id.json +++ b/src/assets/i18n/id.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/io.json b/src/assets/i18n/io.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/io.json +++ b/src/assets/i18n/io.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/is.json b/src/assets/i18n/is.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/is.json +++ b/src/assets/i18n/is.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index e74134a4352..ff314c2be4a 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -1605,6 +1605,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2315,6 +2316,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3614,6 +3616,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4370,6 +4375,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ja.json b/src/assets/i18n/ja.json index d6088afe3c2..9bfdeaf0ea2 100644 --- a/src/assets/i18n/ja.json +++ b/src/assets/i18n/ja.json @@ -1512,6 +1512,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2185,6 +2186,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools Found": "", @@ -3336,6 +3338,9 @@ "System Data Pool": "", "System Dataset": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4037,6 +4042,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ka.json b/src/assets/i18n/ka.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ka.json +++ b/src/assets/i18n/ka.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/kk.json b/src/assets/i18n/kk.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/kk.json +++ b/src/assets/i18n/kk.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/km.json b/src/assets/i18n/km.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/km.json +++ b/src/assets/i18n/km.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/kn.json b/src/assets/i18n/kn.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/kn.json +++ b/src/assets/i18n/kn.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index 95706c21621..00a733b0a98 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -1327,6 +1327,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2037,6 +2038,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3336,6 +3338,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4092,6 +4097,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/lb.json b/src/assets/i18n/lb.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/lb.json +++ b/src/assets/i18n/lb.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/lt.json b/src/assets/i18n/lt.json index 7bc0f943334..02e7397a51e 100644 --- a/src/assets/i18n/lt.json +++ b/src/assets/i18n/lt.json @@ -1815,6 +1815,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2525,6 +2526,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3824,6 +3826,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4568,6 +4573,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/lv.json b/src/assets/i18n/lv.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/lv.json +++ b/src/assets/i18n/lv.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/mk.json b/src/assets/i18n/mk.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/mk.json +++ b/src/assets/i18n/mk.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ml.json b/src/assets/i18n/ml.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ml.json +++ b/src/assets/i18n/ml.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/mn.json b/src/assets/i18n/mn.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/mn.json +++ b/src/assets/i18n/mn.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/mr.json b/src/assets/i18n/mr.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/mr.json +++ b/src/assets/i18n/mr.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/my.json b/src/assets/i18n/my.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/my.json +++ b/src/assets/i18n/my.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/nb.json b/src/assets/i18n/nb.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/nb.json +++ b/src/assets/i18n/nb.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ne.json b/src/assets/i18n/ne.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ne.json +++ b/src/assets/i18n/ne.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/nl.json b/src/assets/i18n/nl.json index debfc76ed8e..3e95840ed5d 100644 --- a/src/assets/i18n/nl.json +++ b/src/assets/i18n/nl.json @@ -72,6 +72,7 @@ "Gmail": "", "Go back": "", "Go to Documentation": "", + "HA is Disabled": "", "IP of 1st Redfish management interface.": "", "IPs": "", "IPv4 Datapoint": "", @@ -104,6 +105,7 @@ "New Bucket Name": "", "New Enclosure": "", "New View Enclosure": "", + "No License": "", "No available licensed Expansion Shelves ": "", "No logs available": "", "No results found in {section}": "", @@ -167,6 +169,9 @@ "Source Path": "", "Subfolder": "", "System Data Pool": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "Task Details for {task}": "", "Task Settings": "", "Tasks": "", @@ -194,6 +199,7 @@ "Widgets": "", "Widgets ({n, plural, =1 {# item} other {# items}})": "", "You can search both for local groups as well as groups from Active Directory. Press ENTER to separate entries.": "", + "standby": "", "{comparator} (Range In)": "", "{comparator} (Range Not In)": "", "{coreCount, plural, one {# core} other {# cores} }": "", diff --git a/src/assets/i18n/nn.json b/src/assets/i18n/nn.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/nn.json +++ b/src/assets/i18n/nn.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/os.json b/src/assets/i18n/os.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/os.json +++ b/src/assets/i18n/os.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/pa.json b/src/assets/i18n/pa.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/pa.json +++ b/src/assets/i18n/pa.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/pl.json b/src/assets/i18n/pl.json index f7bad2f0704..5d07ba00ac1 100644 --- a/src/assets/i18n/pl.json +++ b/src/assets/i18n/pl.json @@ -1760,6 +1760,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2467,6 +2468,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3743,6 +3745,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4496,6 +4501,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/pt-br.json b/src/assets/i18n/pt-br.json index 7ef585b04f1..8feed331a96 100644 --- a/src/assets/i18n/pt-br.json +++ b/src/assets/i18n/pt-br.json @@ -1758,6 +1758,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2467,6 +2468,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3766,6 +3768,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4522,6 +4527,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/pt.json b/src/assets/i18n/pt.json index 8a79bef2caf..1b79336ff0b 100644 --- a/src/assets/i18n/pt.json +++ b/src/assets/i18n/pt.json @@ -649,6 +649,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -1078,6 +1079,7 @@ "No Enclosure Dispersal Strategy": "", "No Encryption (less secure, but faster)": "", "No Isolated GPU Device(s) configured": "", + "No License": "", "No Pods Found": "", "No Propagate Inherit": "", "No Safety Check (CAUTION)": "", @@ -1845,6 +1847,9 @@ "System Dataset": "", "System Dataset Pool": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Widgets": "", @@ -2352,6 +2357,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "vdev": "", "zle (runs of zeros)": "", "zstd (default level, 3)": "", diff --git a/src/assets/i18n/ro.json b/src/assets/i18n/ro.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ro.json +++ b/src/assets/i18n/ro.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ru.json b/src/assets/i18n/ru.json index 16951fb0ba2..930d99ed961 100644 --- a/src/assets/i18n/ru.json +++ b/src/assets/i18n/ru.json @@ -907,6 +907,7 @@ "Groupname": "", "Groups could not be loaded": "", "Groups that can log in using password": "", + "HA is Disabled": "", "HA is disabled": "", "HA is reconnecting": "", "HEX": "", @@ -1305,6 +1306,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Pods Found": "", "No Pools Found": "", "No Propagate Inherit": "", @@ -2112,6 +2114,9 @@ "System Data Pool": "", "System Dataset": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -2613,6 +2618,7 @@ "pigz (all rounder)": "", "plzip (best compression)": "", "readonly": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/sk.json b/src/assets/i18n/sk.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/sk.json +++ b/src/assets/i18n/sk.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/sl.json b/src/assets/i18n/sl.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/sl.json +++ b/src/assets/i18n/sl.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/sq.json b/src/assets/i18n/sq.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/sq.json +++ b/src/assets/i18n/sq.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/sr-latn.json b/src/assets/i18n/sr-latn.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/sr-latn.json +++ b/src/assets/i18n/sr-latn.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/sr.json b/src/assets/i18n/sr.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/sr.json +++ b/src/assets/i18n/sr.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/strings.json b/src/assets/i18n/strings.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/strings.json +++ b/src/assets/i18n/strings.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/sv.json b/src/assets/i18n/sv.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/sv.json +++ b/src/assets/i18n/sv.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/sw.json b/src/assets/i18n/sw.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/sw.json +++ b/src/assets/i18n/sw.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/ta.json b/src/assets/i18n/ta.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/ta.json +++ b/src/assets/i18n/ta.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/te.json b/src/assets/i18n/te.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/te.json +++ b/src/assets/i18n/te.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/th.json b/src/assets/i18n/th.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/th.json +++ b/src/assets/i18n/th.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/tr.json b/src/assets/i18n/tr.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/tr.json +++ b/src/assets/i18n/tr.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/tt.json b/src/assets/i18n/tt.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/tt.json +++ b/src/assets/i18n/tt.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/udm.json b/src/assets/i18n/udm.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/udm.json +++ b/src/assets/i18n/udm.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/uk.json b/src/assets/i18n/uk.json index bc1eb21aafb..22955a98129 100644 --- a/src/assets/i18n/uk.json +++ b/src/assets/i18n/uk.json @@ -345,6 +345,7 @@ "Groupname": "", "Groups": "", "Groups that can log in using password": "", + "HA is Disabled": "", "HA is disabled": "", "HA is reconnecting": "", "HTTP": "", @@ -499,6 +500,7 @@ "New Privilege": "", "New View Enclosure": "", "No Enclosure Dispersal Strategy": "", + "No License": "", "No VDEVs added.": "", "No available licensed Expansion Shelves ": "", "No disks available.": "", @@ -777,6 +779,9 @@ "System Audit Read": "", "System Audit Write": "", "System Data Pool": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "Table Actions of Expandable Table": "", @@ -914,6 +919,7 @@ "of": "", "pCloud": "", "readonly": "", + "standby": "", "to another TrueNAS": "", "to cloud": "", "{catalog} Catalog": "", diff --git a/src/assets/i18n/vi.json b/src/assets/i18n/vi.json index dcbd3270520..a82f46d09a2 100644 --- a/src/assets/i18n/vi.json +++ b/src/assets/i18n/vi.json @@ -1821,6 +1821,7 @@ "HA Disabled": "", "HA Enabled": "", "HA Status": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is enabled": "", @@ -2531,6 +2532,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3830,6 +3832,9 @@ "System Dataset Pool": "", "System Information": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -4586,6 +4591,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "threads": "", "to another TrueNAS": "", "to cloud": "", diff --git a/src/assets/i18n/zh-hans.json b/src/assets/i18n/zh-hans.json index f223e7b84cf..a86cfea99bd 100644 --- a/src/assets/i18n/zh-hans.json +++ b/src/assets/i18n/zh-hans.json @@ -90,6 +90,7 @@ "Gmail": "", "Go back": "", "Go to Documentation": "", + "HA is Disabled": "", "Helm Chart Info": "", "Highlighted path is {node}. Press 'Space' to {expand}. Press 'Enter' to {select}.": "", "Host Mounts": "", @@ -145,6 +146,7 @@ "New Enclosure": "", "New View Enclosure": "", "No Enclosure Dispersal Strategy": "", + "No License": "", "No available licensed Expansion Shelves ": "", "No enclosure": "", "No logs available": "", @@ -233,6 +235,9 @@ "Subfolder": "", "Subject Alternative Name": "", "System Data Pool": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "Table Actions of Expandable Table": "", "Task Details for {task}": "", "Task Settings": "", @@ -270,6 +275,7 @@ "Widgets ({n, plural, =1 {# item} other {# items}})": "", "You can search both for local groups as well as groups from Active Directory. Press ENTER to separate entries.": "", "of": "", + "standby": "", "{checked} exporter: {name}": "", "{comparator} (Contains)": "", "{comparator} (Ends With)": "", diff --git a/src/assets/i18n/zh-hant.json b/src/assets/i18n/zh-hant.json index 816cb4d4b4c..8bebb487c3e 100644 --- a/src/assets/i18n/zh-hant.json +++ b/src/assets/i18n/zh-hant.json @@ -1417,6 +1417,7 @@ "Groups": "", "Groups could not be loaded": "", "Groups that can log in using password": "", + "HA is Disabled": "", "HA is administratively disabled.": "", "HA is disabled": "", "HA is in a faulted state": "", @@ -1985,6 +1986,7 @@ "No Inherit": "", "No Isolated GPU Device(s) configured": "", "No Item": "", + "No License": "", "No Logs": "", "No Pods Found": "", "No Pools": "", @@ -3059,6 +3061,9 @@ "System Audit Write": "", "System Data Pool": "", "System Information (Standby)": "", + "System Information Active Node": "", + "System Information Standby Node": "", + "System Reports": "", "System Security": "", "System Security Settings Updated.": "", "System Serial": "", @@ -3695,6 +3700,7 @@ "readonly": "", "rpc.lockd(8) bind port": "", "rpc.statd(8) bind port": "", + "standby": "", "to another TrueNAS": "", "to cloud": "", "vdev": "", diff --git a/tsconfig.strictNullChecks.json b/tsconfig.strictNullChecks.json index 850e54347c6..579502f6395 100644 --- a/tsconfig.strictNullChecks.json +++ b/tsconfig.strictNullChecks.json @@ -22,6 +22,7 @@ "./src/app/constants/catalog.constants.ts", "./src/app/constants/dataset.constants.ts", "./src/app/constants/name-patterns.constant.ts", + "./src/app/constants/name-validator.constant.ts", "./src/app/constants/toggle-menu-duration.ts", "./src/app/constants/truenas-db-key-location.constant.ts", "./src/app/core/classes/icu-translations-loader.ts", @@ -35,8 +36,6 @@ "./src/app/core/pipes/clean-link.pipe.ts", "./src/app/core/pipes/schedule-to-crontab.pipe.spec.ts", "./src/app/core/pipes/schedule-to-crontab.pipe.ts", - "./src/app/core/pipes/uptime.pipe.spec.ts", - "./src/app/core/pipes/uptime.pipe.ts", "./src/app/core/pipes/yes-no.pipe.spec.ts", "./src/app/core/pipes/yes-no.pipe.ts", "./src/app/core/testing/classes/fake-translate.service.ts", @@ -54,8 +53,8 @@ "./src/app/core/testing/utils/enclosure-templates/mock-m40.ts", "./src/app/core/testing/utils/enclosure-templates/mock-m60.ts", "./src/app/core/testing/utils/enclosure-templates/mock-mini-3.0-e+.ts", - "./src/app/core/testing/utils/enclosure-templates/mock-mini-3.0-x+.ts", "./src/app/core/testing/utils/enclosure-templates/mock-mini-3.0-x.ts", + "./src/app/core/testing/utils/enclosure-templates/mock-mini-3.0-x+.ts", "./src/app/core/testing/utils/enclosure-templates/mock-mini-3.0-xl+.ts", "./src/app/core/testing/utils/enclosure-templates/mock-mini-r.ts", "./src/app/core/testing/utils/enclosure-templates/mock-r10.ts", @@ -452,6 +451,7 @@ "./src/app/modules/dialog/components/redirect-dialog/redirect-dialog.component.spec.ts", "./src/app/modules/dialog/components/redirect-dialog/redirect-dialog.component.ts", "./src/app/modules/dialog/components/session-expiring-dialog/session-expiring-dialog.component.ts", + "./src/app/modules/empty/empty.service.ts", "./src/app/modules/entity/entity-job/entity-job-config.interface.ts", "./src/app/modules/entity/entity-toolbar/components/toolbar-slider/toolbar-slider.component.ts", "./src/app/modules/feedback/interfaces/feedback.interface.ts", @@ -527,10 +527,10 @@ "./src/app/modules/ix-table/components/ix-table-body/cells/ix-cell-text/ix-cell-text.component.ts", "./src/app/modules/ix-table/components/ix-table-body/cells/ix-cell-toggle/ix-cell-toggle.component.ts", "./src/app/modules/ix-table/components/ix-table-body/cells/ix-cell-yes-no/ix-cell-yes-no.component.ts", + "./src/app/modules/ix-table/components/ix-table-expandable-row/ix-table-expandable-row.component.ts", "./src/app/modules/ix-table/components/ix-table-head/head-cells/ix-header-cell-text/ix-header-cell-text.component.ts", "./src/app/modules/ix-table/components/ix-table-pager-show-more/ix-table-pager-show-more.component.ts", "./src/app/modules/ix-table/components/ix-table-pager/ix-table-pager.component.ts", - "./src/app/modules/ix-table/components/ix-table-expandable-row/ix-table-expandable-row.component.ts", "./src/app/modules/ix-table/components/ix-table/cell.harness.ts", "./src/app/modules/ix-table/components/ix-table/ix-table.component.ts", "./src/app/modules/ix-table/components/ix-table/ix-table.harness.ts", @@ -545,7 +545,6 @@ "./src/app/modules/ix-table/interfaces/table-pagination.interface.ts", "./src/app/modules/ix-table/interfaces/table-sort.interface.ts", "./src/app/modules/ix-table/utils.ts", - "./src/app/modules/empty/empty.service.ts", "./src/app/modules/ix-tree/components/tree-node/tree-node.component.ts", "./src/app/modules/ix-tree/components/tree-view/tree-view.component.ts", "./src/app/modules/ix-tree/components/tree-virtual-scroll-view/tree-virtual-scroll-view.component.ts", @@ -636,6 +635,8 @@ "./src/app/pages/dashboard-old/components/widget/widget.component.ts", "./src/app/pages/dashboard-old/interfaces/widget-data.interface.ts", "./src/app/pages/dashboard-old/utils/deep-clone-state.helper.ts", + "./src/app/pages/dashboard/widgets/system/common/uptime.pipe.spec.ts", + "./src/app/pages/dashboard/widgets/system/common/uptime.pipe.ts", "./src/app/pages/data-protection/cloudsync/cloudsync-provider-description/cloudsync-provider-description.ts", "./src/app/pages/data-protection/cloudsync/transfer-mode-explanation/transfer-mode-explanation.component.ts", "./src/app/pages/data-protection/data-protection-dashboard.component.ts", @@ -749,7 +750,6 @@ "./src/app/pages/vm/utils/vm-form-patterns.constant.ts", "./src/app/pages/vm/vm-serial-shell/vm-serial-shell.component.ts", "./src/app/services/calendar.service.ts", - "./src/app/constants/name-validator.constant.ts", "./src/app/services/route-parts/route-parts.service.ts", "./src/app/services/shell.service.ts", "./src/app/services/theme/theme.constants.ts",