mgr/dashboard: fixed unit tests

* fixed unit tests due to upgrade to angular v18
* run npm fix in order to fix code style violations
* upgraded eslint/* packages' versions
* fixed eslint errors and warnings

Fixes: https://tracker.ceph.com/issues/68896
Signed-off-by: Ivo Almeida <ialmeida@redhat.com>
This commit is contained in:
Ivo Almeida 2024-11-13 12:16:23 +00:00
parent 6803f28124
commit 3f16e0c593
76 changed files with 1162 additions and 2044 deletions

6
package-lock.json generated Normal file
View File

@ -0,0 +1,6 @@
{
"name": "ceph",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

View File

@ -6,6 +6,10 @@
"plugins/index.js" "plugins/index.js"
], ],
"compilerOptions": { "compilerOptions": {
"typeRoots": [
"../node_modules",
"../node_modules/@types"
],
"sourceMap": false, "sourceMap": false,
"types": [ "types": [
"cypress", "cypress",
@ -14,4 +18,4 @@
], ],
"target": "es6" "target": "es6"
} }
} }

View File

@ -9,32 +9,38 @@ const esModules = [
'@ng-bootstrap' '@ng-bootstrap'
]; ];
const jestConfig = { const jestConfig = {
globals: {
'ts-jest': {
useESM: true,
stringifyContentPathRegex: '\\.(html|svg)$',
tsconfig: '<rootDir>/tsconfig.spec.json',
isolatedModules: true
}
},
globalSetup: 'jest-preset-angular/global-setup',
moduleNameMapper: { moduleNameMapper: {
'\\.scss$': 'identity-obj-proxy', '\\.scss$': 'identity-obj-proxy',
'~/(.*)$': '<rootDir>/src/$1', '~/(.*)$': '<rootDir>/src/$1',
'^@carbon/icons/es/(.*)$': '@carbon/icons/lib/$1.js', '^@carbon/icons/es/(.*)$': '@carbon/icons/lib/$1.js'
}, },
moduleFileExtensions: ['ts', 'html', 'js', 'json', 'mjs', 'cjs'], moduleFileExtensions: ['ts', 'html', 'js', 'json', 'mjs', 'cjs'],
preset: 'jest-preset-angular', preset: 'jest-preset-angular',
setupFilesAfterEnv: ['<rootDir>/src/setupJest.ts'], setupFilesAfterEnv: ['<rootDir>/src/setupJest.ts'],
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$|'.concat(esModules.join('|'), ')')], transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$|'.concat(esModules.join('|'), ')')],
transform: { transform: {
'^.+\\.(ts|html|mjs)$': 'jest-preset-angular', '^.+\\.(ts|html|mjs)$': [
'jest-preset-angular',
{
useESM: true,
stringifyContentPathRegex: '\\.(html|svg)$',
tsconfig: '<rootDir>/tsconfig.spec.json',
isolatedModules: true
}
],
'^.+\\.(js)$': 'babel-jest' '^.+\\.(js)$': 'babel-jest'
}, },
setupFiles: ['jest-canvas-mock'], setupFiles: ['jest-canvas-mock'],
coverageReporters: ['cobertura', 'html'], coverageReporters: ['cobertura', 'html'],
modulePathIgnorePatterns: ['<rootDir>/coverage/', '<rootDir>/node_modules/simplebar-angular', '<rootDir>/cypress'], modulePathIgnorePatterns: [
'<rootDir>/coverage/',
'<rootDir>/node_modules/simplebar-angular',
'<rootDir>/cypress'
],
testMatch: ['**/*.spec.ts'], testMatch: ['**/*.spec.ts'],
testRunner: 'jest-jasmine2' testRunner: 'jest-jasmine2',
testEnvironmentOptions: {
detectOpenHandles: true
}
}; };
module.exports = jestConfig; module.exports = jestConfig;

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@
"i18n:merge": "npx i18ntool merge -c i18n.config.json", "i18n:merge": "npx i18ntool merge -c i18n.config.json",
"i18n:token": "npx i18ntool config token", "i18n:token": "npx i18ntool config token",
"test": "jest --watch", "test": "jest --watch",
"test:ci": "jest --clearCache && JEST_SILENT_REPORTER_DOTS=true jest --coverage --reporters jest-silent-reporter", "test:ci": "jest --clearCache && JEST_SILENT_REPORTER_DOTS=true jest --detectOpenHandles --coverage --reporters jest-silent-reporter",
"pree2e": "rm -f cypress/reports/results-*.xml || true", "pree2e": "rm -f cypress/reports/results-*.xml || true",
"e2e": "start-test 4200 'cypress open'", "e2e": "start-test 4200 'cypress open'",
"pree2e:ci": "npm run pree2e", "pree2e:ci": "npm run pree2e",
@ -28,7 +28,6 @@
"lint:gherkin": "gherkin-lint -c .gherkin-lintrc cypress/e2e", "lint:gherkin": "gherkin-lint -c .gherkin-lintrc cypress/e2e",
"lint:prettier": "prettier --list-different \"{src,cypress}/**/*.{ts,scss}\"", "lint:prettier": "prettier --list-different \"{src,cypress}/**/*.{ts,scss}\"",
"lint:html": "htmllint src/app/**/*.html && html-linter --config html-linter.config.json", "lint:html": "htmllint src/app/**/*.html && html-linter --config html-linter.config.json",
"prelint:tsc": "npm run postinstall",
"lint:tsc": "tsc -p tsconfig.app.json --noEmit && tsc -p tsconfig.spec.json --noEmit && tsc -p cypress/tsconfig.json --noEmit", "lint:tsc": "tsc -p tsconfig.app.json --noEmit && tsc -p tsconfig.spec.json --noEmit && tsc -p cypress/tsconfig.json --noEmit",
"lint:scss": "stylelint '**/*.scss'", "lint:scss": "stylelint '**/*.scss'",
"lint": "run-p -csl --aggregate-output lint:*", "lint": "run-p -csl --aggregate-output lint:*",
@ -61,9 +60,9 @@
"@popperjs/core": "2.10.2", "@popperjs/core": "2.10.2",
"@types/file-saver": "2.0.1", "@types/file-saver": "2.0.1",
"async-mutex": "0.2.4", "async-mutex": "0.2.4",
"bootstrap": "5.2.3", "bootstrap": "5.3.2",
"carbon-components-angular": "5.56.2", "carbon-components-angular": "5.56.2",
"chart.js": "4.4.0", "chart.js": "4.4.7",
"chartjs-adapter-moment": "1.0.1", "chartjs-adapter-moment": "1.0.1",
"detect-browser": "5.2.0", "detect-browser": "5.2.0",
"file-saver": "2.0.2", "file-saver": "2.0.2",
@ -72,7 +71,7 @@
"moment": "2.29.4", "moment": "2.29.4",
"ng-block-ui": "4.0.1", "ng-block-ui": "4.0.1",
"ng-click-outside": "9.0.1", "ng-click-outside": "9.0.1",
"ng2-charts": "4.1.1", "ng2-charts": "7.0.0",
"ngx-cookie-service": "18.0.0", "ngx-cookie-service": "18.0.0",
"ngx-toastr": "17.0.2", "ngx-toastr": "17.0.2",
"rxjs": "6.6.3", "rxjs": "6.6.3",
@ -86,43 +85,46 @@
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "18.2.11", "@angular-devkit/build-angular": "18.2.11",
"@angular-eslint/builder": "13.5.0", "@angular-eslint/builder": "18.4.0",
"@angular-eslint/eslint-plugin": "13.5.0", "@angular-eslint/eslint-plugin": "18.4.0",
"@angular-eslint/eslint-plugin-template": "13.5.0", "@angular-eslint/eslint-plugin-template": "18.4.0",
"@angular-eslint/schematics": "18.3.1", "@angular-eslint/schematics": "18.4.0",
"@angular-eslint/template-parser": "13.5.0", "@angular-eslint/template-parser": "18.4.0",
"@angular/cli": "18.2.11", "@angular/cli": "18.2.11",
"@angular/compiler-cli": "18.2.11", "@angular/compiler-cli": "18.2.11",
"@angular/language-service": "18.2.11", "@angular/language-service": "18.2.11",
"@applitools/eyes-cypress": "3.22.5", "@applitools/eyes-cypress": "3.22.5",
"@compodoc/compodoc": "1.1.18", "@compodoc/compodoc": "1.1.18",
"@cypress/browserify-preprocessor": "3.0.2", "@cypress/browserify-preprocessor": "3.0.2",
"@juggle/resize-observer": "3.4.0",
"@types/brace-expansion": "1.1.0", "@types/brace-expansion": "1.1.0",
"@types/cypress": "0.1.6",
"@types/cypress-axe": "0.8.0",
"@types/cypress-cucumber-preprocessor": "4.0.1", "@types/cypress-cucumber-preprocessor": "4.0.1",
"@types/jest": "29.5.4", "@types/jest": "29.5.4",
"@types/lodash": "4.14.161", "@types/lodash": "4.14.161",
"@types/node": "18.17.12", "@types/node": "18.17.12",
"@types/swagger-ui": "3.52.0", "@types/swagger-ui": "3.52.0",
"@types/xml2js": "0.4.14", "@types/xml2js": "0.4.14",
"@typescript-eslint/eslint-plugin": "5.27.1", "@typescript-eslint/eslint-plugin": "8.14.0",
"@typescript-eslint/parser": "5.27.1", "@typescript-eslint/parser": "8.14.0",
"axe-core": "4.4.3", "axe-core": "4.4.3",
"cypress": "12.17.4", "cypress": "12.17.4",
"cypress-axe": "1.5.0", "cypress-axe": "1.5.0",
"cypress-cucumber-preprocessor": "4.3.1", "cypress-cucumber-preprocessor": "4.3.1",
"cypress-iframe": "1.0.1", "cypress-iframe": "1.0.1",
"cypress-multi-reporters": "1.5.0", "cypress-multi-reporters": "1.5.0",
"eslint": "8.17.0", "eslint": "9.14.0",
"gherkin-lint": "4.2.2", "gherkin-lint": "4.2.2",
"html-linter": "1.1.1", "html-linter": "1.1.1",
"htmllint-cli": "0.0.7", "htmllint-cli": "0.0.7",
"identity-obj-proxy": "3.0.0", "identity-obj-proxy": "3.0.0",
"isomorphic-form-data": "2.0.0", "isomorphic-form-data": "2.0.0",
"jest": "29.6.4", "jest": "29.7.0",
"jest-canvas-mock": "2.4.0", "jest-canvas-mock": "2.4.0",
"jest-jasmine2": "28.1.3", "jest-jasmine2": "28.1.3",
"jest-preset-angular": "14.2.4", "jest-preset-angular": "14.2.4",
"jest-silent-reporter": "0.5.0", "jest-silent-reporter": "0.6.0",
"mocha-junit-reporter": "2.1.0", "mocha-junit-reporter": "2.1.0",
"ng-mocks": "14.13.1", "ng-mocks": "14.13.1",
"npm-run-all": "4.1.5", "npm-run-all": "4.1.5",

View File

@ -14,32 +14,38 @@ import { ApiInterceptorService } from './shared/services/api-interceptor.service
import { JsErrorHandler } from './shared/services/js-error-handler.service'; import { JsErrorHandler } from './shared/services/js-error-handler.service';
import { SharedModule } from './shared/shared.module'; import { SharedModule } from './shared/shared.module';
@NgModule({ declarations: [AppComponent], @NgModule({
exports: [SharedModule], declarations: [AppComponent],
bootstrap: [AppComponent], imports: [BrowserModule, exports: [SharedModule],
BrowserAnimationsModule, bootstrap: [AppComponent],
ToastrModule.forRoot({ imports: [
positionClass: 'toast-top-right', BrowserModule,
preventDuplicates: true, BrowserAnimationsModule,
enableHtml: true ToastrModule.forRoot({
}), positionClass: 'toast-top-right',
AppRoutingModule, preventDuplicates: true,
CoreModule, enableHtml: true
SharedModule, }),
CephModule], providers: [ AppRoutingModule,
{ CoreModule,
provide: ErrorHandler, SharedModule,
useClass: JsErrorHandler CephModule
}, ],
{ providers: [
provide: HTTP_INTERCEPTORS, {
useClass: ApiInterceptorService, provide: ErrorHandler,
multi: true useClass: JsErrorHandler
}, },
{ {
provide: APP_BASE_HREF, provide: HTTP_INTERCEPTORS,
useValue: '/' + (window.location.pathname.split('/', 1)[1] || '') useClass: ApiInterceptorService,
}, multi: true
provideHttpClient(withInterceptorsFromDi()) },
] }) {
provide: APP_BASE_HREF,
useValue: '/' + (window.location.pathname.split('/', 1)[1] || '')
},
provideHttpClient(withInterceptorsFromDi())
]
})
export class AppModule {} export class AppModule {}

