From eb3e0cf49ea9f3a8dd7c5e941a9fb3f878273cb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henry=20T=C3=A4schner?= <129834483+HenryT-CG@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:34:49 +0100 Subject: [PATCH] fix: use pia lib v4 and code refactoring (#18) --- .eslintrc.json | 6 +- .prettierignore | 2 +- Dockerfile | 2 +- angular.json | 9 +-- helm/microfrontend.json | 21 ------ helm/permissions.csv | 5 -- helm/templates/apm-csv.cm.yaml | 14 ---- helm/templates/mf-config.yaml | 7 -- nginx/locations.conf | 2 +- package-lock.json | 56 +++++++------- package.json | 12 +-- proxy.conf.js | 4 +- sonar-local-project.properties | 2 +- src/app/app.component.scss | 0 src/app/app.component.spec.ts | 4 +- src/app/app.component.ts | 7 +- src/app/app.module.ts | 64 +++++++++++----- src/app/help-mgmt-remote.module.ts | 22 ------ .../help-detail/help-detail.component.html | 4 +- .../help-detail/help-detail.component.spec.ts | 12 ++- .../help/help-detail/help-detail.component.ts | 4 +- .../help/help-form/help-form.component.html | 10 +-- .../help/help-form/help-form.component.scss | 0 .../help-form/help-form.component.spec.ts | 6 +- src/app/help/help-form/help-form.component.ts | 7 +- .../help-criteria.component.scss | 0 .../help-criteria.component.spec.ts | 11 ++- .../help-criteria/help-criteria.component.ts | 7 +- .../help-search/help-search.component.html | 8 +- .../help-search/help-search.component.spec.ts | 58 +++++++++++++-- .../help/help-search/help-search.component.ts | 4 +- src/app/help/help.module.ts | 30 ++------ src/app/onecx-help-remote.module.ts | 43 +++++++++++ .../shared/can-active-guard.service.spec.ts | 74 ------------------- src/app/shared/can-active-guard.service.ts | 56 -------------- src/app/{ => shared}/generated/.gitignore | 0 .../generated/.openapi-generator-ignore | 0 .../generated/.openapi-generator/FILES | 0 .../generated/.openapi-generator/VERSION | 0 src/app/{ => shared}/generated/README.md | 0 src/app/{ => shared}/generated/api.module.ts | 0 src/app/{ => shared}/generated/api/api.ts | 0 .../generated/api/helpsInternal.service.ts | 0 .../{ => shared}/generated/configuration.ts | 0 src/app/{ => shared}/generated/encoder.ts | 0 src/app/{ => shared}/generated/index.ts | 0 .../generated/model/createHelp.ts | 0 src/app/{ => shared}/generated/model/help.ts | 0 .../generated/model/helpAppIds.ts | 0 .../generated/model/helpPageResult.ts | 0 .../generated/model/helpSearchCriteria.ts | 0 .../{ => shared}/generated/model/models.ts | 0 .../model/problemDetailInvalidParam.ts | 0 .../generated/model/problemDetailParam.ts | 0 .../generated/model/problemDetailResponse.ts | 0 .../generated/model/updateHelp.ts | 0 src/app/{ => shared}/generated/param.ts | 0 src/app/{ => shared}/generated/variables.ts | 0 src/app/shared/label.resolver.spec.ts | 20 +++-- src/app/shared/label.resolver.ts | 9 ++- src/app/shared/shared.module.spec.ts | 46 ------------ src/app/shared/shared.module.ts | 51 ++++--------- src/app/test/mocks/auth-mock.service.ts | 27 ------- src/environments/environment.prod.ts | 4 +- src/environments/environment.ts | 2 +- src/index.html | 4 +- tsconfig.app.json | 11 +-- tsconfig.spec.json | 2 +- webpack.config.js | 16 ++-- 69 files changed, 276 insertions(+), 489 deletions(-) delete mode 100644 helm/microfrontend.json delete mode 100644 helm/permissions.csv delete mode 100644 helm/templates/apm-csv.cm.yaml delete mode 100644 helm/templates/mf-config.yaml delete mode 100644 src/app/app.component.scss delete mode 100644 src/app/help-mgmt-remote.module.ts delete mode 100644 src/app/help/help-form/help-form.component.scss delete mode 100644 src/app/help/help-search/help-criteria/help-criteria.component.scss create mode 100644 src/app/onecx-help-remote.module.ts delete mode 100644 src/app/shared/can-active-guard.service.spec.ts delete mode 100644 src/app/shared/can-active-guard.service.ts rename src/app/{ => shared}/generated/.gitignore (100%) rename src/app/{ => shared}/generated/.openapi-generator-ignore (100%) rename src/app/{ => shared}/generated/.openapi-generator/FILES (100%) rename src/app/{ => shared}/generated/.openapi-generator/VERSION (100%) rename src/app/{ => shared}/generated/README.md (100%) rename src/app/{ => shared}/generated/api.module.ts (100%) rename src/app/{ => shared}/generated/api/api.ts (100%) rename src/app/{ => shared}/generated/api/helpsInternal.service.ts (100%) rename src/app/{ => shared}/generated/configuration.ts (100%) rename src/app/{ => shared}/generated/encoder.ts (100%) rename src/app/{ => shared}/generated/index.ts (100%) rename src/app/{ => shared}/generated/model/createHelp.ts (100%) rename src/app/{ => shared}/generated/model/help.ts (100%) rename src/app/{ => shared}/generated/model/helpAppIds.ts (100%) rename src/app/{ => shared}/generated/model/helpPageResult.ts (100%) rename src/app/{ => shared}/generated/model/helpSearchCriteria.ts (100%) rename src/app/{ => shared}/generated/model/models.ts (100%) rename src/app/{ => shared}/generated/model/problemDetailInvalidParam.ts (100%) rename src/app/{ => shared}/generated/model/problemDetailParam.ts (100%) rename src/app/{ => shared}/generated/model/problemDetailResponse.ts (100%) rename src/app/{ => shared}/generated/model/updateHelp.ts (100%) rename src/app/{ => shared}/generated/param.ts (100%) rename src/app/{ => shared}/generated/variables.ts (100%) delete mode 100644 src/app/shared/shared.module.spec.ts delete mode 100644 src/app/test/mocks/auth-mock.service.ts diff --git a/.eslintrc.json b/.eslintrc.json index fe57225..aef10d8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,7 @@ "dist/**", "helm/**", "node_modules/**", - "src/app/generated/**", + "src/app/shared/generated/**", "src/app/api/*", "src/app/model/*", "src/**/*.ico", @@ -39,7 +39,7 @@ "error", { "type": "attribute", - "prefix": "hm", + "prefix": "app", "style": "camelCase" } ], @@ -47,7 +47,7 @@ "warn", { "type": "element", - "prefix": "hm", + "prefix": "app", "style": "kebab-case" } ], diff --git a/.prettierignore b/.prettierignore index 6f46742..5a7360f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -15,6 +15,6 @@ README.md Dockerfile *.log *.sh -src/app/generated/** +src/app/shared/generated/** src/app/api/* src/app/model/* diff --git a/Dockerfile b/Dockerfile index 77e7f9c..6c76ca1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ COPY dist/onecx-help-ui/ $DIR_HTML # Application environments default values ENV BFF_URL http://onecx-help-bff:8080/ -ENV APP_BASE_HREF /help/ +ENV APP_BASE_HREF / RUN chmod 775 -R $DIR_HTML/assets USER 1001 diff --git a/angular.json b/angular.json index dc760c9..b693864 100644 --- a/angular.json +++ b/angular.json @@ -8,7 +8,7 @@ "schematics": {}, "root": "", "sourceRoot": "src", - "prefix": "hm", + "prefix": "app", "architect": { "build": { "builder": "ngx-build-plus:browser", @@ -109,12 +109,7 @@ "assets": ["src/favicon.ico", "src/assets"], "styles": ["src/styles.scss"], "scripts": [], - "codeCoverageExclude": [ - "**/*.module.ts", - "src/app/test/**", - "src/app/environments/**", - "src/app/generated/**" - ] + "codeCoverageExclude": ["**/*.module.ts", "src/app/environments/**", "src/app/shared/generated/**"] } }, "lint": { diff --git a/helm/microfrontend.json b/helm/microfrontend.json deleted file mode 100644 index 3859490..0000000 --- a/helm/microfrontend.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "id": "ONECX_HELP_UI", - {{- if .Values.app.routing.hostName }} - "remoteEntry": "https://{{ .Values.app.routing.hostName }}{{ .Values.app.routing.path }}remoteEntry.js", - {{- else if .Values.global.hostName }} - "remoteEntry": "https://{{ .Values.global.hostName }}{{ .Values.app.routing.path }}remoteEntry.js", - {{- end }} - "remoteName": "HelpMgmtModule", - {{- if .Values.app.routing.hostName }} - "remoteBaseUrl": "https://{{ .Values.app.routing.hostName }}{{ .Values.app.routing.path }}", - {{- else if .Values.global.hostName }} - "remoteBaseUrl": "https://{{ .Values.global.hostName }}{{ .Values.app.routing.path }}", - {{- end }} - "exposedModule": "./HelpMgmtModule", - "displayName": "OneCX Help Mgmt", - "moduleType": "ANGULAR", - "wcTagName": "UPMF", - "appVersion": "{{ .Chart.Version }}", - "note": "OneCX Help Mgmt Module auto import via MF operator", - "contact": "onecx@1000kit.org" -} diff --git a/helm/permissions.csv b/helm/permissions.csv deleted file mode 100644 index f8c85d0..0000000 --- a/helm/permissions.csv +++ /dev/null @@ -1,5 +0,0 @@ -PERMISSION NAME;PERMISSION_KEY;onecx-help-admin;onecx-help-user -Show search page for Help items;HELP#SEARCH;x;x -Show details of Help item;HELP#VIEW;x;x -Edit Help item;HELP#EDIT;x; -Delete Help item;HELP#DELETE;x; \ No newline at end of file diff --git a/helm/templates/apm-csv.cm.yaml b/helm/templates/apm-csv.cm.yaml deleted file mode 100644 index e9dccc5..0000000 --- a/helm/templates/apm-csv.cm.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: "{{ .Release.Name }}-apm-config" - annotations: - appId: {{ .Release.Name }} - filename: "permissions.csv" - labels: - app: {{ .Release.Name }} -{{ include "angular.labels.common" .Subcharts.app | indent 4 }} -data: - permissions.csv: |- -{{ $.Files.Get "permissions.csv" | indent 4 }} - diff --git a/helm/templates/mf-config.yaml b/helm/templates/mf-config.yaml deleted file mode 100644 index cb84bcf..0000000 --- a/helm/templates/mf-config.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: 'onecx-help-ui-mf-config' -data: - microfrontend: |- -{{ tpl (.Files.Get "microfrontend.json") . | indent 4 }} diff --git a/nginx/locations.conf b/nginx/locations.conf index 3d30da3..2ce449a 100644 --- a/nginx/locations.conf +++ b/nginx/locations.conf @@ -1,4 +1,4 @@ -location @@APP_BASE_HREF { +location @@APP_BASE_HREFbff { proxy_pass @@BFF_URL; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; diff --git a/package-lock.json b/package-lock.json index b591004..5de54fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "help-mgmt-ui", + "name": "onecx-help-ui", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "help-mgmt-ui", + "name": "onecx-help-ui", "version": "0.0.0", "license": "Apache-2.0", "dependencies": { @@ -23,11 +23,11 @@ "@ngneat/falso": "^6.4.0", "@ngx-translate/core": "^14.0.0", "@ngx-translate/http-loader": "^7.0.0", - "@onecx/accelerator": "^3.7.1", - "@onecx/integration-interface": "^3.7.1", - "@onecx/keycloak-auth": "^3.7.1", - "@onecx/portal-integration-angular": "^3.7.1", - "@onecx/portal-layout-styles": "^3.7.1", + "@onecx/accelerator": "^4.1.2", + "@onecx/integration-interface": "^4.1.2", + "@onecx/keycloak-auth": "^4.1.2", + "@onecx/portal-integration-angular": "^4.1.2", + "@onecx/portal-layout-styles": "^4.1.2", "file-saver": "^2.0.5", "i18n-iso-countries": "^7.6.0", "ngx-color": "^8.0.3", @@ -6613,44 +6613,44 @@ } }, "node_modules/@onecx/accelerator": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@onecx/accelerator/-/accelerator-3.7.1.tgz", - "integrity": "sha512-s/+4oNgHOWN9NabbF+BeHDv091kxv9o/XiUrBP9ssnfK4sDaS0/7g16Wprmt2SMJMQxm6nLczBgJ+nkJHSrITQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@onecx/accelerator/-/accelerator-4.1.2.tgz", + "integrity": "sha512-PujQII1motqpXwPUN0H+x6aN3BkHkmQBbQTkv+be+xlAnZD2qu7Y1gtDTfrESyj5FXBLvGw7+vIM7Bmf0NpPtA==", "peerDependencies": { "rxjs": "7.8.1", "tslib": "^2.3.0" } }, "node_modules/@onecx/integration-interface": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@onecx/integration-interface/-/integration-interface-3.7.1.tgz", - "integrity": "sha512-fsqKJGlXkM05uvVuodVDE3q37Ykz1/LtypAXWjsmK2mc+EGOfjBtEJi7UGmnWVup7U0lFZR+eTTAzYbc6LIXzQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@onecx/integration-interface/-/integration-interface-4.1.2.tgz", + "integrity": "sha512-XED3fNOiD+dnVEDSz8haGvfgaNVCeQjn9ECAftTJ4SZ+laD5dkdv0uI21UH9ZpTTt6jUUtfNhHZZ8wChNcYdRg==", "peerDependencies": { - "@onecx/accelerator": "^3", + "@onecx/accelerator": "~4", "rxjs": "7.8.1", "tslib": "^2.3.0" } }, "node_modules/@onecx/keycloak-auth": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@onecx/keycloak-auth/-/keycloak-auth-3.7.1.tgz", - "integrity": "sha512-QqkhJdAvn0y/9X/QTSHOn1B7RDZ6qVp/JM7pjfwwCZZcQQT2KW+wDlQWMiNBPhnsSQua1RlsaI5dqeQyipgbmA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@onecx/keycloak-auth/-/keycloak-auth-4.1.2.tgz", + "integrity": "sha512-pXrz/KHudCHVhIKqX31D3qeu513jErsqEAMmCix48MpcG/ZfFIibbLU0SAZtzp7uCIa+KcQL5MJhbsWMHb1vZA==", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/common": ">=15.2.7", "@angular/core": ">=15.2.7", - "@onecx/portal-integration-angular": "~3", + "@onecx/portal-integration-angular": "~4", "keycloak-angular": "^13.0.0", "keycloak-js": "^18.0.0", "rxjs": "~7.8.0" } }, "node_modules/@onecx/portal-integration-angular": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@onecx/portal-integration-angular/-/portal-integration-angular-3.7.1.tgz", - "integrity": "sha512-JFzo03qdRlU3Y25VduTVzENIhlL4Y4XmanUSfDdxoPU3sCD3PjpYI30y95WzA/1vDZFaerjs+9wYXHmfMx1k5A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@onecx/portal-integration-angular/-/portal-integration-angular-4.1.2.tgz", + "integrity": "sha512-dtGK9bqeDIf9RTqevQfr05Fxzfutr8xtP2nbYblAuKW4/D6xonUl6f0DS4ij40fW9745k+3MFg99FXA635fFqw==", "dependencies": { "tslib": "^2.3.0" }, @@ -6669,7 +6669,7 @@ "@ngrx/store": "^15.4.0", "@ngx-translate/core": "^14.0.0", "@ngx-translate/http-loader": "^7.0.0", - "@onecx/integration-interface": "^3", + "@onecx/integration-interface": "~4", "chart.js": "^4.4.0", "d3-scale-chromatic": "^3.0.0", "fast-deep-equal": "^3.1.3", @@ -6680,9 +6680,9 @@ } }, "node_modules/@onecx/portal-layout-styles": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@onecx/portal-layout-styles/-/portal-layout-styles-3.7.1.tgz", - "integrity": "sha512-RBFWbP22bh5sotUXcoo4Ur3/LZ481M8mR6Gb80KephFS8zppTyKMcCI4sDy4mEbtrsvKFOxyIVLw/ZBJX9LdgQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@onecx/portal-layout-styles/-/portal-layout-styles-4.1.2.tgz", + "integrity": "sha512-9rDqAkbJyN3OmBEuSXZuHL6VmVuZJkTyNOW3VGHuIsy0dBrbPiqToQ6E8aNdz78FztG3RXSceyhq/Ot05IXaOQ==", "peerDependencies": { "tslib": "^2.5.0" } @@ -12357,9 +12357,9 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, "node_modules/chart.js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz", - "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", + "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" diff --git a/package.json b/package.json index 8ae8e9c..29838f7 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ], "config": { "openapiYaml": "src/assets/api/help-bff-api.yaml", - "openapiOutput": "src/app/generated" + "openapiOutput": "src/app/shared/generated" }, "scripts": { "build": "ng build", @@ -49,11 +49,11 @@ "@ngneat/falso": "^6.4.0", "@ngx-translate/core": "^14.0.0", "@ngx-translate/http-loader": "^7.0.0", - "@onecx/accelerator": "^3.7.1", - "@onecx/integration-interface": "^3.7.1", - "@onecx/keycloak-auth": "^3.7.1", - "@onecx/portal-integration-angular": "^3.7.1", - "@onecx/portal-layout-styles": "^3.7.1", + "@onecx/accelerator": "^4.1.2", + "@onecx/integration-interface": "^4.1.2", + "@onecx/keycloak-auth": "^4.1.2", + "@onecx/portal-integration-angular": "^4.1.2", + "@onecx/portal-layout-styles": "^4.1.2", "file-saver": "^2.0.5", "i18n-iso-countries": "^7.6.0", "ngx-color": "^8.0.3", diff --git a/proxy.conf.js b/proxy.conf.js index ed50dd8..70ceecb 100644 --- a/proxy.conf.js +++ b/proxy.conf.js @@ -17,11 +17,11 @@ const bypassFn = function (req, res) { } const PROXY_CONFIG = { - '/help-bff': { + '/bff': { target: 'http://onecx-help-bff', secure: false, pathRewrite: { - '^.*/help-bff': '' + '^.*/bff': '' }, changeOrigin: true, logLevel: 'debug', diff --git a/sonar-local-project.properties b/sonar-local-project.properties index d204825..6a1164e 100644 --- a/sonar-local-project.properties +++ b/sonar-local-project.properties @@ -18,7 +18,7 @@ sonar.testExecutionReportPaths=reports/sonarqube_report.xml sonar.sourceEncoding=UTF-8 #sonar.sources=src/app #sonar.working.directory=dist/sonar -sonar.coverage.exclusions=*.ts,*.js,src/*.ts,src/**/*.module.ts,src/environments/*,src/assets/**/*,src/app/generated/**/*,src/test/* +sonar.coverage.exclusions=*.ts,*.js,src/*.ts,src/**/*.module.ts,src/environments/*,src/assets/**/*,src/app/shared/generated/**/* #sonar.exclusions=src/app/generated/**/* #sonar.cpd.exclusions= #sonar.tests=src/app diff --git a/src/app/app.component.scss b/src/app/app.component.scss deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 76586c6..c03db24 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -16,10 +16,10 @@ describe('AppComponent', () => { expect(app).toBeTruthy() }) - it(`should have as title 'help-mgmt'`, () => { + it(`should have as title 'onecx-help-ui'`, () => { const fixture = TestBed.createComponent(AppComponent) const app = fixture.componentInstance - expect(app.title).toEqual('help-mgmt') + expect(app.title).toEqual('onecx-help-ui') }) /* diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5a8bfd0..39ba20d 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,10 +1,9 @@ import { Component } from '@angular/core' @Component({ - selector: 'hm-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'] + selector: 'app-root', + templateUrl: './app.component.html' }) export class AppComponent { - title = 'help-mgmt' + title = 'onecx-help-ui' } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b832221..5ce3a90 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,35 +1,61 @@ import { APP_INITIALIZER, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { HttpClient, HttpClientModule } from '@angular/common/http' +import { RouterModule, Routes } from '@angular/router' import { BrowserModule } from '@angular/platform-browser' import { BrowserAnimationsModule } from '@angular/platform-browser/animations' -import { TranslateService } from '@ngx-translate/core' -import { DialogService } from 'primeng/dynamicdialog' -import { Observable } from 'rxjs' +import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core' -import { APP_CONFIG, PortalCoreModule } from '@onecx/portal-integration-angular' +import { + APP_CONFIG, + AppStateService, + createTranslateLoader, + translateServiceInitializer, + PortalCoreModule, + UserService +} from '@onecx/portal-integration-angular' import { KeycloakAuthModule } from '@onecx/keycloak-auth' import { AppComponent } from './app.component' -import { environment } from '../environments/environment' - -// standalone app: ensure translations are loaded during app init -function initializer(translate: TranslateService): () => Observable { - console.log('App module initializer') - return () => { - translate.addLangs(['en', 'de']) - const browserLang = translate.getBrowserLang() - return translate.use(browserLang?.match(/en|de/) ? browserLang : 'en') - } -} +import { environment } from 'src/environments/environment' +const routes: Routes = [{ path: '', pathMatch: 'full' }] @NgModule({ bootstrap: [AppComponent], declarations: [AppComponent], - imports: [BrowserModule, KeycloakAuthModule, BrowserAnimationsModule, PortalCoreModule.forRoot('help-mgmt-ui')], + imports: [ + CommonModule, + BrowserModule, + HttpClientModule, + KeycloakAuthModule, + BrowserAnimationsModule, + RouterModule.forRoot(routes, { + initialNavigation: 'enabledBlocking', + enableTracing: true + }), + PortalCoreModule.forRoot('onecx-help-ui'), + TranslateModule.forRoot({ + isolate: true, + loader: { + provide: TranslateLoader, + useFactory: createTranslateLoader, + deps: [HttpClient, AppStateService] + } + }) + ], providers: [ - DialogService, { provide: APP_CONFIG, useValue: environment }, - { provide: APP_INITIALIZER, useFactory: initializer, multi: true, deps: [TranslateService] } + { + provide: APP_INITIALIZER, + useFactory: translateServiceInitializer, + multi: true, + deps: [UserService, TranslateService] + } ], schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA] }) -export class AppModule {} +export class AppModule { + constructor() { + console.info('App Module constructor') + } +} diff --git a/src/app/help-mgmt-remote.module.ts b/src/app/help-mgmt-remote.module.ts deleted file mode 100644 index 287f885..0000000 --- a/src/app/help-mgmt-remote.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Inject, NgModule } from '@angular/core' -import { RouterModule, Routes } from '@angular/router' - -import { MFE_INFO, MfeInfo, PortalCoreModule } from '@onecx/portal-integration-angular' - -const routes: Routes = [ - { - path: '', - loadChildren: () => import('./help/help.module').then((m) => m.HelpModule) - } -] -@NgModule({ - imports: [PortalCoreModule.forMicroFrontend(), RouterModule.forChild(routes)], - exports: [], - providers: [], - schemas: [] -}) -export class HelpMgmtModule { - constructor(@Inject(MFE_INFO) mfeInfo?: MfeInfo) { - console.info('Help Mgmt Module constructor', mfeInfo) - } -} diff --git a/src/app/help/help-detail/help-detail.component.html b/src/app/help/help-detail/help-detail.component.html index 07e12bf..d3240af 100644 --- a/src/app/help/help-detail/help-detail.component.html +++ b/src/app/help/help-detail/help-detail.component.html @@ -7,7 +7,7 @@ [resizable]="true" [closable]="true" [modal]="true" - [style]="{ width: '350px' }" + [style]="{ width: '400px' }" [showHeader]="true" [breakpoints]="{ '992px': '50vw', @@ -17,7 +17,7 @@ '400px': '100vw', }" > - +
diff --git a/src/app/help/help-detail/help-detail.component.spec.ts b/src/app/help/help-detail/help-detail.component.spec.ts index 5b739cc..91f1da0 100644 --- a/src/app/help/help-detail/help-detail.component.spec.ts +++ b/src/app/help/help-detail/help-detail.component.spec.ts @@ -6,11 +6,9 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core' import { of, throwError } from 'rxjs' import { FormControl, FormGroup, Validators } from '@angular/forms' -import { PortalMessageService, Column } from '@onecx/portal-integration-angular' -import { HttpLoaderFactory } from 'src/app/shared/shared.module' - +import { AppStateService, createTranslateLoader, Column, PortalMessageService } from '@onecx/portal-integration-angular' +import { HelpsInternalAPIService, CreateHelp } from 'src/app/shared/generated' import { HelpDetailComponent } from './help-detail.component' -import { HelpsInternalAPIService, CreateHelp } from 'src/app/generated' describe('HelpDetailComponent', () => { let component: HelpDetailComponent @@ -23,7 +21,7 @@ describe('HelpDetailComponent', () => { } @Component({ - selector: 'hm-help-form', + selector: 'app-help-form', template: '' }) class MockHelpFormComponent { @@ -48,8 +46,8 @@ describe('HelpDetailComponent', () => { TranslateModule.forRoot({ loader: { provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] + useFactory: createTranslateLoader, + deps: [HttpClient, AppStateService] } }) ], diff --git a/src/app/help/help-detail/help-detail.component.ts b/src/app/help/help-detail/help-detail.component.ts index 1f422eb..306caca 100644 --- a/src/app/help/help-detail/help-detail.component.ts +++ b/src/app/help/help-detail/help-detail.component.ts @@ -1,11 +1,11 @@ import { Component, EventEmitter, Input, Output, ViewChild, OnChanges } from '@angular/core' import { PortalMessageService } from '@onecx/portal-integration-angular' -import { HelpsInternalAPIService, Help, CreateHelp } from '../../generated' +import { HelpsInternalAPIService, Help, CreateHelp } from 'src/app/shared/generated' import { HelpFormComponent } from '../help-form/help-form.component' @Component({ - selector: 'hm-help-detail', + selector: 'app-help-detail', templateUrl: './help-detail.component.html', styleUrls: ['./help-detail.component.scss'] }) diff --git a/src/app/help/help-form/help-form.component.html b/src/app/help/help-form/help-form.component.html index a62868e..c93e298 100644 --- a/src/app/help/help-form/help-form.component.html +++ b/src/app/help/help-form/help-form.component.html @@ -4,7 +4,7 @@
- +
- +
- +
- +
- + { let component: HelpFormComponent @@ -28,8 +28,8 @@ describe('HelpFormComponent', () => { TranslateModule.forRoot({ loader: { provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] + useFactory: createTranslateLoader, + deps: [HttpClient, AppStateService] } }) ], diff --git a/src/app/help/help-form/help-form.component.ts b/src/app/help/help-form/help-form.component.ts index b969df3..86da9a6 100644 --- a/src/app/help/help-form/help-form.component.ts +++ b/src/app/help/help-form/help-form.component.ts @@ -2,7 +2,7 @@ import { Component, Input, OnChanges, SimpleChanges } from '@angular/core' import { FormControl, FormGroup, Validators } from '@angular/forms' import { Column } from '@onecx/portal-integration-angular' -import { CreateHelp } from 'src/app/generated' +import { CreateHelp } from 'src/app/shared/generated' export interface HelpDetailForm { appId: FormControl @@ -13,9 +13,8 @@ export interface HelpDetailForm { } @Component({ - selector: 'hm-help-form', - templateUrl: './help-form.component.html', - styleUrls: ['./help-form.component.scss'] + selector: 'app-help-form', + templateUrl: './help-form.component.html' }) export class HelpFormComponent implements OnChanges { @Input() helpItem: CreateHelp | undefined diff --git a/src/app/help/help-search/help-criteria/help-criteria.component.scss b/src/app/help/help-search/help-criteria/help-criteria.component.scss deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/help/help-search/help-criteria/help-criteria.component.spec.ts b/src/app/help/help-search/help-criteria/help-criteria.component.spec.ts index 9105758..b3d2687 100644 --- a/src/app/help/help-search/help-criteria/help-criteria.component.spec.ts +++ b/src/app/help/help-search/help-criteria/help-criteria.component.spec.ts @@ -2,14 +2,13 @@ import { NO_ERRORS_SCHEMA, SimpleChange, EventEmitter } from '@angular/core' import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing' import { HttpClient } from '@angular/common/http' import { HttpClientTestingModule } from '@angular/common/http/testing' -import { TranslateLoader, TranslateModule } from '@ngx-translate/core' import { FormGroup, FormControl, Validators } from '@angular/forms' +import { TranslateLoader, TranslateModule } from '@ngx-translate/core' import { of } from 'rxjs' -import { PortalMessageService } from '@onecx/portal-integration-angular' -import { HttpLoaderFactory } from 'src/app/shared/shared.module' +import { AppStateService, createTranslateLoader, PortalMessageService } from '@onecx/portal-integration-angular' +import { HelpSearchCriteria, HelpsInternalAPIService } from 'src/app/shared/generated' import { HelpCriteriaComponent, HelpCriteriaForm } from './help-criteria.component' -import { HelpSearchCriteria, HelpsInternalAPIService } from '../../../generated' describe('HelpDetailComponent', () => { let component: HelpCriteriaComponent @@ -28,8 +27,8 @@ describe('HelpDetailComponent', () => { TranslateModule.forRoot({ loader: { provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] + useFactory: createTranslateLoader, + deps: [HttpClient, AppStateService] } }) ], diff --git a/src/app/help/help-search/help-criteria/help-criteria.component.ts b/src/app/help/help-search/help-criteria/help-criteria.component.ts index 1353195..21f0de5 100644 --- a/src/app/help/help-search/help-criteria/help-criteria.component.ts +++ b/src/app/help/help-search/help-criteria/help-criteria.component.ts @@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChange import { FormControl, FormGroup } from '@angular/forms' import { Action, PortalMessageService } from '@onecx/portal-integration-angular' -import { HelpSearchCriteria, HelpsInternalAPIService } from '../../../generated' +import { HelpSearchCriteria, HelpsInternalAPIService } from 'src/app/shared/generated' export interface HelpCriteriaForm { itemId: FormControl @@ -10,9 +10,8 @@ export interface HelpCriteriaForm { } @Component({ - selector: 'hm-help-criteria', - templateUrl: './help-criteria.component.html', - styleUrls: ['./help-criteria.component.scss'] + selector: 'app-help-criteria', + templateUrl: './help-criteria.component.html' }) export class HelpCriteriaComponent implements OnInit, OnChanges { @Input() public actions: Action[] = [] diff --git a/src/app/help/help-search/help-search.component.html b/src/app/help/help-search/help-search.component.html index 4d96216..6043e6a 100644 --- a/src/app/help/help-search/help-search.component.html +++ b/src/app/help/help-search/help-search.component.html @@ -1,9 +1,9 @@ - + > - +> diff --git a/src/app/help/help-search/help-search.component.spec.ts b/src/app/help/help-search/help-search.component.spec.ts index ba114a8..8edd559 100644 --- a/src/app/help/help-search/help-search.component.spec.ts +++ b/src/app/help/help-search/help-search.component.spec.ts @@ -5,10 +5,9 @@ import { HttpClientTestingModule } from '@angular/common/http/testing' import { TranslateLoader, TranslateModule } from '@ngx-translate/core' import { of, throwError } from 'rxjs' -import { Column, PortalMessageService } from '@onecx/portal-integration-angular' -import { HttpLoaderFactory } from 'src/app/shared/shared.module' +import { AppStateService, createTranslateLoader, Column, PortalMessageService } from '@onecx/portal-integration-angular' +import { HelpsInternalAPIService, Help, SearchHelpsRequestParams } from 'src/app/shared/generated' import { HelpSearchComponent } from './help-search.component' -import { HelpsInternalAPIService, Help, SearchHelpsRequestParams } from '../../generated' describe('HelpSearchComponent', () => { let component: HelpSearchComponent @@ -38,8 +37,8 @@ describe('HelpSearchComponent', () => { TranslateModule.forRoot({ loader: { provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient] + useFactory: createTranslateLoader, + deps: [HttpClient, AppStateService] } }) ], @@ -251,7 +250,7 @@ describe('HelpSearchComponent', () => { expect(component.displayDeleteDialog).toBeTrue() }) - it('should correctly sort appIds using sortHelpItemsByDefault', () => { + it('should correctly sort appIds using sortHelpItemsByDefault 1', () => { component.results = [ { appId: 'B', itemId: '2' }, { appId: 'A', itemId: '1' } @@ -264,6 +263,53 @@ describe('HelpSearchComponent', () => { ]) }) + it('should correctly sort appIds using sortHelpItemsByDefault 2', () => { + component.results = [ + { appId: '', itemId: '1' }, + { appId: 'A', itemId: '2' } + ] + component.results.sort(component['sortHelpItemByDefault']) + + expect(component.results).toEqual([ + { appId: '', itemId: '1' }, + { appId: 'A', itemId: '2' } + ]) + }) + + it('should correctly sort appIds using sortHelpItemsByDefault 3', () => { + component.results = [ + { appId: 'A', itemId: '2' }, + { appId: '', itemId: '1' } + ] + component.results.sort(component['sortHelpItemByDefault']) + + expect(component.results).toEqual([ + { appId: '', itemId: '1' }, + { appId: 'A', itemId: '2' } + ]) + }) + + it('should correctly sort appIds using sortHelpItemsByDefault 4', () => { + component.results = [ + { appId: 'A', itemId: '' }, + { appId: 'A', itemId: '2' }, + { appId: 'A', itemId: '1' }, + { appId: '', itemId: '1' }, + { appId: '', itemId: '2' }, + { appId: '', itemId: '' } + ] + component.results.sort(component['sortHelpItemByDefault']) + + expect(component.results).toEqual([ + { appId: '', itemId: '' }, + { appId: '', itemId: '1' }, + { appId: '', itemId: '2' }, + { appId: 'A', itemId: '' }, + { appId: 'A', itemId: '1' }, + { appId: 'A', itemId: '2' } + ]) + }) + it('should correctly sort itemIds using sortHelpItemsByDefault', () => { component.results = [ { appId: 'A', itemId: '2' }, diff --git a/src/app/help/help-search/help-search.component.ts b/src/app/help/help-search/help-search.component.ts index 7e6a0f9..2df7722 100644 --- a/src/app/help/help-search/help-search.component.ts +++ b/src/app/help/help-search/help-search.component.ts @@ -4,13 +4,13 @@ import { finalize, Observable } from 'rxjs' import { Table } from 'primeng/table' import { Action, Column, PortalMessageService } from '@onecx/portal-integration-angular' -import { HelpsInternalAPIService, Help, SearchHelpsRequestParams, HelpSearchCriteria } from '../../generated' +import { HelpsInternalAPIService, Help, SearchHelpsRequestParams, HelpSearchCriteria } from 'src/app/shared/generated' type ExtendedColumn = Column & { css?: string; limit?: boolean } type ChangeMode = 'VIEW' | 'NEW' | 'EDIT' @Component({ - selector: 'hm-help-search', + selector: 'app-help-search', templateUrl: './help-search.component.html', styleUrls: ['./help-search.component.scss'] }) diff --git a/src/app/help/help.module.ts b/src/app/help/help.module.ts index a8b706c..2484304 100644 --- a/src/app/help/help.module.ts +++ b/src/app/help/help.module.ts @@ -1,12 +1,10 @@ import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, NgModule } from '@angular/core' -import { HttpClient } from '@angular/common/http' +import { CommonModule } from '@angular/common' import { FormsModule } from '@angular/forms' import { RouterModule, Routes } from '@angular/router' -import { MissingTranslationHandler, TranslateLoader, TranslateModule } from '@ngx-translate/core' -import { MFE_INFO, PortalCoreModule, MyMissingTranslationHandler } from '@onecx/portal-integration-angular' -import { CanActivateGuard } from '../shared/can-active-guard.service' -import { HttpLoaderFactory, SharedModule } from '../shared/shared.module' +import { addInitializeModuleGuard, InitializeModuleGuard, PortalCoreModule } from '@onecx/portal-integration-angular' +import { SharedModule } from 'src/app/shared/shared.module' import { HelpSearchComponent } from './help-search/help-search.component' import { HelpCriteriaComponent } from './help-search/help-criteria/help-criteria.component' @@ -17,31 +15,19 @@ const routes: Routes = [ { path: '', component: HelpSearchComponent, - canActivate: [CanActivateGuard], pathMatch: 'full' } ] @NgModule({ - declarations: [HelpSearchComponent, HelpDetailComponent, HelpFormComponent, HelpCriteriaComponent], + declarations: [HelpSearchComponent, HelpDetailComponent, HelpCriteriaComponent, HelpFormComponent], imports: [ + CommonModule, FormsModule, PortalCoreModule.forMicroFrontend(), - [RouterModule.forChild(routes)], - SharedModule, - TranslateModule.forChild({ - isolate: true, - missingTranslationHandler: { - provide: MissingTranslationHandler, - useClass: MyMissingTranslationHandler - }, - loader: { - provide: TranslateLoader, - useFactory: HttpLoaderFactory, - deps: [HttpClient, MFE_INFO] - } - }) + [RouterModule.forChild(addInitializeModuleGuard(routes))], + SharedModule ], - providers: [], + providers: [InitializeModuleGuard], schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA] }) export class HelpModule { diff --git a/src/app/onecx-help-remote.module.ts b/src/app/onecx-help-remote.module.ts new file mode 100644 index 0000000..384d527 --- /dev/null +++ b/src/app/onecx-help-remote.module.ts @@ -0,0 +1,43 @@ +import { HttpClient } from '@angular/common/http' +import { NgModule } from '@angular/core' +import { RouterModule, Routes } from '@angular/router' +import { MissingTranslationHandler, TranslateLoader, TranslateModule } from '@ngx-translate/core' + +import { + addInitializeModuleGuard, + AppStateService, + ConfigurationService, + createTranslateLoader, + PortalCoreModule, + PortalMissingTranslationHandler +} from '@onecx/portal-integration-angular' + +const routes: Routes = [ + { + path: '', + loadChildren: () => import('./help/help.module').then((m) => m.HelpModule) + } +] +@NgModule({ + imports: [ + PortalCoreModule.forMicroFrontend(), + RouterModule.forChild(addInitializeModuleGuard(routes)), + TranslateModule.forRoot({ + isolate: true, + loader: { + provide: TranslateLoader, + useFactory: createTranslateLoader, + deps: [HttpClient, AppStateService] + }, + missingTranslationHandler: { provide: MissingTranslationHandler, useClass: PortalMissingTranslationHandler } + }) + ], + exports: [], + providers: [ConfigurationService], + schemas: [] +}) +export class OneCXHelpModule { + constructor() { + console.info('OneCX Help Module constructor') + } +} diff --git a/src/app/shared/can-active-guard.service.spec.ts b/src/app/shared/can-active-guard.service.spec.ts deleted file mode 100644 index 18fde15..0000000 --- a/src/app/shared/can-active-guard.service.spec.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { BehaviorSubject, Observable, of } from 'rxjs' -import { CanActivateGuard } from './can-active-guard.service' - -let canActivateGuard: CanActivateGuard - -describe('CanActivateGuard', () => { - const translateServiceSpy = jasmine.createSpyObj('TranslateService', ['setDefaultLang', 'use']) - - const configSpy = jasmine.createSpyObj('ConfigurationService', [], { lang$: new BehaviorSubject(undefined) }) - - const activatedRouteSpy = jasmine.createSpyObj('ActivatedRouteSnapshot', [], { - routeConfig: { - path: 'path' - } - }) - - beforeEach(async () => { - canActivateGuard = new CanActivateGuard(translateServiceSpy, configSpy) - translateServiceSpy.setDefaultLang.calls.reset() - translateServiceSpy.use.calls.reset() - }) - - it('should return default lang if provided is not supported', () => { - const result = canActivateGuard.getBestMatchLanguage('pl') - expect(result).toBe('en') - }) - - it('should use default language if current not supported and return true', (doneFn: DoneFn) => { - const langSpy = Object.getOwnPropertyDescriptor(configSpy, 'lang$')?.get as jasmine.Spy< - () => BehaviorSubject - > - langSpy.and.returnValue(new BehaviorSubject('pl')) - // spyOn(console, 'log') - translateServiceSpy.use.and.returnValue(of({})) - - const resultObs = canActivateGuard.canActivate(activatedRouteSpy) as Observable - resultObs.subscribe({ - next: (result) => { - expect(result).toBe(true) - doneFn() - }, - error: () => { - doneFn.fail - } - }) - - expect(translateServiceSpy.setDefaultLang).toHaveBeenCalledWith('en') - expect(translateServiceSpy.use).toHaveBeenCalledWith('en') - }) - - it('should use provided language if current supported and return true', (doneFn: DoneFn) => { - const langSpy = Object.getOwnPropertyDescriptor(configSpy, 'lang$')?.get as jasmine.Spy< - () => BehaviorSubject - > - langSpy.and.returnValue(new BehaviorSubject('de')) - // spyOn(console, 'log') - translateServiceSpy.use.and.returnValue(of({})) - - const resultObs = canActivateGuard.canActivate(activatedRouteSpy) as Observable - resultObs.subscribe({ - next: (result) => { - expect(result).toBe(true) - doneFn() - }, - error: () => { - doneFn.fail - } - }) - - expect(translateServiceSpy.setDefaultLang).toHaveBeenCalledWith('en') - // expect(console.log).toHaveBeenCalledOnceWith('user profile GUARD path') - expect(translateServiceSpy.use).toHaveBeenCalledWith('de') - }) -}) diff --git a/src/app/shared/can-active-guard.service.ts b/src/app/shared/can-active-guard.service.ts deleted file mode 100644 index 334dac0..0000000 --- a/src/app/shared/can-active-guard.service.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Injectable } from '@angular/core' -import { CanActivate, ActivatedRouteSnapshot, UrlTree } from '@angular/router' -import { TranslateService } from '@ngx-translate/core' -import { ConfigurationService } from '@onecx/portal-integration-angular' -import { filter, map, Observable, OperatorFunction, tap } from 'rxjs' - -const SUPPORTED_LANGUAGES = ['de', 'en'] -const DEFAULT_LANG = 'en' - -@Injectable() -export class CanActivateGuard implements CanActivate { - constructor(private txService: TranslateService, private config: ConfigurationService) {} - - /* eslint-disable @typescript-eslint/no-unused-vars */ /* TODO: is route and state needed */ - canActivate( - route: ActivatedRouteSnapshot - /* state: RouterStateSnapshot */ - ): Observable | Promise | boolean | UrlTree { - return this.loadTranslations() - } - - loadTranslations() { - console.log('load translations in help-mgmt') - // this language will be used as a fallback when a translation isn't found in the current language - this.txService.setDefaultLang(DEFAULT_LANG) - - return this.txService.use(this.getBestMatchLanguage(this.config.lang)).pipe( - //optional, after we set the language, we can listen for eventual changes to the lang - tap(() => { - //console.log(`Translations guard done ${this.config.lang}`) - this.config.lang$ - //the explict cast is to help linter understand that we will never get undefined - .pipe( - filter((x) => x !== undefined) as OperatorFunction, - map((lang) => lang.toLowerCase()) - ) - .subscribe((newLang) => { - // console.log(`Configuration language: ${newLang}`) - this.txService.use(this.getBestMatchLanguage(newLang)) - }) - }), - map(() => true) - ) - } - - getBestMatchLanguage(lang: string) { - if (SUPPORTED_LANGUAGES.includes(lang)) { - return lang - } else { - console.warn( - `⚠ requested language: ${lang} is not among supported languages: ${SUPPORTED_LANGUAGES}, using ${DEFAULT_LANG} as fallback` - ) - return DEFAULT_LANG - } - } -} diff --git a/src/app/generated/.gitignore b/src/app/shared/generated/.gitignore similarity index 100% rename from src/app/generated/.gitignore rename to src/app/shared/generated/.gitignore diff --git a/src/app/generated/.openapi-generator-ignore b/src/app/shared/generated/.openapi-generator-ignore similarity index 100% rename from src/app/generated/.openapi-generator-ignore rename to src/app/shared/generated/.openapi-generator-ignore diff --git a/src/app/generated/.openapi-generator/FILES b/src/app/shared/generated/.openapi-generator/FILES similarity index 100% rename from src/app/generated/.openapi-generator/FILES rename to src/app/shared/generated/.openapi-generator/FILES diff --git a/src/app/generated/.openapi-generator/VERSION b/src/app/shared/generated/.openapi-generator/VERSION similarity index 100% rename from src/app/generated/.openapi-generator/VERSION rename to src/app/shared/generated/.openapi-generator/VERSION diff --git a/src/app/generated/README.md b/src/app/shared/generated/README.md similarity index 100% rename from src/app/generated/README.md rename to src/app/shared/generated/README.md diff --git a/src/app/generated/api.module.ts b/src/app/shared/generated/api.module.ts similarity index 100% rename from src/app/generated/api.module.ts rename to src/app/shared/generated/api.module.ts diff --git a/src/app/generated/api/api.ts b/src/app/shared/generated/api/api.ts similarity index 100% rename from src/app/generated/api/api.ts rename to src/app/shared/generated/api/api.ts diff --git a/src/app/generated/api/helpsInternal.service.ts b/src/app/shared/generated/api/helpsInternal.service.ts similarity index 100% rename from src/app/generated/api/helpsInternal.service.ts rename to src/app/shared/generated/api/helpsInternal.service.ts diff --git a/src/app/generated/configuration.ts b/src/app/shared/generated/configuration.ts similarity index 100% rename from src/app/generated/configuration.ts rename to src/app/shared/generated/configuration.ts diff --git a/src/app/generated/encoder.ts b/src/app/shared/generated/encoder.ts similarity index 100% rename from src/app/generated/encoder.ts rename to src/app/shared/generated/encoder.ts diff --git a/src/app/generated/index.ts b/src/app/shared/generated/index.ts similarity index 100% rename from src/app/generated/index.ts rename to src/app/shared/generated/index.ts diff --git a/src/app/generated/model/createHelp.ts b/src/app/shared/generated/model/createHelp.ts similarity index 100% rename from src/app/generated/model/createHelp.ts rename to src/app/shared/generated/model/createHelp.ts diff --git a/src/app/generated/model/help.ts b/src/app/shared/generated/model/help.ts similarity index 100% rename from src/app/generated/model/help.ts rename to src/app/shared/generated/model/help.ts diff --git a/src/app/generated/model/helpAppIds.ts b/src/app/shared/generated/model/helpAppIds.ts similarity index 100% rename from src/app/generated/model/helpAppIds.ts rename to src/app/shared/generated/model/helpAppIds.ts diff --git a/src/app/generated/model/helpPageResult.ts b/src/app/shared/generated/model/helpPageResult.ts similarity index 100% rename from src/app/generated/model/helpPageResult.ts rename to src/app/shared/generated/model/helpPageResult.ts diff --git a/src/app/generated/model/helpSearchCriteria.ts b/src/app/shared/generated/model/helpSearchCriteria.ts similarity index 100% rename from src/app/generated/model/helpSearchCriteria.ts rename to src/app/shared/generated/model/helpSearchCriteria.ts diff --git a/src/app/generated/model/models.ts b/src/app/shared/generated/model/models.ts similarity index 100% rename from src/app/generated/model/models.ts rename to src/app/shared/generated/model/models.ts diff --git a/src/app/generated/model/problemDetailInvalidParam.ts b/src/app/shared/generated/model/problemDetailInvalidParam.ts similarity index 100% rename from src/app/generated/model/problemDetailInvalidParam.ts rename to src/app/shared/generated/model/problemDetailInvalidParam.ts diff --git a/src/app/generated/model/problemDetailParam.ts b/src/app/shared/generated/model/problemDetailParam.ts similarity index 100% rename from src/app/generated/model/problemDetailParam.ts rename to src/app/shared/generated/model/problemDetailParam.ts diff --git a/src/app/generated/model/problemDetailResponse.ts b/src/app/shared/generated/model/problemDetailResponse.ts similarity index 100% rename from src/app/generated/model/problemDetailResponse.ts rename to src/app/shared/generated/model/problemDetailResponse.ts diff --git a/src/app/generated/model/updateHelp.ts b/src/app/shared/generated/model/updateHelp.ts similarity index 100% rename from src/app/generated/model/updateHelp.ts rename to src/app/shared/generated/model/updateHelp.ts diff --git a/src/app/generated/param.ts b/src/app/shared/generated/param.ts similarity index 100% rename from src/app/generated/param.ts rename to src/app/shared/generated/param.ts diff --git a/src/app/generated/variables.ts b/src/app/shared/generated/variables.ts similarity index 100% rename from src/app/generated/variables.ts rename to src/app/shared/generated/variables.ts diff --git a/src/app/shared/label.resolver.spec.ts b/src/app/shared/label.resolver.spec.ts index 97b5285..1e15aed 100644 --- a/src/app/shared/label.resolver.spec.ts +++ b/src/app/shared/label.resolver.spec.ts @@ -1,9 +1,10 @@ +import { Observable, of } from 'rxjs' import { LabelResolver } from './label.resolver' let labelResolver: LabelResolver describe('LabelResolver', () => { - const translateServiceSpy = jasmine.createSpyObj('TranslateService', ['instant']) + const translateServiceSpy = jasmine.createSpyObj('TranslateService', ['get']) const activatedRouteSpy = jasmine.createSpyObj('ActivatedRouteSnapshot', [], { routeConfig: { @@ -16,28 +17,31 @@ describe('LabelResolver', () => { beforeEach(async () => { labelResolver = new LabelResolver(translateServiceSpy) - translateServiceSpy.instant.calls.reset() + translateServiceSpy.get.calls.reset() const dataSpy = Object.getOwnPropertyDescriptor(activatedRouteSpy, 'data')?.get as jasmine.Spy<() => {}> dataSpy.and.returnValue({}) }) - it('should translate if breadcrumb is present', () => { + it('should translate if breadcrumb is present', (done: DoneFn) => { const dataSpy = Object.getOwnPropertyDescriptor(activatedRouteSpy, 'data')?.get as jasmine.Spy<() => {}> dataSpy.and.returnValue({ breadcrumb: 'defined' }) - translateServiceSpy.instant.and.returnValue('translation') + translateServiceSpy.get.and.returnValue(of('translation')) - const result = labelResolver.resolve(activatedRouteSpy, routerStateSpy) + const obsResult = labelResolver.resolve(activatedRouteSpy, routerStateSpy) as Observable + obsResult.subscribe((result) => { + expect(result).toBe('translation') + expect(translateServiceSpy.get).toHaveBeenCalledOnceWith('defined') - expect(result).toBe('translation') - expect(translateServiceSpy.instant).toHaveBeenCalledOnceWith('defined') + done() + }) }) it('should use route path if breadcrumb is not present', () => { const result = labelResolver.resolve(activatedRouteSpy, routerStateSpy) expect(result).toBe('path') - expect(translateServiceSpy.instant).toHaveBeenCalledTimes(0) + expect(translateServiceSpy.get).toHaveBeenCalledTimes(0) }) }) diff --git a/src/app/shared/label.resolver.ts b/src/app/shared/label.resolver.ts index 538e552..c09047b 100644 --- a/src/app/shared/label.resolver.ts +++ b/src/app/shared/label.resolver.ts @@ -1,14 +1,15 @@ import { Injectable } from '@angular/core' import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router' import { TranslateService } from '@ngx-translate/core' -import { Observable } from 'rxjs' +import { Observable, map } from 'rxjs' //dont use `providedIn root` - wont work when we are in shell @Injectable() export class LabelResolver implements Resolve { constructor(private translate: TranslateService) {} - /* eslint-disable @typescript-eslint/no-unused-vars */ /* TODO: is state needed */ - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): string | Observable | Promise { - return route.data['breadcrumb'] ? this.translate.instant(route.data['breadcrumb']) : route.routeConfig?.path + resolve(route: ActivatedRouteSnapshot, _state: RouterStateSnapshot): string | Observable | Promise { + return route.data['breadcrumb'] + ? this.translate.get(route.data['breadcrumb']).pipe(map((t) => t.toString())) + : route.routeConfig?.path ?? '' } } diff --git a/src/app/shared/shared.module.spec.ts b/src/app/shared/shared.module.spec.ts deleted file mode 100644 index 058add2..0000000 --- a/src/app/shared/shared.module.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { NO_ERRORS_SCHEMA } from '@angular/core' -import { TestBed } from '@angular/core/testing' -import { HttpClient } from '@angular/common/http' -import { HttpClientTestingModule } from '@angular/common/http/testing' - -import { MfeInfo, TranslateCombinedLoader } from '@onecx/portal-integration-angular' -import { basePathProvider, HttpLoaderFactory } from './shared.module' - -describe('SharedModule', () => { - let httpClient: HttpClient - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [HttpClientTestingModule], - schemas: [NO_ERRORS_SCHEMA] - }) - - httpClient = TestBed.inject(HttpClient) - }) - - it('should return the correct basePath with mfeInfo', () => { - const mfeInfo: MfeInfo = { - mountPath: '', - remoteBaseUrl: 'http://localhost:4200/', - baseHref: 'helps', - shellName: '' - } - - const result = basePathProvider(mfeInfo) - - expect(result).toEqual('http://localhost:4200/help-bff') - }) - - it('should return a translate loader', () => { - const mfeInfo: MfeInfo = { - mountPath: '', - remoteBaseUrl: 'http://localhost:4200/', - baseHref: '', - shellName: '' - } - - const result = HttpLoaderFactory(httpClient, mfeInfo) - - expect(result).toBeInstanceOf(TranslateCombinedLoader) - }) -}) diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 7a61e88..bf7e848 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -1,22 +1,19 @@ import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, NgModule } from '@angular/core' import { CommonModule } from '@angular/common' -import { HttpClient } from '@angular/common/http' import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { TranslateModule, TranslateService } from '@ngx-translate/core' -import { TranslateHttpLoader } from '@ngx-translate/http-loader' import { ErrorTailorModule } from '@ngneat/error-tailor' import { AutoCompleteModule } from 'primeng/autocomplete' +import { ConfirmDialogModule } from 'primeng/confirmdialog' import { ConfirmPopupModule } from 'primeng/confirmpopup' -import { ConfirmationService, MessageService } from 'primeng/api' +import { ConfirmationService } from 'primeng/api' import { DataViewModule } from 'primeng/dataview' import { DialogModule } from 'primeng/dialog' import { DialogService } from 'primeng/dynamicdialog' import { DropdownModule } from 'primeng/dropdown' import { InputTextModule } from 'primeng/inputtext' import { InputTextareaModule } from 'primeng/inputtextarea' -import { CalendarModule } from 'primeng/calendar' -import { StyleClassModule } from 'primeng/styleclass' import { KeyFilterModule } from 'primeng/keyfilter' import { ListboxModule } from 'primeng/listbox' import { MultiSelectModule } from 'primeng/multiselect' @@ -25,43 +22,26 @@ import { TableModule } from 'primeng/table' import { ToastModule } from 'primeng/toast' import { - MfeInfo, - MFE_INFO, + AppStateService, + ConfigurationService, PortalDialogService, - PortalMessageService, - TranslateCombinedLoader + PortalApiConfiguration } from '@onecx/portal-integration-angular' -import { environment } from '../../environments/environment' -import { BASE_PATH } from '../generated/variables' -import { CanActivateGuard } from './can-active-guard.service' +import { Configuration } from 'src/app/shared/generated' +import { environment } from 'src/environments/environment' import { LabelResolver } from './label.resolver' -export const basePathProvider = (mfeInfo: MfeInfo) => { - /* console.log( - 'Base path provider: ' + (mfeInfo ? mfeInfo.remoteBaseUrl + '' + environment.apiPrefix : '' + environment.apiPrefix) - ) */ - return mfeInfo ? mfeInfo.remoteBaseUrl + '' + environment.apiPrefix : '' + environment.apiPrefix -} - -export function HttpLoaderFactory(http: HttpClient, mfeInfo: MfeInfo) { - /* if (mfeInfo) { - console.log(`Configuring translation loader ${mfeInfo?.remoteBaseUrl}`) - } */ - // if running standalone then load the app assets directly from remote base URL - const appAssetPrefix = mfeInfo && mfeInfo.remoteBaseUrl ? mfeInfo.remoteBaseUrl : './' - return new TranslateCombinedLoader( - new TranslateHttpLoader(http, appAssetPrefix + 'assets/i18n/', '.json'), - new TranslateHttpLoader(http, appAssetPrefix + 'onecx-portal-lib/assets/i18n/', '.json') - ) +export function apiConfigProvider(configService: ConfigurationService, appStateService: AppStateService) { + return new PortalApiConfiguration(Configuration, environment.apiPrefix, configService, appStateService) } @NgModule({ declarations: [], imports: [ AutoCompleteModule, - CalendarModule, CommonModule, + ConfirmDialogModule, ConfirmPopupModule, DataViewModule, DialogModule, @@ -74,10 +54,9 @@ export function HttpLoaderFactory(http: HttpClient, mfeInfo: MfeInfo) { MultiSelectModule, ReactiveFormsModule, SelectButtonModule, - StyleClassModule, TableModule, ToastModule, - TranslateModule.forChild({ isolate: true }), + TranslateModule, ErrorTailorModule.forRoot({ controlErrorsOn: { async: true, blur: true, change: true }, errors: { @@ -103,8 +82,8 @@ export function HttpLoaderFactory(http: HttpClient, mfeInfo: MfeInfo) { ], exports: [ AutoCompleteModule, - CalendarModule, CommonModule, + ConfirmDialogModule, ConfirmPopupModule, DataViewModule, DialogModule, @@ -118,20 +97,16 @@ export function HttpLoaderFactory(http: HttpClient, mfeInfo: MfeInfo) { MultiSelectModule, ReactiveFormsModule, SelectButtonModule, - StyleClassModule, TableModule, ToastModule, TranslateModule ], //this is not elegant, for some reason the injection token from primeng does not work across federated module providers: [ - CanActivateGuard, ConfirmationService, LabelResolver, - HttpClient, - { provide: MessageService, useExisting: PortalMessageService }, { provide: DialogService, useClass: PortalDialogService }, - { provide: BASE_PATH, useFactory: basePathProvider, deps: [MFE_INFO] } + { provide: Configuration, useFactory: apiConfigProvider, deps: [ConfigurationService, AppStateService] } ], schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA] }) diff --git a/src/app/test/mocks/auth-mock.service.ts b/src/app/test/mocks/auth-mock.service.ts deleted file mode 100644 index ed76935..0000000 --- a/src/app/test/mocks/auth-mock.service.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { IAuthService, UserProfile } from '@onecx/portal-integration-angular' -import { BehaviorSubject } from 'rxjs' - -export class IAuthMockService implements IAuthService { - currentUser$ = new BehaviorSubject(undefined) - getCurrentUser(): UserProfile | null { - return null - } - logout(): void {} - hasPermission(permissionKey: string): boolean { - return false - } - getAuthProviderName(): string { - return 'mock' - } - hasRole(role: string | string[]): boolean { - return false - } - init(): Promise { - return new Promise((resolve, reject) => { - resolve(false) - }) - } - getUserRoles(): string[] { - return [] - } -} diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 0f24226..9c02573 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,5 +1,5 @@ export const environment = { production: true, - BASE_PATH: '/help-bff', - apiPrefix: 'help-bff' + BASE_PATH: '/bff', + apiPrefix: 'bff' } diff --git a/src/environments/environment.ts b/src/environments/environment.ts index dff07bf..ae32583 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -9,7 +9,7 @@ export const environment = { KEYCLOAK_CLIENT_ID: 'tkit-angular-example', TKIT_PORTAL_ID: 'ADMIN', skipRemoteConfigLoad: true, - apiPrefix: 'help-bff' + apiPrefix: 'bff' } /* diff --git a/src/index.html b/src/index.html index f208b9d..579d62a 100644 --- a/src/index.html +++ b/src/index.html @@ -2,12 +2,12 @@ - Help Mgmt + OneCX Help -   +   diff --git a/tsconfig.app.json b/tsconfig.app.json index f02c28f..7405f61 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -7,14 +7,7 @@ "inlineSources": true, "target": "ES2022" }, - "files": ["src/main.ts", "src/polyfills.ts", "src/app/help-mgmt-remote.module.ts"], + "files": ["src/main.ts", "src/polyfills.ts", "src/app/onecx-help-remote.module.ts"], "include": ["src/**/*.ts", "src/**/*.d.ts"], - "exclude": [ - "src/test.ts", - "src/test-setup.ts", - "src/app/test/**/*", - "src/**/*.spec.ts", - "src/**/*.stories.ts", - "src/**/*.stories.js" - ] + "exclude": ["src/test.ts", "src/test-setup.ts", "src/**/*.spec.ts", "src/**/*.stories.ts", "src/**/*.stories.js"] } diff --git a/tsconfig.spec.json b/tsconfig.spec.json index 9b2f08e..a366065 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -10,6 +10,6 @@ "useDefineForClassFields": false }, "files": ["src/test.ts", "src/polyfills.ts"], - "exclude": ["src/app/generated/**/*", "node_modules"], + "exclude": ["src/app/shared/generated/**/*", "node_modules"], "include": ["**/*.spec.ts", "**/*.d.ts"] } diff --git a/webpack.config.js b/webpack.config.js index f93e325..69deb72 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -5,7 +5,7 @@ const config = withModuleFederationPlugin({ name: 'onecx-help-ui', filename: 'remoteEntry.js', exposes: { - './HelpMgmtModule': 'src/app/help-mgmt-remote.module.ts' + './OneCXHelpModule': 'src/app/onecx-help-remote.module.ts' }, shared: share({ '@angular/core': { singleton: true, strictVersion: true, requiredVersion: 'auto' }, @@ -30,17 +30,13 @@ const config = withModuleFederationPlugin({ requiredVersion: 'auto', includeSecondaries: true }, - '@angular/router': { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, rxjs: { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, + '@angular/router': { singleton: true, strictVersion: true, requiredVersion: 'auto', includeSecondaries: true }, '@ngx-translate/core': { singleton: true, strictVersion: false, requiredVersion: '^14.0.0' }, - '@onecx/portal-integration-angular': { - singleton: true, - requiredVersion: 'auto' - }, - '@onecx/keycloak-auth': { - singleton: true, - requiredVersion: 'auto' - } + '@onecx/keycloak-auth': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/portal-integration-angular': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/accelerator': { requiredVersion: 'auto', includeSecondaries: true }, + '@onecx/integration-interface': { requiredVersion: 'auto', includeSecondaries: true } }), sharedMappings: ['@onecx/portal-integration-angular'] })