From b33cf329b5422466210d5f826f4c9d88c0cc4a83 Mon Sep 17 00:00:00 2001 From: undsoft Date: Wed, 25 Dec 2024 16:29:29 -0500 Subject: [PATCH 1/2] NAS-133262: Fix more strict null issues --- .../reboot-required-dialog.component.spec.ts | 2 +- .../ix-date-picker.component.spec.ts | 4 +- .../slide-in/slide-in.component.spec.ts | 6 +-- .../slide-ins/old-slide-in.component.spec.ts | 4 +- src/app/pages/audit/audit.component.ts | 20 ++++------ .../cloud-credentials-card.elements.ts | 2 +- .../cloud-credentials-form.component.spec.ts | 12 +++--- ...ertificate-authority-add.component.spec.ts | 8 ++-- .../certificate-details.component.spec.ts | 4 +- .../csr-add/csr-add.component.spec.ts | 8 ++-- .../steps/csr-import/csr-import.component.ts | 4 +- .../acmedns-form.component.spec.ts | 2 +- .../delete-group-dialog.component.ts | 2 +- .../group-details-row.component.spec.ts | 2 +- .../group-form/group-form.component.spec.ts | 2 +- .../groups/group-list/group-list.component.ts | 2 +- .../privilege-form.component.ts | 2 +- .../privilege-list.component.ts | 6 +-- .../user-details-row.component.spec.ts | 6 +-- .../users/user-list/user-list.component.ts | 2 +- .../widget-group-controls.component.spec.ts | 8 ++-- .../widget-group-form.component.spec.ts | 10 ++--- .../backup-task-actions.component.spec.ts | 4 +- .../backup-task-empty.component.spec.ts | 6 +-- .../widget-datapoint.component.ts | 2 +- .../cpu-core-bar.component.spec.ts | 2 +- .../widget-cpu-model.component.spec.ts | 2 +- .../widget-cpu-usage-recent.component.spec.ts | 2 +- .../widget-arbitrary-text.component.spec.ts | 2 +- .../widget-memory.component.spec.ts | 2 +- .../network-chart.component.spec.ts | 2 +- .../widget-interface-ip.component.spec.ts | 12 +++--- .../widget-interface.utils.spec.ts | 2 +- ...ol-disks-with-zfs-errors.component.spec.ts | 2 +- ...et-pool-last-scan-errors.component.spec.ts | 2 +- .../widget-pool-status.component.spec.ts | 2 +- .../widget-pool-usage-gauge.component.spec.ts | 2 +- .../disks-with-zfs-errors.component.spec.ts | 2 +- .../pool-status/pool-status.component.spec.ts | 2 +- .../pool-usage-gauge.component.spec.ts | 10 ++--- .../widget-storage.component.spec.ts | 2 +- .../widget-hostname-passive.component.spec.ts | 2 +- .../widget-serial-active.component.spec.ts | 2 +- .../widget-serial-passive.component.spec.ts | 2 +- .../widget-system-uptime.component.spec.ts | 2 +- ...capacity-management-card.component.spec.ts | 8 ++-- .../dataset-details-card.component.spec.ts | 6 +-- .../dataset-details-panel.component.spec.ts | 10 ++--- .../encryption-section.component.ts | 2 +- ...name-and-options-section.component.spec.ts | 6 +-- .../other-options-section.component.ts | 39 ++++++++++--------- .../dataset-management.component.spec.ts | 6 +-- .../dataset-node.component.spec.ts | 6 +-- .../delete-dataset-dialog.component.spec.ts | 6 +-- ...ncryption-options-dialog.component.spec.ts | 4 +- .../zfs-encryption-card.component.spec.ts | 4 +- .../permissions-item.component.spec.ts | 2 +- .../save-as-preset-modal.component.spec.ts | 4 +- .../view-nfs-permissions.component.spec.ts | 16 ++++---- .../view-nfs-permissions.component.ts | 10 +++-- .../acl-editor-save-controls.component.ts | 2 +- .../dataset-acl-editor.component.spec.ts | 2 +- .../permissions-card.component.spec.ts | 10 ++--- .../permissions-sidebar-state.interface.ts | 4 +- .../utils/nfs-ace-to-permission-item.utils.ts | 8 ++-- .../snapshot-add-form.component.ts | 4 +- src/app/pages/jobs/jobs-list.component.ts | 2 +- .../configuration.component.spec.ts | 8 ++-- .../interface-form.component.spec.ts | 6 +-- .../interface-name-validator.service.ts | 4 +- .../ip-addresses-cell.component.spec.ts | 8 ++-- src/app/pages/network/network.component.ts | 10 ++--- .../add-spn-dialog.component.ts | 7 ++-- src/app/pages/services/services.component.ts | 2 +- .../all-targets/all-targets.component.ts | 2 +- .../connections-card.component.ts | 2 +- .../target-details.component.spec.ts | 2 +- .../target-details.component.ts | 2 +- .../delete-target-dialog.component.ts | 2 +- .../failover-status.component.ts | 16 ++++---- .../set-admin-password-form.component.ts | 4 +- src/app/pages/signin/signin.component.spec.ts | 2 +- .../dashboard-pool.component.spec.ts | 4 +- .../disk-health-card.component.spec.ts | 10 ++--- .../export-disconnect-modal.component.ts | 8 ++-- .../pool-card-icon.component.spec.ts | 8 ++-- .../pool-usage-card.component.spec.ts | 22 +++++------ .../topology-card.component.spec.ts | 2 +- .../zfs-health-card.component.spec.ts | 34 ++++++++-------- .../import-pool/import-pool.component.ts | 4 +- .../modules/devices/devices.component.ts | 2 +- .../test-progress-row.component.spec.ts | 10 ++--- .../access-form/access-form.component.ts | 9 +++-- .../allowed-addresses-form.component.ts | 2 +- .../init-shutdown-card.component.spec.ts | 3 +- .../init-shutdown-list.component.spec.ts | 2 +- .../init-shutdown-list.component.ts | 4 +- .../isolated-gpus-form.component.ts | 1 + .../alert-service-list.component.ts | 4 +- .../snmp-trap-service.component.ts | 2 +- .../alert-settings2.component.ts | 2 +- .../enclosure-side.component.spec.ts | 6 +-- .../enclosure-side.component.ts | 2 +- .../enclosure-svg/enclosure-svg.component.ts | 2 +- .../disk-details-overview.component.spec.ts | 4 +- .../enclosure-selector.component.spec.ts | 4 +- ...isk-topology-description.component.spec.ts | 4 +- .../pools-view/pools-view.component.spec.ts | 2 +- .../pools-view/pools-view.component.ts | 2 +- .../statuses-legend.component.ts | 2 +- .../mini-drive-temperatures.component.spec.ts | 4 +- .../mini-page/mini-page.component.spec.ts | 4 +- .../set-enclosure-label-dialog.component.ts | 2 +- .../enclosure/services/enclosure.store.ts | 2 +- .../utils/get-item-value-factory.utils.ts | 2 +- .../support/license/license.component.ts | 4 +- .../instance-disks.component.spec.ts | 2 +- .../instance-edit-form.component.spec.ts | 2 +- .../instance-edit-form.component.ts | 2 +- .../instance-general-info.component.spec.ts | 2 +- ...stance-metrics-linechart.component.spec.ts | 4 +- .../instance-list-bulk-actions.component.ts | 2 +- .../utils/get-device-description.utils.ts | 4 +- .../select-image-dialog.component.spec.ts | 4 +- .../stores/virtualization-config.store.ts | 8 ++-- .../stores/virtualization-devices.store.ts | 2 +- .../stores/virtualization-instances.store.ts | 4 +- src/assets/i18n/af.json | 3 +- src/assets/i18n/ar.json | 3 +- src/assets/i18n/ast.json | 3 +- src/assets/i18n/az.json | 3 +- src/assets/i18n/be.json | 3 +- src/assets/i18n/bg.json | 3 +- src/assets/i18n/bn.json | 3 +- src/assets/i18n/br.json | 3 +- src/assets/i18n/bs.json | 3 +- src/assets/i18n/ca.json | 3 +- src/assets/i18n/cs.json | 3 +- src/assets/i18n/cy.json | 3 +- src/assets/i18n/da.json | 3 +- src/assets/i18n/de.json | 3 +- src/assets/i18n/dsb.json | 3 +- src/assets/i18n/el.json | 3 +- src/assets/i18n/en-au.json | 3 +- src/assets/i18n/en-gb.json | 3 +- src/assets/i18n/en.json | 3 +- src/assets/i18n/eo.json | 3 +- src/assets/i18n/es-ar.json | 3 +- src/assets/i18n/es-co.json | 3 +- src/assets/i18n/es-mx.json | 3 +- src/assets/i18n/es-ni.json | 3 +- src/assets/i18n/es-ve.json | 3 +- src/assets/i18n/es.json | 3 +- src/assets/i18n/et.json | 3 +- src/assets/i18n/eu.json | 3 +- src/assets/i18n/fa.json | 3 +- src/assets/i18n/fi.json | 3 +- src/assets/i18n/fr.json | 3 +- src/assets/i18n/fy.json | 3 +- src/assets/i18n/ga.json | 3 +- src/assets/i18n/gd.json | 3 +- src/assets/i18n/gl.json | 3 +- src/assets/i18n/he.json | 3 +- src/assets/i18n/hi.json | 3 +- src/assets/i18n/hr.json | 3 +- src/assets/i18n/hsb.json | 3 +- src/assets/i18n/hu.json | 3 +- src/assets/i18n/ia.json | 3 +- src/assets/i18n/id.json | 3 +- src/assets/i18n/io.json | 3 +- src/assets/i18n/is.json | 3 +- src/assets/i18n/it.json | 3 +- src/assets/i18n/ja.json | 3 +- src/assets/i18n/ka.json | 3 +- src/assets/i18n/kk.json | 3 +- src/assets/i18n/km.json | 3 +- src/assets/i18n/kn.json | 3 +- src/assets/i18n/ko.json | 3 +- src/assets/i18n/lb.json | 3 +- src/assets/i18n/lt.json | 3 +- src/assets/i18n/lv.json | 3 +- src/assets/i18n/mk.json | 3 +- src/assets/i18n/ml.json | 3 +- src/assets/i18n/mn.json | 3 +- src/assets/i18n/mr.json | 3 +- src/assets/i18n/my.json | 3 +- src/assets/i18n/nb.json | 3 +- src/assets/i18n/ne.json | 3 +- src/assets/i18n/nl.json | 3 +- src/assets/i18n/nn.json | 3 +- src/assets/i18n/os.json | 3 +- src/assets/i18n/pa.json | 3 +- src/assets/i18n/pl.json | 3 +- src/assets/i18n/pt-br.json | 3 +- src/assets/i18n/pt.json | 3 +- src/assets/i18n/ro.json | 3 +- src/assets/i18n/ru.json | 3 +- src/assets/i18n/sk.json | 3 +- src/assets/i18n/sl.json | 3 +- src/assets/i18n/sq.json | 3 +- src/assets/i18n/sr-latn.json | 3 +- src/assets/i18n/sr.json | 3 +- src/assets/i18n/strings.json | 3 +- src/assets/i18n/sv.json | 3 +- src/assets/i18n/sw.json | 3 +- src/assets/i18n/ta.json | 3 +- src/assets/i18n/te.json | 3 +- src/assets/i18n/th.json | 3 +- src/assets/i18n/tr.json | 3 +- src/assets/i18n/tt.json | 3 +- src/assets/i18n/udm.json | 3 +- src/assets/i18n/uk.json | 3 +- src/assets/i18n/vi.json | 3 +- src/assets/i18n/zh-hans.json | 3 +- src/assets/i18n/zh-hant.json | 3 +- src/assets/ui-searchable-elements.json | 2 +- 216 files changed, 500 insertions(+), 407 deletions(-) diff --git a/src/app/modules/dialog/components/reboot-required-dialog/reboot-required-dialog.component.spec.ts b/src/app/modules/dialog/components/reboot-required-dialog/reboot-required-dialog.component.spec.ts index 6720752c9f4..d5c0e85a475 100644 --- a/src/app/modules/dialog/components/reboot-required-dialog/reboot-required-dialog.component.spec.ts +++ b/src/app/modules/dialog/components/reboot-required-dialog/reboot-required-dialog.component.spec.ts @@ -49,7 +49,7 @@ describe('RebootRequiredDialogComponent', () => { it('shows reasons', () => { expect( - spectator.queryAll('.reasons li').map((item) => item.textContent.trim()), + spectator.queryAll('.reasons li').map((item) => item.textContent!.trim()), ).toEqual([ 'Test Reason 1', 'Test Reason 2', diff --git a/src/app/modules/forms/ix-forms/components/ix-date-picker/ix-date-picker.component.spec.ts b/src/app/modules/forms/ix-forms/components/ix-date-picker/ix-date-picker.component.spec.ts index aa021dc2ac7..e713cc8acf6 100644 --- a/src/app/modules/forms/ix-forms/components/ix-date-picker/ix-date-picker.component.spec.ts +++ b/src/app/modules/forms/ix-forms/components/ix-date-picker/ix-date-picker.component.spec.ts @@ -15,7 +15,7 @@ import { IxDatepickerComponent } from './ix-date-picker.component'; describe('IxDatePickerComponent', () => { let spectator: SpectatorHost; let loader: HarnessLoader; - const formControl = new FormControl(null); + const formControl = new FormControl(null); const createHost = createHostFactory({ component: IxDatepickerComponent, @@ -57,7 +57,7 @@ describe('IxDatePickerComponent', () => { }, }); - const label = spectator.query(IxLabelComponent); + const label = spectator.query(IxLabelComponent)!; expect(label).toExist(); expect(label.label()).toBe('Label'); expect(label.tooltip()).toBe('Tooltip'); diff --git a/src/app/modules/slide-ins/components/slide-in/slide-in.component.spec.ts b/src/app/modules/slide-ins/components/slide-in/slide-in.component.spec.ts index 8ed907decf7..e57f06f43ec 100644 --- a/src/app/modules/slide-ins/components/slide-in/slide-in.component.spec.ts +++ b/src/app/modules/slide-ins/components/slide-in/slide-in.component.spec.ts @@ -187,7 +187,7 @@ describe('IxSlideIn2Component', () => { it('close slide-in when backdrop is clicked', fakeAsync(() => { setupComponent(); - const backdrop = spectator.query('.ix-slide-in2-background'); + const backdrop = spectator.query('.ix-slide-in2-background')!; backdrop.dispatchEvent(new Event('click')); spectator.detectChanges(); expect(close$.next).toHaveBeenCalledWith({ response: false, error: null }); @@ -205,7 +205,7 @@ describe('IxSlideIn2Component', () => { it('asks for confirmation when require confirmation method setup', fakeAsync(() => { setupComponent(); - const form = spectator.query(CloudSyncFormComponent); + const form = spectator.query(CloudSyncFormComponent)!; form.form.markAsDirty(); spectator.detectChanges(); const backdrop = spectator.query('.ix-slide-in2-background'); @@ -234,7 +234,7 @@ describe('IxSlideIn2Component', () => { await saveButton.click(); form.form.markAsDirty(); spectator.detectChanges(); - const backdrop = spectator.query('.ix-slide-in2-background'); + const backdrop = spectator.query('.ix-slide-in2-background')!; backdrop.dispatchEvent(new Event('click')); expect(spectator.inject(DialogService).confirm).not.toHaveBeenCalledWith({ diff --git a/src/app/modules/slide-ins/old-slide-in.component.spec.ts b/src/app/modules/slide-ins/old-slide-in.component.spec.ts index ac5d788e2bd..60fa3d13eb5 100644 --- a/src/app/modules/slide-ins/old-slide-in.component.spec.ts +++ b/src/app/modules/slide-ins/old-slide-in.component.spec.ts @@ -48,7 +48,7 @@ describe('SlideInComponent', () => { it('call \'openSlideIn\' should create a host element in the body of the slide', () => { spectator.component.openSlideIn(TestClassComponent, { wide: true, data: 'Component created dynamically' }); - const dynamicElement: HTMLElement = (spectator.debugElement.nativeElement as Element).querySelector('h1'); + const dynamicElement = (spectator.debugElement.nativeElement as Element).querySelector('h1'); spectator.fixture.detectChanges(); expect(dynamicElement).toHaveText('Component created dynamically'); @@ -62,7 +62,7 @@ describe('SlideInComponent', () => { spectator.component.closeSlideIn(); spectator.tick(200); - const dynamicElement: HTMLElement = (spectator.debugElement.nativeElement as Element).querySelector('.ix-slide-in-body'); + const dynamicElement = (spectator.debugElement.nativeElement as Element).querySelector('.ix-slide-in-body'); expect(dynamicElement).toBeEmpty(); })); }); diff --git a/src/app/pages/audit/audit.component.ts b/src/app/pages/audit/audit.component.ts index 99484411e89..0daec9151be 100644 --- a/src/app/pages/audit/audit.component.ts +++ b/src/app/pages/audit/audit.component.ts @@ -126,9 +126,7 @@ export class AuditComponent implements OnInit, OnDestroy { textColumn({ title: this.translate.instant('Service'), propertyName: 'service', - getValue: (row) => (auditServiceLabels.has(row.service) - ? this.translate.instant(auditServiceLabels.get(row.service)) - : row.service || '-'), + getValue: (row) => this.translate.instant(auditServiceLabels.get(row.service) || row.service || '-'), }), textColumn({ title: this.translate.instant('User'), @@ -142,9 +140,7 @@ export class AuditComponent implements OnInit, OnDestroy { textColumn({ title: this.translate.instant('Event'), propertyName: 'event', - getValue: (row) => (auditEventLabels.has(row.event) - ? this.translate.instant(auditEventLabels.get(row.event)) - : row.event || '-'), + getValue: (row) => this.translate.instant(auditEventLabels.get(row.event) || row.event || '-'), }), textColumn({ title: this.translate.instant('Event Data'), @@ -334,8 +330,8 @@ export class AuditComponent implements OnInit, OnDestroy { 'service', this.translate.instant('Service'), of(Object.values(AuditService).map((key) => ({ - label: this.translate.instant(auditServiceLabels.get(key)), - value: `"${this.translate.instant(auditServiceLabels.get(key))}"`, + label: this.translate.instant(auditServiceLabels.get(key) || key), + value: `"${this.translate.instant(auditServiceLabels.get(key) || key)}"`, }))), auditServiceLabels, ), @@ -348,8 +344,8 @@ export class AuditComponent implements OnInit, OnDestroy { 'event', this.translate.instant('Event'), of(Object.values(AuditEvent).map((key) => ({ - label: this.translate.instant(auditEventLabels.get(key)), - value: `"${this.translate.instant(auditEventLabels.get(key))}"`, + label: this.translate.instant(auditEventLabels.get(key) || key), + value: `"${this.translate.instant(auditEventLabels.get(key) || key)}"`, }))), auditEventLabels, ), @@ -388,8 +384,8 @@ export class AuditComponent implements OnInit, OnDestroy { 'event_data.credentials.credentials', this.translate.instant('Middleware - Credentials'), of(Object.values(CredentialType).map((key) => ({ - label: this.translate.instant(credentialTypeLabels.get(key)), - value: `"${this.translate.instant(credentialTypeLabels.get(key))}"`, + label: this.translate.instant(credentialTypeLabels.get(key) || key), + value: `"${this.translate.instant(credentialTypeLabels.get(key) || key)}"`, }))), credentialTypeLabels, ), diff --git a/src/app/pages/credentials/backup-credentials/cloud-credentials-card/cloud-credentials-card.elements.ts b/src/app/pages/credentials/backup-credentials/cloud-credentials-card/cloud-credentials-card.elements.ts index 6dcee149c1b..ff89ddf824b 100644 --- a/src/app/pages/credentials/backup-credentials/cloud-credentials-card/cloud-credentials-card.elements.ts +++ b/src/app/pages/credentials/backup-credentials/cloud-credentials-card/cloud-credentials-card.elements.ts @@ -14,7 +14,7 @@ export const cloudCredentialsCardElements = { T('Add Credential'), T('Add Backup Credential'), T('New Credential'), - T('New Could Credential'), + T('New Cloud Credential'), T('New Backup Credential'), T('Create Credential'), T('Create Cloud Credential'), diff --git a/src/app/pages/credentials/backup-credentials/cloud-credentials-form/cloud-credentials-form.component.spec.ts b/src/app/pages/credentials/backup-credentials/cloud-credentials-form/cloud-credentials-form.component.spec.ts index bb4227163a6..88c664f1bc6 100644 --- a/src/app/pages/credentials/backup-credentials/cloud-credentials-form/cloud-credentials-form.component.spec.ts +++ b/src/app/pages/credentials/backup-credentials/cloud-credentials-form/cloud-credentials-form.component.spec.ts @@ -135,7 +135,7 @@ describe('CloudCredentialsFormComponent', () => { const providersSelect = await form.getControl('Provider') as IxSelectHarness; await providersSelect.setValue('Amazon S3'); - const providerForm = spectator.query(S3ProviderFormComponent); + const providerForm = spectator.query(S3ProviderFormComponent)!; expect(providerForm).toBeTruthy(); expect(providerForm.provider).toBe(s3Provider); }); @@ -144,7 +144,7 @@ describe('CloudCredentialsFormComponent', () => { const providersSelect = await form.getControl('Provider') as IxSelectHarness; await providersSelect.setValue('Storj iX'); - const providerForm = spectator.query(StorjProviderFormComponent); + const providerForm = spectator.query(StorjProviderFormComponent)!; expect(providerForm).toBeTruthy(); expect(providerForm.provider).toBe(storjProvider); expect(spectator.query(CloudSyncProviderDescriptionComponent)).toBeTruthy(); @@ -154,7 +154,7 @@ describe('CloudCredentialsFormComponent', () => { const providersSelect = await form.getControl('Provider') as IxSelectHarness; await providersSelect.setValue('Box'); - const providerForm = spectator.query(TokenProviderFormComponent); + const providerForm = spectator.query(TokenProviderFormComponent)!; expect(providerForm).toBeTruthy(); expect(providerForm.provider).toBe(boxProvider); }); @@ -184,7 +184,7 @@ describe('CloudCredentialsFormComponent', () => { const saveButton = await loader.getHarness(MatButtonHarness.with({ text: 'Verify Credential' })); await saveButton.click(); - const providerForm = spectator.query(S3ProviderFormComponent); + const providerForm = spectator.query(S3ProviderFormComponent)!; expect(providerForm.beforeSubmit).toHaveBeenCalled(); }); @@ -222,7 +222,7 @@ describe('CloudCredentialsFormComponent', () => { const saveButton = await loader.getHarness(MatButtonHarness.with({ text: 'Save' })); await saveButton.click(); - const providerForm = spectator.query(S3ProviderFormComponent); + const providerForm = spectator.query(S3ProviderFormComponent)!; expect(providerForm.beforeSubmit).toHaveBeenCalled(); }); @@ -299,7 +299,7 @@ describe('CloudCredentialsFormComponent', () => { Provider: 'Amazon S3', }); - const providerForm = spectator.query(S3ProviderFormComponent); + const providerForm = spectator.query(S3ProviderFormComponent)!; expect(providerForm).toBeTruthy(); expect(providerForm.getFormSetter$().next).toHaveBeenCalledWith({ type: CloudSyncProviderName.AmazonS3, diff --git a/src/app/pages/credentials/certificates-dash/certificate-authority-add/certificate-authority-add.component.spec.ts b/src/app/pages/credentials/certificates-dash/certificate-authority-add/certificate-authority-add.component.spec.ts index 3474a79eb0c..c299ad0e6ce 100644 --- a/src/app/pages/credentials/certificates-dash/certificate-authority-add/certificate-authority-add.component.spec.ts +++ b/src/app/pages/credentials/certificates-dash/certificate-authority-add/certificate-authority-add.component.spec.ts @@ -258,7 +258,7 @@ describe('CertificateAuthorityAddComponent', () => { await goToNextStep(); await goToNextStep(); - const summary = spectator.query(SummaryComponent); + const summary = spectator.query(SummaryComponent)!; expect(summary.summary).toEqual([ [ { label: 'Name', value: 'new' }, @@ -286,13 +286,13 @@ describe('CertificateAuthorityAddComponent', () => { }); it('updates form fields and sets constrains when Profile is emitted by CertificateIdentifierAndTypeComponent', async () => { - const optionsForm = spectator.query(CertificateOptionsComponent); - const subjectForm = spectator.query(CertificateSubjectComponent); + const optionsForm = spectator.query(CertificateOptionsComponent)!; + const subjectForm = spectator.query(CertificateSubjectComponent)!; jest.spyOn(optionsForm.form, 'patchValue'); jest.spyOn(subjectForm.form, 'patchValue'); - const constraintsForm = spectator.query(CertificateConstraintsComponent); + const constraintsForm = spectator.query(CertificateConstraintsComponent)!; jest.spyOn(constraintsForm, 'setFromProfile'); await form.fillForm({ diff --git a/src/app/pages/credentials/certificates-dash/certificate-details/certificate-details.component.spec.ts b/src/app/pages/credentials/certificates-dash/certificate-details/certificate-details.component.spec.ts index 1fcec7740a5..c6c835986af 100644 --- a/src/app/pages/credentials/certificates-dash/certificate-details/certificate-details.component.spec.ts +++ b/src/app/pages/credentials/certificates-dash/certificate-details/certificate-details.component.spec.ts @@ -47,8 +47,8 @@ describe('CertificateDetailsComponent', () => { function getDetails(): Record { const itemElements = spectator.queryAll('dl > div'); return itemElements.reduce((acc, item) => { - const key = item.querySelector('dt')!.textContent; - const value = item.querySelector('dd')!.textContent; + const key = item.querySelector('dt')!.textContent!; + const value = item.querySelector('dd')!.textContent!; acc[key] = value; return acc; }, {} as Record); diff --git a/src/app/pages/credentials/certificates-dash/csr-add/csr-add.component.spec.ts b/src/app/pages/credentials/certificates-dash/csr-add/csr-add.component.spec.ts index 1224c1fd284..bb1173d2437 100644 --- a/src/app/pages/credentials/certificates-dash/csr-add/csr-add.component.spec.ts +++ b/src/app/pages/credentials/certificates-dash/csr-add/csr-add.component.spec.ts @@ -237,7 +237,7 @@ describe('CsrAddComponent', () => { await nextButton.click(); - const summary = spectator.query(SummaryComponent); + const summary = spectator.query(SummaryComponent)!; expect(summary.summary).toEqual([ [ { label: 'Name', value: 'import' }, @@ -251,13 +251,13 @@ describe('CsrAddComponent', () => { }); it('updates form fields and sets constrains when Profile is emitted by CertificateIdentifierAndTypeComponent', async () => { - const optionsForm = spectator.query(CertificateOptionsComponent); - const subjectForm = spectator.query(CertificateSubjectComponent); + const optionsForm = spectator.query(CertificateOptionsComponent)!; + const subjectForm = spectator.query(CertificateSubjectComponent)!; jest.spyOn(optionsForm.form, 'patchValue'); jest.spyOn(subjectForm.form, 'patchValue'); - const constraintsForm = spectator.query(CertificateConstraintsComponent); + const constraintsForm = spectator.query(CertificateConstraintsComponent)!; jest.spyOn(constraintsForm, 'setFromProfile'); await form.fillForm({ diff --git a/src/app/pages/credentials/certificates-dash/csr-add/steps/csr-import/csr-import.component.ts b/src/app/pages/credentials/certificates-dash/csr-add/steps/csr-import/csr-import.component.ts index 0775d0ae515..b274792b7a4 100644 --- a/src/app/pages/credentials/certificates-dash/csr-add/steps/csr-import/csr-import.component.ts +++ b/src/app/pages/credentials/certificates-dash/csr-add/steps/csr-import/csr-import.component.ts @@ -35,7 +35,7 @@ import { getCertificatePreview } from 'app/pages/credentials/certificates-dash/u ], }) export class CsrImportComponent implements SummaryProvider { - form = this.formBuilder.group({ + form = this.formBuilder.nonNullable.group({ CSR: ['', Validators.required], privatekey: ['', Validators.required], passphrase: [''], @@ -58,7 +58,7 @@ export class CsrImportComponent implements SummaryProvider { ) {} getSummary(): SummarySection { - const values = this.form.value; + const values = this.form.getRawValue(); const csrPreview = getCertificatePreview(values.CSR); const summary: SummarySection = [ diff --git a/src/app/pages/credentials/certificates-dash/forms/acmedns-form/acmedns-form.component.spec.ts b/src/app/pages/credentials/certificates-dash/forms/acmedns-form/acmedns-form.component.spec.ts index 03700f1cd6b..528079117d6 100644 --- a/src/app/pages/credentials/certificates-dash/forms/acmedns-form/acmedns-form.component.spec.ts +++ b/src/app/pages/credentials/certificates-dash/forms/acmedns-form/acmedns-form.component.spec.ts @@ -96,7 +96,7 @@ describe('AcmednsFormComponent', () => { it('shows values for an existing DNS Authenticator when form is opened for edit', async () => { spectator.component.ngOnInit(); - let authenticator: Option[]; + let authenticator: Option[] = []; spectator.component.authenticatorOptions$.subscribe((options) => authenticator = options); expect(spectator.inject(ApiService).call).toHaveBeenCalledWith('acme.dns.authenticator.authenticator_schemas'); diff --git a/src/app/pages/credentials/groups/group-details-row/delete-group-dialog/delete-group-dialog.component.ts b/src/app/pages/credentials/groups/group-details-row/delete-group-dialog/delete-group-dialog.component.ts index 098704a0c13..346341764b2 100644 --- a/src/app/pages/credentials/groups/group-details-row/delete-group-dialog/delete-group-dialog.component.ts +++ b/src/app/pages/credentials/groups/group-details-row/delete-group-dialog/delete-group-dialog.component.ts @@ -44,7 +44,7 @@ import { ApiService } from 'app/services/websocket/api.service'; export class DeleteGroupDialogComponent { readonly requiredRoles = [Role.AccountWrite]; - deleteUsersCheckbox = new FormControl(false); + deleteUsersCheckbox = new FormControl(false, { nonNullable: true }); readonly deleteMessage = T('Are you sure you want to delete group "{name}"?'); diff --git a/src/app/pages/credentials/groups/group-details-row/group-details-row.component.spec.ts b/src/app/pages/credentials/groups/group-details-row/group-details-row.component.spec.ts index fd4e46837fa..c7f09134d80 100644 --- a/src/app/pages/credentials/groups/group-details-row/group-details-row.component.spec.ts +++ b/src/app/pages/credentials/groups/group-details-row/group-details-row.component.spec.ts @@ -29,7 +29,7 @@ const dummyGroup = { group: 'dummy', builtin: false, smb: true, - users: [], + users: [] as number[], } as Group; describe('GroupDetailsRowComponent', () => { diff --git a/src/app/pages/credentials/groups/group-form/group-form.component.spec.ts b/src/app/pages/credentials/groups/group-form/group-form.component.spec.ts index 95ecb95572c..7bc4ea9eaed 100644 --- a/src/app/pages/credentials/groups/group-form/group-form.component.spec.ts +++ b/src/app/pages/credentials/groups/group-form/group-form.component.spec.ts @@ -47,7 +47,7 @@ describe('GroupFormComponent', () => { const fakeDataGroup = { id: 13, gid: 1111, - sudo_commands: [], + sudo_commands: [] as string[], name: 'Group A', sudo_commands_nopasswd: [allCommands], smb: false, diff --git a/src/app/pages/credentials/groups/group-list/group-list.component.ts b/src/app/pages/credentials/groups/group-list/group-list.component.ts index be11a7b31ca..e4e27af94de 100644 --- a/src/app/pages/credentials/groups/group-list/group-list.component.ts +++ b/src/app/pages/credentials/groups/group-list/group-list.component.ts @@ -102,7 +102,7 @@ export class GroupListComponent implements OnInit { textColumn({ title: this.translate.instant('Roles'), getValue: (row) => row.roles - .map((role) => (roleNames.has(role) ? this.translate.instant(roleNames.get(role)) : role)) + .map((role) => this.translate.instant(roleNames.get(role) || role)) .join(', ') || this.translate.instant('N/A'), }), ], { diff --git a/src/app/pages/credentials/groups/privilege/privilege-form/privilege-form.component.ts b/src/app/pages/credentials/groups/privilege/privilege-form/privilege-form.component.ts index 87f84734fe4..ccc34a5d97f 100644 --- a/src/app/pages/credentials/groups/privilege/privilege-form/privilege-form.component.ts +++ b/src/app/pages/credentials/groups/privilege/privilege-form/privilege-form.component.ts @@ -99,7 +99,7 @@ export class PrivilegeFormComponent implements OnInit { }); return sortedRoles.map((role) => ({ - label: roleNames.has(role.name) ? this.translate.instant(roleNames.get(role.name)) : role.name, + label: this.translate.instant(roleNames.get(role.name) || role.name), value: role.name, })); }), diff --git a/src/app/pages/credentials/groups/privilege/privilege-list/privilege-list.component.ts b/src/app/pages/credentials/groups/privilege/privilege-list/privilege-list.component.ts index f20251fa36f..3bbd1df8781 100644 --- a/src/app/pages/credentials/groups/privilege/privilege-list/privilege-list.component.ts +++ b/src/app/pages/credentials/groups/privilege/privilege-list/privilege-list.component.ts @@ -80,7 +80,7 @@ export class PrivilegeListComponent implements OnInit { textColumn({ title: this.translate.instant('Roles'), getValue: (row) => row.roles.map((role) => { - return roleNames.has(role) ? this.translate.instant(roleNames.get(role)) : role; + return this.translate.instant(roleNames.get(role) || role); }).join(', ') || this.translate.instant('N/A'), disableSorting: true, }), @@ -137,8 +137,8 @@ export class PrivilegeListComponent implements OnInit { private readonly rolesSuggestions$ = of(Object.values(Role)).pipe( map((roles) => roles.map((key) => ({ - label: this.translate.instant(roleNames.get(key)), - value: `"${this.translate.instant(roleNames.get(key))}"`, + label: this.translate.instant(roleNames.get(key) || key), + value: `"${this.translate.instant(roleNames.get(key) || key)}"`, }))), ); diff --git a/src/app/pages/credentials/users/user-details-row/user-details-row.component.spec.ts b/src/app/pages/credentials/users/user-details-row/user-details-row.component.spec.ts index a5632c52afa..b9ed7527c92 100644 --- a/src/app/pages/credentials/users/user-details-row/user-details-row.component.spec.ts +++ b/src/app/pages/credentials/users/user-details-row/user-details-row.component.spec.ts @@ -36,15 +36,15 @@ const dummyUser = { smb: false, password_disabled: false, locked: false, - sudo_commands: [], - sudo_commands_nopasswd: [], + sudo_commands: [] as string[], + sudo_commands_nopasswd: [] as string[], email: 'test-user@test-user.com', group: { id: 41, bsdgrp_gid: 0, bsdgrp_group: 'test-user', }, - groups: [], + groups: [] as number[], } as User; describe('UserDetailsRowComponent', () => { diff --git a/src/app/pages/credentials/users/user-list/user-list.component.ts b/src/app/pages/credentials/users/user-list/user-list.component.ts index 843f26db8c4..2f19514e5d3 100644 --- a/src/app/pages/credentials/users/user-list/user-list.component.ts +++ b/src/app/pages/credentials/users/user-list/user-list.component.ts @@ -94,7 +94,7 @@ export class UserListComponent implements OnInit { textColumn({ title: this.translate.instant('Roles'), getValue: (row) => row.roles - .map((role) => (roleNames.has(role) ? this.translate.instant(roleNames.get(role)) : role)) + .map((role) => this.translate.instant(roleNames.get(role) || role)) .join(', ') || this.translate.instant('N/A'), }), ], { diff --git a/src/app/pages/dashboard/components/dashboard/widget-group-controls/widget-group-controls.component.spec.ts b/src/app/pages/dashboard/components/dashboard/widget-group-controls/widget-group-controls.component.spec.ts index f8d0cee5e3a..557e885c3e7 100644 --- a/src/app/pages/dashboard/components/dashboard/widget-group-controls/widget-group-controls.component.spec.ts +++ b/src/app/pages/dashboard/components/dashboard/widget-group-controls/widget-group-controls.component.spec.ts @@ -23,7 +23,7 @@ describe('WidgetGroupControlsComponent', () => { it('renders a button to move widget up on mobile', () => { jest.spyOn(spectator.component.moveUp, 'emit').mockReturnValue(); - const button = spectator.query('[aria-label="Move widget up"]'); + const button = spectator.query('[aria-label="Move widget up"]')!; expect(button).toExist(); expect(button.querySelector('ix-icon')).toHaveAttribute('name', 'mdi-menu-up'); @@ -44,7 +44,7 @@ describe('WidgetGroupControlsComponent', () => { it('renders a button to move widget down on mobile', () => { jest.spyOn(spectator.component.moveDown, 'emit').mockReturnValue(); - const button = spectator.query('[aria-label="Move widget down"]'); + const button = spectator.query('[aria-label="Move widget down"]')!; expect(button).toExist(); expect(button.querySelector('ix-icon')).toHaveAttribute('name', 'mdi-menu-down'); @@ -64,7 +64,7 @@ describe('WidgetGroupControlsComponent', () => { it('renders a button to edit a widget', () => { jest.spyOn(spectator.component.edit, 'emit').mockReturnValue(); - const button = spectator.query('[aria-label="Edit group"]'); + const button = spectator.query('[aria-label="Edit group"]')!; expect(button).toExist(); expect(button.querySelector('ix-icon')).toHaveAttribute('name', 'edit'); @@ -76,7 +76,7 @@ describe('WidgetGroupControlsComponent', () => { it('renders a button to delete a widget', () => { jest.spyOn(spectator.component.delete, 'emit').mockReturnValue(); - const button = spectator.query('[aria-label="Delete group"]'); + const button = spectator.query('[aria-label="Delete group"]')!; expect(button).toExist(); expect(button.querySelector('ix-icon')).toHaveAttribute('name', 'mdi-delete'); diff --git a/src/app/pages/dashboard/components/widget-group-form/widget-group-form.component.spec.ts b/src/app/pages/dashboard/components/widget-group-form/widget-group-form.component.spec.ts index 612d7c9ebae..77a28c0130b 100644 --- a/src/app/pages/dashboard/components/widget-group-form/widget-group-form.component.spec.ts +++ b/src/app/pages/dashboard/components/widget-group-form/widget-group-form.component.spec.ts @@ -62,7 +62,7 @@ describe('WidgetGroupFormComponent', () => { it('checks layout selector', async () => { const layoutSelector = await loader.getHarness(IxIconGroupHarness.with({ label: 'Layout' })); - const editor = spectator.query(WidgetEditorGroupComponent); + const editor = spectator.query(WidgetEditorGroupComponent)!; expect(await layoutSelector.getValue()).toEqual(WidgetGroupLayout.Full); expect(editor.group).toEqual({ layout: WidgetGroupLayout.Full, slots: [{ type: null }] }); await layoutSelector.setValue(WidgetGroupLayout.Halves); @@ -111,11 +111,11 @@ describe('WidgetGroupFormComponent', () => { }); it('changes slot', () => { - const editor = spectator.query(WidgetEditorGroupComponent); + const editor = spectator.query(WidgetEditorGroupComponent)!; editor.selectedSlotChange.emit(1); spectator.detectChanges(); - const slotForm = spectator.query(WidgetGroupSlotFormComponent); + const slotForm = spectator.query(WidgetGroupSlotFormComponent)!; expect(slotForm.slotConfig).toEqual({ type: WidgetType.Ipv4Address, settings: { @@ -127,7 +127,7 @@ describe('WidgetGroupFormComponent', () => { }); it('disables button when slot has validation errors', async () => { - const slotForm = spectator.query(WidgetGroupSlotFormComponent); + const slotForm = spectator.query(WidgetGroupSlotFormComponent)!; slotForm.validityChange.emit([SlotPosition.First, { interface: { required: true } }]); spectator.detectChanges(); const submitBtn = await loader.getHarness(MatButtonHarness.with({ text: 'Save' })); @@ -135,7 +135,7 @@ describe('WidgetGroupFormComponent', () => { }); it('updates settings', async () => { - const slotForm = spectator.query(WidgetGroupSlotFormComponent); + const slotForm = spectator.query(WidgetGroupSlotFormComponent)!; slotForm.settingsChange.emit({ slotPosition: SlotPosition.First, type: WidgetType.Ipv4Address, diff --git a/src/app/pages/dashboard/widgets/backup/widget-backup/backup-task-actions/backup-task-actions.component.spec.ts b/src/app/pages/dashboard/widgets/backup/widget-backup/backup-task-actions/backup-task-actions.component.spec.ts index adb04d73b87..40fc539cbea 100644 --- a/src/app/pages/dashboard/widgets/backup/widget-backup/backup-task-actions/backup-task-actions.component.spec.ts +++ b/src/app/pages/dashboard/widgets/backup/widget-backup/backup-task-actions/backup-task-actions.component.spec.ts @@ -31,7 +31,7 @@ describe('BackupTaskActionsComponent', () => { spectator.setInput('allCount', 1); spectator.detectChanges(); const spy = jest.spyOn(spectator.component.addCloudSyncTask, 'emit'); - spectator.click(spectator.query('[ixTest="cloud"]')); + spectator.click(spectator.query('[ixTest="cloud"]')!); expect(spy).toHaveBeenCalled(); }); @@ -39,7 +39,7 @@ describe('BackupTaskActionsComponent', () => { spectator.setInput('allCount', 1); spectator.detectChanges(); const spy = jest.spyOn(spectator.component.addReplicationTask, 'emit'); - spectator.click(spectator.query('[ixTest="another-TrueNAS"]')); + spectator.click(spectator.query('[ixTest="another-TrueNAS"]')!); expect(spy).toHaveBeenCalled(); }); }); diff --git a/src/app/pages/dashboard/widgets/backup/widget-backup/backup-task-empty/backup-task-empty.component.spec.ts b/src/app/pages/dashboard/widgets/backup/widget-backup/backup-task-empty/backup-task-empty.component.spec.ts index 77603dfcbb0..3bbeb14906f 100644 --- a/src/app/pages/dashboard/widgets/backup/widget-backup/backup-task-empty/backup-task-empty.component.spec.ts +++ b/src/app/pages/dashboard/widgets/backup/widget-backup/backup-task-empty/backup-task-empty.component.spec.ts @@ -33,7 +33,7 @@ describe('BackupTaskEmptyComponent', () => { spectator.setInput('isLoading', false); spectator.detectChanges(); const spy = jest.spyOn(spectator.component.addCloudSyncTask, 'emit'); - spectator.click(spectator.query('[ixTest="cloud-sync"]')); + spectator.click(spectator.query('[ixTest="cloud-sync"]')!); expect(spy).toHaveBeenCalled(); }); @@ -41,7 +41,7 @@ describe('BackupTaskEmptyComponent', () => { spectator.setInput('isLoading', false); spectator.detectChanges(); const spy = jest.spyOn(spectator.component.addReplicationTask, 'emit'); - spectator.click(spectator.query('[ixTest="replication"]')); + spectator.click(spectator.query('[ixTest="replication"]')!); expect(spy).toHaveBeenCalled(); }); @@ -49,7 +49,7 @@ describe('BackupTaskEmptyComponent', () => { spectator.setInput('isLoading', false); spectator.detectChanges(); const spy = jest.spyOn(spectator.component.addRsyncTask, 'emit'); - spectator.click(spectator.query('[ixTest="rsync"]')); + spectator.click(spectator.query('[ixTest="rsync"]')!); expect(spy).toHaveBeenCalled(); }); }); diff --git a/src/app/pages/dashboard/widgets/common/widget-datapoint/widget-datapoint.component.ts b/src/app/pages/dashboard/widgets/common/widget-datapoint/widget-datapoint.component.ts index 383a442dc01..36919ead509 100644 --- a/src/app/pages/dashboard/widgets/common/widget-datapoint/widget-datapoint.component.ts +++ b/src/app/pages/dashboard/widgets/common/widget-datapoint/widget-datapoint.component.ts @@ -22,7 +22,7 @@ import { SlotSize } from 'app/pages/dashboard/types/widget.interface'; export class WidgetDatapointComponent { size = input.required(); label = input(); - text = input(); + text = input.required(); subText = input(); get maxFontSize(): number { diff --git a/src/app/pages/dashboard/widgets/cpu/common/cpu-core-bar/cpu-core-bar.component.spec.ts b/src/app/pages/dashboard/widgets/cpu/common/cpu-core-bar/cpu-core-bar.component.spec.ts index 6f9b8e0fdbe..41c0fba4e73 100644 --- a/src/app/pages/dashboard/widgets/cpu/common/cpu-core-bar/cpu-core-bar.component.spec.ts +++ b/src/app/pages/dashboard/widgets/cpu/common/cpu-core-bar/cpu-core-bar.component.spec.ts @@ -61,7 +61,7 @@ describe('CpuCoreBarComponent', () => { }); it('shows a chart with cpu stats', () => { - const chart = spectator.query(BaseChartDirective); + const chart = spectator.query(BaseChartDirective)!; expect(chart).not.toBeNull(); expect(chart.type).toBe('bar'); diff --git a/src/app/pages/dashboard/widgets/cpu/widget-cpu-model/widget-cpu-model.component.spec.ts b/src/app/pages/dashboard/widgets/cpu/widget-cpu-model/widget-cpu-model.component.spec.ts index 55b1ca0b297..f2d3024935c 100644 --- a/src/app/pages/dashboard/widgets/cpu/widget-cpu-model/widget-cpu-model.component.spec.ts +++ b/src/app/pages/dashboard/widgets/cpu/widget-cpu-model/widget-cpu-model.component.spec.ts @@ -29,7 +29,7 @@ describe('WidgetCpuModelComponent', () => { ], }); - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('AMD EPYC 7313P 16-Core Processor'); }); diff --git a/src/app/pages/dashboard/widgets/cpu/widget-cpu-usage-recent/widget-cpu-usage-recent.component.spec.ts b/src/app/pages/dashboard/widgets/cpu/widget-cpu-usage-recent/widget-cpu-usage-recent.component.spec.ts index 0368848623e..6bba2dd527b 100644 --- a/src/app/pages/dashboard/widgets/cpu/widget-cpu-usage-recent/widget-cpu-usage-recent.component.spec.ts +++ b/src/app/pages/dashboard/widgets/cpu/widget-cpu-usage-recent/widget-cpu-usage-recent.component.spec.ts @@ -74,7 +74,7 @@ describe('WidgetCpuUsageRecentComponent', () => { }); it('shows a chart with cpu usage', () => { - const chart = spectator.query(BaseChartDirective); + const chart = spectator.query(BaseChartDirective)!; expect(chart).not.toBeNull(); expect(chart.type).toBe('line'); diff --git a/src/app/pages/dashboard/widgets/custom/arbitrary-text/widget-arbitrary-text.component.spec.ts b/src/app/pages/dashboard/widgets/custom/arbitrary-text/widget-arbitrary-text.component.spec.ts index d19493ec4c4..40b5aedfd62 100644 --- a/src/app/pages/dashboard/widgets/custom/arbitrary-text/widget-arbitrary-text.component.spec.ts +++ b/src/app/pages/dashboard/widgets/custom/arbitrary-text/widget-arbitrary-text.component.spec.ts @@ -23,7 +23,7 @@ describe('WidgetArbitraryTextSettings', () => { }); it('renders arbitrary text and title', () => { - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.label()).toBe('Widget Title'); expect(widget.text()).toBe('Widget Text'); diff --git a/src/app/pages/dashboard/widgets/memory/widget-memory/widget-memory.component.spec.ts b/src/app/pages/dashboard/widgets/memory/widget-memory/widget-memory.component.spec.ts index 99c52f45d1f..6f7e03f3a33 100644 --- a/src/app/pages/dashboard/widgets/memory/widget-memory/widget-memory.component.spec.ts +++ b/src/app/pages/dashboard/widgets/memory/widget-memory/widget-memory.component.spec.ts @@ -76,7 +76,7 @@ describe('WidgetMemoryComponent', () => { }); it('shows a chart with memory stats', () => { - const chart = spectator.query(BaseChartDirective); + const chart = spectator.query(BaseChartDirective)!; expect(chart).not.toBeNull(); expect(chart.type).toBe('doughnut'); diff --git a/src/app/pages/dashboard/widgets/network/common/network-chart/network-chart.component.spec.ts b/src/app/pages/dashboard/widgets/network/common/network-chart/network-chart.component.spec.ts index d00e15adec1..4fec18a5d75 100644 --- a/src/app/pages/dashboard/widgets/network/common/network-chart/network-chart.component.spec.ts +++ b/src/app/pages/dashboard/widgets/network/common/network-chart/network-chart.component.spec.ts @@ -48,7 +48,7 @@ describe('NetworkChartComponent', () => { spectator.setInput('data', { datasets: [], labels: [] }); spectator.detectChanges(); - const chart = spectator.query(ViewChartAreaMockComponent); + const chart = spectator.query(ViewChartAreaMockComponent)!; expect(chart).toBeTruthy(); const data = chart.data(); diff --git a/src/app/pages/dashboard/widgets/network/widget-interface-ip/widget-interface-ip.component.spec.ts b/src/app/pages/dashboard/widgets/network/widget-interface-ip/widget-interface-ip.component.spec.ts index f90cfa80584..2379c33e961 100644 --- a/src/app/pages/dashboard/widgets/network/widget-interface-ip/widget-interface-ip.component.spec.ts +++ b/src/app/pages/dashboard/widgets/network/widget-interface-ip/widget-interface-ip.component.spec.ts @@ -63,7 +63,7 @@ describe('WidgetInterfaceIpComponent', () => { }); it('renders IPv4 addresses for the selected network interface', () => { - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('192.168.1.1\n192.168.1.2'); }); @@ -71,7 +71,7 @@ describe('WidgetInterfaceIpComponent', () => { it('renders IPv4 addresses for the selected network interface from state', () => { spectator.setInput('settings', { interface: 'eth2' }); - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('192.168.1.10\n192.168.1.11'); }); @@ -82,7 +82,7 @@ describe('WidgetInterfaceIpComponent', () => { widgetName: 'IPv6 Address', }); - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('fe80::1'); }); @@ -90,7 +90,7 @@ describe('WidgetInterfaceIpComponent', () => { it('renders "interface not found" when selected interface is not available in interface data', () => { spectator.setInput('settings', { interface: 'eth404' }); - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('Network interface eth404 not found.'); }); @@ -98,7 +98,7 @@ describe('WidgetInterfaceIpComponent', () => { it('renders N/A when an interface has no IPv4 addresses', () => { spectator.setInput('settings', { interface: 'eth1' }); - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('N/A'); }); @@ -115,7 +115,7 @@ describe('WidgetInterfaceIpComponent', () => { }); it('renders IPv4 addresses for the first picked network interface', () => { - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.label()).toBe('eth0 Address'); expect(widget.text()).toBe('192.168.1.1\n192.168.1.2'); diff --git a/src/app/pages/dashboard/widgets/network/widget-interface/widget-interface.utils.spec.ts b/src/app/pages/dashboard/widgets/network/widget-interface/widget-interface.utils.spec.ts index 316982b0410..ca5dc8e17c3 100644 --- a/src/app/pages/dashboard/widgets/network/widget-interface/widget-interface.utils.spec.ts +++ b/src/app/pages/dashboard/widgets/network/widget-interface/widget-interface.utils.spec.ts @@ -111,7 +111,7 @@ describe('processNetworkInterfaces', () => { ], }, bridge_members: ['bond0'], - }, + } as NetworkInterface, ] as NetworkInterface[]; expect(processNetworkInterfaces(interfaces)).toEqual([ diff --git a/src/app/pages/dashboard/widgets/storage/widget-pool-disks-with-zfs-errors/widget-pool-disks-with-zfs-errors.component.spec.ts b/src/app/pages/dashboard/widgets/storage/widget-pool-disks-with-zfs-errors/widget-pool-disks-with-zfs-errors.component.spec.ts index ea3337aa271..ca43972a92b 100644 --- a/src/app/pages/dashboard/widgets/storage/widget-pool-disks-with-zfs-errors/widget-pool-disks-with-zfs-errors.component.spec.ts +++ b/src/app/pages/dashboard/widgets/storage/widget-pool-disks-with-zfs-errors/widget-pool-disks-with-zfs-errors.component.spec.ts @@ -62,7 +62,7 @@ describe('WidgetDisksWithZfsErrorsComponent', () => { }); it('should render "Pool does not exist" message', () => { - const component = spectator.query(WidgetDatapointComponent); + const component = spectator.query(WidgetDatapointComponent)!; expect(component.label()).toBe('Disks w/ZFS Errors'); expect(component.text()).toBe('Pool does not exist'); }); diff --git a/src/app/pages/dashboard/widgets/storage/widget-pool-last-scan-errors/widget-pool-last-scan-errors.component.spec.ts b/src/app/pages/dashboard/widgets/storage/widget-pool-last-scan-errors/widget-pool-last-scan-errors.component.spec.ts index 11d52a5ebe8..aff3cf34a7b 100644 --- a/src/app/pages/dashboard/widgets/storage/widget-pool-last-scan-errors/widget-pool-last-scan-errors.component.spec.ts +++ b/src/app/pages/dashboard/widgets/storage/widget-pool-last-scan-errors/widget-pool-last-scan-errors.component.spec.ts @@ -66,7 +66,7 @@ describe('WidgetPoolLastScanErrorsComponent', () => { }); it('should render "Pool does not exist" message', () => { - const component = spectator.query(WidgetDatapointComponent); + const component = spectator.query(WidgetDatapointComponent)!; expect(component.label()).toBe('Last Scan Errors'); expect(component.text()).toBe('Pool does not exist'); }); diff --git a/src/app/pages/dashboard/widgets/storage/widget-pool-status/widget-pool-status.component.spec.ts b/src/app/pages/dashboard/widgets/storage/widget-pool-status/widget-pool-status.component.spec.ts index d468f139391..5d6ea8f0992 100644 --- a/src/app/pages/dashboard/widgets/storage/widget-pool-status/widget-pool-status.component.spec.ts +++ b/src/app/pages/dashboard/widgets/storage/widget-pool-status/widget-pool-status.component.spec.ts @@ -62,7 +62,7 @@ describe('WidgetPoolStatusComponent', () => { }); it('should render "Pool does not exist" message', () => { - const component = spectator.query(WidgetDatapointComponent); + const component = spectator.query(WidgetDatapointComponent)!; expect(component.label()).toBe('Pool Status'); expect(component.text()).toBe('Pool does not exist'); }); diff --git a/src/app/pages/dashboard/widgets/storage/widget-pool-usage-gauge/widget-pool-usage-gauge.component.spec.ts b/src/app/pages/dashboard/widgets/storage/widget-pool-usage-gauge/widget-pool-usage-gauge.component.spec.ts index 5048a89f0f5..4f8d940c67d 100644 --- a/src/app/pages/dashboard/widgets/storage/widget-pool-usage-gauge/widget-pool-usage-gauge.component.spec.ts +++ b/src/app/pages/dashboard/widgets/storage/widget-pool-usage-gauge/widget-pool-usage-gauge.component.spec.ts @@ -71,7 +71,7 @@ describe('WidgetPoolUsageGaugeComponent', () => { }); it('should render "Pool does not exist" message', () => { - const component = spectator.query(WidgetDatapointComponent); + const component = spectator.query(WidgetDatapointComponent)!; expect(component.label).toBe('Pool Usage'); expect(component.text).toBe('Pool does not exist'); }); diff --git a/src/app/pages/dashboard/widgets/storage/widget-pool/common/disks-with-zfs-errors/disks-with-zfs-errors.component.spec.ts b/src/app/pages/dashboard/widgets/storage/widget-pool/common/disks-with-zfs-errors/disks-with-zfs-errors.component.spec.ts index d1834666b53..9a1f1f08aed 100644 --- a/src/app/pages/dashboard/widgets/storage/widget-pool/common/disks-with-zfs-errors/disks-with-zfs-errors.component.spec.ts +++ b/src/app/pages/dashboard/widgets/storage/widget-pool/common/disks-with-zfs-errors/disks-with-zfs-errors.component.spec.ts @@ -14,7 +14,7 @@ describe('DisksWithZfsErrorsComponent', () => { beforeEach(() => { spectator = createComponent({ props: { - pool: null, + pool: undefined, }, }); }); diff --git a/src/app/pages/dashboard/widgets/storage/widget-pool/common/pool-status/pool-status.component.spec.ts b/src/app/pages/dashboard/widgets/storage/widget-pool/common/pool-status/pool-status.component.spec.ts index f63c091294c..dec2545bd95 100644 --- a/src/app/pages/dashboard/widgets/storage/widget-pool/common/pool-status/pool-status.component.spec.ts +++ b/src/app/pages/dashboard/widgets/storage/widget-pool/common/pool-status/pool-status.component.spec.ts @@ -15,7 +15,7 @@ describe('PoolStatusComponent', () => { beforeEach(() => { spectator = createComponent({ props: { - pool: null, + pool: undefined, }, }); }); diff --git a/src/app/pages/dashboard/widgets/storage/widget-pool/common/pool-usage-gauge/pool-usage-gauge.component.spec.ts b/src/app/pages/dashboard/widgets/storage/widget-pool/common/pool-usage-gauge/pool-usage-gauge.component.spec.ts index a6919b220ba..1f9fd4dbd1e 100644 --- a/src/app/pages/dashboard/widgets/storage/widget-pool/common/pool-usage-gauge/pool-usage-gauge.component.spec.ts +++ b/src/app/pages/dashboard/widgets/storage/widget-pool/common/pool-usage-gauge/pool-usage-gauge.component.spec.ts @@ -110,8 +110,8 @@ describe('PoolUsageGaugeComponent', () => { const lines: { label: string; value: string }[] = []; spectator.queryAll('.lines > .line').forEach((line) => { lines.push({ - label: line.querySelector('.label').textContent.trim(), - value: line.querySelector('.value').textContent.trim(), + label: line.querySelector('.label')!.textContent!.trim(), + value: line.querySelector('.value')!.textContent!.trim(), }); }); expect(lines).toEqual([ @@ -128,10 +128,10 @@ describe('PoolUsageGaugeComponent', () => { }); it('shows chart', () => { - expect(spectator.query(GaugeChartComponent).label).toBe('80.2%'); - const value = spectator.query(GaugeChartComponent).value; + expect(spectator.query(GaugeChartComponent)!.label).toBe('80.2%'); + const value = spectator.query(GaugeChartComponent)!.value; expect(value).toBeCloseTo(80, 0); - expect(spectator.query(GaugeChartComponent).colorFill).toBe('red'); + expect(spectator.query(GaugeChartComponent)!.colorFill).toBe('red'); }); it('should display skeleton loader when pool is loading', () => { diff --git a/src/app/pages/dashboard/widgets/storage/widget-storage/widget-storage.component.spec.ts b/src/app/pages/dashboard/widgets/storage/widget-storage/widget-storage.component.spec.ts index 751a6e4120e..fb6721390ae 100644 --- a/src/app/pages/dashboard/widgets/storage/widget-storage/widget-storage.component.spec.ts +++ b/src/app/pages/dashboard/widgets/storage/widget-storage/widget-storage.component.spec.ts @@ -155,7 +155,7 @@ describe('WidgetStorageComponent', () => { const tiles = spectator.queryAll('.tile'); expect(tiles).toHaveLength(1); - const headers = tiles.map((tile) => tile.querySelector('.tile-header-title').textContent.trim()); + const headers = tiles.map((tile) => tile.querySelector('.tile-header-title')!.textContent!.trim()); expect(headers).toEqual(['my pool']); const contents = tiles.map((tile) => { diff --git a/src/app/pages/dashboard/widgets/system/widget-hostname-passive/widget-hostname-passive.component.spec.ts b/src/app/pages/dashboard/widgets/system/widget-hostname-passive/widget-hostname-passive.component.spec.ts index ff42c1ae991..e1208bca150 100644 --- a/src/app/pages/dashboard/widgets/system/widget-hostname-passive/widget-hostname-passive.component.spec.ts +++ b/src/app/pages/dashboard/widgets/system/widget-hostname-passive/widget-hostname-passive.component.spec.ts @@ -35,7 +35,7 @@ describe('WidgetHostnamePassiveComponent', () => { ], }); - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('truenas.com'); }); diff --git a/src/app/pages/dashboard/widgets/system/widget-serial-active/widget-serial-active.component.spec.ts b/src/app/pages/dashboard/widgets/system/widget-serial-active/widget-serial-active.component.spec.ts index 3d69eb8bef3..a0bc68be3f5 100644 --- a/src/app/pages/dashboard/widgets/system/widget-serial-active/widget-serial-active.component.spec.ts +++ b/src/app/pages/dashboard/widgets/system/widget-serial-active/widget-serial-active.component.spec.ts @@ -33,7 +33,7 @@ describe('WidgetSerialActiveComponent', () => { ], }); - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('123456'); }); diff --git a/src/app/pages/dashboard/widgets/system/widget-serial-passive/widget-serial-passive.component.spec.ts b/src/app/pages/dashboard/widgets/system/widget-serial-passive/widget-serial-passive.component.spec.ts index 6f80d441fb4..cb1f81a3e08 100644 --- a/src/app/pages/dashboard/widgets/system/widget-serial-passive/widget-serial-passive.component.spec.ts +++ b/src/app/pages/dashboard/widgets/system/widget-serial-passive/widget-serial-passive.component.spec.ts @@ -35,7 +35,7 @@ describe('WidgetSerialPassiveComponent', () => { ], }); - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('123456'); }); diff --git a/src/app/pages/dashboard/widgets/system/widget-system-uptime/widget-system-uptime.component.spec.ts b/src/app/pages/dashboard/widgets/system/widget-system-uptime/widget-system-uptime.component.spec.ts index dbeacda739b..240e058177a 100644 --- a/src/app/pages/dashboard/widgets/system/widget-system-uptime/widget-system-uptime.component.spec.ts +++ b/src/app/pages/dashboard/widgets/system/widget-system-uptime/widget-system-uptime.component.spec.ts @@ -45,7 +45,7 @@ describe('WidgetSystemUptimeComponent', () => { }); it('renders System Uptime for the current system', () => { - const widget = spectator.query(WidgetDatapointComponent); + const widget = spectator.query(WidgetDatapointComponent)!; expect(widget).toBeTruthy(); expect(widget.text()).toBe('23 hours 12 minutes as of 10:34'); expect(widget.label()).toBe('System Uptime'); diff --git a/src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.spec.ts b/src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.spec.ts index 71972029477..838f2966824 100644 --- a/src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.spec.ts +++ b/src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.spec.ts @@ -110,11 +110,11 @@ describe('DatasetCapacityManagementCardComponent', () => { }); it('shows SpaceManagementChartComponent', () => { - expect(spectator.query(SpaceManagementChartComponent).dataset).toBe(datasetFilesystem); + expect(spectator.query(SpaceManagementChartComponent)!.dataset).toBe(datasetFilesystem); }); it('shows chart block', () => { - const chartExtra = spectator.query('.chart-extra').querySelectorAll('.details-item'); + const chartExtra = spectator.query('.chart-extra')!.querySelectorAll('.details-item'); expect(chartExtra).toHaveLength(2); expect(chartExtra[0].querySelector('.label')).toHaveText('Reserved for Dataset:'); expect(chartExtra[0].querySelector('.value')).toHaveText('1 KiB'); @@ -159,11 +159,11 @@ describe('DatasetCapacityManagementCardComponent', () => { }); it('shows SpaceManagementChartComponent', () => { - expect(spectator.query(SpaceManagementChartComponent).dataset).toBe(datasetZvol); + expect(spectator.query(SpaceManagementChartComponent)!.dataset).toBe(datasetZvol); }); it('shows chart block', () => { - const chartExtra = spectator.query('.chart-extra').querySelectorAll('.details-item'); + const chartExtra = spectator.query('.chart-extra')!.querySelectorAll('.details-item'); expect(chartExtra).toHaveLength(2); expect(chartExtra[0].querySelector('.label')).toHaveText('Provisioning Type:'); expect(chartExtra[0].querySelector('.value')).toHaveText('Thick'); diff --git a/src/app/pages/datasets/components/dataset-details-card/dataset-details-card.component.spec.ts b/src/app/pages/datasets/components/dataset-details-card/dataset-details-card.component.spec.ts index 67e72734889..8f520ba8f01 100644 --- a/src/app/pages/datasets/components/dataset-details-card/dataset-details-card.component.spec.ts +++ b/src/app/pages/datasets/components/dataset-details-card/dataset-details-card.component.spec.ts @@ -80,8 +80,8 @@ describe('DatasetDetailsCardComponent', () => { function getDetails(): Record { return spectator.queryAll('.details-item').reduce((acc, item: HTMLElement) => { - const key = item.querySelector('.label')!.textContent; - const value = item.querySelector('.value')!.textContent.trim(); + const key = item.querySelector('.label')!.textContent!; + const value = item.querySelector('.value')!.textContent!.trim(); acc[key] = value; return acc; }, {} as Record); @@ -179,7 +179,7 @@ describe('DatasetDetailsCardComponent', () => { } as DatasetDetails, }); - const promoteButton = await loader.getHarnessOrNull(MatButtonHarness.with({ text: 'Promote' })); + const promoteButton = await loader.getHarness(MatButtonHarness.with({ text: 'Promote' })); await promoteButton.click(); expect(spectator.inject(ApiService).call).toHaveBeenCalledWith('pool.dataset.promote', ['pool/child']); diff --git a/src/app/pages/datasets/components/dataset-details-panel/dataset-details-panel.component.spec.ts b/src/app/pages/datasets/components/dataset-details-panel/dataset-details-panel.component.spec.ts index 7f9022778fd..99b2b43bef5 100644 --- a/src/app/pages/datasets/components/dataset-details-panel/dataset-details-panel.component.spec.ts +++ b/src/app/pages/datasets/components/dataset-details-panel/dataset-details-panel.component.spec.ts @@ -124,23 +124,23 @@ describe('DatasetDetailsPanelComponent', () => { }); it('shows all the cards', () => { - const datasetDetailsCard = spectator.query(DatasetDetailsCardComponent); + const datasetDetailsCard = spectator.query(DatasetDetailsCardComponent)!; expect(datasetDetailsCard).toBeTruthy(); expect(datasetDetailsCard.dataset).toBe(dataset); - const dataProtectionCard = spectator.query(DataProtectionCardComponent); + const dataProtectionCard = spectator.query(DataProtectionCardComponent)!; expect(dataProtectionCard).toBeTruthy(); expect(dataProtectionCard.dataset).toStrictEqual(datasetDetails); - const permissionsCard = spectator.query(PermissionsCardComponent); + const permissionsCard = spectator.query(PermissionsCardComponent)!; expect(permissionsCard).toBeTruthy(); expect(permissionsCard.dataset).toStrictEqual(datasetDetails); - const zfsEncryptionCard = spectator.query(ZfsEncryptionCardComponent); + const zfsEncryptionCard = spectator.query(ZfsEncryptionCardComponent)!; expect(zfsEncryptionCard).toBeTruthy(); expect(zfsEncryptionCard.dataset).toStrictEqual(datasetDetails); - const datasetCapacityManagementCard = spectator.query(DatasetCapacityManagementCardComponent); + const datasetCapacityManagementCard = spectator.query(DatasetCapacityManagementCardComponent)!; expect(datasetCapacityManagementCard).toBeTruthy(); expect(datasetCapacityManagementCard.dataset).toStrictEqual(datasetDetails); }); diff --git a/src/app/pages/datasets/components/dataset-form/sections/encryption-section/encryption-section.component.ts b/src/app/pages/datasets/components/dataset-form/sections/encryption-section/encryption-section.component.ts index 052dd49ba03..70466c81a1f 100644 --- a/src/app/pages/datasets/components/dataset-form/sections/encryption-section/encryption-section.component.ts +++ b/src/app/pages/datasets/components/dataset-form/sections/encryption-section/encryption-section.component.ts @@ -48,7 +48,7 @@ export class EncryptionSectionComponent implements OnChanges, OnInit { }); // TODO: Add conditional validators - readonly form = this.formBuilder.group({ + readonly form = this.formBuilder.nonNullable.group({ inherit_encryption: [true], encryption: [true], encryption_type: [DatasetEncryptionType.Default], diff --git a/src/app/pages/datasets/components/dataset-form/sections/name-and-options-section/name-and-options-section.component.spec.ts b/src/app/pages/datasets/components/dataset-form/sections/name-and-options-section/name-and-options-section.component.spec.ts index a3bcadfd6e5..7dc118f9dd5 100644 --- a/src/app/pages/datasets/components/dataset-form/sections/name-and-options-section/name-and-options-section.component.spec.ts +++ b/src/app/pages/datasets/components/dataset-form/sections/name-and-options-section/name-and-options-section.component.spec.ts @@ -26,7 +26,7 @@ describe('NameAndOptionsSectionComponent', () => { value: DatasetCaseSensitivity.Sensitive, source: ZfsPropertySource.Local, }, - children: [], + children: [] as Dataset[], } as Dataset; const createComponent = createComponentFactory({ @@ -48,7 +48,7 @@ describe('NameAndOptionsSectionComponent', () => { describe('new dataset', () => { it('shows form for new dataset', async () => { spectator.setInput({ - existing: null, + existing: undefined, parent: parentDataset, }); @@ -88,7 +88,7 @@ describe('NameAndOptionsSectionComponent', () => { value: DatasetPreset.Multiprotocol, }, } as Dataset, - parent: null, + parent: undefined, }); const values = await form.getValues(); diff --git a/src/app/pages/datasets/components/dataset-form/sections/other-options-section/other-options-section.component.ts b/src/app/pages/datasets/components/dataset-form/sections/other-options-section/other-options-section.component.ts index fd1272ef083..9eb49dbc856 100644 --- a/src/app/pages/datasets/components/dataset-form/sections/other-options-section/other-options-section.component.ts +++ b/src/app/pages/datasets/components/dataset-form/sections/other-options-section/other-options-section.component.ts @@ -245,34 +245,35 @@ export class OtherOptionsSectionComponent implements OnInit, OnChanges { } private setFormValues(): void { - if (!this.existing()) { + const existing = this.existing(); + if (!existing) { return; } - let specialSmallBlockSize = getFieldValue(this.existing().special_small_block_size, this.parent()) as (number | 'INHERIT'); + let specialSmallBlockSize = getFieldValue(existing.special_small_block_size, this.parent()) as (number | 'INHERIT'); if (specialSmallBlockSize !== 'INHERIT') { specialSmallBlockSize = this.formatter.convertHumanStringToNum(specialSmallBlockSize.toString()); } this.form.patchValue({ - comments: this.existing().comments?.source === ZfsPropertySource.Local ? this.existing().comments.value : '', - sync: getFieldValue(this.existing().sync, this.parent()), - compression: getFieldValue(this.existing().compression, this.parent()), - atime: getFieldValue(this.existing().atime, this.parent()), - deduplication: getFieldValue(this.existing().deduplication, this.parent()), - checksum: getFieldValue(this.existing().checksum, this.parent()), - readonly: getFieldValue(this.existing().readonly, this.parent()), - exec: getFieldValue(this.existing().exec, this.parent()), - recordsize: getFieldValue(this.existing().recordsize, this.parent()), - snapdir: this.existing().snapdir?.value, - snapdev: getFieldValue(this.existing().snapdev, this.parent()), - copies: this.existing().copies - ? Number(this.existing().copies.value) + comments: existing.comments?.source === ZfsPropertySource.Local ? existing.comments.value : '', + sync: getFieldValue(existing.sync, this.parent()), + compression: getFieldValue(existing.compression, this.parent()), + atime: getFieldValue(existing.atime, this.parent()), + deduplication: getFieldValue(existing.deduplication, this.parent()), + checksum: getFieldValue(existing.checksum, this.parent()), + readonly: getFieldValue(existing.readonly, this.parent()), + exec: getFieldValue(existing.exec, this.parent()), + recordsize: getFieldValue(existing.recordsize, this.parent()), + snapdir: existing.snapdir?.value, + snapdev: getFieldValue(existing.snapdev, this.parent()), + copies: existing.copies + ? Number(existing.copies.value) : null, - acltype: getFieldValue(this.existing().acltype, this.parent()) as DatasetAclType, - aclmode: getFieldValue(this.existing().aclmode, this.parent()) as AclMode, - casesensitivity: this.existing().casesensitivity?.value, - special_small_block_size: this.existing().special_small_block_size + acltype: getFieldValue(existing.acltype, this.parent()) as DatasetAclType, + aclmode: getFieldValue(existing.aclmode, this.parent()) as AclMode, + casesensitivity: existing.casesensitivity?.value, + special_small_block_size: existing.special_small_block_size ? specialSmallBlockSize : null, }); diff --git a/src/app/pages/datasets/components/dataset-management/dataset-management.component.spec.ts b/src/app/pages/datasets/components/dataset-management/dataset-management.component.spec.ts index 562bd395bb0..0379cf1f02d 100644 --- a/src/app/pages/datasets/components/dataset-management/dataset-management.component.spec.ts +++ b/src/app/pages/datasets/components/dataset-management/dataset-management.component.spec.ts @@ -24,7 +24,7 @@ describe('DatasetsManagementComponent', () => { { id: 'second', name: 'Second Dataset' }, ]); - const error$ = new BehaviorSubject(null); + const error$ = new BehaviorSubject(null); const createComponent = createRoutingFactory({ component: DatasetsManagementComponent, @@ -91,7 +91,7 @@ describe('DatasetsManagementComponent', () => { spectator.detectChanges(); - expect(spectator.query(EmptyComponent).conf).toEqual( + expect(spectator.query(EmptyComponent)!.conf).toEqual( expect.objectContaining({ large: true, type: 'errors', @@ -109,7 +109,7 @@ describe('DatasetsManagementComponent', () => { datasets$.next([]); spectator.detectChanges(); - expect(spectator.query(EmptyComponent).conf).toEqual( + expect(spectator.query(EmptyComponent)!.conf).toEqual( expect.objectContaining({ type: 'no_page_data', title: 'No Datasets', diff --git a/src/app/pages/datasets/components/dataset-node/dataset-node.component.spec.ts b/src/app/pages/datasets/components/dataset-node/dataset-node.component.spec.ts index ebc8d8af37a..10844494944 100644 --- a/src/app/pages/datasets/components/dataset-node/dataset-node.component.spec.ts +++ b/src/app/pages/datasets/components/dataset-node/dataset-node.component.spec.ts @@ -45,7 +45,7 @@ describe('DatasetNodeComponent', () => { }); it('shows an icon for current dataset', () => { - const icon = spectator.query(DatasetIconComponent); + const icon = spectator.query(DatasetIconComponent)!; expect(icon).toBeTruthy(); expect(icon.dataset).toBe(dataset); }); @@ -55,7 +55,7 @@ describe('DatasetNodeComponent', () => { }); it('shows a dataset encryption cell', () => { - const cell = spectator.query(DatasetEncryptionCellComponent); + const cell = spectator.query(DatasetEncryptionCellComponent)!; expect(cell).toBeTruthy(); expect(cell.dataset).toBe(dataset); }); @@ -63,7 +63,7 @@ describe('DatasetNodeComponent', () => { it('shows a dataset roles cell', () => { spectator.setInput('dataset', dataset); - const cell = spectator.query(DatasetRolesCellComponent); + const cell = spectator.query(DatasetRolesCellComponent)!; expect(cell).toBeTruthy(); expect(cell.dataset).toBe(dataset); expect(cell.isSystemDataset).toBeFalsy(); diff --git a/src/app/pages/datasets/components/delete-dataset-dialog/delete-dataset-dialog.component.spec.ts b/src/app/pages/datasets/components/delete-dataset-dialog/delete-dataset-dialog.component.spec.ts index 0daf514af5c..4275532c84c 100644 --- a/src/app/pages/datasets/components/delete-dataset-dialog/delete-dataset-dialog.component.spec.ts +++ b/src/app/pages/datasets/components/delete-dataset-dialog/delete-dataset-dialog.component.spec.ts @@ -88,7 +88,7 @@ describe('DeleteDatasetDialogComponent', () => { 'These services depend on dataset Lab 1 and will be destroyed if the dataset is deleted:', ); - const services = attachmentsSection.querySelectorAll('.services > li'); + const services = attachmentsSection!.querySelectorAll('.services > li'); expect(services).toHaveLength(2); expect(services[0]).toHaveDescendantWithText({ selector: '.service-name', @@ -113,7 +113,7 @@ describe('DeleteDatasetDialogComponent', () => { const processesSection = spectator.query('.known-processes'); expect(processesSection).toHaveText('These running processes are using Lab 1:'); - const processes = processesSection.querySelectorAll('li'); + const processes = processesSection!.querySelectorAll('li'); expect(processes).toHaveLength(2); expect(processes[0]).toHaveText('zsh'); @@ -123,7 +123,7 @@ describe('DeleteDatasetDialogComponent', () => { it('shows unknown processes that use dataset', () => { const processesSection = spectator.query('.unknown-processes'); expect(processesSection).toHaveText('These unknown processes are using the dataset:'); - const processes = processesSection.querySelectorAll('li'); + const processes = processesSection!.querySelectorAll('li'); expect(processes).toHaveLength(2); expect(processes[0]).toHaveText('1234 - rm -rf /'); diff --git a/src/app/pages/datasets/modules/encryption/components/encryption-options-dialog/encryption-options-dialog.component.spec.ts b/src/app/pages/datasets/modules/encryption/components/encryption-options-dialog/encryption-options-dialog.component.spec.ts index d0e5133ae02..9dc2b28c2eb 100644 --- a/src/app/pages/datasets/modules/encryption/components/encryption-options-dialog/encryption-options-dialog.component.spec.ts +++ b/src/app/pages/datasets/modules/encryption/components/encryption-options-dialog/encryption-options-dialog.component.spec.ts @@ -8,7 +8,7 @@ import { of } from 'rxjs'; import { mockCall, mockJob, mockApi } from 'app/core/testing/utils/mock-api.utils'; import { mockAuth } from 'app/core/testing/utils/mock-auth.utils'; import { EncryptionKeyFormat } from 'app/enums/encryption-key-format.enum'; -import { Dataset } from 'app/interfaces/dataset.interface'; +import { Dataset, DatasetDetails } from 'app/interfaces/dataset.interface'; import { DialogService } from 'app/modules/dialog/dialog.service'; import { IxSelectHarness } from 'app/modules/forms/ix-forms/components/ix-select/ix-select.harness'; import { IxFormHarness } from 'app/modules/forms/ix-forms/testing/ix-form.harness'; @@ -52,7 +52,7 @@ describe('EncryptionOptionsDialogComponent', () => { dataset: { id: 'pool/parent/child', encryption_root: 'pool/parent/child', - children: [], + children: [] as DatasetDetails[], key_format: { value: EncryptionKeyFormat.Passphrase, }, diff --git a/src/app/pages/datasets/modules/encryption/components/zfs-encryption-card/zfs-encryption-card.component.spec.ts b/src/app/pages/datasets/modules/encryption/components/zfs-encryption-card/zfs-encryption-card.component.spec.ts index 53584b844b3..b159df25f0d 100644 --- a/src/app/pages/datasets/modules/encryption/components/zfs-encryption-card/zfs-encryption-card.component.spec.ts +++ b/src/app/pages/datasets/modules/encryption/components/zfs-encryption-card/zfs-encryption-card.component.spec.ts @@ -71,8 +71,8 @@ describe('ZfsEncryptionCardComponent', () => { function getDetails(): Record { return spectator.queryAll('.details-item').reduce((acc, item: HTMLElement) => { - const key = item.querySelector('.label').textContent; - const value = item.querySelector('.value').textContent; + const key = item.querySelector('.label')!.textContent!; + const value = item.querySelector('.value')!.textContent!; acc[key] = value; return acc; }, {} as Record); diff --git a/src/app/pages/datasets/modules/permissions/components/permissions-item/permissions-item.component.spec.ts b/src/app/pages/datasets/modules/permissions/components/permissions-item/permissions-item.component.spec.ts index 648620b4b10..365852ebc0b 100644 --- a/src/app/pages/datasets/modules/permissions/components/permissions-item/permissions-item.component.spec.ts +++ b/src/app/pages/datasets/modules/permissions/components/permissions-item/permissions-item.component.spec.ts @@ -28,7 +28,7 @@ describe('PermissionsItemComponent', () => { }, }); - expect(spectator.query(IxIconComponent).name).toBe('people'); + expect(spectator.query(IxIconComponent)!.name).toBe('people'); expect(spectator.query('.name')).toHaveExactText('Group – johns'); expect(spectator.query('.permissions')).toHaveExactText('Read | Execute'); }); diff --git a/src/app/pages/datasets/modules/permissions/components/save-as-preset-modal/save-as-preset-modal.component.spec.ts b/src/app/pages/datasets/modules/permissions/components/save-as-preset-modal/save-as-preset-modal.component.spec.ts index 6f479227fc1..7ddb806b49f 100644 --- a/src/app/pages/datasets/modules/permissions/components/save-as-preset-modal/save-as-preset-modal.component.spec.ts +++ b/src/app/pages/datasets/modules/permissions/components/save-as-preset-modal/save-as-preset-modal.component.spec.ts @@ -7,7 +7,7 @@ import { createComponentFactory, mockProvider, Spectator } from '@ngneat/spectat import { of } from 'rxjs'; import { mockCall, mockApi } from 'app/core/testing/utils/mock-api.utils'; import { AclType } from 'app/enums/acl-type.enum'; -import { Acl, AclTemplateByPath } from 'app/interfaces/acl.interface'; +import { Acl, AclTemplateByPath, PosixAclItem } from 'app/interfaces/acl.interface'; import { DialogService } from 'app/modules/dialog/dialog.service'; import { IxInputHarness } from 'app/modules/forms/ix-forms/components/ix-input/ix-input.harness'; import { SaveAsPresetModalComponent } from 'app/pages/datasets/modules/permissions/components/save-as-preset-modal/save-as-preset-modal.component'; @@ -44,7 +44,7 @@ describe('SaveAsPresetModalComponent', () => { id: 4, name: 'a', acltype: AclType.Nfs4, acl: [], }, { - id: 5, name: 'b', acltype: AclType.Posix1e, acl: [], + id: 5, name: 'b', acltype: AclType.Posix1e, acl: [] as PosixAclItem[], }, { id: 6, name: 'f', acltype: AclType.Nfs4, acl: [], diff --git a/src/app/pages/datasets/modules/permissions/components/view-nfs-permissions/view-nfs-permissions.component.spec.ts b/src/app/pages/datasets/modules/permissions/components/view-nfs-permissions/view-nfs-permissions.component.spec.ts index 65f15e013c9..e883632acc1 100644 --- a/src/app/pages/datasets/modules/permissions/components/view-nfs-permissions/view-nfs-permissions.component.spec.ts +++ b/src/app/pages/datasets/modules/permissions/components/view-nfs-permissions/view-nfs-permissions.component.spec.ts @@ -73,10 +73,10 @@ describe('ViewNfsPermissionsComponent', () => { it('allows to click on one of the aces to see more details for basic permissions', () => { spectator.click(byText('User - John')); - const permissions = spectator.query(byText('Permissions Basic')) - .parentElement.querySelectorAll('.details-item'); - const flags = spectator.query(byText('Flags Basic')) - .parentElement.querySelectorAll('.details-item'); + const permissions = spectator.query(byText('Permissions Basic'))! + .parentElement!.querySelectorAll('.details-item'); + const flags = spectator.query(byText('Flags Basic'))! + .parentElement!.querySelectorAll('.details-item'); expect(permissions).toHaveLength(1); expect(flags).toHaveLength(1); @@ -87,10 +87,10 @@ describe('ViewNfsPermissionsComponent', () => { it('allows to click on one of the aces to see more details for advanced permissions', () => { spectator.click(byText('User - Sarah')); - const permissions = spectator.query(byText('Permissions Advanced')) - .parentElement.querySelectorAll('.details-item'); - const flags = spectator.query(byText('Flags Advanced')) - .parentElement.querySelectorAll('.details-item'); + const permissions = spectator.query(byText('Permissions Advanced'))! + .parentElement!.querySelectorAll('.details-item'); + const flags = spectator.query(byText('Flags Advanced'))! + .parentElement!.querySelectorAll('.details-item'); expect(permissions).toHaveLength(3); expect(flags).toHaveLength(2); diff --git a/src/app/pages/datasets/modules/permissions/components/view-nfs-permissions/view-nfs-permissions.component.ts b/src/app/pages/datasets/modules/permissions/components/view-nfs-permissions/view-nfs-permissions.component.ts index c9b62fa0370..176a2bf93f2 100644 --- a/src/app/pages/datasets/modules/permissions/components/view-nfs-permissions/view-nfs-permissions.component.ts +++ b/src/app/pages/datasets/modules/permissions/components/view-nfs-permissions/view-nfs-permissions.component.ts @@ -70,13 +70,15 @@ export class ViewNfsPermissionsComponent implements OnChanges { if (areNfsPermissionsBasic(ace.perms)) { arePermissionsBasic = true; - permissions = [this.translate.instant(nfsBasicPermissionLabels.get(ace.perms.BASIC))]; + permissions = [this.translate.instant(nfsBasicPermissionLabels.get(ace.perms.BASIC) || ace.perms.BASIC)]; } else { arePermissionsBasic = false; permissions = Object.entries(ace.perms) .filter(([, isOn]) => isOn) .map(([permission]) => { - return this.translate.instant(nfsAdvancedPermissionLabels.get(permission as NfsAdvancedPermission)); + return this.translate.instant( + nfsAdvancedPermissionLabels.get(permission as NfsAdvancedPermission) || permission, + ); }); } @@ -86,13 +88,13 @@ export class ViewNfsPermissionsComponent implements OnChanges { if (areNfsFlagsBasic(ace.flags)) { areFlagsBasic = true; - flags = [this.translate.instant(nfsBasicFlagLabels.get(ace.flags.BASIC))]; + flags = [this.translate.instant(nfsBasicFlagLabels.get(ace.flags.BASIC) || ace.flags.BASIC)]; } else { areFlagsBasic = false; flags = Object.entries(ace.flags) .filter(([, isOn]) => isOn) .map(([flag]) => { - return this.translate.instant(nfsAdvancedFlagLabels.get(flag as NfsAdvancedFlag)); + return this.translate.instant(nfsAdvancedFlagLabels.get(flag as NfsAdvancedFlag) || flag); }); } diff --git a/src/app/pages/datasets/modules/permissions/containers/dataset-acl-editor/acl-editor-save-controls/acl-editor-save-controls.component.ts b/src/app/pages/datasets/modules/permissions/containers/dataset-acl-editor/acl-editor-save-controls/acl-editor-save-controls.component.ts index 02ebe870c61..b9e8af2dd3a 100644 --- a/src/app/pages/datasets/modules/permissions/containers/dataset-acl-editor/acl-editor-save-controls/acl-editor-save-controls.component.ts +++ b/src/app/pages/datasets/modules/permissions/containers/dataset-acl-editor/acl-editor-save-controls/acl-editor-save-controls.component.ts @@ -85,7 +85,7 @@ export class AclEditorSaveControlsComponent implements OnInit { } private setRecursiveCheckboxWarning(): void { - this.saveParameters.get('recursive').valueChanges.pipe( + this.saveParameters.controls.recursive.valueChanges.pipe( filter(Boolean), switchMap(() => { return this.dialogService.confirm({ diff --git a/src/app/pages/datasets/modules/permissions/containers/dataset-acl-editor/dataset-acl-editor.component.spec.ts b/src/app/pages/datasets/modules/permissions/containers/dataset-acl-editor/dataset-acl-editor.component.spec.ts index 8a82036bd2b..207c9cd3a22 100644 --- a/src/app/pages/datasets/modules/permissions/containers/dataset-acl-editor/dataset-acl-editor.component.spec.ts +++ b/src/app/pages/datasets/modules/permissions/containers/dataset-acl-editor/dataset-acl-editor.component.spec.ts @@ -170,7 +170,7 @@ describe('DatasetAclEditorComponent', () => { }); it('shows form for appropriate ace selected', () => { - const form = spectator.query(EditNfsAceComponent); + const form = spectator.query(EditNfsAceComponent)!; expect(form).toExist(); expect(form.ace).toBe(acl.acl[0]); diff --git a/src/app/pages/datasets/modules/permissions/containers/permissions-card/permissions-card.component.spec.ts b/src/app/pages/datasets/modules/permissions/containers/permissions-card/permissions-card.component.spec.ts index f1f98a5241c..92e5db6f9b1 100644 --- a/src/app/pages/datasets/modules/permissions/containers/permissions-card/permissions-card.component.spec.ts +++ b/src/app/pages/datasets/modules/permissions/containers/permissions-card/permissions-card.component.spec.ts @@ -86,12 +86,12 @@ describe('PermissionsCardComponent', () => { it('shows dataset ownership information', () => { const [ownerItem, groupItem] = spectator.queryAll('.details-item'); - expect(ownerItem.textContent.replace(/\s/g, '')).toBe('Owner:john'); - expect(groupItem.textContent.replace(/\s/g, '')).toBe('Group:johns'); + expect(ownerItem.textContent!.replace(/\s/g, '')).toBe('Owner:john'); + expect(groupItem.textContent!.replace(/\s/g, '')).toBe('Group:johns'); }); it('shows trivial permissions when acl is trivial', () => { - const permissionsComponent = spectator.query(ViewTrivialPermissionsComponent); + const permissionsComponent = spectator.query(ViewTrivialPermissionsComponent)!; expect(permissionsComponent).toExist(); expect(permissionsComponent.stat).toBe(stat); }); @@ -109,7 +109,7 @@ describe('PermissionsCardComponent', () => { mountpoint: '/mnt/test/posix', }); - const permissionsComponent = spectator.query(ViewPosixPermissionsComponent); + const permissionsComponent = spectator.query(ViewPosixPermissionsComponent)!; expect(permissionsComponent).toExist(); expect(permissionsComponent.acl).toBe(acl); }); @@ -141,7 +141,7 @@ describe('PermissionsCardComponent', () => { spectator.tick(); spectator.detectChanges(); - const permissionsComponent = spectator.query(ViewNfsPermissionsComponent); + const permissionsComponent = spectator.query(ViewNfsPermissionsComponent)!; expect(permissionsComponent).toExist(); expect(permissionsComponent.acl).toBe(acl); })); diff --git a/src/app/pages/datasets/modules/permissions/interfaces/permissions-sidebar-state.interface.ts b/src/app/pages/datasets/modules/permissions/interfaces/permissions-sidebar-state.interface.ts index 85da74dffe7..6c8cb27411d 100644 --- a/src/app/pages/datasets/modules/permissions/interfaces/permissions-sidebar-state.interface.ts +++ b/src/app/pages/datasets/modules/permissions/interfaces/permissions-sidebar-state.interface.ts @@ -3,6 +3,6 @@ import { FileSystemStat } from 'app/interfaces/filesystem-stat.interface'; export interface PermissionsCardState { isLoading: boolean; - stat: FileSystemStat; - acl: Acl; + stat: FileSystemStat | null; + acl: Acl | null; } diff --git a/src/app/pages/datasets/modules/permissions/utils/nfs-ace-to-permission-item.utils.ts b/src/app/pages/datasets/modules/permissions/utils/nfs-ace-to-permission-item.utils.ts index 4ce6e9d6064..a20486711bb 100644 --- a/src/app/pages/datasets/modules/permissions/utils/nfs-ace-to-permission-item.utils.ts +++ b/src/app/pages/datasets/modules/permissions/utils/nfs-ace-to-permission-item.utils.ts @@ -14,7 +14,7 @@ import { import { getAceWhoString } from 'app/pages/datasets/modules/permissions/utils/get-ace-who-string.utils'; export function nfsAceToPermissionItem(translate: TranslateService, ace: NfsAclItem): PermissionItem { - let name = translate.instant(nfsAclTagLabels.get(ace.tag)); + let name = translate.instant(nfsAclTagLabels.get(ace.tag) || ace.tag); let type: PermissionsItemType; switch (ace.tag) { @@ -32,14 +32,14 @@ export function nfsAceToPermissionItem(translate: TranslateService, ace: NfsAclI type = PermissionsItemType.Other; } - const access = translate.instant(nfsAclTypeLabels.get(ace.type)); + const access = translate.instant(nfsAclTypeLabels.get(ace.type) || ace.type); let action = translate.instant('Special'); if (areNfsPermissionsBasic(ace.perms)) { - action = translate.instant(nfsBasicPermissionLabels.get(ace.perms.BASIC)); + action = translate.instant(nfsBasicPermissionLabels.get(ace.perms.BASIC) || ace.perms.BASIC); } else { const permissions = Object.keys(ace.perms) as NfsAdvancedPermission[]; if (permissions.length === 1) { - action = translate.instant(nfsAdvancedPermissionLabels.get(permissions[0])); + action = translate.instant(nfsAdvancedPermissionLabels.get(permissions[0]) || permissions[0]); } } diff --git a/src/app/pages/datasets/modules/snapshots/snapshot-add-form/snapshot-add-form.component.ts b/src/app/pages/datasets/modules/snapshots/snapshot-add-form/snapshot-add-form.component.ts index e95abb28259..6fe3416464c 100644 --- a/src/app/pages/datasets/modules/snapshots/snapshot-add-form/snapshot-add-form.component.ts +++ b/src/app/pages/datasets/modules/snapshots/snapshot-add-form/snapshot-add-form.component.ts @@ -69,13 +69,13 @@ export class SnapshotAddFormComponent implements OnInit { readonly requiredRoles = [Role.SnapshotWrite]; isFormLoading = true; - form = this.fb.group({ + form = this.fb.nonNullable.group({ dataset: ['', Validators.required], name: [this.getDefaultSnapshotName(), [this.validatorsService.withMessage( atLeastOne('naming_schema', [helptextSnapshots.snapshot_add_name_placeholder, helptextSnapshots.snapshot_add_naming_schema_placeholder]), this.translate.instant('Name or Naming Schema must be provided.'), ), this.validatorsService.validateOnCondition( - (control: AbstractControl) => control.value && control.parent?.get('naming_schema').value, + (control: AbstractControl) => control.value && control.parent?.get('naming_schema')?.value, this.validatorsService.withMessage( requiredEmpty(), this.translate.instant('Name and Naming Schema cannot be provided at the same time.'), diff --git a/src/app/pages/jobs/jobs-list.component.ts b/src/app/pages/jobs/jobs-list.component.ts index 313f305917c..4f929bd6800 100644 --- a/src/app/pages/jobs/jobs-list.component.ts +++ b/src/app/pages/jobs/jobs-list.component.ts @@ -105,7 +105,7 @@ export class JobsListComponent implements OnInit { dateColumn({ title: this.translate.instant('Finished'), propertyName: 'time_finished', - sortBy: (job) => +job.time_finished, + sortBy: (job) => Number(job.time_finished), }), ], { uniqueRowTag: (row) => `job-${row.id}`, diff --git a/src/app/pages/network/components/configuration/configuration.component.spec.ts b/src/app/pages/network/components/configuration/configuration.component.spec.ts index 9826de7afae..f7f400ba636 100644 --- a/src/app/pages/network/components/configuration/configuration.component.spec.ts +++ b/src/app/pages/network/components/configuration/configuration.component.spec.ts @@ -7,7 +7,7 @@ import { createComponentFactory, mockProvider, Spectator } from '@ngneat/spectat import { mockCall, mockApi } from 'app/core/testing/utils/mock-api.utils'; import { mockAuth } from 'app/core/testing/utils/mock-auth.utils'; import { NetworkActivityType } from 'app/enums/network-activity-type.enum'; -import { NetworkConfiguration } from 'app/interfaces/network-configuration.interface'; +import { NetworkConfiguration, NetworkConfigurationActivity } from 'app/interfaces/network-configuration.interface'; import { DialogService } from 'app/modules/dialog/dialog.service'; import { IxRadioGroupHarness } from 'app/modules/forms/ix-forms/components/ix-radio-group/ix-radio-group.harness'; import { FormErrorHandlerService } from 'app/modules/forms/ix-forms/services/form-error-handler.service'; @@ -40,12 +40,12 @@ describe('NetworkConfigurationComponent', () => { activity: { activities: [], type: NetworkActivityType.Deny, - }, + } as NetworkConfigurationActivity, domain: 'local', - domains: [], + domains: [] as string[], hostname: 'truenas', hostname_local: 'truenas', - hosts: [], + hosts: [] as string[], httpproxy: '', id: 1, ipv4gateway: '', diff --git a/src/app/pages/network/components/interface-form/interface-form.component.spec.ts b/src/app/pages/network/components/interface-form/interface-form.component.spec.ts index 02bb86fe152..6215a6982f1 100644 --- a/src/app/pages/network/components/interface-form/interface-form.component.spec.ts +++ b/src/app/pages/network/components/interface-form/interface-form.component.spec.ts @@ -45,7 +45,7 @@ describe('InterfaceFormComponent', () => { let loader: HarnessLoader; let api: ApiService; let form: IxFormHarness; - let aliasesList: IxListHarness; + let aliasesList: IxListHarness | null; const existingInterface = { id: 'enp0s6', name: 'enp0s6', @@ -152,7 +152,7 @@ describe('InterfaceFormComponent', () => { await form.fillForm({ Type: 'Bridge', }); - await aliasesList.pressAddButton(); + await aliasesList!.pressAddButton(); await form.fillForm({ Name: 'br0', @@ -455,7 +455,7 @@ describe('InterfaceFormComponent', () => { it('shows Failover Critical and Failover Group when failover is enabled', async () => { jest.spyOn(spectator.inject(MatDialog), 'open'); - await aliasesList.pressAddButton(); + await aliasesList!.pressAddButton(); await form.fillForm({ Type: 'Bridge', Name: 'br0', diff --git a/src/app/pages/network/components/interface-form/interface-name-validator.service.ts b/src/app/pages/network/components/interface-form/interface-name-validator.service.ts index 7c76727bd1a..386eecfce63 100644 --- a/src/app/pages/network/components/interface-form/interface-name-validator.service.ts +++ b/src/app/pages/network/components/interface-form/interface-name-validator.service.ts @@ -13,7 +13,7 @@ export class InterfaceNameValidatorService { private validatorsService: IxValidatorsService, ) {} - validate: ValidatorFn = (control: AbstractControl): ValidationErrors => { + validate: ValidatorFn = (control: AbstractControl): ValidationErrors | null => { if (!control.parent) { return null; } @@ -40,7 +40,7 @@ export class InterfaceNameValidatorService { getNameFormatMessage(type: NetworkInterfaceType): string { const prefix = this.getNamePrefix(type); - let interfaceName: string; + let interfaceName = ''; switch (type) { case NetworkInterfaceType.Bridge: interfaceName = this.translate.instant('Bridge interface'); diff --git a/src/app/pages/network/components/interfaces-card/ip-addresses-cell/ip-addresses-cell.component.spec.ts b/src/app/pages/network/components/interfaces-card/ip-addresses-cell/ip-addresses-cell.component.spec.ts index 79f91f7a505..474bfe4280f 100644 --- a/src/app/pages/network/components/interfaces-card/ip-addresses-cell/ip-addresses-cell.component.spec.ts +++ b/src/app/pages/network/components/interfaces-card/ip-addresses-cell/ip-addresses-cell.component.spec.ts @@ -1,6 +1,6 @@ import { createComponentFactory, Spectator } from '@ngneat/spectator/jest'; import { NetworkInterfaceAliasType } from 'app/enums/network-interface.enum'; -import { NetworkInterface } from 'app/interfaces/network-interface.interface'; +import { NetworkInterface, NetworkInterfaceAlias } from 'app/interfaces/network-interface.interface'; import { IpAddressesCellComponent, } from 'app/pages/network/components/interfaces-card/ip-addresses-cell/ip-addresses-cell.component'; @@ -33,7 +33,7 @@ describe('IpAddressesCellComponent', () => { it('shows NICs state aliases for interfaces with DHCP', () => { spectator.component.setRow({ ipv4_dhcp: true, - aliases: [], + aliases: [] as NetworkInterfaceAlias[], state: { aliases: [ { address: '56.23.44.2', netmask: 24, type: NetworkInterfaceAliasType.Inet }, @@ -51,7 +51,7 @@ describe('IpAddressesCellComponent', () => { it('shows failover aliases', () => { spectator.component.setRow({ - aliases: [], + aliases: [] as NetworkInterfaceAlias[], failover_aliases: [ { address: '33.12.44.2', netmask: 24, type: NetworkInterfaceAliasType.Inet }, { address: '33.12.45.2', netmask: 24, type: NetworkInterfaceAliasType.Inet }, @@ -67,7 +67,7 @@ describe('IpAddressesCellComponent', () => { it('shows virtual addresses if any', () => { spectator.component.setRow({ - aliases: [], + aliases: [] as NetworkInterfaceAlias[], failover_virtual_aliases: [ { address: '33.10.44.2', netmask: 24, type: NetworkInterfaceAliasType.Inet }, { address: '33.10.45.2', netmask: 24, type: NetworkInterfaceAliasType.Inet }, diff --git a/src/app/pages/network/network.component.ts b/src/app/pages/network/network.component.ts index ac348142a40..a39bae08972 100644 --- a/src/app/pages/network/network.component.ts +++ b/src/app/pages/network/network.component.ts @@ -82,16 +82,16 @@ export class NetworkComponent implements OnInit { checkinTimeout = 60; checkinTimeoutMinValue = 10; checkinTimeoutPattern = '^[0-9]+$'; - checkinRemaining: number = null; + checkinRemaining: number | null = null; private uniqueIps: string[] = []; private affectedServices: string[] = []; checkinInterval: Interval; - private navigation: Navigation; + private navigation: Navigation | null; helptext = helptextInterfaces; get isCheckinTimeoutFieldInvalid(): boolean { - return this.checkinTimeoutField()?.invalid; + return this.checkinTimeoutField()?.invalid || false; } constructor( @@ -187,7 +187,7 @@ export class NetworkComponent implements OnInit { }); } - private getCheckInWaitingSeconds(): Promise { + private getCheckInWaitingSeconds(): Promise { return lastValueFrom( this.api.call('interface.checkin_waiting'), ); @@ -205,7 +205,7 @@ export class NetworkComponent implements OnInit { ); } - private handleWaitingCheckIn(seconds: number, isAfterInterfaceCommit = false): void { + private handleWaitingCheckIn(seconds: number | null, isAfterInterfaceCommit = false): void { if (seconds !== null) { if (seconds > 0 && this.checkinRemaining === null) { this.checkinRemaining = Math.round(seconds); diff --git a/src/app/pages/services/components/service-nfs/add-spn-dialog/add-spn-dialog.component.ts b/src/app/pages/services/components/service-nfs/add-spn-dialog/add-spn-dialog.component.ts index 0e20352ab69..d671ea90586 100644 --- a/src/app/pages/services/components/service-nfs/add-spn-dialog/add-spn-dialog.component.ts +++ b/src/app/pages/services/components/service-nfs/add-spn-dialog/add-spn-dialog.component.ts @@ -37,7 +37,7 @@ import { ApiService } from 'app/services/websocket/api.service'; export class AddSpnDialogComponent { readonly requiredRoles = [Role.FullAdmin]; - readonly form = this.formBuilder.group({ + readonly form = this.formBuilder.nonNullable.group({ username: ['', Validators.required], password: ['', Validators.required], }); @@ -53,9 +53,10 @@ export class AddSpnDialogComponent { ) { } onSubmit(): void { + const value = this.form.getRawValue(); const payload = { - username: this.form.value.username, - password: this.form.value.password, + username: value.username, + password: value.password, }; this.api.call('nfs.add_principal', [payload]) diff --git a/src/app/pages/services/services.component.ts b/src/app/pages/services/services.component.ts index 800c3055756..d9a1dfa8d82 100644 --- a/src/app/pages/services/services.component.ts +++ b/src/app/pages/services/services.component.ts @@ -176,7 +176,7 @@ export class ServicesComponent implements OnInit { waitForServices, map((services) => services.map((service) => ({ ...service, - name: serviceNames.has(service.service) ? serviceNames.get(service.service) : service.service, + name: serviceNames.get(service.service) || service.service, }))), untilDestroyed(this), ).subscribe({ diff --git a/src/app/pages/sharing/iscsi/target/all-targets/all-targets.component.ts b/src/app/pages/sharing/iscsi/target/all-targets/all-targets.component.ts index d3e8381cd4c..047d2bef44e 100644 --- a/src/app/pages/sharing/iscsi/target/all-targets/all-targets.component.ts +++ b/src/app/pages/sharing/iscsi/target/all-targets/all-targets.component.ts @@ -46,7 +46,7 @@ import { ApiService } from 'app/services/websocket/api.service'; }) export class AllTargetsComponent implements OnInit { protected dataProvider: AsyncDataProvider; - targets = signal(null); + targets = signal(null); readonly requiredRoles = [ Role.SharingIscsiTargetWrite, diff --git a/src/app/pages/sharing/iscsi/target/all-targets/target-details/connections-card/connections-card.component.ts b/src/app/pages/sharing/iscsi/target/all-targets/target-details/connections-card/connections-card.component.ts index b7535d6f6d4..daa781c4f18 100644 --- a/src/app/pages/sharing/iscsi/target/all-targets/target-details/connections-card/connections-card.component.ts +++ b/src/app/pages/sharing/iscsi/target/all-targets/target-details/connections-card/connections-card.component.ts @@ -38,7 +38,7 @@ export class ConnectionsCardComponent { readonly target = input.required(); isLoading = signal(false); - sessions = signal(null); + sessions = signal(null); constructor( private api: ApiService, diff --git a/src/app/pages/sharing/iscsi/target/all-targets/target-details/target-details.component.spec.ts b/src/app/pages/sharing/iscsi/target/all-targets/target-details/target-details.component.spec.ts index 9adfc57fb44..7de0d3273b1 100644 --- a/src/app/pages/sharing/iscsi/target/all-targets/target-details/target-details.component.spec.ts +++ b/src/app/pages/sharing/iscsi/target/all-targets/target-details/target-details.component.spec.ts @@ -91,7 +91,7 @@ describe('TargetDetailsComponent', () => { target: { id: 2, mode: 'FC', - auth_networks: [], + auth_networks: [] as string[], } as IscsiTarget, }); diff --git a/src/app/pages/sharing/iscsi/target/all-targets/target-details/target-details.component.ts b/src/app/pages/sharing/iscsi/target/all-targets/target-details/target-details.component.ts index 66632c0c7fb..68830f685a7 100644 --- a/src/app/pages/sharing/iscsi/target/all-targets/target-details/target-details.component.ts +++ b/src/app/pages/sharing/iscsi/target/all-targets/target-details/target-details.component.ts @@ -34,7 +34,7 @@ import { ApiService } from 'app/services/websocket/api.service'; export class TargetDetailsComponent { readonly target = input.required(); - targetPort = signal(null); + targetPort = signal(null); connections = toSignal(this.api.call('fcport.status')); protected hasIscsiCards = computed(() => [ diff --git a/src/app/pages/sharing/iscsi/target/delete-target-dialog/delete-target-dialog.component.ts b/src/app/pages/sharing/iscsi/target/delete-target-dialog/delete-target-dialog.component.ts index 3554d49386b..f189379d1a5 100644 --- a/src/app/pages/sharing/iscsi/target/delete-target-dialog/delete-target-dialog.component.ts +++ b/src/app/pages/sharing/iscsi/target/delete-target-dialog/delete-target-dialog.component.ts @@ -47,7 +47,7 @@ export class DeleteTargetDialogComponent implements OnInit { protected readonly requiredRoles = [Role.SharingIscsiTargetWrite]; readonly targetExtents = signal([]); - protected warningMessage: string = null; + protected warningMessage = ''; form = this.formBuilder.group({ delete_extents: [false], diff --git a/src/app/pages/signin/failover-status/failover-status.component.ts b/src/app/pages/signin/failover-status/failover-status.component.ts index 01469d2a78b..9fa3edba8ce 100644 --- a/src/app/pages/signin/failover-status/failover-status.component.ts +++ b/src/app/pages/signin/failover-status/failover-status.component.ts @@ -37,17 +37,19 @@ export class FailoverStatusComponent { }; protected statusMessage = computed(() => { + const disabledReasons = this.disabledReasons(); + if (!disabledReasons) { + return this.translate.instant('Checking HA status'); + } + switch (true) { - case !this.disabledReasons(): { - return this.translate.instant('Checking HA status'); - } - case this.disabledReasons().length === 0: { + case disabledReasons.length === 0: { return this.translate.instant('HA is enabled.'); } - case this.disabledReasons()[0] === FailoverDisabledReason.NoSystemReady: { + case disabledReasons[0] === FailoverDisabledReason.NoSystemReady: { return this.translate.instant('HA is reconnecting.'); } - case this.disabledReasons()[0] === FailoverDisabledReason.NoFailover: + case disabledReasons[0] === FailoverDisabledReason.NoFailover: return this.translate.instant('HA is administratively disabled.'); default: { return this.translate.instant('HA is in a faulted state'); @@ -55,7 +57,7 @@ export class FailoverStatusComponent { } }); - protected areReasonsShown = computed(() => this.disabledReasons()?.length > 1); + protected areReasonsShown = computed(() => Number(this.disabledReasons()?.length) > 1); constructor( private translate: TranslateService, diff --git a/src/app/pages/signin/set-admin-password-form/set-admin-password-form.component.ts b/src/app/pages/signin/set-admin-password-form/set-admin-password-form.component.ts index 2cec0aca71e..0a5e561708c 100644 --- a/src/app/pages/signin/set-admin-password-form/set-admin-password-form.component.ts +++ b/src/app/pages/signin/set-admin-password-form/set-admin-password-form.component.ts @@ -40,7 +40,7 @@ const adminUsername = 'truenas_admin'; export class SetAdminPasswordFormComponent { isLoading$ = this.signinStore.isLoading$; - form = this.formBuilder.group({ + form = this.formBuilder.nonNullable.group({ username: [adminUsername, Validators.required], password: ['', Validators.required], password2: ['', [ @@ -66,7 +66,7 @@ export class SetAdminPasswordFormComponent { ) { } onSubmit(): void { - const { username, password } = this.form.value; + const { username, password } = this.form.getRawValue(); this.signinStore.setLoadingState(true); const request$ = this.api.call('user.setup_local_administrator', [username, password]); diff --git a/src/app/pages/signin/signin.component.spec.ts b/src/app/pages/signin/signin.component.spec.ts index 4115fe2643d..ad75a97735f 100644 --- a/src/app/pages/signin/signin.component.spec.ts +++ b/src/app/pages/signin/signin.component.spec.ts @@ -134,7 +134,7 @@ describe('SigninComponent', () => { hasFailover$.next(true); spectator.detectChanges(); - const failoverStatus = spectator.query(FailoverStatusComponent); + const failoverStatus = spectator.query(FailoverStatusComponent)!; expect(failoverStatus).toExist(); expect(failoverStatus.disabledReasons).toEqual([FailoverDisabledReason.NoPong]); expect(failoverStatus.status).toEqual(FailoverStatus.Error); diff --git a/src/app/pages/storage/components/dashboard-pool/dashboard-pool.component.spec.ts b/src/app/pages/storage/components/dashboard-pool/dashboard-pool.component.spec.ts index 55a4d4286db..30ca8f8a1c8 100644 --- a/src/app/pages/storage/components/dashboard-pool/dashboard-pool.component.spec.ts +++ b/src/app/pages/storage/components/dashboard-pool/dashboard-pool.component.spec.ts @@ -111,13 +111,13 @@ describe('DashboardPoolComponent', () => { }); it('shows a ZFS Health card for the pool', () => { - const card = spectator.query(ZfsHealthCardComponent); + const card = spectator.query(ZfsHealthCardComponent)!; expect(card).toBeTruthy(); expect(card.pool).toBe(pool); }); it('shows a disk health card for the pool', () => { - const card = spectator.query(DiskHealthCardComponent); + const card = spectator.query(DiskHealthCardComponent)!; expect(card).toBeTruthy(); expect(card.poolState).toBe(pool); }); diff --git a/src/app/pages/storage/components/dashboard-pool/disk-health-card/disk-health-card.component.spec.ts b/src/app/pages/storage/components/dashboard-pool/disk-health-card/disk-health-card.component.spec.ts index fc397d9cada..8efc38c4926 100644 --- a/src/app/pages/storage/components/dashboard-pool/disk-health-card/disk-health-card.component.spec.ts +++ b/src/app/pages/storage/components/dashboard-pool/disk-health-card/disk-health-card.component.spec.ts @@ -84,29 +84,29 @@ describe('DiskHealthCardComponent', () => { describe('Temperatures', () => { it('shows disks temperature related alerts', () => { - const detailsItem = spectator.query(byText('Disks temperature related alerts:')).parentElement; + const detailsItem = spectator.query(byText('Disks temperature related alerts:'))!.parentElement!; expect(detailsItem.querySelector('.value')).toHaveText('0'); }); it('shows highest temperature', () => { - const detailsItem = spectator.query(byText('Highest Temperature:')).parentElement; + const detailsItem = spectator.query(byText('Highest Temperature:'))!.parentElement!; expect(detailsItem.querySelector('.value')).toHaveText('50 °C'); }); it('shows lowest temperature', () => { - const detailsItem = spectator.query(byText('Lowest Temperature:')).parentElement; + const detailsItem = spectator.query(byText('Lowest Temperature:'))!.parentElement!; expect(detailsItem.querySelector('.value')).toHaveText('10 °C'); }); it('shows average temperature', () => { - const detailsItem = spectator.query(byText('Average Disk Temperature:')).parentElement; + const detailsItem = spectator.query(byText('Average Disk Temperature:'))!.parentElement!; expect(detailsItem.querySelector('.value')).toHaveText('30 °C'); }); }); describe('Smart Tests', () => { it('shows failed smart tests', () => { - const detailsItem = spectator.query(byText('Failed S.M.A.R.T. Tests:')).parentElement; + const detailsItem = spectator.query(byText('Failed S.M.A.R.T. Tests:'))!.parentElement!; expect(detailsItem.querySelector('.value')).toHaveText('0'); }); }); diff --git a/src/app/pages/storage/components/dashboard-pool/export-disconnect-modal/export-disconnect-modal.component.ts b/src/app/pages/storage/components/dashboard-pool/export-disconnect-modal/export-disconnect-modal.component.ts index 5c293daacfc..ceceb1ed90f 100644 --- a/src/app/pages/storage/components/dashboard-pool/export-disconnect-modal/export-disconnect-modal.component.ts +++ b/src/app/pages/storage/components/dashboard-pool/export-disconnect-modal/export-disconnect-modal.component.ts @@ -87,17 +87,17 @@ export class ExportDisconnectModalComponent implements OnInit { systemConfig: SystemDatasetConfig; isFormLoading = false; - form = this.fb.group({ + form = this.fb.nonNullable.group({ destroy: [false], cascade: [true], confirm: [false, [Validators.requiredTrue]], nameInput: ['', [ this.validatorsService.validateOnCondition( - (control: AbstractControl) => control.parent?.get('destroy').value, + (control: AbstractControl) => control.parent?.get('destroy')?.value, this.nameInputRequired, ), this.validatorsService.validateOnCondition( - (control: AbstractControl) => control.parent?.get('destroy').value, + (control: AbstractControl) => control.parent?.get('destroy')?.value, this.nameInputMustMatch, ), ]], @@ -136,7 +136,7 @@ export class ExportDisconnectModalComponent implements OnInit { } startExportDisconnectJob(): void { - const value = this.form.value; + const value = this.form.getRawValue(); const job$ = this.api.job('pool.export', [ this.pool.id, diff --git a/src/app/pages/storage/components/dashboard-pool/pool-card-icon/pool-card-icon.component.spec.ts b/src/app/pages/storage/components/dashboard-pool/pool-card-icon/pool-card-icon.component.spec.ts index d7850d0497a..020ddc88c9a 100644 --- a/src/app/pages/storage/components/dashboard-pool/pool-card-icon/pool-card-icon.component.spec.ts +++ b/src/app/pages/storage/components/dashboard-pool/pool-card-icon/pool-card-icon.component.spec.ts @@ -24,27 +24,27 @@ describe('PoolCardIconComponent', () => { spectator = createComponent({ props: { type: PoolCardIconType.Safe }, }); - expect(spectator.query(IxIconComponent).name).toBe('check_circle'); + expect(spectator.query(IxIconComponent)!.name).toBe('check_circle'); }); it('renders icon when type is warn', () => { spectator = createComponent({ props: { type: PoolCardIconType.Warn }, }); - expect(spectator.query(IxIconComponent).name).toBe('error'); + expect(spectator.query(IxIconComponent)!.name).toBe('error'); }); it('renders icon when type is faulted', () => { spectator = createComponent({ props: { type: PoolCardIconType.Faulted }, }); - expect(spectator.query(IxIconComponent).name).toBe('help'); + expect(spectator.query(IxIconComponent)!.name).toBe('help'); }); it('renders icon when type is error', () => { spectator = createComponent({ props: { type: PoolCardIconType.Error }, }); - expect(spectator.query(IxIconComponent).name).toBe('cancel'); + expect(spectator.query(IxIconComponent)!.name).toBe('cancel'); }); }); diff --git a/src/app/pages/storage/components/dashboard-pool/pool-usage-card/pool-usage-card.component.spec.ts b/src/app/pages/storage/components/dashboard-pool/pool-usage-card/pool-usage-card.component.spec.ts index 4cddb1cbd30..039742de716 100644 --- a/src/app/pages/storage/components/dashboard-pool/pool-usage-card/pool-usage-card.component.spec.ts +++ b/src/app/pages/storage/components/dashboard-pool/pool-usage-card/pool-usage-card.component.spec.ts @@ -79,9 +79,9 @@ describe('PoolUsageCardComponent', () => { expect(spectator.query('.used-caption')).toHaveText('Used: 3.15 GiB'); expect(spectator.query('.available-caption')).toHaveText('Available: 858.01 MiB'); expect(spectator.query('.warning-container')).not.toBeVisible(); - expect(spectator.query(GaugeChartComponent).label).toBe('79%'); - expect(spectator.query(GaugeChartComponent).value).toBeCloseTo(79, 0); - expect(spectator.query(GaugeChartComponent).colorFill).toBe('var(--blue)'); + expect(spectator.query(GaugeChartComponent)!.label).toBe('79%'); + expect(spectator.query(GaugeChartComponent)!.value).toBeCloseTo(79, 0); + expect(spectator.query(GaugeChartComponent)!.colorFill).toBe('var(--blue)'); }); it('renders component values when usage is above 80%', () => { @@ -99,14 +99,14 @@ describe('PoolUsageCardComponent', () => { expect(spectator.query('.available-caption')).toHaveText('Available: 480.56 GiB'); expect(spectator.query('.warning-container')).toBeVisible(); expect(spectator.query('.warning-container')).toHaveText('Warning: Low Capacity'); - expect(spectator.query(GaugeChartComponent).label).toBe('81%'); - expect(spectator.query(GaugeChartComponent).value).toBeCloseTo(81, 0); - expect(spectator.query(GaugeChartComponent).colorFill).toBe('#CE2929'); + expect(spectator.query(GaugeChartComponent)!.label).toBe('81%'); + expect(spectator.query(GaugeChartComponent)!.value).toBeCloseTo(81, 0); + expect(spectator.query(GaugeChartComponent)!.colorFill).toBe('#CE2929'); }); it('renders status icon', () => { - expect(spectator.query(PoolCardIconComponent).type).toBe(PoolCardIconType.Safe); - expect(spectator.query(PoolCardIconComponent).tooltip).toBe('Everything is fine'); + expect(spectator.query(PoolCardIconComponent)!.type).toBe(PoolCardIconType.Safe); + expect(spectator.query(PoolCardIconComponent)!.tooltip).toBe('Everything is fine'); spectator.setInput('rootDataset', { used: { @@ -117,12 +117,12 @@ describe('PoolUsageCardComponent', () => { }, } as Dataset); - expect(spectator.query(PoolCardIconComponent).type).toBe(PoolCardIconType.Warn); - expect(spectator.query(PoolCardIconComponent).tooltip).toBe('Pool is using more than 80% of available space'); + expect(spectator.query(PoolCardIconComponent)!.type).toBe(PoolCardIconType.Warn); + expect(spectator.query(PoolCardIconComponent)!.tooltip).toBe('Pool is using more than 80% of available space'); }); it('should pre-select disks when user click "View Disk Space Reports" link', () => { - const href = spectator.query(byText('View Disk Space Reports')).getAttribute('href'); + const href = spectator.query(byText('View Disk Space Reports'))!.getAttribute('href'); expect(href).toBe('/reportsdashboard/disk?disks=sda&disks=sdb'); }); }); diff --git a/src/app/pages/storage/components/dashboard-pool/topology-card/topology-card.component.spec.ts b/src/app/pages/storage/components/dashboard-pool/topology-card/topology-card.component.spec.ts index 17fd4741f00..48e503e70ed 100644 --- a/src/app/pages/storage/components/dashboard-pool/topology-card/topology-card.component.spec.ts +++ b/src/app/pages/storage/components/dashboard-pool/topology-card/topology-card.component.spec.ts @@ -4468,7 +4468,7 @@ describe('TopologyCardComponent', () => { expect(values).toHaveLength(5); expect(captions[0]).toHaveText('Data VDEVs'); - expect(spectator.query('.offline-data-vdevs').textContent).toBe('Offline VDEVs'); + expect(spectator.query('.offline-data-vdevs')!.textContent).toBe('Offline VDEVs'); // Redundancy level should match data VDEVs expect(captions[1]).toHaveText('Metadata'); diff --git a/src/app/pages/storage/components/dashboard-pool/zfs-health-card/zfs-health-card.component.spec.ts b/src/app/pages/storage/components/dashboard-pool/zfs-health-card/zfs-health-card.component.spec.ts index 70a8f50adf0..39a588486e8 100644 --- a/src/app/pages/storage/components/dashboard-pool/zfs-health-card/zfs-health-card.component.spec.ts +++ b/src/app/pages/storage/components/dashboard-pool/zfs-health-card/zfs-health-card.component.spec.ts @@ -117,17 +117,17 @@ describe('ZfsHealthCardComponent', () => { describe('health indication', () => { it('shows an icon for pool status', () => { - expect(spectator.query(PoolCardIconComponent).type).toBe(PoolCardIconType.Safe); - expect(spectator.query(PoolCardIconComponent).tooltip).toBe('Everything is fine'); + expect(spectator.query(PoolCardIconComponent)!.type).toBe(PoolCardIconType.Safe); + expect(spectator.query(PoolCardIconComponent)!.tooltip).toBe('Everything is fine'); }); it('shows pool status string', () => { - const detailsItem = spectator.query(byText('Pool Status:')).parentElement; + const detailsItem = spectator.query(byText('Pool Status:'))!.parentElement!; expect(detailsItem.querySelector('.value')).toHaveText('Online'); }); it('shows total ZFS error count', () => { - const detailsItem = spectator.query(byText('Total ZFS Errors:')).parentElement; + const detailsItem = spectator.query(byText('Total ZFS Errors:'))!.parentElement!; expect(detailsItem.querySelector('.value')).toHaveText('3'); }); }); @@ -136,7 +136,7 @@ describe('ZfsHealthCardComponent', () => { it('loads and shows if scrub task is set along with a link to view all scrub tasks', () => { expect(api.call).toHaveBeenCalledWith('pool.scrub.query', [[['pool_name', '=', 'tank']]]); - const detailsItem = spectator.query(byText('Scheduled Scrub Task:')).parentElement; + const detailsItem = spectator.query(byText('Scheduled Scrub Task:'))!.parentElement!; expect(detailsItem.querySelector('.value')).toHaveText('Set'); const link = detailsItem.querySelector('a'); @@ -145,13 +145,13 @@ describe('ZfsHealthCardComponent', () => { }); it('shows information about last scan', () => { - const lastScan = spectator.query(byText('Last Scan:')).parentElement; + const lastScan = spectator.query(byText('Last Scan:'))!.parentElement!; expect(lastScan.querySelector('.value')).toHaveText('Finished Scrub on 2022-06-22 19:58:45'); - const lastScanErrors = spectator.query(byText('Last Scan Errors:')).parentElement; + const lastScanErrors = spectator.query(byText('Last Scan Errors:'))!.parentElement!; expect(lastScanErrors.querySelector('.value')).toHaveText('1'); - const lastScanDuration = spectator.query(byText('Last Scan Duration:')).parentElement; + const lastScanDuration = spectator.query(byText('Last Scan Duration:'))!.parentElement!; expect(lastScanDuration.querySelector('.value')).toHaveText('44 seconds'); }); @@ -177,7 +177,7 @@ describe('ZfsHealthCardComponent', () => { }); spectator.detectChanges(); - const scanInProgress = spectator.query('.scan-in-progress'); + const scanInProgress = spectator.query('.scan-in-progress')!; expect(scanInProgress.querySelector('.scan-description')).toHaveText('Scrub In Progress: 17.43%'); expect(scanInProgress.querySelector('.time-left')).toHaveText('9 minutes 34 seconds remaining'); @@ -207,19 +207,19 @@ describe('ZfsHealthCardComponent', () => { }, }); - const scanInProgress = spectator.query('.scan-in-progress'); + const scanInProgress = spectator.query('.scan-in-progress')!; expect(scanInProgress.querySelector('.scan-description')).toHaveText('Resilvering: 17.43%'); }); }); describe('auto TRIM', () => { it('shows current auto TRIM setting', () => { - const detailsItem = spectator.query(byText('Auto TRIM:')).parentElement; + const detailsItem = spectator.query(byText('Auto TRIM:'))!.parentElement!; expect(detailsItem.querySelector('.value')).toHaveText('On'); }); it('shows an AutotrimDialog when Edit auto Trim is pressed', () => { - spectator.click(spectator.query(byText('Edit Auto TRIM'))); + spectator.click(spectator.query(byText('Edit Auto TRIM'))!); expect(spectator.inject(MatDialog).open).toHaveBeenCalledWith(AutotrimDialogComponent, { data: pool, @@ -283,7 +283,7 @@ describe('ZfsHealthCardComponent', () => { dedup_table_quota: 'auto', dedup_table_size: 100 * KiB, }); - expect(spectator.query(byText('Deduplication Table:')).parentElement.querySelector('.value')).toHaveText('100 KiB'); + expect(spectator.query(byText('Deduplication Table:'))!.parentElement!.querySelector('.value')).toHaveText('100 KiB'); // Custom spectator.setInput('pool', { @@ -291,7 +291,7 @@ describe('ZfsHealthCardComponent', () => { dedup_table_quota: String(200 * KiB), dedup_table_size: 100 * KiB, }); - expect(spectator.query(byText('Deduplication Table:')).parentElement.querySelector('.value')).toHaveText('100 KiB / 200 KiB'); + expect(spectator.query(byText('Deduplication Table:'))!.parentElement!.querySelector('.value')).toHaveText('100 KiB / 200 KiB'); // None spectator.setInput('pool', { @@ -299,7 +299,7 @@ describe('ZfsHealthCardComponent', () => { dedup_table_quota: '0', dedup_table_size: 100 * KiB, }); - expect(spectator.query(byText('Deduplication Table:')).parentElement.querySelector('.value')).toHaveText('100 KiB'); + expect(spectator.query(byText('Deduplication Table:'))!.parentElement!.querySelector('.value')).toHaveText('100 KiB'); }); it('opens SetDedupQuotaComponent when Set Quota is pressed', () => { @@ -308,7 +308,7 @@ describe('ZfsHealthCardComponent', () => { dedup_table_size: 100 * KiB, }); - spectator.click(spectator.query(byText('Set Quota'))); + spectator.click(spectator.query(byText('Set Quota'))!); expect(spectator.inject(MatDialog).open).toHaveBeenCalledWith(SetDedupQuotaComponent, { data: { @@ -324,7 +324,7 @@ describe('ZfsHealthCardComponent', () => { dedup_table_size: 100 * KiB, }); - spectator.click(spectator.query(byText('Prune'))); + spectator.click(spectator.query(byText('Prune'))!); expect(spectator.inject(MatDialog).open).toHaveBeenCalledWith(PruneDedupTableDialogComponent, { data: { diff --git a/src/app/pages/storage/components/import-pool/import-pool.component.ts b/src/app/pages/storage/components/import-pool/import-pool.component.ts index e7b3acee23f..1b1ac1a9508 100644 --- a/src/app/pages/storage/components/import-pool/import-pool.component.ts +++ b/src/app/pages/storage/components/import-pool/import-pool.component.ts @@ -61,7 +61,7 @@ export class ImportPoolComponent implements OnInit { guid: string; }[] = []; - formGroup = this.fb.group({ + formGroup = this.fb.nonNullable.group({ guid: ['' as string, Validators.required], }); @@ -117,7 +117,7 @@ export class ImportPoolComponent implements OnInit { onSubmit(): void { this.dialogService.jobDialog( - this.api.job('pool.import_pool', [{ guid: this.formGroup.value.guid }]), + this.api.job('pool.import_pool', [{ guid: this.formGroup.getRawValue().guid }]), { title: this.translate.instant('Importing Pool') }, ) .afterClosed() diff --git a/src/app/pages/storage/modules/devices/devices.component.ts b/src/app/pages/storage/modules/devices/devices.component.ts index a107e2b8d0d..257cfd97f9e 100644 --- a/src/app/pages/storage/modules/devices/devices.component.ts +++ b/src/app/pages/storage/modules/devices/devices.component.ts @@ -138,7 +138,7 @@ export class DevicesComponent implements OnInit, AfterViewInit { @Inject(WINDOW) private window: Window, ) { } - getDisk(node: DeviceNestedDataNode): Disk { + getDisk(node: DeviceNestedDataNode): Disk | undefined { if (isVdevGroup(node) || !isTopologyDisk(node)) { return undefined; } diff --git a/src/app/pages/storage/modules/disks/components/manual-test-dialog/test-progress-row/test-progress-row.component.spec.ts b/src/app/pages/storage/modules/disks/components/manual-test-dialog/test-progress-row/test-progress-row.component.spec.ts index 58c8f74a8aa..8cb7d381799 100644 --- a/src/app/pages/storage/modules/disks/components/manual-test-dialog/test-progress-row/test-progress-row.component.spec.ts +++ b/src/app/pages/storage/modules/disks/components/manual-test-dialog/test-progress-row/test-progress-row.component.spec.ts @@ -47,7 +47,7 @@ describe('IxTestProgressRowComponent', () => { }); it('shows disk name', () => { - const h4 = spectator.query('h4'); + const h4 = spectator.query('h4')!; expect(h4.textContent).toBe('sdd (serial)'); }); @@ -82,7 +82,7 @@ describe('IxTestProgressRowComponent', () => { }); it('shows disk name', () => { - const h4 = spectator.query('h4'); + const h4 = spectator.query('h4')!; expect(h4.textContent).toBe('sdd (serial)'); }); @@ -114,7 +114,7 @@ describe('IxTestProgressRowComponent', () => { spectator.detectChanges(); - const progressBar = spectator.query(MatProgressBar); + const progressBar = spectator.query(MatProgressBar)!; expect(progressBar.value).toBe(15); }); @@ -167,13 +167,13 @@ describe('IxTestProgressRowComponent', () => { expect(icons).toHaveLength(1); expect(icons[0].name()).toBe('error'); - const link = spectator.query('a'); + const link = spectator.query('a')!; expect(link).toBeTruthy(); expect(link.textContent).toBe(' View logs '); }); it('shows dialog info with error log', () => { - const link = spectator.query('a'); + const link = spectator.query('a')!; link.dispatchEvent(new Event('click')); expect(spectator.inject(DialogService).info).toHaveBeenCalledWith( diff --git a/src/app/pages/system/advanced/access/access-form/access-form.component.ts b/src/app/pages/system/advanced/access/access-form/access-form.component.ts index f715559ad6a..e591837a70c 100644 --- a/src/app/pages/system/advanced/access/access-form/access-form.component.ts +++ b/src/app/pages/system/advanced/access/access-form/access-form.component.ts @@ -31,7 +31,10 @@ import { defaultPreferences } from 'app/store/preferences/default-preferences.co import { lifetimeTokenUpdated } from 'app/store/preferences/preferences.actions'; import { selectPreferences } from 'app/store/preferences/preferences.selectors'; import { advancedConfigUpdated, generalConfigUpdated, loginBannerUpdated } from 'app/store/system-config/system-config.actions'; -import { selectAdvancedConfig, selectGeneralConfig } from 'app/store/system-config/system-config.selectors'; +import { + waitForAdvancedConfig, + waitForGeneralConfig, +} from 'app/store/system-config/system-config.selectors'; @UntilDestroy() @Component({ @@ -95,12 +98,12 @@ export class AccessFormComponent implements OnInit { } }); - this.store$.select(selectGeneralConfig).pipe(untilDestroyed(this)).subscribe((config) => { + this.store$.pipe(waitForGeneralConfig, untilDestroyed(this)).subscribe((config) => { this.form.controls.ds_auth.setValue(config.ds_auth); this.cdr.markForCheck(); }); - this.store$.select(selectAdvancedConfig).pipe(untilDestroyed(this)).subscribe((config) => { + this.store$.pipe(waitForAdvancedConfig, untilDestroyed(this)).subscribe((config) => { this.form.controls.login_banner.setValue(config.login_banner); this.cdr.markForCheck(); }); diff --git a/src/app/pages/system/advanced/allowed-addresses/allowed-addresses-form/allowed-addresses-form.component.ts b/src/app/pages/system/advanced/allowed-addresses/allowed-addresses-form/allowed-addresses-form.component.ts index 88e68309d86..9b9a0e069ca 100644 --- a/src/app/pages/system/advanced/allowed-addresses/allowed-addresses-form/allowed-addresses-form.component.ts +++ b/src/app/pages/system/advanced/allowed-addresses/allowed-addresses-form/allowed-addresses-form.component.ts @@ -57,7 +57,7 @@ export class AllowedAddressesFormComponent implements OnInit { protected readonly helpText = helptextSystemAdvanced; isFormLoading = true; - form = this.fb.group({ + form = this.fb.nonNullable.group({ addresses: this.fb.array([]), }); diff --git a/src/app/pages/system/advanced/init-shutdown/init-shutdown-card/init-shutdown-card.component.spec.ts b/src/app/pages/system/advanced/init-shutdown/init-shutdown-card/init-shutdown-card.component.spec.ts index af681247e55..746c746aeb1 100644 --- a/src/app/pages/system/advanced/init-shutdown/init-shutdown-card/init-shutdown-card.component.spec.ts +++ b/src/app/pages/system/advanced/init-shutdown/init-shutdown-card/init-shutdown-card.component.spec.ts @@ -45,8 +45,7 @@ describe('InitShutdownCardComponent', () => { comment: 'Greeting', timeout: 20, type: InitShutdownScriptType.Command, - }, - + } as InitShutdownScript, ] as InitShutdownScript[]; const createComponent = createComponentFactory({ diff --git a/src/app/pages/system/advanced/init-shutdown/init-shutdown-list/init-shutdown-list.component.spec.ts b/src/app/pages/system/advanced/init-shutdown/init-shutdown-list/init-shutdown-list.component.spec.ts index 57e24fb66ea..2dd30454ff9 100644 --- a/src/app/pages/system/advanced/init-shutdown/init-shutdown-list/init-shutdown-list.component.spec.ts +++ b/src/app/pages/system/advanced/init-shutdown/init-shutdown-list/init-shutdown-list.component.spec.ts @@ -40,7 +40,7 @@ describe('InitShutdownListComponent', () => { enabled: false, type: InitShutdownScriptType.Command, comment: 'Remove Peter files', - }, + } as InitShutdownScript, ] as InitShutdownScript[]; const createComponent = createComponentFactory({ diff --git a/src/app/pages/system/advanced/init-shutdown/init-shutdown-list/init-shutdown-list.component.ts b/src/app/pages/system/advanced/init-shutdown/init-shutdown-list/init-shutdown-list.component.ts index 86963706c91..cdc0849a806 100644 --- a/src/app/pages/system/advanced/init-shutdown/init-shutdown-list/init-shutdown-list.component.ts +++ b/src/app/pages/system/advanced/init-shutdown/init-shutdown-list/init-shutdown-list.component.ts @@ -71,7 +71,7 @@ export class InitShutdownListComponent implements OnInit { title: this.translate.instant('Type'), propertyName: 'type', getValue: (row) => { - const typeLabel = initShutdownScriptTypeLabels.get(row.type); + const typeLabel = initShutdownScriptTypeLabels.get(row.type) || row.type; return this.translate.instant(typeLabel); }, }), @@ -83,7 +83,7 @@ export class InitShutdownListComponent implements OnInit { title: this.translate.instant('When'), propertyName: 'when', getValue: (row) => { - const whenLabel = initShutdownScriptWhenLabels.get(row.when); + const whenLabel = initShutdownScriptWhenLabels.get(row.when) || row.when; return this.translate.instant(whenLabel); }, }), diff --git a/src/app/pages/system/advanced/isolated-gpus/isolated-gpus-form/isolated-gpus-form.component.ts b/src/app/pages/system/advanced/isolated-gpus/isolated-gpus-form/isolated-gpus-form.component.ts index 4300ebf7bc0..331ef0c3873 100644 --- a/src/app/pages/system/advanced/isolated-gpus/isolated-gpus-form/isolated-gpus-form.component.ts +++ b/src/app/pages/system/advanced/isolated-gpus/isolated-gpus-form/isolated-gpus-form.component.ts @@ -51,6 +51,7 @@ export class IsolatedGpusFormComponent implements OnInit { formGroup = new FormGroup({ isolated_gpu_pci_ids: new FormControl([], { + nonNullable: true, asyncValidators: [this.gpuValidator.validateGpu], }), }); diff --git a/src/app/pages/system/alert-service/alert-service-list/alert-service-list.component.ts b/src/app/pages/system/alert-service/alert-service-list/alert-service-list.component.ts index 2478abeea74..39dcd886c27 100644 --- a/src/app/pages/system/alert-service/alert-service-list/alert-service-list.component.ts +++ b/src/app/pages/system/alert-service/alert-service-list/alert-service-list.component.ts @@ -79,13 +79,13 @@ export class AlertServiceListComponent implements OnInit { title: this.translate.instant('Type'), propertyName: 'type', getValue: (service) => this.translate.instant( - alertServiceNames.find((alertService) => alertService.value === service.type).label, + alertServiceNames.find((alertService) => alertService.value === service.type)?.label, ), }), textColumn({ title: this.translate.instant('Level'), propertyName: 'level', - getValue: (service) => this.translate.instant(alertLevelLabels.get(service.level)), + getValue: (service) => this.translate.instant(alertLevelLabels.get(service.level) || service.level), }), textColumn({ title: this.translate.instant('Enabled'), diff --git a/src/app/pages/system/alert-service/alert-service/alert-services/snmp-trap-service/snmp-trap-service.component.ts b/src/app/pages/system/alert-service/alert-service/alert-services/snmp-trap-service/snmp-trap-service.component.ts index f782d0fb0eb..a00a983788c 100644 --- a/src/app/pages/system/alert-service/alert-service/alert-services/snmp-trap-service/snmp-trap-service.component.ts +++ b/src/app/pages/system/alert-service/alert-service/alert-services/snmp-trap-service/snmp-trap-service.component.ts @@ -25,7 +25,7 @@ const disabledValue = 'disabled'; ], }) export class SnmpTrapServiceComponent extends BaseAlertServiceForm { - form = this.formBuilder.group({ + form = this.formBuilder.nonNullable.group({ host: ['', Validators.required], port: [162], v3: [false], diff --git a/src/app/pages/system/alert-settings2/alert-settings2.component.ts b/src/app/pages/system/alert-settings2/alert-settings2.component.ts index 55d38ab4c5b..c1130f51607 100644 --- a/src/app/pages/system/alert-settings2/alert-settings2.component.ts +++ b/src/app/pages/system/alert-settings2/alert-settings2.component.ts @@ -142,7 +142,7 @@ export class AlertSettings2Component implements OnInit { if (option) { const path = option.value.toString(); - const nextElement: HTMLElement = document.getElementById(path); + const nextElement = document.getElementById(path); nextElement?.scrollIntoView(); } }); diff --git a/src/app/pages/system/enclosure/components/enclosure-side/enclosure-side.component.spec.ts b/src/app/pages/system/enclosure/components/enclosure-side/enclosure-side.component.spec.ts index f661c28e2fd..69ca84b77d8 100644 --- a/src/app/pages/system/enclosure/components/enclosure-side/enclosure-side.component.spec.ts +++ b/src/app/pages/system/enclosure/components/enclosure-side/enclosure-side.component.spec.ts @@ -77,7 +77,7 @@ describe('EnclosureSideComponent', () => { }); it('renders an svg component with correct svg url and passes input properties', () => { - const svg = spectator.query(EnclosureSvgStubComponent); + const svg = spectator.query(EnclosureSvgStubComponent)!; expect(svg).toExist(); expect(svg.selectedSlot()).toBe(props.selectedSlot); expect(svg.slotTintFn()).toBe(props.slotTintFn); @@ -90,7 +90,7 @@ describe('EnclosureSideComponent', () => { it('automatically selects Front or Top enclosure based on what is available when side is undefined', () => { spectator.setInput('side', undefined); - const svg = spectator.query(EnclosureSvgStubComponent); + const svg = spectator.query(EnclosureSvgStubComponent)!; expect(svg.svgUrl()).toBe(supportedEnclosures[props.enclosure.model][EnclosureSide.Front]); }); @@ -100,7 +100,7 @@ describe('EnclosureSideComponent', () => { model: 'fake-model', }); - const notSupportedModel = spectator.query(NotSupportedModelComponent); + const notSupportedModel = spectator.query(NotSupportedModelComponent)!; expect(notSupportedModel).toExist(); expect(notSupportedModel.model).toBe('fake-model'); }); diff --git a/src/app/pages/system/enclosure/components/enclosure-side/enclosure-side.component.ts b/src/app/pages/system/enclosure/components/enclosure-side/enclosure-side.component.ts index 3bdac1d53d6..c466805cb16 100644 --- a/src/app/pages/system/enclosure/components/enclosure-side/enclosure-side.component.ts +++ b/src/app/pages/system/enclosure/components/enclosure-side/enclosure-side.component.ts @@ -29,7 +29,7 @@ export class EnclosureSideComponent { /** * When side is not provided will default to showing front or top, depending on what's available. */ - readonly side = input(undefined); + readonly side = input(undefined); readonly sideSlots = computed(() => { return getSlotsOfSide(this.enclosure(), this.shownSide()); diff --git a/src/app/pages/system/enclosure/components/enclosure-side/enclosure-svg/enclosure-svg.component.ts b/src/app/pages/system/enclosure/components/enclosure-side/enclosure-svg/enclosure-svg.component.ts index 6259291b6b8..c2e0ab9b710 100644 --- a/src/app/pages/system/enclosure/components/enclosure-side/enclosure-svg/enclosure-svg.component.ts +++ b/src/app/pages/system/enclosure/components/enclosure-side/enclosure-svg/enclosure-svg.component.ts @@ -266,7 +266,7 @@ export class EnclosureSvgComponent implements OnDestroy { this.renderer.setStyle(overlay, 'fill', slotTint); } - private getSlotForTray(tray: SVGGElement): DashboardEnclosureSlot { + private getSlotForTray(tray: SVGGElement): DashboardEnclosureSlot | undefined { const slotNumber = Number(tray.id.split('_').pop()); const traySlot = this.slots().find((slot) => slot.drive_bay_number === slotNumber); diff --git a/src/app/pages/system/enclosure/components/pages/enclosure-page/disk-details-overview/disk-details-overview.component.spec.ts b/src/app/pages/system/enclosure/components/pages/enclosure-page/disk-details-overview/disk-details-overview.component.spec.ts index 7a30396db10..0d5dd5af90a 100644 --- a/src/app/pages/system/enclosure/components/pages/enclosure-page/disk-details-overview/disk-details-overview.component.spec.ts +++ b/src/app/pages/system/enclosure/components/pages/enclosure-page/disk-details-overview/disk-details-overview.component.spec.ts @@ -60,7 +60,7 @@ describe('DiskDetailsOverviewComponent', () => { }); it('shows disk icon component', () => { - const diskIcon = spectator.query(DiskIconComponent); + const diskIcon = spectator.query(DiskIconComponent)!; expect(diskIcon).toExist(); expect(diskIcon.type).toBe(DiskType.Hdd); expect(diskIcon.size).toBe(100 * GiB); @@ -68,7 +68,7 @@ describe('DiskDetailsOverviewComponent', () => { }); it('shows disks overview details', () => { - const component = spectator.query(DiskDetailsComponent); + const component = spectator.query(DiskDetailsComponent)!; expect(component).toExist(); expect(component.selectedSlot).toBe(initialSelectedSlot); }); diff --git a/src/app/pages/system/enclosure/components/pages/enclosure-page/enclosure-selector/enclosure-selector.component.spec.ts b/src/app/pages/system/enclosure/components/pages/enclosure-page/enclosure-selector/enclosure-selector.component.spec.ts index 2877a28953b..ae9c7836281 100644 --- a/src/app/pages/system/enclosure/components/pages/enclosure-page/enclosure-selector/enclosure-selector.component.spec.ts +++ b/src/app/pages/system/enclosure/components/pages/enclosure-page/enclosure-selector/enclosure-selector.component.spec.ts @@ -44,10 +44,10 @@ describe('EnclosureSelectorComponent', () => { expect(enclosureElements[0]).toHaveText('M40 (1)'); expect(enclosureElements[1]).toHaveText('ES24N (2)'); - const enclosureSvg1 = spectator.query(EnclosureSideComponent, { parentSelector: '.enclosure:first-of-type' }); + const enclosureSvg1 = spectator.query(EnclosureSideComponent, { parentSelector: '.enclosure:first-of-type' })!; expect(enclosureSvg1.enclosure).toBe(enclosures[0]); - const enclosureSvg2 = spectator.query(EnclosureSideComponent, { parentSelector: '.enclosure:last-of-type' }); + const enclosureSvg2 = spectator.query(EnclosureSideComponent, { parentSelector: '.enclosure:last-of-type' })!; expect(enclosureSvg2.enclosure).toBe(enclosures[1]); }); diff --git a/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/disk-topology-description/disk-topology-description.component.spec.ts b/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/disk-topology-description/disk-topology-description.component.spec.ts index 8759861a3c0..e4f6e810536 100644 --- a/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/disk-topology-description/disk-topology-description.component.spec.ts +++ b/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/disk-topology-description/disk-topology-description.component.spec.ts @@ -17,8 +17,8 @@ describe('DiskTopologyDescriptionComponent', () => { }); function getItemValue(title: string): string { - const titleElement = spectator.query(byText(title)); - return titleElement.nextElementSibling.textContent; + const titleElement = spectator.query(byText(title))!; + return titleElement.nextElementSibling!.textContent!; } describe('occupied', () => { diff --git a/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/pools-view.component.spec.ts b/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/pools-view.component.spec.ts index 7e9d487c71d..a6681ee984d 100644 --- a/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/pools-view.component.spec.ts +++ b/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/pools-view.component.spec.ts @@ -24,7 +24,7 @@ import { EnclosureSide } from 'app/pages/system/enclosure/utils/supported-enclos describe('PoolsViewComponent', () => { let spectator: Spectator; - const selectedSlot = signal(null); + const selectedSlot = signal(null); const createComponent = createComponentFactory({ component: PoolsViewComponent, imports: [ diff --git a/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/pools-view.component.ts b/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/pools-view.component.ts index 50ab211ab5c..131eb643979 100644 --- a/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/pools-view.component.ts +++ b/src/app/pages/system/enclosure/components/pages/enclosure-page/pools-view/pools-view.component.ts @@ -38,7 +38,7 @@ export class PoolsViewComponent { ) {} protected onSlotSelected(slot: DashboardEnclosureSlot | null): void { - this.store.selectSlot(slot ? slot.drive_bay_number : null); + this.store.selectSlot(slot?.drive_bay_number || null); } readonly slotTintFn = computed(() => { diff --git a/src/app/pages/system/enclosure/components/pages/enclosure-page/status-view/statuses-legend/statuses-legend.component.ts b/src/app/pages/system/enclosure/components/pages/enclosure-page/status-view/statuses-legend/statuses-legend.component.ts index ed7c7eb645c..5fc8a409908 100644 --- a/src/app/pages/system/enclosure/components/pages/enclosure-page/status-view/statuses-legend/statuses-legend.component.ts +++ b/src/app/pages/system/enclosure/components/pages/enclosure-page/status-view/statuses-legend/statuses-legend.component.ts @@ -23,7 +23,7 @@ export class StatusesLegendComponent { const statuses = uniq(slotsWithPool.map((slot) => slot.pool_info.disk_status)); return statuses.map((status) => { - const statusLabel = enclosureDiskStatusLabels.has(status) ? enclosureDiskStatusLabels.get(status) : status; + const statusLabel = enclosureDiskStatusLabels.get(status) || status; return [ this.translate.instant(statusLabel), getDiskStatusColor(status), diff --git a/src/app/pages/system/enclosure/components/pages/mini-page/mini-drive-temperatures/mini-drive-temperatures.component.spec.ts b/src/app/pages/system/enclosure/components/pages/mini-page/mini-drive-temperatures/mini-drive-temperatures.component.spec.ts index fe8dfbf318e..2f447fd8171 100644 --- a/src/app/pages/system/enclosure/components/pages/mini-page/mini-drive-temperatures/mini-drive-temperatures.component.spec.ts +++ b/src/app/pages/system/enclosure/components/pages/mini-page/mini-drive-temperatures/mini-drive-temperatures.component.spec.ts @@ -63,8 +63,8 @@ describe('MiniDriveTemperaturesComponent', () => { const contents = lines.map((line) => { return { - label: line.querySelector('.dev').textContent.trim(), - temperature: line.querySelector('.temperature').textContent.trim(), + label: line.querySelector('.dev')!.textContent!.trim(), + temperature: line.querySelector('.temperature')!.textContent!.trim(), hideTooltip: !line.querySelector('ix-tooltip'), }; }); diff --git a/src/app/pages/system/enclosure/components/pages/mini-page/mini-page.component.spec.ts b/src/app/pages/system/enclosure/components/pages/mini-page/mini-page.component.spec.ts index 31524ca32d8..dd41e846780 100644 --- a/src/app/pages/system/enclosure/components/pages/mini-page/mini-page.component.spec.ts +++ b/src/app/pages/system/enclosure/components/pages/mini-page/mini-page.component.spec.ts @@ -94,7 +94,7 @@ describe('MiniPageComponent', () => { describe('when no slot is selected', () => { it('shows disks overview and temperatures components', () => { - const disksOverview = spectator.query(MiniDisksOverviewComponent); + const disksOverview = spectator.query(MiniDisksOverviewComponent)!; expect(disksOverview).toExist(); expect(disksOverview.slots).toMatchObject(slots); @@ -111,7 +111,7 @@ describe('MiniPageComponent', () => { const driveDetails = spectator.query(MiniDriveDetailsComponent); expect(driveDetails).toExist(); - const driveStats = spectator.query(MiniDriveStatsComponent); + const driveStats = spectator.query(MiniDriveStatsComponent)!; expect(driveStats).toExist(); expect(driveStats.slot).toMatchObject(slots[0]); }); diff --git a/src/app/pages/system/enclosure/components/set-enclosure-label-dialog/set-enclosure-label-dialog.component.ts b/src/app/pages/system/enclosure/components/set-enclosure-label-dialog/set-enclosure-label-dialog.component.ts index b1ca10ddbb4..58281192d7e 100644 --- a/src/app/pages/system/enclosure/components/set-enclosure-label-dialog/set-enclosure-label-dialog.component.ts +++ b/src/app/pages/system/enclosure/components/set-enclosure-label-dialog/set-enclosure-label-dialog.component.ts @@ -77,7 +77,7 @@ export class SetEnclosureLabelDialogComponent implements OnInit { } onSubmit(): void { - const formValues = this.form.value; + const formValues = this.form.getRawValue(); const newLabel = formValues.resetToDefault ? this.data.defaultLabel : formValues.label; this.api.call('enclosure.label.set', [this.data.enclosureId, newLabel]) diff --git a/src/app/pages/system/enclosure/services/enclosure.store.ts b/src/app/pages/system/enclosure/services/enclosure.store.ts index 88f55b4576b..bd3dcb10f92 100644 --- a/src/app/pages/system/enclosure/services/enclosure.store.ts +++ b/src/app/pages/system/enclosure/services/enclosure.store.ts @@ -24,7 +24,7 @@ export interface EnclosureState { selectedEnclosureIndex: number; selectedSlotNumber: number | null; selectedView: EnclosureView; - selectedSide: EnclosureSide; + selectedSide: EnclosureSide | undefined; } const initialState: EnclosureState = { diff --git a/src/app/pages/system/enclosure/utils/get-item-value-factory.utils.ts b/src/app/pages/system/enclosure/utils/get-item-value-factory.utils.ts index faa26a33b86..c0a6fed15e5 100644 --- a/src/app/pages/system/enclosure/utils/get-item-value-factory.utils.ts +++ b/src/app/pages/system/enclosure/utils/get-item-value-factory.utils.ts @@ -4,6 +4,6 @@ import { Spectator } from '@ngneat/spectator/jest'; export function getItemValueFactory(spectator: Spectator): (name: string) => string { return (name: string): string => { const item = spectator.query(byText(name, { selector: '.label' })); - return item.nextElementSibling.textContent || ''; + return item?.nextElementSibling?.textContent || ''; }; } diff --git a/src/app/pages/system/general-settings/support/license/license.component.ts b/src/app/pages/system/general-settings/support/license/license.component.ts index 89ffa9750bb..03040efdee2 100644 --- a/src/app/pages/system/general-settings/support/license/license.component.ts +++ b/src/app/pages/system/general-settings/support/license/license.component.ts @@ -47,7 +47,7 @@ export class LicenseComponent { isFormLoading = false; title = helptext.update_license.license_placeholder; - form = this.fb.group({ + form = this.fb.nonNullable.group({ license: ['', Validators.required], }); @@ -68,7 +68,7 @@ export class LicenseComponent { onSubmit(): void { this.isFormLoading = true; - const { license } = this.form.value; + const { license } = this.form.getRawValue(); this.api.call('system.license_update', [license]).pipe(untilDestroyed(this)).subscribe({ next: () => { this.isFormLoading = false; diff --git a/src/app/pages/virtualization/components/all-instances/instance-details/instance-disks/instance-disks.component.spec.ts b/src/app/pages/virtualization/components/all-instances/instance-details/instance-disks/instance-disks.component.spec.ts index d28afcd6d27..a3ea4358184 100644 --- a/src/app/pages/virtualization/components/all-instances/instance-details/instance-disks/instance-disks.component.spec.ts +++ b/src/app/pages/virtualization/components/all-instances/instance-details/instance-disks/instance-disks.component.spec.ts @@ -83,7 +83,7 @@ describe('InstanceDisksComponent', () => { }); it('opens disk for for edit when actions menu emits (edit)', () => { - const actionsMenu = spectator.query(DeviceActionsMenuComponent); + const actionsMenu = spectator.query(DeviceActionsMenuComponent)!; actionsMenu.edit.emit(); expect(spectator.inject(SlideIn).open) diff --git a/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-edit-form/instance-edit-form.component.spec.ts b/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-edit-form/instance-edit-form.component.spec.ts index 74abe4cfef0..15404ae7192 100644 --- a/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-edit-form/instance-edit-form.component.spec.ts +++ b/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-edit-form/instance-edit-form.component.spec.ts @@ -32,7 +32,7 @@ describe('InstanceEditFormComponent', () => { autostart: false, cpu: '1-3', memory: 2 * GiB, - environment: null, + environment: {}, } as VirtualizationInstance; const createComponent = createComponentFactory({ diff --git a/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-edit-form/instance-edit-form.component.ts b/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-edit-form/instance-edit-form.component.ts index faa1eee9b21..c014046f648 100644 --- a/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-edit-form/instance-edit-form.component.ts +++ b/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-edit-form/instance-edit-form.component.ts @@ -108,7 +108,7 @@ export class InstanceEditFormComponent { } addEnvironmentVariable(name = '', value = ''): void { - const control = this.formBuilder.group({ + const control = this.formBuilder.nonNullable.group({ name: [name, Validators.required], value: [value, Validators.required], }); diff --git a/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-general-info.component.spec.ts b/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-general-info.component.spec.ts index 616c466ef5e..a6b928fb7e8 100644 --- a/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-general-info.component.spec.ts +++ b/src/app/pages/virtualization/components/all-instances/instance-details/instance-general-info/instance-general-info.component.spec.ts @@ -117,7 +117,7 @@ describe('InstanceGeneralInfoComponent', () => { memory: null, }); - const chartExtra = spectator.query('mat-card-content').querySelectorAll('p'); + const chartExtra = spectator.query('mat-card-content')!.querySelectorAll('p'); expect(chartExtra[3]).toHaveText('CPU: All Host CPUs'); expect(chartExtra[4]).toHaveText('Memory: Available Host Memory'); diff --git a/src/app/pages/virtualization/components/all-instances/instance-details/instance-metrics/instance-metrics-linechart/instance-metrics-linechart.component.spec.ts b/src/app/pages/virtualization/components/all-instances/instance-details/instance-metrics/instance-metrics-linechart/instance-metrics-linechart.component.spec.ts index d7497c65f58..af6561a5536 100644 --- a/src/app/pages/virtualization/components/all-instances/instance-details/instance-metrics/instance-metrics-linechart/instance-metrics-linechart.component.spec.ts +++ b/src/app/pages/virtualization/components/all-instances/instance-details/instance-metrics/instance-metrics-linechart/instance-metrics-linechart.component.spec.ts @@ -59,7 +59,7 @@ describe('InstanceMetricsLineChartComponent', () => { }); it('configures chart data correctly', () => { - const chart = spectator.query(BaseChartDirective); + const chart = spectator.query(BaseChartDirective)!; const data = chart.data as ChartData<'line'>; expect(data).toMatchObject({ @@ -78,7 +78,7 @@ describe('InstanceMetricsLineChartComponent', () => { }); it('uses correct chart options', () => { - const chart = spectator.query(BaseChartDirective); + const chart = spectator.query(BaseChartDirective)!; const options = chart.options; expect(options).toMatchObject({ diff --git a/src/app/pages/virtualization/components/all-instances/instance-list/instance-list-bulk-actions/instance-list-bulk-actions.component.ts b/src/app/pages/virtualization/components/all-instances/instance-list/instance-list-bulk-actions/instance-list-bulk-actions.component.ts index f759a15d836..8211462a056 100644 --- a/src/app/pages/virtualization/components/all-instances/instance-list/instance-list-bulk-actions/instance-list-bulk-actions.component.ts +++ b/src/app/pages/virtualization/components/all-instances/instance-list/instance-list-bulk-actions/instance-list-bulk-actions.component.ts @@ -45,7 +45,7 @@ import { ApiService } from 'app/services/websocket/api.service'; }) export class InstanceListBulkActionsComponent { - readonly checkedInstances = input(); + readonly checkedInstances = input.required(); readonly resetBulkSelection = output(); protected readonly requiredRoles = [Role.VirtInstanceWrite]; diff --git a/src/app/pages/virtualization/components/common/utils/get-device-description.utils.ts b/src/app/pages/virtualization/components/common/utils/get-device-description.utils.ts index 4fd559a29d0..10caa88b949 100644 --- a/src/app/pages/virtualization/components/common/utils/get-device-description.utils.ts +++ b/src/app/pages/virtualization/components/common/utils/get-device-description.utils.ts @@ -3,9 +3,7 @@ import { VirtualizationDeviceType, virtualizationDeviceTypeLabels } from 'app/en import { VirtualizationDevice } from 'app/interfaces/virtualization.interface'; export function getDeviceDescription(translate: TranslateService, device: VirtualizationDevice): string { - const typeLabel = virtualizationDeviceTypeLabels.has(device.dev_type) - ? translate.instant(virtualizationDeviceTypeLabels.get(device.dev_type)) - : device.dev_type; + const typeLabel = translate.instant(virtualizationDeviceTypeLabels.get(device.dev_type) || device.dev_type); if (device.dev_type === VirtualizationDeviceType.Nic) { return `${typeLabel}: ${device.name} (${device.nic_type})`; diff --git a/src/app/pages/virtualization/components/instance-wizard/select-image-dialog/select-image-dialog.component.spec.ts b/src/app/pages/virtualization/components/instance-wizard/select-image-dialog/select-image-dialog.component.spec.ts index 829cd3d1ee2..d502889d974 100644 --- a/src/app/pages/virtualization/components/instance-wizard/select-image-dialog/select-image-dialog.component.spec.ts +++ b/src/app/pages/virtualization/components/instance-wizard/select-image-dialog/select-image-dialog.component.spec.ts @@ -82,7 +82,7 @@ describe('SelectImageDialogComponent', () => { it('shows the rows', () => { const rows = spectator.queryAll('tr').slice(1).map((row) => { - return Array.from(row.querySelectorAll('td')).map((item) => item.textContent.trim()); + return Array.from(row.querySelectorAll('td')).map((item) => item.textContent!.trim()); }); expect(rows).toEqual([ @@ -98,7 +98,7 @@ describe('SelectImageDialogComponent', () => { }); const rows = spectator.queryAll('tr').slice(1).map((row) => { - return Array.from(row.querySelectorAll('td')).map((item) => item.textContent.trim()); + return Array.from(row.querySelectorAll('td')).map((item) => item.textContent!.trim()); }); expect(rows).toEqual([ diff --git a/src/app/pages/virtualization/stores/virtualization-config.store.ts b/src/app/pages/virtualization/stores/virtualization-config.store.ts index 13099d4e237..6c030fa5a2d 100644 --- a/src/app/pages/virtualization/stores/virtualization-config.store.ts +++ b/src/app/pages/virtualization/stores/virtualization-config.store.ts @@ -2,7 +2,9 @@ import { computed, Injectable } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; import { ComponentStore } from '@ngrx/component-store'; -import { Subscription, switchMap, tap } from 'rxjs'; +import { + of, Subscription, switchMap, tap, +} from 'rxjs'; import { catchError } from 'rxjs/operators'; import { VirtualizationGlobalConfig } from 'app/interfaces/virtualization.interface'; import { ErrorHandlerService } from 'app/services/error-handler.service'; @@ -10,7 +12,7 @@ import { ApiService } from 'app/services/websocket/api.service'; export interface VirtualizationConfigState { isLoading: boolean; - config: VirtualizationGlobalConfig; + config: VirtualizationGlobalConfig | null; } const initialState: VirtualizationConfigState = { @@ -52,7 +54,7 @@ export class VirtualizationConfigStore extends ComponentStore { this.patchState({ isLoading: false }); this.errorHandler.showErrorModal(error); - return undefined; + return of(undefined); }), ); }), diff --git a/src/app/pages/virtualization/stores/virtualization-devices.store.ts b/src/app/pages/virtualization/stores/virtualization-devices.store.ts index 71a48b925f3..afa4961da32 100644 --- a/src/app/pages/virtualization/stores/virtualization-devices.store.ts +++ b/src/app/pages/virtualization/stores/virtualization-devices.store.ts @@ -13,7 +13,7 @@ import { ApiService } from 'app/services/websocket/api.service'; export interface VirtualizationInstanceDeviceState { isLoading: boolean; devices: VirtualizationDevice[]; - selectedInstance: VirtualizationInstance; + selectedInstance: VirtualizationInstance | null; } const initialState: VirtualizationInstanceDeviceState = { diff --git a/src/app/pages/virtualization/stores/virtualization-instances.store.ts b/src/app/pages/virtualization/stores/virtualization-instances.store.ts index b69397d7f3d..db2f114ef00 100644 --- a/src/app/pages/virtualization/stores/virtualization-instances.store.ts +++ b/src/app/pages/virtualization/stores/virtualization-instances.store.ts @@ -2,7 +2,7 @@ import { computed, Injectable } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; import { UntilDestroy } from '@ngneat/until-destroy'; import { ComponentStore } from '@ngrx/component-store'; -import { switchMap, tap } from 'rxjs'; +import { of, switchMap, tap } from 'rxjs'; import { catchError, map, startWith } from 'rxjs/operators'; import { CollectionChangeType } from 'app/enums/api.enum'; import { VirtualizationInstance } from 'app/interfaces/virtualization.interface'; @@ -72,7 +72,7 @@ export class VirtualizationInstancesStore extends ComponentStore { this.patchState({ isLoading: false, instances: [] }); this.errorHandler.showErrorModal(error); - return undefined; + return of(undefined); }), ); }), diff --git a/src/assets/i18n/af.json b/src/assets/i18n/af.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/af.json +++ b/src/assets/i18n/af.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ar.json b/src/assets/i18n/ar.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/ar.json +++ b/src/assets/i18n/ar.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ast.json b/src/assets/i18n/ast.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/ast.json +++ b/src/assets/i18n/ast.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/az.json b/src/assets/i18n/az.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/az.json +++ b/src/assets/i18n/az.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/be.json b/src/assets/i18n/be.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/be.json +++ b/src/assets/i18n/be.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/bg.json b/src/assets/i18n/bg.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/bg.json +++ b/src/assets/i18n/bg.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/bn.json b/src/assets/i18n/bn.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/bn.json +++ b/src/assets/i18n/bn.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/br.json b/src/assets/i18n/br.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/br.json +++ b/src/assets/i18n/br.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/bs.json b/src/assets/i18n/bs.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/bs.json +++ b/src/assets/i18n/bs.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ca.json b/src/assets/i18n/ca.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/ca.json +++ b/src/assets/i18n/ca.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/cs.json b/src/assets/i18n/cs.json index 55280e5ded1..94552293125 100644 --- a/src/assets/i18n/cs.json +++ b/src/assets/i18n/cs.json @@ -1,6 +1,7 @@ { "": "", "\"Power On Hours\" are how many hours have passed while the disk has been powered on. \"Power On Hours Ago\" is how many power on hours have passed since each test.": "", + "-": "", " TrueNAS Forums - Find answers from other users in the forums.": "", "Transport Protocol for the remote system log server connection. Choosing Transport Layer Security (TLS) also requires selecting a preconfigured system Certificate.": "", " TrueNAS Licensing - Learn more about enterprise-grade support.": "", @@ -2332,8 +2333,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/cy.json b/src/assets/i18n/cy.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/cy.json +++ b/src/assets/i18n/cy.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/da.json b/src/assets/i18n/da.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/da.json +++ b/src/assets/i18n/da.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index d039ee94636..12e43456a49 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -11,6 +11,7 @@ "(Optional)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "1m Average": "", @@ -2070,8 +2071,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/dsb.json b/src/assets/i18n/dsb.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/dsb.json +++ b/src/assets/i18n/dsb.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/el.json b/src/assets/i18n/el.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/el.json +++ b/src/assets/i18n/el.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/en-au.json b/src/assets/i18n/en-au.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/en-au.json +++ b/src/assets/i18n/en-au.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/en-gb.json b/src/assets/i18n/en-gb.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/en-gb.json +++ b/src/assets/i18n/en-gb.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/eo.json b/src/assets/i18n/eo.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/eo.json +++ b/src/assets/i18n/eo.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/es-ar.json b/src/assets/i18n/es-ar.json index 7165d405e9b..18f58adf231 100644 --- a/src/assets/i18n/es-ar.json +++ b/src/assets/i18n/es-ar.json @@ -5,6 +5,7 @@ "'Hosts Allow' or 'Hosts Deny' has been set": "", "'Hosts Allow' or 'Hosts Deny' has been updated": "", "({n, plural, =1 {# widget} other {# widgets}})": "", + "-": "", "Copy & Paste
\n Context menu copy and paste operations are disabled in the Shell. Copy and paste shortcuts for Mac are Command+C and Command+V. For most operating systems, use Ctrl+Insert to copy and Shift+Insert to paste.

\n Kill Process
\n Kill process shortcut is Ctrl+C.": "", "WARNING: Rolling the dataset back destroys data on the dataset and can destroy additional snapshots that are related to the dataset. This can result in permanent data loss! Do not roll back until all desired data and snapshots are backed up.": "", "Certificate Signing Requests control when an external CA will issue (sign) the certificate. Typically used with ACME or other CAs that most popular browsers trust by default Import Certificate Signing Request lets you import an existing CSR onto the system. Typically used with ACME or internal CAs.": "", @@ -203,8 +204,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Tunable": "", "New Virtual Machine": "", "No Enclosure Dispersal Strategy": "", diff --git a/src/assets/i18n/es-co.json b/src/assets/i18n/es-co.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/es-co.json +++ b/src/assets/i18n/es-co.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/es-mx.json b/src/assets/i18n/es-mx.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/es-mx.json +++ b/src/assets/i18n/es-mx.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/es-ni.json b/src/assets/i18n/es-ni.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/es-ni.json +++ b/src/assets/i18n/es-ni.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/es-ve.json b/src/assets/i18n/es-ve.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/es-ve.json +++ b/src/assets/i18n/es-ve.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index 15f87b6273f..c50a9182675 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -17,6 +17,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2591,8 +2592,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/et.json b/src/assets/i18n/et.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/et.json +++ b/src/assets/i18n/et.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/eu.json b/src/assets/i18n/eu.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/eu.json +++ b/src/assets/i18n/eu.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/fa.json b/src/assets/i18n/fa.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/fa.json +++ b/src/assets/i18n/fa.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/fi.json b/src/assets/i18n/fi.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/fi.json +++ b/src/assets/i18n/fi.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 92670a42ea5..5fbc64326b3 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -1,6 +1,7 @@ { "": "", "({n, plural, =1 {# widget} other {# widgets}})": "", + "-": "", "...": "", "1m Average": "", "2FA": "", @@ -457,8 +458,8 @@ "New CSR": "", "New Certificate": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/fy.json b/src/assets/i18n/fy.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/fy.json +++ b/src/assets/i18n/fy.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ga.json b/src/assets/i18n/ga.json index 2d3d8c0521a..c191c200413 100644 --- a/src/assets/i18n/ga.json +++ b/src/assets/i18n/ga.json @@ -1,6 +1,7 @@ { "": "", "\"Power On Hours\" are how many hours have passed while the disk has been powered on. \"Power On Hours Ago\" is how many power on hours have passed since each test.": "", + "-": "", "1m Average": "", "This option is experimental in rclone and we recommend you do not use it. It may not work correctly with long filenames.

Encrypt (PUSH) or decrypt (PULL) file names with the rclone \"Standard\" file name encryption mode. The original directory structure is preserved. A filename with the same name always has the same encrypted filename.

PULL tasks that have Filename Encryption enabled and an incorrect Encryption Password or Encryption Salt will not transfer any files but still report that the task was successful. To verify that files were transferred successfully, click the finished task status to see a list of transferred files.": "", "

The system will restart to perform this operation!

All passwords are reset when the uploaded configuration database file was saved without the Password Secret Seed.

": "", @@ -215,6 +216,7 @@ "Network Reconnection Issue": "", "Network Reset": "", "Network size of each docker network which will be cut off from base subnet.": "", + "New Cloud Credential": "", "No NICs added.": "", "No connections": "", "No containers are available.": "", @@ -3069,7 +3071,6 @@ "New Certificate Signing Requests": "Iarratais Nua ar Shíniú Teastais", "New Cloud Backup": "Cúltaca Néal Nua", "New Cloud Sync Task": "Tasc Nua Sync Cloud", - "New Could Credential": "Dintiúir Níorbh fhéidir Nua", "New Credential": "Dintiúir Nua", "New Cron Job": "Job Nua Cron", "New DNS Authenticator": "Fíordheimhnitheoir DNS nua", diff --git a/src/assets/i18n/gd.json b/src/assets/i18n/gd.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/gd.json +++ b/src/assets/i18n/gd.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/gl.json b/src/assets/i18n/gl.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/gl.json +++ b/src/assets/i18n/gl.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/he.json b/src/assets/i18n/he.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/he.json +++ b/src/assets/i18n/he.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/hi.json b/src/assets/i18n/hi.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/hi.json +++ b/src/assets/i18n/hi.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/hr.json b/src/assets/i18n/hr.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/hr.json +++ b/src/assets/i18n/hr.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/hsb.json b/src/assets/i18n/hsb.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/hsb.json +++ b/src/assets/i18n/hsb.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/hu.json b/src/assets/i18n/hu.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/hu.json +++ b/src/assets/i18n/hu.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ia.json b/src/assets/i18n/ia.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/ia.json +++ b/src/assets/i18n/ia.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/id.json b/src/assets/i18n/id.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/id.json +++ b/src/assets/i18n/id.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/io.json b/src/assets/i18n/io.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/io.json +++ b/src/assets/i18n/io.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/is.json b/src/assets/i18n/is.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/is.json +++ b/src/assets/i18n/is.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index f8c560123c4..d2b19e31c25 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2678,8 +2679,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ja.json b/src/assets/i18n/ja.json index f11bf693298..3950ce2cd01 100644 --- a/src/assets/i18n/ja.json +++ b/src/assets/i18n/ja.json @@ -14,6 +14,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "1 day": "", @@ -2556,8 +2557,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ka.json b/src/assets/i18n/ka.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/ka.json +++ b/src/assets/i18n/ka.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/kk.json b/src/assets/i18n/kk.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/kk.json +++ b/src/assets/i18n/kk.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/km.json b/src/assets/i18n/km.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/km.json +++ b/src/assets/i18n/km.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/kn.json b/src/assets/i18n/kn.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/kn.json +++ b/src/assets/i18n/kn.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index b3508e452dd..6b2a8d45b87 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -1,5 +1,6 @@ { "": "", + "-": "", "Burst": "", "Change Session Timeout in": "", "Change from public to increase system security. Can only contain alphanumeric characters, underscores, dashes, periods, and spaces. This can be left empty for SNMPv3 networks.": "", @@ -913,7 +914,7 @@ "Never": "", "New ACME DNS-Authenticator": "", "New Certificate Signing Requests": "", - "New Could Credential": "", + "New Cloud Credential": "", "New Cron Job": "", "New DNS Authenticator": "", "New Exporter": "", diff --git a/src/assets/i18n/lb.json b/src/assets/i18n/lb.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/lb.json +++ b/src/assets/i18n/lb.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/lt.json b/src/assets/i18n/lt.json index a6396888cb7..f50bbbbce36 100644 --- a/src/assets/i18n/lt.json +++ b/src/assets/i18n/lt.json @@ -17,6 +17,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "1 day": "", @@ -2859,8 +2860,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/lv.json b/src/assets/i18n/lv.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/lv.json +++ b/src/assets/i18n/lv.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/mk.json b/src/assets/i18n/mk.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/mk.json +++ b/src/assets/i18n/mk.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ml.json b/src/assets/i18n/ml.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/ml.json +++ b/src/assets/i18n/ml.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/mn.json b/src/assets/i18n/mn.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/mn.json +++ b/src/assets/i18n/mn.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/mr.json b/src/assets/i18n/mr.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/mr.json +++ b/src/assets/i18n/mr.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/my.json b/src/assets/i18n/my.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/my.json +++ b/src/assets/i18n/my.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/nb.json b/src/assets/i18n/nb.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/nb.json +++ b/src/assets/i18n/nb.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ne.json b/src/assets/i18n/ne.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/ne.json +++ b/src/assets/i18n/ne.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/nl.json b/src/assets/i18n/nl.json index 223993619d8..e221f10fbce 100644 --- a/src/assets/i18n/nl.json +++ b/src/assets/i18n/nl.json @@ -1,7 +1,9 @@ { "": "", + "-": "", "Delete Target \"{name}\"": "", "Delete {n} associated {n, plural, one {extent} other {extents}}": "", + "New Cloud Credential": "", "Warning: iSCSI Target is currently in use.
": "", "You are about to delete the target \"{name}\".": "", "You are about to delete the target \"{name}\". You may also choose to delete all extents associated with this target. Note the volumes will not be deleted with the extents.": "", @@ -2884,7 +2886,6 @@ "New Certificate Signing Requests": "Nieuwe certificaatondertekeningsverzoeken", "New Cloud Backup": "Nieuwe cloudback-up", "New Cloud Sync Task": "Nieuwe cloudsynchronisatietaak", - "New Could Credential": "Nieuw cloudinloggegeven", "New Credential": "Nieuw inloggegeven", "New Cron Job": "Nieuwe cronjob", "New DNS Authenticator": "Nieuwe DNS-authenticator", diff --git a/src/assets/i18n/nn.json b/src/assets/i18n/nn.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/nn.json +++ b/src/assets/i18n/nn.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/os.json b/src/assets/i18n/os.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/os.json +++ b/src/assets/i18n/os.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/pa.json b/src/assets/i18n/pa.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/pa.json +++ b/src/assets/i18n/pa.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/pl.json b/src/assets/i18n/pl.json index c7daacda5bb..1c70fd42bcb 100644 --- a/src/assets/i18n/pl.json +++ b/src/assets/i18n/pl.json @@ -15,6 +15,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "1 day": "", @@ -2811,8 +2812,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/pt-br.json b/src/assets/i18n/pt-br.json index 3155ec1cc11..f709d6601b8 100644 --- a/src/assets/i18n/pt-br.json +++ b/src/assets/i18n/pt-br.json @@ -14,6 +14,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "1 day": "", @@ -2806,8 +2807,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/pt.json b/src/assets/i18n/pt.json index 639c74e81ab..c1deda5bb2e 100644 --- a/src/assets/i18n/pt.json +++ b/src/assets/i18n/pt.json @@ -3,6 +3,7 @@ " Est. Usable Raw Capacity": "", "\"Power On Hours\" are how many hours have passed while the disk has been powered on. \"Power On Hours Ago\" is how many power on hours have passed since each test.": "", "({n, plural, =1 {# widget} other {# widgets}})": "", + "-": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "1m Average": "", "2FA Settings": "", @@ -1678,8 +1679,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ro.json b/src/assets/i18n/ro.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/ro.json +++ b/src/assets/i18n/ro.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ru.json b/src/assets/i18n/ru.json index 75c67db4d63..d15a7de418a 100644 --- a/src/assets/i18n/ru.json +++ b/src/assets/i18n/ru.json @@ -14,6 +14,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "1m Average": "", @@ -1798,8 +1799,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/sk.json b/src/assets/i18n/sk.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/sk.json +++ b/src/assets/i18n/sk.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/sl.json b/src/assets/i18n/sl.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/sl.json +++ b/src/assets/i18n/sl.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/sq.json b/src/assets/i18n/sq.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/sq.json +++ b/src/assets/i18n/sq.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/sr-latn.json b/src/assets/i18n/sr-latn.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/sr-latn.json +++ b/src/assets/i18n/sr-latn.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/sr.json b/src/assets/i18n/sr.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/sr.json +++ b/src/assets/i18n/sr.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/strings.json b/src/assets/i18n/strings.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/strings.json +++ b/src/assets/i18n/strings.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/sv.json b/src/assets/i18n/sv.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/sv.json +++ b/src/assets/i18n/sv.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/sw.json b/src/assets/i18n/sw.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/sw.json +++ b/src/assets/i18n/sw.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/ta.json b/src/assets/i18n/ta.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/ta.json +++ b/src/assets/i18n/ta.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/te.json b/src/assets/i18n/te.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/te.json +++ b/src/assets/i18n/te.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/th.json b/src/assets/i18n/th.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/th.json +++ b/src/assets/i18n/th.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/tr.json b/src/assets/i18n/tr.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/tr.json +++ b/src/assets/i18n/tr.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/tt.json b/src/assets/i18n/tt.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/tt.json +++ b/src/assets/i18n/tt.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/udm.json b/src/assets/i18n/udm.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/udm.json +++ b/src/assets/i18n/udm.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/uk.json b/src/assets/i18n/uk.json index 8f14b1a4188..64c3584ec0f 100644 --- a/src/assets/i18n/uk.json +++ b/src/assets/i18n/uk.json @@ -6,6 +6,7 @@ "\"Power On Hours\" are how many hours have passed while the disk has been powered on. \"Power On Hours Ago\" is how many power on hours have passed since each test.": "", "(Optional)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "1m Average": "", @@ -1157,8 +1158,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/vi.json b/src/assets/i18n/vi.json index e1c1fa4fd5a..9cff775662a 100644 --- a/src/assets/i18n/vi.json +++ b/src/assets/i18n/vi.json @@ -20,6 +20,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "0=Disabled, blank=inherit": "", @@ -2865,8 +2866,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/i18n/zh-hans.json b/src/assets/i18n/zh-hans.json index 43ee1e6b7cf..cc46066d0f4 100644 --- a/src/assets/i18n/zh-hans.json +++ b/src/assets/i18n/zh-hans.json @@ -1,11 +1,13 @@ { "": "", + "-": "", "...": "", "Api Keys": "", "Both": "", "Delete Target \"{name}\"": "", "Delete {n} associated {n, plural, one {extent} other {extents}}": "", "Deleted {n, plural, one {# snapshot} other {# snapshots} }": "", + "New Cloud Credential": "", "Warning: iSCSI Target is currently in use.
": "", "You are about to delete the target \"{name}\".": "", "You are about to delete the target \"{name}\". You may also choose to delete all extents associated with this target. Note the volumes will not be deleted with the extents.": "", @@ -2894,7 +2896,6 @@ "New Certificate Signing Requests": "新的证书签名请求", "New Cloud Backup": "新的云备份", "New Cloud Sync Task": "新的云同步任务", - "New Could Credential": "新可以凭证", "New Credential": "新凭据", "New Cron Job": "新的定时任务", "New DNS Authenticator": "新的DNS身份验证器", diff --git a/src/assets/i18n/zh-hant.json b/src/assets/i18n/zh-hant.json index d4140ff509d..edfddfdc641 100644 --- a/src/assets/i18n/zh-hant.json +++ b/src/assets/i18n/zh-hant.json @@ -15,6 +15,7 @@ "(TrueNAS Controller 2)": "", "({n, plural, =1 {# widget} other {# widgets}})": "", "+ Add a backup credential": "", + "-": "", "...": "", "... Make sure the TrueNAS system is powered on and connected to the network.": "", "1 day": "", @@ -2401,8 +2402,8 @@ "New Certificate Authority": "", "New Certificate Signing Requests": "", "New Cloud Backup": "", + "New Cloud Credential": "", "New Cloud Sync Task": "", - "New Could Credential": "", "New Credential": "", "New Cron Job": "", "New DNS Authenticator": "", diff --git a/src/assets/ui-searchable-elements.json b/src/assets/ui-searchable-elements.json index f06dcf0a899..32af5d0d22b 100644 --- a/src/assets/ui-searchable-elements.json +++ b/src/assets/ui-searchable-elements.json @@ -372,7 +372,7 @@ "Add Credential", "Add Backup Credential", "New Credential", - "New Could Credential", + "New Cloud Credential", "New Backup Credential", "Create Credential", "Create Cloud Credential", From 1ee9936a6889d1d3d67b23767791a3d73cd7f6cd Mon Sep 17 00:00:00 2001 From: undsoft Date: Wed, 25 Dec 2024 17:31:58 -0500 Subject: [PATCH 2/2] NAS-133262: Fix more strict null issues --- .../device-actions-menu/device-actions-menu.component.spec.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/pages/virtualization/components/common/device-actions-menu/device-actions-menu.component.spec.ts b/src/app/pages/virtualization/components/common/device-actions-menu/device-actions-menu.component.spec.ts index b9eefd41fc2..d0f33c9e54a 100644 --- a/src/app/pages/virtualization/components/common/device-actions-menu/device-actions-menu.component.spec.ts +++ b/src/app/pages/virtualization/components/common/device-actions-menu/device-actions-menu.component.spec.ts @@ -4,6 +4,7 @@ import { MatMenuHarness } from '@angular/material/menu/testing'; import { createComponentFactory, mockProvider, Spectator } from '@ngneat/spectator/jest'; import { of } from 'rxjs'; import { mockApi, mockCall } from 'app/core/testing/utils/mock-api.utils'; +import { VirtualizationDeviceType } from 'app/enums/virtualization.enum'; import { VirtualizationDevice } from 'app/interfaces/virtualization.interface'; import { DialogService } from 'app/modules/dialog/dialog.service'; import { SnackbarService } from 'app/modules/snackbar/services/snackbar.service'; @@ -40,6 +41,7 @@ describe('DeviceActionsMenuComponent', () => { props: { device: { name: 'my-device', + dev_type: VirtualizationDeviceType.Gpu, } as VirtualizationDevice, }, });