View File

@ -6,7 +6,6 @@ import { RouterTestingModule } from '@angular/router/testing';
import { ToastrModule } from 'ngx-toastr'; import { ToastrModule } from 'ngx-toastr';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SelectOption } from '~/app/shared/components/select/select-option.model'; import { SelectOption } from '~/app/shared/components/select/select-option.model';
import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
@ -137,25 +136,22 @@ describe('IscsiTargetFormComponent', () => {
} }
]; ];
configureTestBed( configureTestBed({
{ declarations: [IscsiTargetFormComponent],
declarations: [IscsiTargetFormComponent], imports: [
imports: [ SharedModule,
SharedModule, ReactiveFormsModule,
ReactiveFormsModule, HttpClientTestingModule,
HttpClientTestingModule, RouterTestingModule,
RouterTestingModule, ToastrModule.forRoot()
ToastrModule.forRoot() ],
], providers: [
providers: [ {
{ provide: ActivatedRoute,
provide: ActivatedRoute, useValue: new ActivatedRouteStub({ target_iqn: undefined })
useValue: new ActivatedRouteStub({ target_iqn: undefined }) }
} ]
] });
},
[LoadingPanelComponent]
);
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(IscsiTargetFormComponent); fixture = TestBed.createComponent(IscsiTargetFormComponent);

View File

@ -1,4 +1,4 @@
import { Component, TemplateRef, ViewChild } from '@angular/core'; import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import _ from 'lodash'; import _ from 'lodash';
@ -28,7 +28,7 @@ type Gateway = {
templateUrl: './nvmeof-gateway.component.html', templateUrl: './nvmeof-gateway.component.html',
styleUrls: ['./nvmeof-gateway.component.scss'] styleUrls: ['./nvmeof-gateway.component.scss']
}) })
export class NvmeofGatewayComponent { export class NvmeofGatewayComponent implements OnInit {
@ViewChild('statusTpl', { static: true }) @ViewChild('statusTpl', { static: true })
statusTpl: TemplateRef<any>; statusTpl: TemplateRef<any>;

View File

@ -4,7 +4,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { NgChartsModule } from 'ng2-charts'; import { BaseChartDirective } from 'ng2-charts';
import { ComponentsModule } from '~/app/shared/components/components.module'; import { ComponentsModule } from '~/app/shared/components/components.module';
import { RbdConfigurationEntry } from '~/app/shared/models/configuration'; import { RbdConfigurationEntry } from '~/app/shared/models/configuration';
@ -25,7 +25,7 @@ describe('RbdConfigurationListComponent', () => {
RouterTestingModule, RouterTestingModule,
ComponentsModule, ComponentsModule,
NgbDropdownModule, NgbDropdownModule,
NgChartsModule, BaseChartDirective,
SharedModule, SharedModule,
NgbTooltipModule NgbTooltipModule
], ],

View File

@ -10,7 +10,6 @@ import { Subject, throwError as observableThrowError } from 'rxjs';
import { RbdService } from '~/app/shared/api/rbd.service'; import { RbdService } from '~/app/shared/api/rbd.service';
import { ComponentsModule } from '~/app/shared/components/components.module'; import { ComponentsModule } from '~/app/shared/components/components.module';
import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
import { ActionLabelsI18n } from '~/app/shared/constants/app.constants'; import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
import { DataTableModule } from '~/app/shared/datatable/datatable.module'; import { DataTableModule } from '~/app/shared/datatable/datatable.module';
import { TableActionsComponent } from '~/app/shared/datatable/table-actions/table-actions.component'; import { TableActionsComponent } from '~/app/shared/datatable/table-actions/table-actions.component';
@ -55,38 +54,35 @@ describe('RbdSnapshotListComponent', () => {
} }
}; };
configureTestBed( configureTestBed({
{ declarations: [
declarations: [ RbdSnapshotListComponent,
RbdSnapshotListComponent, RbdTabsComponent,
RbdTabsComponent, MockComponent(RbdSnapshotFormModalComponent),
MockComponent(RbdSnapshotFormModalComponent), BaseModal
BaseModal ],
], imports: [
imports: [ BrowserAnimationsModule,
BrowserAnimationsModule, ComponentsModule,
ComponentsModule, DataTableModule,
DataTableModule, HttpClientTestingModule,
HttpClientTestingModule, PipesModule,
PipesModule, RouterTestingModule,
RouterTestingModule, NgbNavModule,
NgbNavModule, ToastrModule.forRoot(),
ToastrModule.forRoot(), ModalModule,
ModalModule, PlaceholderModule,
PlaceholderModule, CoreModule
CoreModule ],
], providers: [
providers: [ { provide: AuthStorageService, useValue: fakeAuthStorageService },
{ provide: AuthStorageService, useValue: fakeAuthStorageService }, TaskListService,
TaskListService, ModalService,
ModalService, PlaceholderService,
PlaceholderService, BaseModalService
BaseModalService ],
], schemas: [NO_ERRORS_SCHEMA]
schemas: [NO_ERRORS_SCHEMA] });
},
[CriticalConfirmationModalComponent]
);
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(RbdSnapshotListComponent); fixture = TestBed.createComponent(RbdSnapshotListComponent);

View File

@ -90,7 +90,6 @@
formControlName="directory" formControlName="directory"
[skeleton]="directoryStore.isLoading" [skeleton]="directoryStore.isLoading"
[invalid]="!form.controls['directory'].valid && (form.controls['directory'].dirty)" [invalid]="!form.controls['directory'].valid && (form.controls['directory'].dirty)"
[disabled]="directoryStore.isLoading"
[ngbTypeahead]="search"> [ngbTypeahead]="search">
</cds-text-label> </cds-text-label>
<ng-template #directoryError> <ng-template #directoryError>

View File

@ -83,6 +83,11 @@ export class CephfsAuthModalComponent extends CdForm implements OnInit, AfterVie
this.directoryStore.loadDirectories(this.id, '/', 3); this.directoryStore.loadDirectories(this.id, '/', 3);
this.createForm(); this.createForm();
this.loadingReady(); this.loadingReady();
if (this.directoryStore?.isLoading) {
this.form.get('directory').disable();
} else {
this.form.get('directory').disable();
}
} }
createForm() { createForm() {

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NgChartsModule } from 'ng2-charts'; import { BaseChartDirective } from 'ng2-charts';
import { configureTestBed } from '~/testing/unit-test-helper'; import { configureTestBed } from '~/testing/unit-test-helper';
import { CephfsChartComponent } from './cephfs-chart.component'; import { CephfsChartComponent } from './cephfs-chart.component';
@ -18,7 +18,7 @@ describe('CephfsChartComponent', () => {
]; ];
configureTestBed({ configureTestBed({
imports: [NgChartsModule], imports: [BaseChartDirective],
declarations: [CephfsChartComponent] declarations: [CephfsChartComponent]
}); });

View File

@ -3,6 +3,7 @@ import { Component, ElementRef, Input, OnChanges, OnInit, ViewChild } from '@ang
import _ from 'lodash'; import _ from 'lodash';
import moment from 'moment'; import moment from 'moment';
import 'chartjs-adapter-moment'; import 'chartjs-adapter-moment';
import { Chart, registerables } from 'chart.js';
import { ChartTooltip } from '~/app/shared/models/chart-tooltip'; import { ChartTooltip } from '~/app/shared/models/chart-tooltip';
@ -102,6 +103,10 @@ export class CephfsChartComponent implements OnChanges, OnInit {
chartType: 'line' chartType: 'line'
}; };
constructor() {
Chart.register(...registerables);
}
ngOnInit() { ngOnInit() {
if (_.isUndefined(this.mdsCounter)) { if (_.isUndefined(this.mdsCounter)) {
return; return;

View File

@ -12,7 +12,6 @@ import _ from 'lodash';
import { CephfsService } from '~/app/shared/api/cephfs.service'; import { CephfsService } from '~/app/shared/api/cephfs.service';
import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component'; import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component';
import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
import { FormModalComponent } from '~/app/shared/components/form-modal/form-modal.component'; import { FormModalComponent } from '~/app/shared/components/form-modal/form-modal.component';
import { NotificationType } from '~/app/shared/enum/notification-type.enum'; import { NotificationType } from '~/app/shared/enum/notification-type.enum';
import { CdValidators } from '~/app/shared/forms/cd-validators'; import { CdValidators } from '~/app/shared/forms/cd-validators';
@ -388,21 +387,18 @@ describe('CephfsDirectoriesComponent', () => {
} }
}; };
configureTestBed( configureTestBed({
{ imports: [
imports: [ HttpClientTestingModule,
HttpClientTestingModule, SharedModule,
SharedModule, RouterTestingModule,
RouterTestingModule, TreeviewModule,
TreeviewModule, ToastrModule.forRoot(),
ToastrModule.forRoot(), NgbModalModule
NgbModalModule ],
], declarations: [CephfsDirectoriesComponent],
declarations: [CephfsDirectoriesComponent], providers: [NgbActiveModal]
providers: [NgbActiveModal] });
},
[CriticalConfirmationModalComponent, FormModalComponent, ConfirmationModalComponent]
);
beforeEach(() => { beforeEach(() => {
noAsyncUpdate = false; noAsyncUpdate = false;
@ -674,7 +670,6 @@ describe('CephfsDirectoriesComponent', () => {
mockLib.selectNode('/a/c'); mockLib.selectNode('/a/c');
mockLib.selectNode('/a/c/a'); mockLib.selectNode('/a/c/a');
component.selectOrigin('/a'); component.selectOrigin('/a');
console.debug('component.selectedDir', component.selectedDir);
expect(component.selectedDir.path).toBe('/a'); expect(component.selectedDir.path).toBe('/a');
}); });

View File

@ -68,26 +68,7 @@ export class CephfsSnapshotscheduleListComponent
errorMessage: string = ''; errorMessage: string = '';
selectedName: string = ''; selectedName: string = '';
icons = Icons; icons = Icons;
tableActions: CdTableAction[] = [ tableActions!: CdTableAction[];
{
name: this.actionLabels.CREATE,
permission: 'create',
icon: Icons.add,
click: () => this.openModal(false)
},
{
name: this.actionLabels.EDIT,
permission: 'update',
icon: Icons.edit,
click: () => this.openModal(true)
},
{
name: this.actionLabels.DELETE,
permission: 'delete',
icon: Icons.trash,
click: () => this.deleteSnapshotSchedule()
}
];
MODULE_NAME = 'snap_schedule'; MODULE_NAME = 'snap_schedule';
ENABLE_MODULE_TIMER = 2 * 1000; ENABLE_MODULE_TIMER = 2 * 1000;
@ -112,6 +93,27 @@ export class CephfsSnapshotscheduleListComponent
} }
ngOnInit(): void { ngOnInit(): void {
this.tableActions = [
{
name: this.actionLabels.CREATE,
permission: 'create',
icon: Icons.add,
click: () => this.openModal(false)
},
{
name: this.actionLabels.EDIT,
permission: 'update',
icon: Icons.edit,
click: () => this.openModal(true)
},
{
name: this.actionLabels.DELETE,
permission: 'delete',
icon: Icons.trash,
click: () => this.deleteSnapshotSchedule()
}
];
this.moduleServiceListSub = this.mgrModuleService this.moduleServiceListSub = this.mgrModuleService
.list() .list()
.pipe( .pipe(

View File

@ -9,7 +9,7 @@ import {
NgbTooltipModule, NgbTooltipModule,
NgbTypeaheadModule NgbTypeaheadModule
} from '@ng-bootstrap/ng-bootstrap'; } from '@ng-bootstrap/ng-bootstrap';
import { NgChartsModule } from 'ng2-charts'; import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { AppRoutingModule } from '~/app/app-routing.module'; import { AppRoutingModule } from '~/app/app-routing.module';
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
@ -59,7 +59,6 @@ import Trash from '@carbon/icons/es/trash-can/32';
CommonModule, CommonModule,
SharedModule, SharedModule,
AppRoutingModule, AppRoutingModule,
NgChartsModule,
TreeviewModule, TreeviewModule,
NgbNavModule, NgbNavModule,
FormsModule, FormsModule,
@ -83,7 +82,8 @@ import Trash from '@carbon/icons/es/trash-can/32';
NumberModule, NumberModule,
LayoutModule, LayoutModule,
ComboBoxModule, ComboBoxModule,
IconModule IconModule,
BaseChartDirective
], ],
declarations: [ declarations: [
CephfsDetailComponent, CephfsDetailComponent,
@ -104,7 +104,8 @@ import Trash from '@carbon/icons/es/trash-can/32';
CephfsSubvolumeSnapshotsFormComponent, CephfsSubvolumeSnapshotsFormComponent,
CephfsMountDetailsComponent, CephfsMountDetailsComponent,
CephfsAuthModalComponent CephfsAuthModalComponent
] ],
providers: [provideCharts(withDefaultRegisterables())]
}) })
export class CephfsModule { export class CephfsModule {
constructor(private iconService: IconService) { constructor(private iconService: IconService) {

View File

@ -45,7 +45,7 @@
<div cdsCol <div cdsCol
[columnNumbers]="{'lg': 14, 'md': 14, 'sm': 14}"> [columnNumbers]="{'lg': 14, 'md': 14, 'sm': 14}">
<ng-container [ngSwitch]="currentStep?.stepIndex"> <ng-container [ngSwitch]="currentStep?.stepIndex">
<div *ngSwitchCase="'0'" <div *ngSwitchCase="0"
class="ms-5"> class="ms-5">
<h4 class="title" <h4 class="title"
i18n>Add Hosts</h4> i18n>Add Hosts</h4>
@ -56,7 +56,7 @@
[showGeneralActionsOnly]="true" [showGeneralActionsOnly]="true"
[showExpandClusterBtn]="false"></cd-hosts> [showExpandClusterBtn]="false"></cd-hosts>
</div> </div>
<div *ngSwitchCase="'1'" <div *ngSwitchCase="1"
class="ms-5"> class="ms-5">
<h4 class="title" <h4 class="title"
i18n>Create OSDs</h4> i18n>Create OSDs</h4>
@ -68,7 +68,7 @@
(emitMode)="setDeploymentMode($event)"></cd-osd-form> (emitMode)="setDeploymentMode($event)"></cd-osd-form>
</div> </div>
</div> </div>
<div *ngSwitchCase="'2'" <div *ngSwitchCase="2"
class="ms-5"> class="ms-5">
<h4 class="title" <h4 class="title"
i18n>Create Services</h4> i18n>Create Services</h4>
@ -77,7 +77,7 @@
[hiddenColumns]="['status.running', 'status.size', 'status.last_refresh']" [hiddenColumns]="['status.running', 'status.size', 'status.last_refresh']"
[routedModal]="false"></cd-services> [routedModal]="false"></cd-services>
</div> </div>
<div *ngSwitchCase="'3'" <div *ngSwitchCase="3"
class="ms-5"> class="ms-5">
<cd-create-cluster-review></cd-create-cluster-review> <cd-create-cluster-review></cd-create-cluster-review>
</div> </div>

View File

@ -10,7 +10,6 @@ import { CoreModule } from '~/app/core/core.module';
import { HostService } from '~/app/shared/api/host.service'; import { HostService } from '~/app/shared/api/host.service';
import { OsdService } from '~/app/shared/api/osd.service'; import { OsdService } from '~/app/shared/api/osd.service';
import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component'; import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { AppConstants } from '~/app/shared/constants/app.constants'; import { AppConstants } from '~/app/shared/constants/app.constants';
import { ModalService } from '~/app/shared/services/modal.service'; import { ModalService } from '~/app/shared/services/modal.service';
import { WizardStepsService } from '~/app/shared/services/wizard-steps.service'; import { WizardStepsService } from '~/app/shared/services/wizard-steps.service';
@ -27,19 +26,16 @@ describe('CreateClusterComponent', () => {
let modalServiceShowSpy: jasmine.Spy; let modalServiceShowSpy: jasmine.Spy;
const projectConstants: typeof AppConstants = AppConstants; const projectConstants: typeof AppConstants = AppConstants;
configureTestBed( configureTestBed({
{ imports: [
imports: [ HttpClientTestingModule,
HttpClientTestingModule, RouterTestingModule,
RouterTestingModule, ToastrModule.forRoot(),
ToastrModule.forRoot(), SharedModule,
SharedModule, CoreModule,
CoreModule, CephModule
CephModule ]
] });
},
[LoadingPanelComponent]
);
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(CreateClusterComponent); fixture = TestBed.createComponent(CreateClusterComponent);

View File

@ -1,4 +1,6 @@
import { import {
AfterViewInit,
ChangeDetectorRef,
Component, Component,
EventEmitter, EventEmitter,
OnDestroy, OnDestroy,
@ -39,7 +41,7 @@ import { Step } from 'carbon-components-angular';
templateUrl: './create-cluster.component.html', templateUrl: './create-cluster.component.html',
styleUrls: ['./create-cluster.component.scss'] styleUrls: ['./create-cluster.component.scss']
}) })
export class CreateClusterComponent implements OnInit, OnDestroy { export class CreateClusterComponent implements OnInit, OnDestroy, AfterViewInit {
@ViewChild('skipConfirmTpl', { static: true }) @ViewChild('skipConfirmTpl', { static: true })
skipConfirmTpl: TemplateRef<any>; skipConfirmTpl: TemplateRef<any>;
currentStep: WizardStepModel; currentStep: WizardStepModel;
@ -88,7 +90,8 @@ export class CreateClusterComponent implements OnInit, OnDestroy {
private taskWrapper: TaskWrapperService, private taskWrapper: TaskWrapperService,
private osdService: OsdService, private osdService: OsdService,
private route: ActivatedRoute, private route: ActivatedRoute,
private location: Location private location: Location,
private changeDetectorRef: ChangeDetectorRef
) { ) {
this.permissions = this.authStorageService.getPermissions(); this.permissions = this.authStorageService.getPermissions();
this.currentStepSub = this.wizardStepsService this.currentStepSub = this.wizardStepsService
@ -98,6 +101,9 @@ export class CreateClusterComponent implements OnInit, OnDestroy {
}); });
this.currentStep.stepIndex = 0; this.currentStep.stepIndex = 0;
} }
ngAfterViewInit(): void {
this.changeDetectorRef.detectChanges();
}
ngOnInit(): void { ngOnInit(): void {
this.stepTitles.forEach((steps, index) => { this.stepTitles.forEach((steps, index) => {

View File

@ -6,7 +6,6 @@ import { RouterTestingModule } from '@angular/router/testing';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrModule } from 'ngx-toastr'; import { ToastrModule } from 'ngx-toastr';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed, FormHelper } from '~/testing/unit-test-helper'; import { configureTestBed, FormHelper } from '~/testing/unit-test-helper';
import { HostFormComponent } from './host-form.component'; import { HostFormComponent } from './host-form.component';
@ -17,22 +16,19 @@ describe('HostFormComponent', () => {
let fixture: ComponentFixture<HostFormComponent>; let fixture: ComponentFixture<HostFormComponent>;
let formHelper: FormHelper; let formHelper: FormHelper;
configureTestBed( configureTestBed({
{ imports: [
imports: [ SharedModule,
SharedModule, HttpClientTestingModule,
HttpClientTestingModule, RouterTestingModule,
RouterTestingModule, ReactiveFormsModule,
ReactiveFormsModule, ToastrModule.forRoot(),
ToastrModule.forRoot(), InputModule,
InputModule, ModalModule
ModalModule ],
], declarations: [HostFormComponent],
declarations: [HostFormComponent], providers: [NgbActiveModal]
providers: [NgbActiveModal] });
},
[LoadingPanelComponent]
);
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(HostFormComponent); fixture = TestBed.createComponent(HostFormComponent);

View File

@ -18,8 +18,7 @@
[maxLimit]="25" [maxLimit]="25"
(setExpandedRow)="setExpandedRow($event)" (setExpandedRow)="setExpandedRow($event)"
(updateSelection)="updateSelection($event)" (updateSelection)="updateSelection($event)"
[toolHeader]="!hideToolHeader" [toolHeader]="!hideToolHeader">
[showMenu]="showMenu">
<div class="table-actions"> <div class="table-actions">
<cd-table-actions [permission]="permissions.hosts" <cd-table-actions [permission]="permissions.hosts"
[selection]="selection" [selection]="selection"

View File

@ -5,7 +5,6 @@ import { RouterTestingModule } from '@angular/router/testing';
import { ToastrModule } from 'ngx-toastr'; import { ToastrModule } from 'ngx-toastr';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed } from '~/testing/unit-test-helper'; import { configureTestBed } from '~/testing/unit-test-helper';
import { MgrModuleFormComponent } from './mgr-module-form.component'; import { MgrModuleFormComponent } from './mgr-module-form.component';
@ -14,19 +13,16 @@ describe('MgrModuleFormComponent', () => {
let component: MgrModuleFormComponent; let component: MgrModuleFormComponent;
let fixture: ComponentFixture<MgrModuleFormComponent>; let fixture: ComponentFixture<MgrModuleFormComponent>;
configureTestBed( configureTestBed({
{ declarations: [MgrModuleFormComponent],
declarations: [MgrModuleFormComponent], imports: [
imports: [ HttpClientTestingModule,
HttpClientTestingModule, ReactiveFormsModule,
ReactiveFormsModule, RouterTestingModule,
RouterTestingModule, SharedModule,
SharedModule, ToastrModule.forRoot()
ToastrModule.forRoot() ]
] });
},
[LoadingPanelComponent]
);
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(MgrModuleFormComponent); fixture = TestBed.createComponent(MgrModuleFormComponent);

View File

@ -86,7 +86,7 @@ describe('SilenceFormComponent', () => {
}); });
const changeAction = (action: string) => { const changeAction = (action: string) => {
const modes = { const modes: Record<string, string> = {
add: '/monitoring/silences/add', add: '/monitoring/silences/add',
alertAdd: '/monitoring/silences/add/alert0', alertAdd: '/monitoring/silences/add/alert0',
recreate: '/monitoring/silences/recreate/someExpiredId', recreate: '/monitoring/silences/recreate/someExpiredId',
@ -180,7 +180,7 @@ describe('SilenceFormComponent', () => {
let navigateSpy: jasmine.Spy; let navigateSpy: jasmine.Spy;
const expectError = (action: string, redirected: boolean) => { const expectError = (action: string, redirected: boolean) => {
Object.defineProperty(router, 'url', { value: action }); Object.defineProperty(router, 'url', { value: action, configurable: true });
if (redirected) { if (redirected) {
expect(() => callInit()).toThrowError(DashboardNotFoundError); expect(() => callInit()).toThrowError(DashboardNotFoundError);
} else { } else {

View File

@ -9,8 +9,6 @@ import { ToastrModule } from 'ngx-toastr';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { MgrModuleService } from '~/app/shared/api/mgr-module.service'; import { MgrModuleService } from '~/app/shared/api/mgr-module.service';
import { DownloadButtonComponent } from '~/app/shared/components/download-button/download-button.component';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed } from '~/testing/unit-test-helper'; import { configureTestBed } from '~/testing/unit-test-helper';
import { TelemetryComponent } from './telemetry.component'; import { TelemetryComponent } from './telemetry.component';
@ -46,19 +44,16 @@ describe('TelemetryComponent', () => {
'url' 'url'
]; ];
configureTestBed( configureTestBed({
{ declarations: [TelemetryComponent],
declarations: [TelemetryComponent], imports: [
imports: [ HttpClientTestingModule,
HttpClientTestingModule, ReactiveFormsModule,
ReactiveFormsModule, RouterTestingModule,
RouterTestingModule, SharedModule,
SharedModule, ToastrModule.forRoot()
ToastrModule.forRoot() ]
] });
},
[LoadingPanelComponent, DownloadButtonComponent]
);
describe('configForm', () => { describe('configForm', () => {
beforeEach(() => { beforeEach(() => {

View File

@ -1,4 +1,11 @@
import { Component, Input, ViewChild, OnChanges, SimpleChanges } from '@angular/core'; import {
Component,
Input,
ViewChild,
OnChanges,
SimpleChanges,
AfterViewInit
} from '@angular/core';
import { CssHelper } from '~/app/shared/classes/css-helper'; import { CssHelper } from '~/app/shared/classes/css-helper';
import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe'; import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
@ -14,7 +21,7 @@ import 'chartjs-adapter-moment';
templateUrl: './dashboard-area-chart.component.html', templateUrl: './dashboard-area-chart.component.html',
styleUrls: ['./dashboard-area-chart.component.scss'] styleUrls: ['./dashboard-area-chart.component.scss']
}) })
export class DashboardAreaChartComponent implements OnChanges { export class DashboardAreaChartComponent implements OnChanges, AfterViewInit {
@ViewChild(BaseChartDirective) chart: BaseChartDirective; @ViewChild(BaseChartDirective) chart: BaseChartDirective;
@Input() @Input()
@ -44,32 +51,7 @@ export class DashboardAreaChartComponent implements OnChanges {
options: any = {}; options: any = {};
currentChartData: any = {}; currentChartData: any = {};
chartColors: any[] = [ chartColors!: any[];
[
this.cssHelper.propertyValue('chart-color-strong-blue'),
this.cssHelper.propertyValue('chart-color-translucent-blue')
],
[
this.cssHelper.propertyValue('chart-color-orange'),
this.cssHelper.propertyValue('chart-color-translucent-orange')
],
[
this.cssHelper.propertyValue('chart-color-green'),
this.cssHelper.propertyValue('chart-color-translucent-green')
],
[
this.cssHelper.propertyValue('chart-color-cyan'),
this.cssHelper.propertyValue('chart-color-translucent-cyan')
],
[
this.cssHelper.propertyValue('chart-color-purple'),
this.cssHelper.propertyValue('chart-color-translucent-purple')
],
[
this.cssHelper.propertyValue('chart-color-red'),
this.cssHelper.propertyValue('chart-color-translucent-red')
]
];
public chartAreaBorderPlugin: any[] = [ public chartAreaBorderPlugin: any[] = [
{ {
@ -100,6 +82,33 @@ export class DashboardAreaChartComponent implements OnChanges {
private formatter: FormatterService, private formatter: FormatterService,
private numberFormatter: NumberFormatterService private numberFormatter: NumberFormatterService
) { ) {
this.chartColors = [
[
this.cssHelper.propertyValue('chart-color-strong-blue'),
this.cssHelper.propertyValue('chart-color-translucent-blue')
],
[
this.cssHelper.propertyValue('chart-color-orange'),
this.cssHelper.propertyValue('chart-color-translucent-orange')
],
[
this.cssHelper.propertyValue('chart-color-green'),
this.cssHelper.propertyValue('chart-color-translucent-green')
],
[
this.cssHelper.propertyValue('chart-color-cyan'),
this.cssHelper.propertyValue('chart-color-translucent-cyan')
],
[
this.cssHelper.propertyValue('chart-color-purple'),
this.cssHelper.propertyValue('chart-color-translucent-purple')
],
[
this.cssHelper.propertyValue('chart-color-red'),
this.cssHelper.propertyValue('chart-color-translucent-red')
]
];
this.options = { this.options = {
plugins: { plugins: {
legend: { legend: {

View File

@ -4,7 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { NgbNavModule, NgbPopoverModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbNavModule, NgbPopoverModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { NgChartsModule } from 'ng2-charts'; import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { SimplebarAngularModule } from 'simplebar-angular'; import { SimplebarAngularModule } from 'simplebar-angular';
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
@ -21,15 +21,14 @@ import { PgSummaryPipe } from './pg-summary.pipe';
CommonModule, CommonModule,
NgbNavModule, NgbNavModule,
SharedModule, SharedModule,
NgChartsModule,
RouterModule, RouterModule,
NgbPopoverModule, NgbPopoverModule,
NgbTooltipModule, NgbTooltipModule,
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
SimplebarAngularModule SimplebarAngularModule,
BaseChartDirective
], ],
declarations: [ declarations: [
DashboardV3Component, DashboardV3Component,
DashboardPieComponent, DashboardPieComponent,
@ -37,12 +36,12 @@ import { PgSummaryPipe } from './pg-summary.pipe';
DashboardAreaChartComponent, DashboardAreaChartComponent,
DashboardTimeSelectorComponent DashboardTimeSelectorComponent
], ],
exports: [ exports: [
DashboardV3Component, DashboardV3Component,
DashboardAreaChartComponent, DashboardAreaChartComponent,
DashboardTimeSelectorComponent, DashboardTimeSelectorComponent,
DashboardPieComponent DashboardPieComponent
] ],
providers: [provideCharts(withDefaultRegisterables())]
}) })
export class DashboardV3Module {} export class DashboardV3Module {}

View File

@ -4,7 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { NgbNavModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbNavModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap';
import { NgChartsModule } from 'ng2-charts'; import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
import { DashboardV3Module } from '../dashboard-v3/dashboard-v3.module'; import { DashboardV3Module } from '../dashboard-v3/dashboard-v3.module';
@ -15,10 +15,10 @@ import { HealthPieComponent } from './health-pie/health-pie.component';
import { HealthComponent } from './health/health.component'; import { HealthComponent } from './health/health.component';
import { InfoCardComponent } from './info-card/info-card.component'; import { InfoCardComponent } from './info-card/info-card.component';
import { InfoGroupComponent } from './info-group/info-group.component'; import { InfoGroupComponent } from './info-group/info-group.component';
import { MdsSummaryPipe } from './mds-summary.pipe'; import { MdsDashboardSummaryPipe } from './mds-dashboard-summary.pipe';
import { MgrSummaryPipe } from './mgr-summary.pipe'; import { MgrDashboardSummaryPipe } from './mgr-dashboard-summary.pipe';
import { MonSummaryPipe } from './mon-summary.pipe'; import { MonSummaryPipe } from './mon-summary.pipe';
import { OsdSummaryPipe } from './osd-summary.pipe'; import { osdDashboardSummaryPipe } from './osd-dashboard-summary.pipe';
@NgModule({ @NgModule({
imports: [ imports: [
@ -26,25 +26,25 @@ import { OsdSummaryPipe } from './osd-summary.pipe';
CommonModule, CommonModule,
NgbNavModule, NgbNavModule,
SharedModule, SharedModule,
NgChartsModule,
RouterModule, RouterModule,
NgbPopoverModule, NgbPopoverModule,
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
DashboardV3Module DashboardV3Module,
BaseChartDirective
], ],
declarations: [ declarations: [
HealthComponent, HealthComponent,
DashboardComponent, DashboardComponent,
MonSummaryPipe, MonSummaryPipe,
OsdSummaryPipe, osdDashboardSummaryPipe,
MgrSummaryPipe, MgrDashboardSummaryPipe,
MdsSummaryPipe, MdsDashboardSummaryPipe,
HealthPieComponent, HealthPieComponent,
InfoCardComponent, InfoCardComponent,
InfoGroupComponent, InfoGroupComponent,
FeedbackComponent FeedbackComponent
] ],
providers: [provideCharts(withDefaultRegisterables())]
}) })
export class DashboardModule {} export class DashboardModule {}

View File

@ -2,36 +2,36 @@
class="container-fluid"> class="container-fluid">
<cd-info-group groupTitle="Status" <cd-info-group groupTitle="Status"
i18n-groupTitle i18n-groupTitle
*ngIf="healthData.health?.status *ngIf="healthData?.health?.status
|| healthData.mon_status || healthData?.mon_status
|| healthData.osd_map || healthData?.osd_map
|| healthData.mgr_map || healthData?.mgr_map
|| healthData.hosts != null || healthData?.hosts != null
|| healthData.rgw != null || healthData?.rgw != null
|| healthData.fs_map || healthData?.fs_map
|| healthData.iscsi_daemons != null"> || healthData?.iscsi_daemons != null">
<cd-info-card cardTitle="Cluster Status" <cd-info-card cardTitle="Cluster Status"
i18n-cardTitle i18n-cardTitle
class="cd-status-card" class="cd-status-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="healthData.health?.status"> *ngIf="healthData?.health?.status">
<ng-container *ngIf="healthData.health?.checks?.length > 0"> <ng-container *ngIf="healthData?.health?.checks?.length > 0">
<ng-template #healthChecks> <ng-template #healthChecks>
<cd-health-checks [healthData]="healthData"></cd-health-checks> <cd-health-checks [healthData]="healthData"></cd-health-checks>
</ng-template> </ng-template>
<div class="info-card-content-clickable" <div class="info-card-content-clickable"
[ngStyle]="healthData.health.status | healthColor" [ngStyle]="healthData?.health?.status | healthColor"
[ngbPopover]="healthChecks" [ngbPopover]="healthChecks"
popoverClass="info-card-popover-cluster-status"> popoverClass="info-card-popover-cluster-status">
{{ healthData.health.status | healthLabel | uppercase }} {{ healthData?.health?.status | healthLabel | uppercase }}
<i *ngIf="healthData.health?.status !== 'HEALTH_OK'" <i *ngIf="healthData?.health?.status !== 'HEALTH_OK'"
class="fa fa-exclamation-triangle"></i> class="fa fa-exclamation-triangle"></i>
</div> </div>
</ng-container> </ng-container>
<ng-container *ngIf="!healthData.health?.checks?.length"> <ng-container *ngIf="!healthData?.health?.checks?.length">
<div [ngStyle]="healthData.health.status | healthColor"> <div [ngStyle]="healthData?.health.status | healthColor">
{{ healthData.health.status | healthLabel | uppercase }} {{ healthData?.health.status | healthLabel | uppercase }}
</div> </div>
</ng-container> </ng-container>
</cd-info-card> </cd-info-card>
@ -41,8 +41,8 @@
link="/hosts" link="/hosts"
class="cd-status-card" class="cd-status-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="healthData.hosts != null"> *ngIf="healthData?.hosts != null">
{{ healthData.hosts }} total {{ healthData?.hosts }} total
</cd-info-card> </cd-info-card>
<cd-info-card cardTitle="Monitors" <cd-info-card cardTitle="Monitors"
@ -50,15 +50,15 @@
link="/monitor" link="/monitor"
class="cd-status-card" class="cd-status-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="healthData.mon_status"> *ngIf="healthData?.mon_status">
{{ healthData.mon_status | monSummary }} {{ healthData?.mon_status | monSummary }}
</cd-info-card> </cd-info-card>
<cd-info-card cardTitle="OSDs" <cd-info-card cardTitle="OSDs"
i18n-cardTitle i18n-cardTitle
link="/osd" link="/osd"
class="cd-status-card" class="cd-status-card"
*ngIf="(healthData.osd_map | osdSummary) as transformedResult" *ngIf="(healthData?.osd_map | osdDashboardSummary) as transformedResult"
contentClass="content-highlight"> contentClass="content-highlight">
<span *ngFor="let result of transformedResult" <span *ngFor="let result of transformedResult"
[ngClass]="result.class"> [ngClass]="result.class">
@ -70,8 +70,8 @@
i18n-cardTitle i18n-cardTitle
class="cd-status-card" class="cd-status-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="healthData.mgr_map"> *ngIf="healthData?.mgr_map">
<span *ngFor="let result of (healthData.mgr_map | mgrSummary)" <span *ngFor="let result of (healthData?.mgr_map | mgrDashboardSummary)"
[ngClass]="result.class" [ngClass]="result.class"
[title]="result.titleText != null ? result.titleText : ''"> [title]="result.titleText != null ? result.titleText : ''">
{{ result.content }} {{ result.content }}
@ -83,14 +83,14 @@
link="/rgw/daemon" link="/rgw/daemon"
class="cd-status-card" class="cd-status-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="enabledFeature.rgw && healthData?.rgw != null"> *ngIf="enabledFeature?.rgw && healthData?.rgw != null">
{{ healthData.rgw }} total {{ healthData?.rgw }} total
</cd-info-card> </cd-info-card>
<cd-info-card cardTitle="Metadata Servers" <cd-info-card cardTitle="Metadata Servers"
i18n-cardTitle i18n-cardTitle
class="cd-status-card" class="cd-status-card"
*ngIf="(enabledFeature.cephfs && healthData.fs_map | mdsSummary) as transformedResult" *ngIf="(enabledFeature?.cephfs && healthData?.fs_map | mdsDashboardSummary) as transformedResult"
[contentClass]="(transformedResult.length > 1 ? 'text-area-size-2' : '') + ' content-highlight'"> [contentClass]="(transformedResult.length > 1 ? 'text-area-size-2' : '') + ' content-highlight'">
<!-- TODO: check text-area-size-2 --> <!-- TODO: check text-area-size-2 -->
<span *ngFor="let result of transformedResult" <span *ngFor="let result of transformedResult"
@ -105,25 +105,25 @@
link="/block/iscsi" link="/block/iscsi"
class="cd-status-card" class="cd-status-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="enabledFeature.iscsi && healthData?.iscsi_daemons != null"> *ngIf="enabledFeature?.iscsi && healthData?.iscsi_daemons != null">
{{ healthData.iscsi_daemons.up + healthData.iscsi_daemons.down }} total {{ healthData?.iscsi_daemons.up + healthData?.iscsi_daemons.down }} total
<span class="card-text-line-break"></span> <span class="card-text-line-break"></span>
{{ healthData.iscsi_daemons.up }} up, {{ healthData?.iscsi_daemons.up }} up,
<span [ngClass]="{'card-text-error': healthData.iscsi_daemons.down > 0}">{{ healthData.iscsi_daemons.down }} <span [ngClass]="{'card-text-error': healthData?.iscsi_daemons.down > 0}">{{ healthData?.iscsi_daemons.down }}
down</span> down</span>
</cd-info-card> </cd-info-card>
</cd-info-group> </cd-info-group>
<cd-info-group groupTitle="Capacity" <cd-info-group groupTitle="Capacity"
i18n-groupTitle i18n-groupTitle
*ngIf="healthData.pools *ngIf="healthData?.pools
|| healthData.df || healthData?.df
|| healthData.pg_info"> || healthData?.pg_info">
<cd-info-card cardTitle="Raw Capacity" <cd-info-card cardTitle="Raw Capacity"
i18n-cardTitle i18n-cardTitle
class="cd-capacity-card cd-chart-card" class="cd-capacity-card cd-chart-card"
contentClass="content-chart" contentClass="content-chart"
*ngIf="healthData.df"> *ngIf="healthData?.df">
<cd-health-pie [data]="healthData" <cd-health-pie [data]="healthData"
[config]="rawCapacityChartConfig" [config]="rawCapacityChartConfig"
[isBytesData]="true" [isBytesData]="true"
@ -135,7 +135,7 @@
i18n-cardTitle i18n-cardTitle
class="cd-capacity-card cd-chart-card" class="cd-capacity-card cd-chart-card"
contentClass="content-chart" contentClass="content-chart"
*ngIf="healthData.pg_info?.object_stats?.num_objects != null"> *ngIf="healthData?.pg_info?.object_stats?.num_objects != null">
<cd-health-pie [data]="healthData" <cd-health-pie [data]="healthData"
(prepareFn)="prepareObjects($event[0], $event[1])"> (prepareFn)="prepareObjects($event[0], $event[1])">
</cd-health-pie> </cd-health-pie>
@ -145,11 +145,11 @@
i18n-cardTitle i18n-cardTitle
class="cd-capacity-card cd-chart-card" class="cd-capacity-card cd-chart-card"
contentClass="content-chart" contentClass="content-chart"
*ngIf="healthData.pg_info"> *ngIf="healthData?.pg_info">
<ng-template #pgStatus> <ng-template #pgStatus>
<ng-container *ngTemplateOutlet="logsLink"></ng-container> <ng-container *ngTemplateOutlet="logsLink"></ng-container>
<ul> <ul>
<li *ngFor="let pgStatesText of healthData.pg_info.statuses | keyvalue"> <li *ngFor="let pgStatesText of healthData?.pg_info.statuses | keyvalue">
{{ pgStatesText.key }}: {{ pgStatesText.value }} {{ pgStatesText.key }}: {{ pgStatesText.value }}
</li> </li>
</ul> </ul>
@ -169,27 +169,27 @@
link="/pool" link="/pool"
class="cd-capacity-card" class="cd-capacity-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="healthData.pools"> *ngIf="healthData?.pools">
{{ healthData.pools.length }} {{ healthData?.pools.length }}
</cd-info-card> </cd-info-card>
<cd-info-card cardTitle="PGs per OSD" <cd-info-card cardTitle="PGs per OSD"
i18n-cardTitle i18n-cardTitle
class="cd-capacity-card" class="cd-capacity-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="healthData.pg_info"> *ngIf="healthData?.pg_info">
{{ healthData.pg_info.pgs_per_osd | dimless }} {{ healthData?.pg_info.pgs_per_osd | dimless }}
</cd-info-card> </cd-info-card>
</cd-info-group> </cd-info-group>
<cd-info-group groupTitle="Performance" <cd-info-group groupTitle="Performance"
i18n-groupTitle i18n-groupTitle
*ngIf="healthData.client_perf || healthData.scrub_status"> *ngIf="healthData?.client_perf || healthData?.scrub_status">
<cd-info-card cardTitle="Client Read/Write" <cd-info-card cardTitle="Client Read/Write"
i18n-cardTitle i18n-cardTitle
class="cd-performance-card cd-chart-card" class="cd-performance-card cd-chart-card"
contentClass="content-chart" contentClass="content-chart"
*ngIf="healthData.client_perf"> *ngIf="healthData?.client_perf">
<cd-health-pie [data]="healthData" <cd-health-pie [data]="healthData"
[config]="clientStatsConfig" [config]="clientStatsConfig"
(prepareFn)="prepareReadWriteRatio($event[0], $event[1])"> (prepareFn)="prepareReadWriteRatio($event[0], $event[1])">
@ -200,7 +200,7 @@
i18n-cardTitle i18n-cardTitle
class="cd-performance-card cd-chart-card" class="cd-performance-card cd-chart-card"
contentClass="content-chart" contentClass="content-chart"
*ngIf="healthData.client_perf"> *ngIf="healthData?.client_perf">
<cd-health-pie [data]="healthData" <cd-health-pie [data]="healthData"
[config]="clientStatsConfig" [config]="clientStatsConfig"
(prepareFn)="prepareClientThroughput($event[0], $event[1])"> (prepareFn)="prepareClientThroughput($event[0], $event[1])">
@ -211,21 +211,21 @@
i18n-cardTitle i18n-cardTitle
class="cd-performance-card" class="cd-performance-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="healthData.client_perf"> *ngIf="healthData?.client_perf">
{{ (healthData.client_perf.recovering_bytes_per_sec | dimlessBinary) + '/s' }} {{ (healthData?.client_perf.recovering_bytes_per_sec | dimlessBinary) + '/s' }}
</cd-info-card> </cd-info-card>
<cd-info-card cardTitle="Scrubbing" <cd-info-card cardTitle="Scrubbing"
i18n-cardTitle i18n-cardTitle
class="cd-performance-card" class="cd-performance-card"
contentClass="content-highlight" contentClass="content-highlight"
*ngIf="healthData.scrub_status"> *ngIf="healthData?.scrub_status">
{{ healthData.scrub_status }} {{ healthData?.scrub_status }}
</cd-info-card> </cd-info-card>
</cd-info-group> </cd-info-group>
<ng-template #logsLink> <ng-template #logsLink>
<ng-container *ngIf="permissions.log.read"> <ng-container *ngIf="permissions?.log?.read">
<p class="logs-link" <p class="logs-link"
i18n><i [ngClass]="[icons.infoCircle]"></i> See <a routerLink="/logs">Logs</a> for more details.</p> i18n><i [ngClass]="[icons.infoCircle]"></i> See <a routerLink="/logs">Logs</a> for more details.</p>
</ng-container> </ng-container>

View File

@ -16,10 +16,10 @@ import { RefreshIntervalService } from '~/app/shared/services/refresh-interval.s
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed } from '~/testing/unit-test-helper'; import { configureTestBed } from '~/testing/unit-test-helper';
import { HealthPieComponent } from '../health-pie/health-pie.component'; import { HealthPieComponent } from '../health-pie/health-pie.component';
import { MdsSummaryPipe } from '../mds-summary.pipe'; import { MdsDashboardSummaryPipe } from '../mds-dashboard-summary.pipe';
import { MgrSummaryPipe } from '../mgr-summary.pipe'; import { MgrDashboardSummaryPipe } from '../mgr-dashboard-summary.pipe';
import { MonSummaryPipe } from '../mon-summary.pipe'; import { MonSummaryPipe } from '../mon-summary.pipe';
import { OsdSummaryPipe } from '../osd-summary.pipe'; import { osdDashboardSummaryPipe } from '../osd-dashboard-summary.pipe';
import { HealthComponent } from './health.component'; import { HealthComponent } from './health.component';
describe('HealthComponent', () => { describe('HealthComponent', () => {
@ -54,9 +54,9 @@ describe('HealthComponent', () => {
HealthComponent, HealthComponent,
HealthPieComponent, HealthPieComponent,
MonSummaryPipe, MonSummaryPipe,
OsdSummaryPipe, osdDashboardSummaryPipe,
MdsSummaryPipe, MdsDashboardSummaryPipe,
MgrSummaryPipe MgrDashboardSummaryPipe
], ],
schemas: [NO_ERRORS_SCHEMA], schemas: [NO_ERRORS_SCHEMA],
providers: [ providers: [

View File

@ -1,17 +1,17 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { configureTestBed } from '~/testing/unit-test-helper'; import { configureTestBed } from '~/testing/unit-test-helper';
import { MdsSummaryPipe } from './mds-summary.pipe'; import { MdsDashboardSummaryPipe } from './mds-dashboard-summary.pipe';
describe('MdsSummaryPipe', () => { describe('MdsDashboardSummaryPipe', () => {
let pipe: MdsSummaryPipe; let pipe: MdsDashboardSummaryPipe;
configureTestBed({ configureTestBed({
providers: [MdsSummaryPipe] providers: [MdsDashboardSummaryPipe]
}); });
beforeEach(() => { beforeEach(() => {
pipe = TestBed.inject(MdsSummaryPipe); pipe = TestBed.inject(MdsDashboardSummaryPipe);
}); });
it('create an instance', () => { it('create an instance', () => {

View File

@ -3,9 +3,9 @@ import { Pipe, PipeTransform } from '@angular/core';
import _ from 'lodash'; import _ from 'lodash';
@Pipe({ @Pipe({
name: 'mdsSummary' name: 'mdsDashboardSummary'
}) })
export class MdsSummaryPipe implements PipeTransform { export class MdsDashboardSummaryPipe implements PipeTransform {
transform(value: any): any { transform(value: any): any {
if (!value) { if (!value) {
return ''; return '';

View File

@ -1,17 +1,17 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { configureTestBed } from '~/testing/unit-test-helper'; import { configureTestBed } from '~/testing/unit-test-helper';
import { MgrSummaryPipe } from './mgr-summary.pipe'; import { MgrDashboardSummaryPipe } from './mgr-dashboard-summary.pipe';
describe('MgrSummaryPipe', () => { describe('MgrDashboardSummaryPipe', () => {
let pipe: MgrSummaryPipe; let pipe: MgrDashboardSummaryPipe;
configureTestBed({ configureTestBed({
providers: [MgrSummaryPipe] providers: [MgrDashboardSummaryPipe]
}); });
beforeEach(() => { beforeEach(() => {
pipe = TestBed.inject(MgrSummaryPipe); pipe = TestBed.inject(MgrDashboardSummaryPipe);
}); });
it('create an instance', () => { it('create an instance', () => {

View File

@ -3,9 +3,9 @@ import { Pipe, PipeTransform } from '@angular/core';
import _ from 'lodash'; import _ from 'lodash';
@Pipe({ @Pipe({
name: 'mgrSummary' name: 'mgrDashboardSummary'
}) })
export class MgrSummaryPipe implements PipeTransform { export class MgrDashboardSummaryPipe implements PipeTransform {
transform(value: any): any { transform(value: any): any {
if (!value) { if (!value) {
return ''; return '';

View File

@ -1,17 +1,17 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { configureTestBed } from '~/testing/unit-test-helper'; import { configureTestBed } from '~/testing/unit-test-helper';
import { OsdSummaryPipe } from './osd-summary.pipe'; import { osdDashboardSummaryPipe } from './osd-dashboard-summary.pipe';
describe('OsdSummaryPipe', () => { describe('osdDashboardSummaryPipe', () => {
let pipe: OsdSummaryPipe; let pipe: osdDashboardSummaryPipe;
configureTestBed({ configureTestBed({
providers: [OsdSummaryPipe] providers: [osdDashboardSummaryPipe]
}); });
beforeEach(() => { beforeEach(() => {
pipe = TestBed.inject(OsdSummaryPipe); pipe = TestBed.inject(osdDashboardSummaryPipe);
}); });
it('create an instance', () => { it('create an instance', () => {

View File

@ -3,9 +3,9 @@ import { Pipe, PipeTransform } from '@angular/core';
import _ from 'lodash'; import _ from 'lodash';
@Pipe({ @Pipe({
name: 'osdSummary' name: 'osdDashboardSummary'
}) })
export class OsdSummaryPipe implements PipeTransform { export class osdDashboardSummaryPipe implements PipeTransform {
transform(value: any): any { transform(value: any): any {
if (!value) { if (!value) {
return ''; return '';

View File

@ -11,7 +11,6 @@ import { Observable, of } from 'rxjs';
import { NfsFormClientComponent } from '~/app/ceph/nfs/nfs-form-client/nfs-form-client.component'; import { NfsFormClientComponent } from '~/app/ceph/nfs/nfs-form-client/nfs-form-client.component';
import { NfsFormComponent } from '~/app/ceph/nfs/nfs-form/nfs-form.component'; import { NfsFormComponent } from '~/app/ceph/nfs/nfs-form/nfs-form.component';
import { Directory } from '~/app/shared/api/nfs.service'; import { Directory } from '~/app/shared/api/nfs.service';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
import { ActivatedRouteStub } from '~/testing/activated-route-stub'; import { ActivatedRouteStub } from '~/testing/activated-route-stub';
import { configureTestBed, RgwHelper } from '~/testing/unit-test-helper'; import { configureTestBed, RgwHelper } from '~/testing/unit-test-helper';
@ -23,26 +22,23 @@ describe('NfsFormComponent', () => {
let activatedRoute: ActivatedRouteStub; let activatedRoute: ActivatedRouteStub;
let router: Router; let router: Router;
configureTestBed( configureTestBed({
{ declarations: [NfsFormComponent, NfsFormClientComponent],
declarations: [NfsFormComponent, NfsFormClientComponent], imports: [
imports: [ HttpClientTestingModule,
HttpClientTestingModule, ReactiveFormsModule,
ReactiveFormsModule, RouterTestingModule,
RouterTestingModule, SharedModule,
SharedModule, ToastrModule.forRoot(),
ToastrModule.forRoot(), NgbTypeaheadModule
NgbTypeaheadModule ],
], providers: [
providers: [ {
{ provide: ActivatedRoute,
provide: ActivatedRoute, useValue: new ActivatedRouteStub({ cluster_id: 'mynfs', export_id: '1' })
useValue: new ActivatedRouteStub({ cluster_id: 'mynfs', export_id: '1' }) }
} ]
] });
},
[LoadingPanelComponent]
);
const matchSquash = (backendSquashValue: string, uiSquashValue: string) => { const matchSquash = (backendSquashValue: string, uiSquashValue: string) => {
component.ngOnInit(); component.ngOnInit();

View File

@ -23,7 +23,7 @@ export class CrushRuleFormModalComponent extends CrushNodeSelectionClass impleme
@Output() @Output()
submitAction = new EventEmitter(); submitAction = new EventEmitter();
tooltips = this.crushRuleService.formTooltips; tooltips!: Record<string, string>;
form: CdFormGroup; form: CdFormGroup;
names: string[]; names: string[];
@ -67,6 +67,8 @@ export class CrushRuleFormModalComponent extends CrushNodeSelectionClass impleme
} }
ngOnInit() { ngOnInit() {
this.tooltips = this.crushRuleService.formTooltips;
this.crushRuleService this.crushRuleService
.getInfo() .getInfo()
.subscribe(({ names, nodes }: { names: string[]; nodes: CrushNode[] }) => { .subscribe(({ names, nodes }: { names: string[]; nodes: CrushNode[] }) => {

View File

@ -26,7 +26,7 @@ export class ErasureCodeProfileFormModalComponent
@Output() @Output()
submitAction = new EventEmitter(); submitAction = new EventEmitter();
tooltips = this.ecpService.formTooltips; tooltips!: Record<string, any>;
PLUGIN = { PLUGIN = {
LRC: 'lrc', // Locally Repairable Erasure Code LRC: 'lrc', // Locally Repairable Erasure Code
SHEC: 'shec', // Shingled Erasure Code SHEC: 'shec', // Shingled Erasure Code
@ -365,6 +365,8 @@ export class ErasureCodeProfileFormModalComponent
} }
ngOnInit() { ngOnInit() {
this.tooltips = this.ecpService.formTooltips;
this.ecpService this.ecpService
.getInfo() .getInfo()
.subscribe( .subscribe(

View File

@ -135,28 +135,25 @@ describe('PoolFormComponent', () => {
const routes: Routes = [{ path: '404', component: ErrorComponent }]; const routes: Routes = [{ path: '404', component: ErrorComponent }];
configureTestBed( configureTestBed({
{ declarations: [ErrorComponent],
declarations: [ErrorComponent], imports: [
imports: [ BrowserAnimationsModule,
BrowserAnimationsModule, HttpClientTestingModule,
HttpClientTestingModule, RouterTestingModule.withRoutes(routes),
RouterTestingModule.withRoutes(routes), ToastrModule.forRoot(),
ToastrModule.forRoot(), NgbNavModule,
NgbNavModule, PoolModule,
PoolModule, SharedModule,
SharedModule, NgbModalModule
NgbModalModule ],
], providers: [
providers: [ ErasureCodeProfileService,
ErasureCodeProfileService, NgbActiveModal,
NgbActiveModal, SelectBadgesComponent,
SelectBadgesComponent, { provide: ActivatedRoute, useValue: { params: of({ name: 'somePoolName' }) } }
{ provide: ActivatedRoute, useValue: { params: of({ name: 'somePoolName' }) } } ]
] });
},
[CriticalConfirmationModalComponent]
);
let navigationSpy: jasmine.Spy; let navigationSpy: jasmine.Spy;

View File

@ -4,6 +4,7 @@ import { BucketTagModalComponent } from './bucket-tag-modal.component';
import { HttpClientTestingModule } from '@angular/common/http/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ReactiveFormsModule } from '@angular/forms'; import { ReactiveFormsModule } from '@angular/forms';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('BucketTagModalComponent', () => { describe('BucketTagModalComponent', () => {
let component: BucketTagModalComponent; let component: BucketTagModalComponent;
@ -13,6 +14,7 @@ describe('BucketTagModalComponent', () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [BucketTagModalComponent], declarations: [BucketTagModalComponent],
imports: [HttpClientTestingModule, ReactiveFormsModule], imports: [HttpClientTestingModule, ReactiveFormsModule],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal] providers: [NgbActiveModal]
}).compileComponents(); }).compileComponents();

View File

@ -62,7 +62,6 @@
for="default_realm" for="default_realm"
formControlName="default_realm" formControlName="default_realm"
name="default_realm" name="default_realm"
[disabled]="action === actionLabels.EDIT"
i18n i18n
>Default >Default
<cd-help-text *ngIf="action === actionLabels.EDIT && info.data.is_default"> <cd-help-text *ngIf="action === actionLabels.EDIT && info.data.is_default">

View File

@ -93,6 +93,12 @@ export class RgwMultisiteRealmFormComponent extends BaseModal implements OnInit
this.defaultRealmDisabled = true; this.defaultRealmDisabled = true;
} }
this.docUrl = this.docService.urlGenerator('rgw-multisite'); this.docUrl = this.docService.urlGenerator('rgw-multisite');
if (this.action === this.actionLabels?.EDIT) {
this.multisiteRealmForm.get('default_realm').disable();
} else {
this.multisiteRealmForm.get('default_realm').enable();
}
} }
submit() { submit() {

View File

@ -8,6 +8,7 @@ import { ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service'; import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
enum FlowType { enum FlowType {
symmetrical = 'symmetrical', symmetrical = 'symmetrical',
@ -33,6 +34,7 @@ describe('RgwMultisiteSyncFlowModalComponent', () => {
ReactiveFormsModule, ReactiveFormsModule,
CommonModule CommonModule
], ],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal, { provide: RgwMultisiteService, useClass: MultisiteServiceMock }] providers: [NgbActiveModal, { provide: RgwMultisiteService, useClass: MultisiteServiceMock }]
}).compileComponents(); }).compileComponents();

View File

@ -9,6 +9,7 @@ import { CommonModule } from '@angular/common';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service'; import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
class MultisiteServiceMock { class MultisiteServiceMock {
createEditSyncPipe = jest.fn().mockReturnValue(of(null)); createEditSyncPipe = jest.fn().mockReturnValue(of(null));
@ -29,6 +30,7 @@ describe('RgwMultisiteSyncPipeModalComponent', () => {
ReactiveFormsModule, ReactiveFormsModule,
CommonModule CommonModule
], ],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal, { provide: RgwMultisiteService, useClass: MultisiteServiceMock }] providers: [NgbActiveModal, { provide: RgwMultisiteService, useClass: MultisiteServiceMock }]
}).compileComponents(); }).compileComponents();

View File

@ -6,6 +6,7 @@ import { ReactiveFormsModule } from '@angular/forms';
import { PipesModule } from '~/app/shared/pipes/pipes.module'; import { PipesModule } from '~/app/shared/pipes/pipes.module';
import { ComponentsModule } from '~/app/shared/components/components.module'; import { ComponentsModule } from '~/app/shared/components/components.module';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('RgwMultisiteSyncPolicyFormComponent', () => { describe('RgwMultisiteSyncPolicyFormComponent', () => {
let component: RgwMultisiteSyncPolicyFormComponent; let component: RgwMultisiteSyncPolicyFormComponent;
@ -22,6 +23,7 @@ describe('RgwMultisiteSyncPolicyFormComponent', () => {
ComponentsModule, ComponentsModule,
RouterTestingModule RouterTestingModule
], ],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [] providers: []
}).compileComponents(); }).compileComponents();

View File

@ -7,6 +7,7 @@ import { SharedModule } from '~/app/shared/shared.module';
import { ReactiveFormsModule } from '@angular/forms'; import { ReactiveFormsModule } from '@angular/forms';
import { ToastrModule } from 'ngx-toastr'; import { ToastrModule } from 'ngx-toastr';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('RgwMultisiteWizardComponent', () => { describe('RgwMultisiteWizardComponent', () => {
let component: RgwMultisiteWizardComponent; let component: RgwMultisiteWizardComponent;
@ -22,6 +23,7 @@ describe('RgwMultisiteWizardComponent', () => {
ToastrModule.forRoot(), ToastrModule.forRoot(),
RouterTestingModule RouterTestingModule
], ],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal] providers: [NgbActiveModal]
}).compileComponents(); }).compileComponents();

View File

@ -62,8 +62,8 @@ describe('RgwSyncDataInfoComponent', () => {
const syncStatus = fixture.debugElement.query(By.css('.text-primary')); const syncStatus = fixture.debugElement.query(By.css('.text-primary'));
expect(syncStatus).toBeTruthy(); expect(syncStatus).toBeTruthy();
expect(syncStatus.nativeElement.textContent).toEqual('Syncing'); expect(syncStatus.nativeElement.textContent).toEqual('Syncing');
const syncPopover = fixture.debugElement.query(By.css('a')); const syncPopover = fixture.nativeElement.querySelector('a');
syncPopover.triggerEventHandler('click', null); syncPopover.dispatchEvent(new Event('click'));
fixture.detectChanges(); fixture.detectChanges();
expect(syncPopover).toBeTruthy(); expect(syncPopover).toBeTruthy();
const syncPopoverText = fixture.debugElement.query(By.css('.text-center')); const syncPopoverText = fixture.debugElement.query(By.css('.text-center'));

View File

@ -65,8 +65,8 @@ describe('RgwSyncMetadataInfoComponent', () => {
const syncStatus = fixture.debugElement.query(By.css('.text-primary')); const syncStatus = fixture.debugElement.query(By.css('.text-primary'));
expect(syncStatus).toBeTruthy(); expect(syncStatus).toBeTruthy();
expect(syncStatus.nativeElement.textContent).toEqual('Syncing'); expect(syncStatus.nativeElement.textContent).toEqual('Syncing');
const syncPopover = fixture.debugElement.query(By.css('a')); const syncPopover = fixture.nativeElement.querySelector('a');
syncPopover.triggerEventHandler('click', null); syncPopover.dispatchEvent(new Event('click'));
fixture.detectChanges(); fixture.detectChanges();
expect(syncPopover).toBeTruthy(); expect(syncPopover).toBeTruthy();
const syncPopoverText = fixture.debugElement.query(By.css('.text-center')); const syncPopoverText = fixture.debugElement.query(By.css('.text-center'));

View File

@ -4,6 +4,7 @@ import { HealthChecksComponent } from './health-checks.component';
import { HealthColorPipe } from '~/app/shared/pipes/health-color.pipe'; import { HealthColorPipe } from '~/app/shared/pipes/health-color.pipe';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { CssHelper } from '~/app/shared/classes/css-helper'; import { CssHelper } from '~/app/shared/classes/css-helper';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
describe('HealthChecksComponent', () => { describe('HealthChecksComponent', () => {
let component: HealthChecksComponent; let component: HealthChecksComponent;
@ -12,7 +13,8 @@ describe('HealthChecksComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [HealthChecksComponent, HealthColorPipe], declarations: [HealthChecksComponent, HealthColorPipe],
providers: [CssHelper] providers: [CssHelper],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(HealthChecksComponent); fixture = TestBed.createComponent(HealthChecksComponent);

View File

@ -49,7 +49,7 @@ export class SmbClusterFormComponent extends CdForm implements OnInit {
resource: string; resource: string;
icons = Icons; icons = Icons;
domainSettingsObject: DomainSettings; domainSettingsObject: DomainSettings;
modalData$ = this.smbService.modalData$; modalData$!: Observable<DomainSettings>;
constructor( constructor(
private hostService: HostService, private hostService: HostService,
@ -63,6 +63,7 @@ export class SmbClusterFormComponent extends CdForm implements OnInit {
) { ) {
super(); super();
this.resource = $localize`Cluster`; this.resource = $localize`Cluster`;
this.modalData$ = this.smbService.modalData$;
} }
ngOnInit() { ngOnInit() {
this.action = this.actionLabels.CREATE; this.action = this.actionLabels.CREATE;

View File

@ -8,6 +8,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { NgbActiveModal, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
import { InputModule, ModalModule, SelectModule } from 'carbon-components-angular'; import { InputModule, ModalModule, SelectModule } from 'carbon-components-angular';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('SmbDomainSettingModalComponent', () => { describe('SmbDomainSettingModalComponent', () => {
let component: SmbDomainSettingModalComponent; let component: SmbDomainSettingModalComponent;
@ -27,6 +28,7 @@ describe('SmbDomainSettingModalComponent', () => {
InputModule, InputModule,
SelectModule SelectModule
], ],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal, { provide: 'domainSettingsObject', useValue: [[]] }] providers: [NgbActiveModal, { provide: 'domainSettingsObject', useValue: [[]] }]
}).compileComponents(); }).compileComponents();

View File

@ -2,7 +2,7 @@ import Close from '@carbon/icons/es/close/32';
import { SmbClusterListComponent } from './smb-cluster-list/smb-cluster-list.component'; import { SmbClusterListComponent } from './smb-cluster-list/smb-cluster-list.component';
import { SmbClusterFormComponent } from './smb-cluster-form/smb-cluster-form.component'; import { SmbClusterFormComponent } from './smb-cluster-form/smb-cluster-form.component';
import { AppRoutingModule } from '~/app/app-routing.module'; import { AppRoutingModule } from '~/app/app-routing.module';
import { NgChartsModule } from 'ng2-charts'; import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { DataTableModule } from '~/app/shared/datatable/datatable.module'; import { DataTableModule } from '~/app/shared/datatable/datatable.module';
import { SmbDomainSettingModalComponent } from './smb-domain-setting-modal/smb-domain-setting-modal.component'; import { SmbDomainSettingModalComponent } from './smb-domain-setting-modal/smb-domain-setting-modal.component';
import { import {
@ -33,7 +33,7 @@ import { NgModule } from '@angular/core';
CommonModule, CommonModule,
SharedModule, SharedModule,
AppRoutingModule, AppRoutingModule,
NgChartsModule, BaseChartDirective,
CommonModule, CommonModule,
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
@ -53,7 +53,8 @@ import { NgModule } from '@angular/core';
IconModule IconModule
], ],
exports: [SmbClusterListComponent, SmbClusterFormComponent], exports: [SmbClusterListComponent, SmbClusterFormComponent],
declarations: [SmbClusterListComponent, SmbClusterFormComponent, SmbDomainSettingModalComponent] declarations: [SmbClusterListComponent, SmbClusterFormComponent, SmbDomainSettingModalComponent],
providers: [provideCharts(withDefaultRegisterables())]
}) })
export class SmbModule { export class SmbModule {
constructor(private iconService: IconService) { constructor(private iconService: IconService) {

View File

@ -10,7 +10,6 @@ import { of } from 'rxjs';
import { RoleService } from '~/app/shared/api/role.service'; import { RoleService } from '~/app/shared/api/role.service';
import { ScopeService } from '~/app/shared/api/scope.service'; import { ScopeService } from '~/app/shared/api/scope.service';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
import { NotificationService } from '~/app/shared/services/notification.service'; import { NotificationService } from '~/app/shared/services/notification.service';
import { SharedModule } from '~/app/shared/shared.module'; import { SharedModule } from '~/app/shared/shared.module';
@ -32,19 +31,16 @@ describe('RoleFormComponent', () => {
const routes: Routes = [{ path: 'roles', component: FakeComponent }]; const routes: Routes = [{ path: 'roles', component: FakeComponent }];
configureTestBed( configureTestBed({
{ imports: [
imports: [ RouterTestingModule.withRoutes(routes),
RouterTestingModule.withRoutes(routes), HttpClientTestingModule,
HttpClientTestingModule, ReactiveFormsModule,
ReactiveFormsModule, ToastrModule.forRoot(),
ToastrModule.forRoot(), SharedModule
SharedModule ],
], declarations: [RoleFormComponent, FakeComponent]
declarations: [RoleFormComponent, FakeComponent] });
},
[LoadingPanelComponent]
);
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(RoleFormComponent); fixture = TestBed.createComponent(RoleFormComponent);

View File

@ -13,7 +13,6 @@ import { RoleService } from '~/app/shared/api/role.service';
import { SettingsService } from '~/app/shared/api/settings.service'; import { SettingsService } from '~/app/shared/api/settings.service';
import { UserService } from '~/app/shared/api/user.service'; import { UserService } from '~/app/shared/api/user.service';
import { ComponentsModule } from '~/app/shared/components/components.module'; import { ComponentsModule } from '~/app/shared/components/components.module';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
import { NotificationService } from '~/app/shared/services/notification.service'; import { NotificationService } from '~/app/shared/services/notification.service';
@ -44,21 +43,18 @@ describe('UserFormComponent', () => {
{ path: 'users', component: FakeComponent } { path: 'users', component: FakeComponent }
]; ];
configureTestBed( configureTestBed({
{ imports: [
imports: [ RouterTestingModule.withRoutes(routes),
RouterTestingModule.withRoutes(routes), HttpClientTestingModule,
HttpClientTestingModule, ReactiveFormsModule,
ReactiveFormsModule, ComponentsModule,
ComponentsModule, ToastrModule.forRoot(),
ToastrModule.forRoot(), SharedModule,
SharedModule, NgbPopoverModule
NgbPopoverModule ],
], declarations: [UserFormComponent, FakeComponent]
declarations: [UserFormComponent, FakeComponent] });
},
[LoadingPanelComponent]
);
beforeEach(() => { beforeEach(() => {
spyOn(TestBed.inject(PasswordPolicyService), 'getHelpText').and.callFake(() => of('')); spyOn(TestBed.inject(PasswordPolicyService), 'getHelpText').and.callFake(() => of(''));

View File

@ -13,7 +13,7 @@ import {
NgbTooltipModule NgbTooltipModule
} from '@ng-bootstrap/ng-bootstrap'; } from '@ng-bootstrap/ng-bootstrap';
import { ClickOutsideModule } from 'ng-click-outside'; import { ClickOutsideModule } from 'ng-click-outside';
import { NgChartsModule } from 'ng2-charts'; import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { SimplebarAngularModule } from 'simplebar-angular'; import { SimplebarAngularModule } from 'simplebar-angular';
import { import {
UIShellModule, UIShellModule,
@ -93,7 +93,6 @@ import InfoIcon from '@carbon/icons/es/information/16';
NgbPopoverModule, NgbPopoverModule,
NgbProgressbarModule, NgbProgressbarModule,
NgbTooltipModule, NgbTooltipModule,
NgChartsModule,
ReactiveFormsModule, ReactiveFormsModule,
PipesModule, PipesModule,
DirectivesModule, DirectivesModule,
@ -121,7 +120,8 @@ import InfoIcon from '@carbon/icons/es/information/16';
DropdownModule, DropdownModule,
SelectModule, SelectModule,
ComboBoxModule, ComboBoxModule,
ProgressIndicatorModule ProgressIndicatorModule,
BaseChartDirective
], ],
declarations: [ declarations: [
SparklineComponent, SparklineComponent,
@ -165,7 +165,7 @@ import InfoIcon from '@carbon/icons/es/information/16';
UpgradableComponent, UpgradableComponent,
ProgressComponent ProgressComponent
], ],
providers: [], providers: [provideCharts(withDefaultRegisterables())],
exports: [ exports: [
SparklineComponent, SparklineComponent,
HelperComponent, HelperComponent,

View File

@ -1,4 +1,4 @@
import { Component, NgModule, NO_ERRORS_SCHEMA, TemplateRef, ViewChild } from '@angular/core'; import { Component, NgModule, TemplateRef, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { NgForm, ReactiveFormsModule } from '@angular/forms'; import { NgForm, ReactiveFormsModule } from '@angular/forms';
@ -9,7 +9,7 @@ import { configureTestBed, modalServiceShow } from '~/testing/unit-test-helper';
import { AlertPanelComponent } from '../alert-panel/alert-panel.component'; import { AlertPanelComponent } from '../alert-panel/alert-panel.component';
import { LoadingPanelComponent } from '../loading-panel/loading-panel.component'; import { LoadingPanelComponent } from '../loading-panel/loading-panel.component';
import { CriticalConfirmationModalComponent } from './critical-confirmation-modal.component'; import { CriticalConfirmationModalComponent } from './critical-confirmation-modal.component';
import { ModalService, PlaceholderService } from 'carbon-components-angular'; import { CheckboxModule, ModalService, PlaceholderService } from 'carbon-components-angular';
import { ModalCdsService } from '../../services/modal-cds.service'; import { ModalCdsService } from '../../services/modal-cds.service';
@NgModule({}) @NgModule({})
@ -88,26 +88,22 @@ describe('CriticalConfirmationModalComponent', () => {
let component: CriticalConfirmationModalComponent; let component: CriticalConfirmationModalComponent;
let mockFixture: ComponentFixture<MockComponent>; let mockFixture: ComponentFixture<MockComponent>;
configureTestBed( configureTestBed({
{ declarations: [
declarations: [ MockComponent,
MockComponent, CriticalConfirmationModalComponent,
CriticalConfirmationModalComponent, LoadingPanelComponent,
LoadingPanelComponent, AlertPanelComponent
AlertPanelComponent ],
], imports: [ReactiveFormsModule, MockModule, DirectivesModule, CheckboxModule],
schemas: [NO_ERRORS_SCHEMA], providers: [
imports: [ReactiveFormsModule, MockModule, DirectivesModule], ModalService,
providers: [ PlaceholderService,
ModalService, { provide: 'itemNames', useValue: [] },
PlaceholderService, { provide: 'itemDescription', useValue: 'entry' },
{ provide: 'itemNames', useValue: [] }, { provide: 'actionDescription', useValue: 'delete' }
{ provide: 'itemDescription', useValue: 'entry' }, ]
{ provide: 'actionDescription', useValue: 'delete' } });
]
},
[CriticalConfirmationModalComponent]
);
beforeEach(() => { beforeEach(() => {
mockFixture = TestBed.createComponent(MockComponent); mockFixture = TestBed.createComponent(MockComponent);

View File

@ -1,6 +1,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset.component'; import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset.component';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('FormAdvancedFieldsetComponent', () => { describe('FormAdvancedFieldsetComponent', () => {
let component: FormAdvancedFieldsetComponent; let component: FormAdvancedFieldsetComponent;
@ -8,7 +9,8 @@ describe('FormAdvancedFieldsetComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [FormAdvancedFieldsetComponent] declarations: [FormAdvancedFieldsetComponent],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(FormAdvancedFieldsetComponent); fixture = TestBed.createComponent(FormAdvancedFieldsetComponent);

View File

@ -18,10 +18,9 @@
<ng-container *ngFor="let field of fields"> <ng-container *ngFor="let field of fields">
<div class="form-item"> <div class="form-item">
<cds-text-label *ngIf="field.type === 'text'" <cds-text-label *ngIf="field.type === 'text'"
[for]="field.name" [labelInputID]="field.name"
[invalid]="getError(field)" [invalid]="getError(field)"
[invalidText]="getError(field)" [invalidText]="getError(field)"
[label]="field.label"
[cdRequiredField]="field?.required === true ? field.label : ''" [cdRequiredField]="field?.required === true ? field.label : ''"
i18n> i18n>
{{ field.label }} {{ field.label }}
@ -34,18 +33,15 @@
autofocus> autofocus>
</cds-text-label> </cds-text-label>
<cds-number *ngIf="field.type === 'number'" <cds-number *ngIf="field.type === 'number'"
[for]="field.name"
[invalid]="getError(field)" [invalid]="getError(field)"
[invalidText]="getError(field)" [invalidText]="getError(field)"
[label]="field.label" [label]="field.label"
[cdRequiredField]="field?.required === true ? field.label : ''" [cdRequiredField]="field?.required === true ? field.label : ''"
[formControlName]="field.name" [formControlName]="field.name"
[id]="field.name" [id]="field.name"
[name]="field.name"
i18n></cds-number> i18n></cds-number>
<cds-text-label *ngIf="field.type === 'binary'" <cds-text-label *ngIf="field.type === 'binary'"
[for]="field.name" [labelInputID]="field.name"
[label]="field.label"
[invalid]="getError(field)" [invalid]="getError(field)"
[invalidText]="getError(field)" [invalidText]="getError(field)"
[cdRequiredField]="field?.required === true ? field.label : ''" [cdRequiredField]="field?.required === true ? field.label : ''"

View File

@ -1,6 +1,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProgressComponent } from './progress.component'; import { ProgressComponent } from './progress.component';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('ProgressComponent', () => { describe('ProgressComponent', () => {
let component: ProgressComponent; let component: ProgressComponent;
@ -8,7 +9,8 @@ describe('ProgressComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ProgressComponent] declarations: [ProgressComponent],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(ProgressComponent); fixture = TestBed.createComponent(ProgressComponent);

View File

@ -1,4 +1,4 @@
import { Component } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { UpgradeService } from '../../api/upgrade.service'; import { UpgradeService } from '../../api/upgrade.service';
@ -13,7 +13,7 @@ import { ExecutingTask } from '../../models/executing-task';
templateUrl: './upgradable.component.html', templateUrl: './upgradable.component.html',
styleUrls: ['./upgradable.component.scss'] styleUrls: ['./upgradable.component.scss']
}) })
export class UpgradableComponent { export class UpgradableComponent implements OnInit, OnDestroy {
orchAvailable: boolean = false; orchAvailable: boolean = false;
upgradeInfo$: Observable<UpgradeInfoInterface>; upgradeInfo$: Observable<UpgradeInfoInterface>;
upgradeStatus$: Observable<UpgradeStatusInterface>; upgradeStatus$: Observable<UpgradeStatusInterface>;

View File

@ -26,7 +26,7 @@ describe('TableKeyValueComponent', () => {
RouterTestingModule, RouterTestingModule,
NgbDropdownModule, NgbDropdownModule,
PipesModule, PipesModule,
NgbTooltipModule, NgbTooltipModule
] ]
}); });

View File

@ -5,8 +5,6 @@ import { By } from '@angular/platform-browser';
import { NgbAlertModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbAlertModule } from '@ng-bootstrap/ng-bootstrap';
import { configureTestBed } from '~/testing/unit-test-helper'; import { configureTestBed } from '~/testing/unit-test-helper';
import { AlertPanelComponent } from '../components/alert-panel/alert-panel.component';
import { LoadingPanelComponent } from '../components/loading-panel/loading-panel.component';
import { CdForm } from '../forms/cd-form'; import { CdForm } from '../forms/cd-form';
import { SharedModule } from '../shared.module'; import { SharedModule } from '../shared.module';
import { FormLoadingDirective } from './form-loading.directive'; import { FormLoadingDirective } from './form-loading.directive';
@ -28,13 +26,10 @@ describe('FormLoadingDirective', () => {
expect(fixture.debugElement.queryAll(By.css('cd-loading-panel')).length).toEqual(loading); expect(fixture.debugElement.queryAll(By.css('cd-loading-panel')).length).toEqual(loading);
}; };
configureTestBed( configureTestBed({
{ declarations: [TestComponent],
declarations: [TestComponent], imports: [SharedModule, NgbAlertModule]
imports: [SharedModule, NgbAlertModule] });
},
[LoadingPanelComponent, AlertPanelComponent]
);
afterEach(() => { afterEach(() => {
fixture = null; fixture = null;

View File

@ -5,7 +5,7 @@ import { AfterViewInit, Directive, ElementRef, Input, Renderer2 } from '@angular
}) })
export class RequiredFieldDirective implements AfterViewInit { export class RequiredFieldDirective implements AfterViewInit {
@Input('cdRequiredField') label: string; @Input('cdRequiredField') label: string;
@Input('skeleton') skeleton: boolean; @Input() skeleton: boolean;
constructor(private elementRef: ElementRef, private renderer: Renderer2) {} constructor(private elementRef: ElementRef, private renderer: Renderer2) {}
ngAfterViewInit() { ngAfterViewInit() {

View File

@ -1,15 +1,29 @@
import { NgbConfig, NgbNav, NgbNavChangeEvent, NgbNavConfig } from '@ng-bootstrap/ng-bootstrap'; import { NgbNav, NgbNavChangeEvent } from '@ng-bootstrap/ng-bootstrap';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { StatefulTabDirective } from './stateful-tab.directive'; import { StatefulTabDirective } from './stateful-tab.directive';
import { TestBed } from '@angular/core/testing';
class NgbNavMock {
select() {}
}
describe('StatefulTabDirective', () => { describe('StatefulTabDirective', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [StatefulTabDirective],
providers: [{ provide: NgbNav, useClass: NgbNavMock }],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
});
it('should create an instance', () => { it('should create an instance', () => {
const directive = new StatefulTabDirective(null); const directive = new StatefulTabDirective(null);
expect(directive).toBeTruthy(); expect(directive).toBeTruthy();
}); });
it('should get and select active tab', () => { it('should get and select active tab', () => {
const nav = new NgbNav('tablist', new NgbNavConfig(new NgbConfig()), <any>null, null); const nav = TestBed.inject(NgbNav);
spyOn(nav, 'select'); spyOn(nav, 'select');
const directive = new StatefulTabDirective(nav); const directive = new StatefulTabDirective(nav);
directive.cdStatefulTab = 'bar'; directive.cdStatefulTab = 'bar';
@ -27,7 +41,7 @@ describe('StatefulTabDirective', () => {
}); });
it('should select the default tab if provided', () => { it('should select the default tab if provided', () => {
const nav = new NgbNav('tablist', new NgbNavConfig(new NgbConfig()), <any>null, null); const nav = TestBed.inject(NgbNav);
spyOn(nav, 'select'); spyOn(nav, 'select');
const directive = new StatefulTabDirective(nav); const directive = new StatefulTabDirective(nav);
directive.cdStatefulTab = 'bar'; directive.cdStatefulTab = 'bar';

View File

@ -26,7 +26,7 @@ import { ActivatedRouteSnapshot, UrlSegment } from '@angular/router';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
export class BreadcrumbsResolver { export class BreadcrumbsResolver {
public resolve( public resolve(
route: ActivatedRouteSnapshot route: ActivatedRouteSnapshot
): Observable<IBreadcrumb[]> | Promise<IBreadcrumb[]> | IBreadcrumb[] { ): Observable<IBreadcrumb[]> | Promise<IBreadcrumb[]> | IBreadcrumb[] {

View File

@ -125,7 +125,8 @@ import { PipeFunctionPipe } from './pipe-function.pipe';
PathPipe, PathPipe,
PluralizePipe, PluralizePipe,
XmlPipe, XmlPipe,
MbpersecondPipe MbpersecondPipe,
PipeFunctionPipe
], ],
providers: [ providers: [
ArrayPipe, ArrayPipe,

View File

@ -1,4 +1,10 @@
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import {
HttpErrorResponse,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest
} from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';

View File

@ -6,7 +6,7 @@ import { AuthStorageService } from './auth-storage.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class AuthGuardService { export class AuthGuardService {
constructor(private router: Router, private authStorageService: AuthStorageService) {} constructor(private router: Router, private authStorageService: AuthStorageService) {}
canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

View File

@ -10,7 +10,7 @@ import { AuthStorageService } from './auth-storage.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class ChangePasswordGuardService { export class ChangePasswordGuardService {
constructor(private router: Router, private authStorageService: AuthStorageService) {} constructor(private router: Router, private authStorageService: AuthStorageService) {}
canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

View File

@ -9,7 +9,7 @@ import { FeatureTogglesMap, FeatureTogglesService } from './feature-toggles.serv
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class FeatureTogglesGuardService { export class FeatureTogglesGuardService {
constructor(private featureToggles: FeatureTogglesService) {} constructor(private featureToggles: FeatureTogglesService) {}
canActivate(route: ActivatedRouteSnapshot) { canActivate(route: ActivatedRouteSnapshot) {

View File

@ -19,7 +19,7 @@ describe('ModalService', () => {
let service: ModalService; let service: ModalService;
let ngbModal: NgbModal; let ngbModal: NgbModal;
configureTestBed({ declarations: [MockComponent], imports: [NgbModalModule] }, [MockComponent]); configureTestBed({ declarations: [MockComponent], imports: [NgbModalModule] });
beforeEach(() => { beforeEach(() => {
service = TestBed.inject(ModalService); service = TestBed.inject(ModalService);

View File

@ -36,7 +36,7 @@ import { Icons } from '~/app/shared/enum/icons.enum';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class ModuleStatusGuardService { export class ModuleStatusGuardService {
// TODO: Hotfix - remove ALLOWLIST'ing when a generic ErrorComponent is implemented // TODO: Hotfix - remove ALLOWLIST'ing when a generic ErrorComponent is implemented
static readonly ALLOWLIST: string[] = ['501']; static readonly ALLOWLIST: string[] = ['501'];

View File

@ -1,6 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { DashboardUserDeniedError } from '~/app/core/error/error'; import { DashboardUserDeniedError } from '~/app/core/error/error';
import { AuthStorageService } from './auth-storage.service'; import { AuthStorageService } from './auth-storage.service';
@ -11,7 +10,7 @@ import { AuthStorageService } from './auth-storage.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class NoSsoGuardService { export class NoSsoGuardService {
constructor(private authStorageService: AuthStorageService) {} constructor(private authStorageService: AuthStorageService) {}
canActivate() { canActivate() {

View File

@ -1,8 +1,7 @@
import { DebugElement, Type } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, DebugElement, NO_ERRORS_SCHEMA, Type } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AbstractControl } from '@angular/forms'; import { AbstractControl } from '@angular/forms';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { NgbModal, NgbNav, NgbNavItem, NgbNavLink } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal, NgbNav, NgbNavItem, NgbNavLink } from '@ng-bootstrap/ng-bootstrap';
import _ from 'lodash'; import _ from 'lodash';
@ -29,20 +28,12 @@ import {
PrometheusRule PrometheusRule
} from '~/app/shared/models/prometheus-alerts'; } from '~/app/shared/models/prometheus-alerts';
export function configureTestBed(configuration: any, entryComponents?: any) { export function configureTestBed(configuration: any) {
beforeEach(async () => { beforeEach(() => {
if (entryComponents) { TestBed.configureTestingModule({
// Declare entryComponents without having to add them to a module ...configuration,
// This is needed since Jest doesn't yet support not declaring entryComponents schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
await TestBed.configureTestingModule(configuration).overrideModule( });
BrowserDynamicTestingModule,
{
set: { entryComponents: entryComponents }
}
);
} else {
await TestBed.configureTestingModule(configuration);
}
}); });
} }

View File

@ -18,8 +18,8 @@
"noImplicitAny": true, "noImplicitAny": true,
"ignoreDeprecations": "5.0", "ignoreDeprecations": "5.0",
"suppressImplicitAnyIndexErrors": true, "suppressImplicitAnyIndexErrors": true,
"target": "ES2020", "target": "ES2022",
"module": "es2020", "module": "ES2022",
"baseUrl": "./", "baseUrl": "./",
"resolveJsonModule": true, "resolveJsonModule": true,
"paths": { "paths": {