Browse Source

Merge branch 'master' into improvement/4601-gateway-extension-add

pull/11815/head
Max Petrov 2 years ago
committed by GitHub
parent
commit
b38dd07e91
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 133
      ui-ngx/.eslintrc.json
  2. 44
      ui-ngx/angular.json
  3. 43
      ui-ngx/e2e/protractor.conf.js
  4. 39
      ui-ngx/e2e/src/app.e2e-spec.ts
  5. 27
      ui-ngx/e2e/src/app.po.ts
  6. 13
      ui-ngx/e2e/tsconfig.e2e.json
  7. 2
      ui-ngx/extra-webpack.config.js
  8. 221
      ui-ngx/package.json
  9. 10
      ui-ngx/patches/@angular+core+18.2.6.patch
  10. 21
      ui-ngx/patches/@angular+flex-layout+15.0.0-beta.42.patch
  11. 51
      ui-ngx/patches/@mat-datetimepicker+core+11.0.3.patch
  12. 34
      ui-ngx/patches/@mat-datetimepicker+core+14.0.0.patch
  13. 28
      ui-ngx/patches/angular-gridster2+18.0.1.patch
  14. 2
      ui-ngx/pom.xml
  15. 1
      ui-ngx/src/app/core/api/widget-api.models.ts
  16. 140
      ui-ngx/src/app/core/core.module.ts
  17. 4
      ui-ngx/src/app/core/guards/auth.guard.ts
  18. 4
      ui-ngx/src/app/core/guards/confirm-on-exit.guard.ts
  19. 23
      ui-ngx/src/app/core/http/rule-chain.service.ts
  20. 10
      ui-ngx/src/app/core/interceptors/entity-conflict.interceptor.ts
  21. 10
      ui-ngx/src/app/core/services/dynamic-component-factory.service.ts
  22. 209
      ui-ngx/src/app/core/services/resources.service.ts
  23. 2
      ui-ngx/src/app/core/settings/settings.utils.ts
  24. 2
      ui-ngx/src/app/core/translate/translate-default-compiler.ts
  25. 8
      ui-ngx/src/app/modules/common/modules-map.ts
  26. 4
      ui-ngx/src/app/modules/dashboard/dashboard-pages.routing.module.ts
  27. 4
      ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.scss
  28. 4
      ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.scss
  29. 3
      ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts
  30. 9
      ui-ngx/src/app/modules/home/components/dashboard-page/states/states-controller.service.ts
  31. 6
      ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.ts
  32. 5
      ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts
  33. 5
      ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts
  34. 10
      ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts
  35. 2
      ui-ngx/src/app/modules/home/components/notification/notification-bell.component.html
  36. 19
      ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts
  37. 14
      ui-ngx/src/app/modules/home/components/profile/asset-profile-dialog.component.ts
  38. 14
      ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.ts
  39. 14
      ui-ngx/src/app/modules/home/components/profile/tenant-profile-dialog.component.ts
  40. 2
      ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts
  41. 16
      ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts
  42. 14
      ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.service.ts
  43. 10
      ui-ngx/src/app/modules/home/components/widget/dialog/embed-dashboard-dialog.component.ts
  44. 8
      ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts
  45. 1
      ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts
  46. 2
      ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.component.ts
  47. 2
      ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.models.ts
  48. 2
      ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts
  49. 7
      ui-ngx/src/app/modules/home/components/widget/lib/maps/common-maps-utils.ts
  50. 50
      ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts
  51. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts
  52. 6
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.interface.ts
  53. 4
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts
  54. 4
      ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts
  55. 18
      ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts
  56. 12
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/google-map.ts
  57. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/here-map.ts
  58. 22
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts
  59. 6
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/openstreet-map.ts
  60. 6
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/tencent-map.ts
  61. 2
      ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts
  62. 11
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts
  63. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html
  64. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.ts
  65. 58
      ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
  66. 5
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts
  67. 45
      ui-ngx/src/app/modules/home/components/widget/widget.component.ts
  68. 10
      ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts
  69. 3
      ui-ngx/src/app/modules/home/pages/admin/mail-server.component.scss
  70. 4
      ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/clients-table-config.resolver.ts
  71. 4
      ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain-table-config.resolver.ts
  72. 4
      ui-ngx/src/app/modules/home/pages/admin/oauth2/mobile-apps/mobile-app-table-config.resolver.ts
  73. 4
      ui-ngx/src/app/modules/home/pages/admin/oauth2/oauth2-routing.module.ts
  74. 4
      ui-ngx/src/app/modules/home/pages/admin/queue/queues-table-config.resolver.ts
  75. 4
      ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts
  76. 4
      ui-ngx/src/app/modules/home/pages/alarm/alarm-routing.module.ts
  77. 4
      ui-ngx/src/app/modules/home/pages/asset-profile/asset-profiles-table-config.resolver.ts
  78. 4
      ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts
  79. 4
      ui-ngx/src/app/modules/home/pages/customer/customers-table-config.resolver.ts
  80. 4
      ui-ngx/src/app/modules/home/pages/dashboard/dashboard-routing.module.ts
  81. 4
      ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts
  82. 4
      ui-ngx/src/app/modules/home/pages/device-profile/device-profiles-table-config.resolver.ts
  83. 4
      ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts
  84. 4
      ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts
  85. 4
      ui-ngx/src/app/modules/home/pages/entity-view/entity-views-table-config.resolver.ts
  86. 4
      ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-table-config.resolver.ts
  87. 3
      ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-table-header.component.scss
  88. 4
      ui-ngx/src/app/modules/home/pages/notification/recipient/recipient-table-config.resolver.ts
  89. 4
      ui-ngx/src/app/modules/home/pages/notification/rule/rule-table-config.resolver.ts
  90. 4
      ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts
  91. 11
      ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts
  92. 4
      ui-ngx/src/app/modules/home/pages/notification/template/template-table-config.resolver.ts
  93. 4
      ui-ngx/src/app/modules/home/pages/ota-update/ota-update-table-config.resolve.ts
  94. 4
      ui-ngx/src/app/modules/home/pages/profile/profile-routing.module.ts
  95. 22
      ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts
  96. 2
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss
  97. 21
      ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts
  98. 4
      ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts
  99. 1
      ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.ts
  100. 6
      ui-ngx/src/app/modules/home/pages/security/security-routing.module.ts

133
ui-ngx/.eslintrc.json

@ -1,68 +1,69 @@
{ {
"root": true, "root": true,
"ignorePatterns": [ "ignorePatterns": [
"projects/**/*" "projects/**/*"
], ],
"overrides": [ "overrides": [
{ {
"files": [ "files": [
"*.ts" "*.ts",
], "*.tsx"
"parserOptions": { ],
"project": [ "parserOptions": {
"tsconfig.json", "project": [
"e2e/tsconfig.json" "tsconfig.json"
], ],
"createDefaultProgram": true "createDefaultProgram": true
}, },
"extends": [ "extends": [
"plugin:@angular-eslint/ng-cli-compat", "plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/ng-cli-compat--formatting-add-on", "plugin:@angular-eslint/template/process-inline-templates"
"plugin:@angular-eslint/template/process-inline-templates" ],
], "rules": {
"rules": { "@typescript-eslint/explicit-member-accessibility": [
"@typescript-eslint/explicit-member-accessibility": [ "off",
"off", {
{ "accessibility": "explicit"
"accessibility": "explicit" }
} ],
], "arrow-parens": [
"arrow-parens": [ "off",
"off", "always"
"always" ],
], "@angular-eslint/component-selector": [
"@angular-eslint/component-selector": [ "error",
"error", {
{ "prefix": [
"prefix": [ "tb" ] "tb"
} ]
], }
"id-blacklist": [ ],
"error", "id-blacklist": [
"any", "error",
"Number", "any",
"String", "Number",
"string", "String",
"Boolean", "string",
"boolean", "Boolean",
"Undefined", "boolean",
"undefined" "Undefined",
], "undefined"
"import/order": "off", ],
"@typescript-eslint/member-ordering": "off", "import/order": "off",
"no-underscore-dangle": "off", "@typescript-eslint/member-ordering": "off",
"@typescript-eslint/naming-convention": "off", "no-underscore-dangle": "off",
"jsdoc/newline-after-description": 0 "@typescript-eslint/naming-convention": "off",
} "jsdoc/newline-after-description": 0
}, }
{ },
"files": [ {
"*.html" "files": [
], "*.html"
"extends": [ ],
"plugin:@angular-eslint/template/recommended" "extends": [
], "plugin:@angular-eslint/template/recommended"
"rules": {} ],
} "rules": {}
] }
]
} }

44
ui-ngx/angular.json

@ -217,15 +217,15 @@
"serve": { "serve": {
"builder": "@angular-builders/custom-webpack:dev-server", "builder": "@angular-builders/custom-webpack:dev-server",
"options": { "options": {
"browserTarget": "thingsboard:build", "buildTarget": "thingsboard:build",
"proxyConfig": "proxy.conf.js" "proxyConfig": "proxy.conf.js"
}, },
"configurations": { "configurations": {
"production": { "production": {
"browserTarget": "thingsboard:build:production" "buildTarget": "thingsboard:build:production"
}, },
"development": { "development": {
"browserTarget": "thingsboard:build:development" "buildTarget": "thingsboard:build:development"
} }
}, },
"defaultConfiguration": "development" "defaultConfiguration": "development"
@ -233,24 +233,7 @@
"extract-i18n": { "extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n", "builder": "@angular-devkit/build-angular:extract-i18n",
"options": { "options": {
"browserTarget": "thingsboard:build" "buildTarget": "thingsboard:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"src/styles.scss"
],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
} }
}, },
"lint": { "lint": {
@ -263,25 +246,6 @@
} }
} }
} }
},
"thingsboard-e2e": {
"root": "e2e/",
"projectType": "application",
"prefix": "",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "thingsboard:serve"
},
"configurations": {
"production": {
"devServerTarget": "thingsboard:serve:production"
}
}
}
}
} }
}, },
"cli": { "cli": {

43
ui-ngx/e2e/protractor.conf.js

@ -1,43 +0,0 @@
/*
* Copyright © 2016-2024 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require("jasmine-spec-reporter");
exports.config = {
allScriptsTimeout: 11000,
specs: [
"./src/**/*.e2e-spec.ts",
],
capabilities: {
"browserName": "chrome",
},
directConnect: true,
baseUrl: "http://localhost:4200/",
framework: "jasmine",
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {},
},
onPrepare() {
require("ts-node").register({
project: require("path").join(__dirname, "./tsconfig.e2e.json"),
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
},
};

39
ui-ngx/e2e/src/app.e2e-spec.ts

@ -1,39 +0,0 @@
///
/// Copyright © 2016-2024 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { AppPage } from './app.po';
import { browser, logging } from 'protractor';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getTitleText()).toEqual('Welcome to tb-license-server!');
});
afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
expect(logs).not.toContain(jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry));
});
});

27
ui-ngx/e2e/src/app.po.ts

@ -1,27 +0,0 @@
///
/// Copyright © 2016-2024 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get(browser.baseUrl) as Promise<any>;
}
getTitleText() {
return element(by.css('tb-root h1')).getText() as Promise<string>;
}
}

13
ui-ngx/e2e/tsconfig.e2e.json

@ -1,13 +0,0 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

2
ui-ngx/extra-webpack.config.js

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
const CompressionPlugin = require("compression-webpack-plugin"); const CompressionPlugin = require("compression-webpack-plugin");
const JavaScriptOptimizerPlugin = require("@angular-devkit/build-angular/src/webpack/plugins/javascript-optimizer-plugin").JavaScriptOptimizerPlugin; const JavaScriptOptimizerPlugin = require("@angular-devkit/build-angular/src/tools/webpack/plugins/javascript-optimizer-plugin").JavaScriptOptimizerPlugin;
const webpack = require("webpack"); const webpack = require("webpack");
const dirTree = require("directory-tree"); const dirTree = require("directory-tree");
const ngWebpack = require('@ngtools/webpack'); const ngWebpack = require('@ngtools/webpack');

221
ui-ngx/package.json

@ -8,172 +8,163 @@
"build:prod": "node --max_old_space_size=4096 ./node_modules/@angular/cli/bin/ng build --configuration production --vendor-chunk", "build:prod": "node --max_old_space_size=4096 ./node_modules/@angular/cli/bin/ng build --configuration production --vendor-chunk",
"build:types": "node generate-types.js", "build:types": "node generate-types.js",
"build:icon-metadata": "node generate-icon-metadata.js", "build:icon-metadata": "node generate-icon-metadata.js",
"test": "ng test",
"lint": "ng lint", "lint": "ng lint",
"e2e": "ng e2e",
"prepare": "patch-package" "prepare": "patch-package"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^15.2.10", "@angular/animations": "18.2.6",
"@angular/cdk": "^15.2.9", "@angular/cdk": "18.2.6",
"@angular/common": "^15.2.10", "@angular/common": "18.2.6",
"@angular/compiler": "^15.2.10", "@angular/compiler": "18.2.6",
"@angular/core": "^15.2.10", "@angular/core": "18.2.6",
"@angular/flex-layout": "^15.0.0-beta.42", "@angular/flex-layout": "^15.0.0-beta.42",
"@angular/forms": "^15.2.10", "@angular/forms": "18.2.6",
"@angular/material": "^15.2.9", "@angular/material": "18.2.6",
"@angular/platform-browser": "^15.2.10", "@angular/platform-browser": "18.2.6",
"@angular/platform-browser-dynamic": "^15.2.10", "@angular/platform-browser-dynamic": "18.2.6",
"@angular/router": "^15.2.10", "@angular/router": "18.2.6",
"@auth0/angular-jwt": "^5.1.2", "@auth0/angular-jwt": "^5.2.0",
"@date-io/core": "1.3.7", "@emotion/react": "11.13.3",
"@date-io/date-fns": "1.3.7", "@emotion/styled": "11.13.0",
"@flowjs/flow.js": "^2.14.1", "@flowjs/flow.js": "^2.14.1",
"@flowjs/ngx-flow": "~0.6.0", "@flowjs/ngx-flow": "~0.8.1",
"@geoman-io/leaflet-geoman-free": "2.14.2", "@fortawesome/fontawesome-svg-core": "^6.6.0",
"@iplab/ngx-color-picker": "^15.0.2", "@geoman-io/leaflet-geoman-free": "2.17.0",
"@mat-datetimepicker/core": "~11.0.3", "@iplab/ngx-color-picker": "^18.0.1",
"@material-ui/core": "4.12.3", "@mat-datetimepicker/core": "~14.0.0",
"@material-ui/icons": "4.11.2", "@mdi/svg": "^7.4.47",
"@material-ui/pickers": "3.3.10", "@messageformat/core": "^3.4.0",
"@mdi/svg": "^7.2.96", "@mui/icons-material": "6.1.2",
"@messageformat/core": "^3.1.0", "@mui/lab": "6.0.0-beta.10",
"@ngrx/effects": "^15.4.0", "@mui/material": "6.1.2",
"@ngrx/store": "^15.4.0", "@mui/styles": "6.1.2",
"@ngrx/store-devtools": "^15.4.0", "@mui/system": "6.1.2",
"@ngx-translate/core": "^14.0.0", "@mui/x-date-pickers": "7.18.0",
"@ngrx/effects": "^18.0.2",
"@ngrx/store": "^18.0.2",
"@ngrx/store-devtools": "^18.0.2",
"@ngx-translate/core": "^15.0.0",
"@svgdotjs/svg.filter.js": "^3.0.8", "@svgdotjs/svg.filter.js": "^3.0.8",
"@svgdotjs/svg.js": "^3.2.0", "@svgdotjs/svg.js": "^3.2.4",
"@svgdotjs/svg.panzoom.js": "^2.1.2", "@svgdotjs/svg.panzoom.js": "^2.1.2",
"@tinymce/tinymce-angular": "^7.0.0", "@tinymce/tinymce-angular": "^8.0.1",
"ace-builds": "1.4.13", "ace-builds": "1.36.2",
"ace-diff": "^3.0.3", "ace-diff": "^3.0.3",
"angular-gridster2": "~15.0.4", "angular-gridster2": "~18.0.1",
"angular2-hotkeys": "^13.1.0", "angular2-hotkeys": "^16.0.1",
"canvas-gauges": "^2.1.7", "canvas-gauges": "^2.1.7",
"core-js": "^3.29.1", "core-js": "^3.38.1",
"date-fns": "2.0.0-alpha.27", "dayjs": "1.11.13",
"dayjs": "1.11.4",
"echarts": "https://github.com/thingsboard/echarts/archive/5.5.0-TB.tar.gz", "echarts": "https://github.com/thingsboard/echarts/archive/5.5.0-TB.tar.gz",
"flot": "https://github.com/thingsboard/flot.git#0.9-work", "flot": "https://github.com/thingsboard/flot.git#0.9-work",
"flot.curvedlines": "https://github.com/MichaelZinsmaier/CurvedLines.git#master", "flot.curvedlines": "https://github.com/MichaelZinsmaier/CurvedLines.git#master",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"html2canvas": "^1.4.1", "html2canvas": "^1.4.1",
"jquery": "^3.7.1", "jquery": "^3.7.1",
"jquery.terminal": "^2.35.3", "jquery.terminal": "^2.43.1",
"js-beautify": "1.14.7", "js-beautify": "1.15.1",
"json-schema-defaults": "^0.4.0", "json-schema-defaults": "^0.4.0",
"jstree": "^3.3.15", "jstree": "^3.3.17",
"jstree-bootstrap-theme": "^1.0.1", "jstree-bootstrap-theme": "^1.0.1",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"leaflet": "1.8.0", "leaflet": "1.9.4",
"leaflet-polylinedecorator": "1.6.0", "leaflet-polylinedecorator": "1.6.0",
"leaflet-providers": "1.13.0", "leaflet-providers": "2.0.0",
"leaflet.gridlayer.googlemutant": "0.14.1", "leaflet.gridlayer.googlemutant": "0.14.1",
"leaflet.markercluster": "1.5.3", "leaflet.markercluster": "1.5.3",
"libphonenumber-js": "^1.10.4", "libphonenumber-js": "^1.11.10",
"marked": "^4.0.17", "marked": "~12.0.2",
"moment": "^2.29.4", "moment": "^2.30.1",
"moment-timezone": "^0.5.42", "moment-timezone": "^0.5.45",
"ngx-clipboard": "^15.1.0", "ngx-clipboard": "^16.0.0",
"ngx-daterangepicker-material": "^6.0.4", "ngx-daterangepicker-material": "^6.0.4",
"ngx-drag-drop": "^15.0.1", "ngx-drag-drop": "^18.0.2",
"ngx-flowchart": "https://github.com/thingsboard/ngx-flowchart.git#release/2.0.0", "ngx-flowchart": "https://github.com/thingsboard/ngx-flowchart.git#release/3.0.0",
"ngx-hm-carousel": "^3.0.0", "ngx-hm-carousel": "^18.0.0",
"ngx-markdown": "^15.1.2", "ngx-markdown": "^18.1.0",
"ngx-sharebuttons": "^12.0.0", "ngx-sharebuttons": "^15.0.3",
"ngx-translate-messageformat-compiler": "^6.2.0", "ngx-translate-messageformat-compiler": "^7.0.0",
"objectpath": "^2.0.0", "objectpath": "^2.0.0",
"prettier": "^2.8.3", "prettier": "^2.8.3",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"qrcode": "^1.5.1", "qrcode": "^1.5.4",
"raphael": "^2.3.0", "raphael": "^2.3.0",
"rc-select": "13.2.1", "rc-select": "14.15.2",
"react": "17.0.2", "react": "18.3.1",
"react-ace": "9.5.0", "react-ace": "12.0.0",
"react-dom": "17.0.2", "react-dom": "18.3.1",
"react-dropzone": "^11.4.2", "react-dropzone": "14.2.9",
"reactcss": "^1.2.3", "reactcss": "^1.2.3",
"rxjs": "~7.8.0", "rxjs": "~7.8.1",
"schema-inspector": "^2.0.2", "schema-inspector": "^2.1.0",
"screenfull": "^6.0.2", "screenfull": "^6.0.2",
"sorted-btree": "^1.8.1", "sorted-btree": "^1.8.1",
"split.js": "^1.6.5", "split.js": "^1.6.5",
"systemjs": "6.14.1", "systemjs": "6.15.1",
"tinycolor2": "^1.6.0", "tinycolor2": "^1.6.0",
"tinymce": "~5.10.7", "tinymce": "~6.8.4",
"tooltipster": "^4.2.8", "tooltipster": "^4.2.8",
"ts-transformer-keys": "^0.4.4", "ts-transformer-keys": "^0.4.4",
"tslib": "^2.5.0", "tslib": "^2.7.0",
"tv4": "^1.3.0", "tv4": "^1.3.0",
"typeface-roboto": "^1.1.13", "typeface-roboto": "^1.1.13",
"zone.js": "~0.13.0" "zone.js": "~0.14.10"
}, },
"devDependencies": { "devDependencies": {
"@angular-builders/custom-webpack": "~15.0.0", "@angular-builders/custom-webpack": "~18.0.0",
"@angular-devkit/build-angular": "^15.2.10", "@angular-devkit/build-angular": "18.2.7",
"@angular-eslint/builder": "15.2.1", "@angular-devkit/core": "18.2.7",
"@angular-eslint/eslint-plugin": "15.2.1", "@angular-devkit/schematics": "18.2.7",
"@angular-eslint/eslint-plugin-template": "15.2.1", "@angular-eslint/builder": "18.3.1",
"@angular-eslint/schematics": "15.2.1", "@angular-eslint/eslint-plugin": "18.3.1",
"@angular-eslint/template-parser": "15.2.1", "@angular-eslint/eslint-plugin-template": "18.3.1",
"@angular/cli": "^15.2.10", "@angular-eslint/schematics": "18.3.1",
"@angular/compiler-cli": "^15.2.10", "@angular-eslint/template-parser": "18.3.1",
"@angular/language-service": "^15.2.10", "@angular/cli": "18.2.7",
"@ngtools/webpack": "15.2.10", "@angular/compiler-cli": "18.2.6",
"@types/ace-diff": "^2.1.1", "@angular/language-service": "18.2.6",
"@types/canvas-gauges": "^2.1.4", "@ngtools/webpack": "18.2.7",
"@types/flot": "^0.0.32", "@types/ace-diff": "^2.1.4",
"@types/flowjs": "^2.13.9", "@types/canvas-gauges": "^2.1.8",
"@types/jasmine": "~3.10.2", "@types/flot": "^0.0.36",
"@types/jasminewd2": "^2.0.10", "@types/flowjs": "^2.13.14",
"@types/jquery": "^3.5.30", "@types/jquery": "^3.5.31",
"@types/js-beautify": "^1.13.3", "@types/js-beautify": "^1.14.3",
"@types/leaflet": "1.8.0", "@types/leaflet": "1.9.12",
"@types/leaflet-polylinedecorator": "1.6.4", "@types/leaflet-polylinedecorator": "1.6.4",
"@types/leaflet-providers": "1.2.4", "@types/leaflet-providers": "1.2.4",
"@types/leaflet.gridlayer.googlemutant": "0.4.9", "@types/leaflet.gridlayer.googlemutant": "0.4.9",
"@types/leaflet.markercluster": "1.5.4", "@types/leaflet.markercluster": "1.5.4",
"@types/lodash": "^4.14.192", "@types/lodash": "^4.17.10",
"@types/marked": "^4.0.8",
"@types/node": "~18.15.11", "@types/node": "~18.15.11",
"@types/raphael": "^2.3.2", "@types/raphael": "^2.3.9",
"@types/react": "17.0.37", "@types/react": "18.3.10",
"@types/react-dom": "17.0.11", "@types/react-dom": "18.3.0",
"@types/systemjs": "6.13.1", "@types/systemjs": "6.15.1",
"@types/tinycolor2": "^1.4.3", "@types/tinycolor2": "^1.4.6",
"@types/tooltipster": "^0.0.31", "@types/tooltipster": "^0.0.35",
"@typescript-eslint/eslint-plugin": "5.57.0", "@typescript-eslint/eslint-plugin": "^8.7.0",
"@typescript-eslint/parser": "5.57.0", "@typescript-eslint/parser": "^8.7.0",
"compression-webpack-plugin": "^10.0.0", "@typescript-eslint/utils": "^8.7.0",
"directory-tree": "^3.5.1", "compression-webpack-plugin": "^11.1.0",
"eslint": "^8.37.0", "directory-tree": "^3.5.2",
"eslint": "~8.57.1",
"eslint-plugin-import": "latest", "eslint-plugin-import": "latest",
"eslint-plugin-jsdoc": "latest", "eslint-plugin-jsdoc": "latest",
"eslint-plugin-prefer-arrow": "latest", "eslint-plugin-prefer-arrow": "latest",
"jasmine-core": "~3.10.1",
"jasmine-spec-reporter": "~7.0.0",
"karma": "~6.3.9",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.3",
"karma-jasmine": "~4.0.1",
"karma-jasmine-html-reporter": "^1.7.0",
"ngrx-store-freeze": "^0.2.4", "ngrx-store-freeze": "^0.2.4",
"patch-package": "^6.5.1", "patch-package": "^8.0.0",
"postinstall-prepare": "^2.0.0", "postinstall-prepare": "^2.0.0",
"protractor": "~7.0.0",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",
"ts-node": "^10.9.1", "ts-node": "^10.9.2",
"typescript": "~4.9.5", "typescript": "~5.5.4",
"webpack": "5.77.0" "webpack": "5.95.0"
}, },
"resolutions": { "resolutions": {
"@types/react": "17.0.37", "@types/react": "18.3.10",
"ace-builds": "1.4.13", "rc-virtual-list": "3.5.2",
"@date-io/core": "1.3.7", "ace-builds": "1.36.2",
"rc-virtual-list": "3.4.13", "tinymce": "6.8.4"
"read-package-json": "6.0.0",
"cacache": "17.0.4"
} }
} }

10
ui-ngx/patches/@angular+core+15.2.10.patch → ui-ngx/patches/@angular+core+18.2.6.patch

@ -1,8 +1,8 @@
diff --git a/node_modules/@angular/core/fesm2020/core.mjs b/node_modules/@angular/core/fesm2020/core.mjs diff --git a/node_modules/@angular/core/fesm2022/core.mjs b/node_modules/@angular/core/fesm2022/core.mjs
index e9a9b75..17044d9 100755 index 0fa881f..b844dfa 100755
--- a/node_modules/@angular/core/fesm2020/core.mjs --- a/node_modules/@angular/core/fesm2022/core.mjs
+++ b/node_modules/@angular/core/fesm2020/core.mjs +++ b/node_modules/@angular/core/fesm2022/core.mjs
@@ -11053,13 +11053,13 @@ function findDirectiveDefMatches(tView, tNode) { @@ -12868,13 +12868,13 @@ function findDirectiveDefMatches(tView, tNode) {
if (isNodeMatchingSelectorList(tNode, def.selectors, /* isProjectionMode */ false)) { if (isNodeMatchingSelectorList(tNode, def.selectors, /* isProjectionMode */ false)) {
matches || (matches = []); matches || (matches = []);
if (isComponentDef(def)) { if (isComponentDef(def)) {

21
ui-ngx/patches/@angular+flex-layout+15.0.0-beta.42.patch

File diff suppressed because one or more lines are too long

51
ui-ngx/patches/@mat-datetimepicker+core+11.0.3.patch

@ -1,51 +0,0 @@
diff --git a/node_modules/@mat-datetimepicker/core/esm2020/datetimepicker/clock.mjs b/node_modules/@mat-datetimepicker/core/esm2020/datetimepicker/clock.mjs
index e3457ea..a069460 100644
--- a/node_modules/@mat-datetimepicker/core/esm2020/datetimepicker/clock.mjs
+++ b/node_modules/@mat-datetimepicker/core/esm2020/datetimepicker/clock.mjs
@@ -259,9 +259,9 @@ export class MatDatetimepickerClockComponent {
value = 0;
}
// Don't close the minutes view if an invalid minute is clicked.
- if (!this._minutes.find((m) => m?.['value'] === value)?.['enabled']) {
- return;
- }
+ // if (!this._minutes.find((m) => m?.['value'] === value)?.['enabled']) {
+ // return;
+ // }
date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), this._adapter.getHour(this.activeDate), value);
}
this._timeChanged = true;
diff --git a/node_modules/@mat-datetimepicker/core/fesm2015/mat-datetimepicker-core.mjs b/node_modules/@mat-datetimepicker/core/fesm2015/mat-datetimepicker-core.mjs
index 7699ff6..01aad13 100644
--- a/node_modules/@mat-datetimepicker/core/fesm2015/mat-datetimepicker-core.mjs
+++ b/node_modules/@mat-datetimepicker/core/fesm2015/mat-datetimepicker-core.mjs
@@ -951,9 +951,9 @@ class MatDatetimepickerClockComponent {
value = 0;
}
// Don't close the minutes view if an invalid minute is clicked.
- if (!((_b = this._minutes.find((m) => (m === null || m === void 0 ? void 0 : m['value']) === value)) === null || _b === void 0 ? void 0 : _b['enabled'])) {
- return;
- }
+ // if (!((_b = this._minutes.find((m) => (m === null || m === void 0 ? void 0 : m['value']) === value)) === null || _b === void 0 ? void 0 : _b['enabled'])) {
+ // return;
+ // }
date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), this._adapter.getHour(this.activeDate), value);
}
this._timeChanged = true;
diff --git a/node_modules/@mat-datetimepicker/core/fesm2020/mat-datetimepicker-core.mjs b/node_modules/@mat-datetimepicker/core/fesm2020/mat-datetimepicker-core.mjs
index 809a57d..f712b84 100644
--- a/node_modules/@mat-datetimepicker/core/fesm2020/mat-datetimepicker-core.mjs
+++ b/node_modules/@mat-datetimepicker/core/fesm2020/mat-datetimepicker-core.mjs
@@ -946,9 +946,9 @@ class MatDatetimepickerClockComponent {
value = 0;
}
// Don't close the minutes view if an invalid minute is clicked.
- if (!this._minutes.find((m) => m?.['value'] === value)?.['enabled']) {
- return;
- }
+ // if (!this._minutes.find((m) => m?.['value'] === value)?.['enabled']) {
+ // return;
+ // }
date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), this._adapter.getHour(this.activeDate), value);
}
this._timeChanged = true;

34
ui-ngx/patches/@mat-datetimepicker+core+14.0.0.patch

@ -0,0 +1,34 @@
diff --git a/node_modules/@mat-datetimepicker/core/esm2022/datetimepicker/clock.mjs b/node_modules/@mat-datetimepicker/core/esm2022/datetimepicker/clock.mjs
index 7ecfae7..08363d3 100644
--- a/node_modules/@mat-datetimepicker/core/esm2022/datetimepicker/clock.mjs
+++ b/node_modules/@mat-datetimepicker/core/esm2022/datetimepicker/clock.mjs
@@ -259,9 +259,9 @@ export class MatDatetimepickerClockComponent {
value = 0;
}
// Don't close the minutes view if an invalid minute is clicked.
- if (!this._minutes.find((m) => m?.['value'] === value)?.['enabled']) {
- return;
- }
+ // if (!this._minutes.find((m) => m?.['value'] === value)?.['enabled']) {
+ // return;
+ // }
date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), this._adapter.getHour(this.activeDate), value);
}
this._timeChanged = true;
diff --git a/node_modules/@mat-datetimepicker/core/fesm2022/mat-datetimepicker-core.mjs b/node_modules/@mat-datetimepicker/core/fesm2022/mat-datetimepicker-core.mjs
index 00f4a52..df688e3 100644
--- a/node_modules/@mat-datetimepicker/core/fesm2022/mat-datetimepicker-core.mjs
+++ b/node_modules/@mat-datetimepicker/core/fesm2022/mat-datetimepicker-core.mjs
@@ -946,9 +946,9 @@ class MatDatetimepickerClockComponent {
value = 0;
}
// Don't close the minutes view if an invalid minute is clicked.
- if (!this._minutes.find((m) => m?.['value'] === value)?.['enabled']) {
- return;
- }
+ // if (!this._minutes.find((m) => m?.['value'] === value)?.['enabled']) {
+ // return;
+ // }
date = this._adapter.createDatetime(this._adapter.getYear(this.activeDate), this._adapter.getMonth(this.activeDate), this._adapter.getDate(this.activeDate), this._adapter.getHour(this.activeDate), value);
}
this._timeChanged = true;

28
ui-ngx/patches/angular-gridster2+15.0.4.patch → ui-ngx/patches/angular-gridster2+18.0.1.patch

@ -1,15 +1,15 @@
diff --git a/node_modules/angular-gridster2/fesm2020/angular-gridster2.mjs b/node_modules/angular-gridster2/fesm2020/angular-gridster2.mjs diff --git a/node_modules/angular-gridster2/fesm2022/angular-gridster2.mjs b/node_modules/angular-gridster2/fesm2022/angular-gridster2.mjs
index cf4e220..df51c91 100644 index 0dcd873..e99b602 100644
--- a/node_modules/angular-gridster2/fesm2020/angular-gridster2.mjs --- a/node_modules/angular-gridster2/fesm2022/angular-gridster2.mjs
+++ b/node_modules/angular-gridster2/fesm2020/angular-gridster2.mjs +++ b/node_modules/angular-gridster2/fesm2022/angular-gridster2.mjs
@@ -666,8 +666,8 @@ class GridsterRenderer { @@ -666,8 +666,8 @@ class GridsterRenderer {
renderer.setStyle(el, DirTypes.LTR ? 'margin-right' : 'margin-left', ''); renderer.setStyle(el, DirTypes.LTR ? 'margin-right' : 'margin-left', '');
} }
else { else {
- const x = Math.round(this.gridster.curColWidth * item.x); - const x = Math.round(this.gridster.curColWidth * item.x);
- const y = Math.round(this.gridster.curRowHeight * item.y); - const y = Math.round(this.gridster.curRowHeight * item.y);
+ const x = this.gridster.curColWidth * item.x; + const x = this.gridster.curColWidth * item.x;
+ const y = this.gridster.curRowHeight * item.y; + const y = this.gridster.curRowHeight * item.y;
const width = this.gridster.curColWidth * item.cols - this.gridster.$options.margin; const width = this.gridster.curColWidth * item.cols - this.gridster.$options.margin;
const height = this.gridster.curRowHeight * item.rows - this.gridster.$options.margin; const height = this.gridster.curRowHeight * item.rows - this.gridster.$options.margin;
// set the cell style // set the cell style

2
ui-ngx/pom.xml

@ -57,7 +57,7 @@
</goals> </goals>
<configuration> <configuration>
<nodeVersion>v20.11.1</nodeVersion> <nodeVersion>v20.11.1</nodeVersion>
<yarnVersion>v1.22.17</yarnVersion> <yarnVersion>v1.22.22</yarnVersion>
</configuration> </configuration>
</execution> </execution>
<execution> <execution>

1
ui-ngx/src/app/core/api/widget-api.models.ts

@ -42,7 +42,6 @@ import { RafService } from '@core/services/raf.service';
import { EntityAliases } from '@shared/models/alias.models'; import { EntityAliases } from '@shared/models/alias.models';
import { EntityInfo } from '@app/shared/models/entity.models'; import { EntityInfo } from '@app/shared/models/entity.models';
import { IDashboardComponent } from '@home/models/dashboard-component.models'; import { IDashboardComponent } from '@home/models/dashboard-component.models';
import moment_ from 'moment';
import { import {
AlarmData, AlarmData,
AlarmDataPageLink, AlarmDataPageLink,

140
ui-ngx/src/app/core/core.module.ts

@ -15,8 +15,8 @@
/// ///
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule, IMAGE_CONFIG } from '@angular/common';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http'; import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { StoreModule } from '@ngrx/store'; import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects'; import { EffectsModule } from '@ngrx/effects';
import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { StoreDevtoolsModule } from '@ngrx/store-devtools';
@ -43,74 +43,72 @@ import { TranslateDefaultParser } from '@core/translate/translate-default-parser
import { TranslateDefaultLoader } from '@core/translate/translate-default-loader'; import { TranslateDefaultLoader } from '@core/translate/translate-default-loader';
import { EntityConflictInterceptor } from '@core/interceptors/entity-conflict.interceptor'; import { EntityConflictInterceptor } from '@core/interceptors/entity-conflict.interceptor';
@NgModule({ @NgModule({ exports: [], imports: [CommonModule,
imports: [ FlexLayoutModule.withConfig({ addFlexToParent: false }),
CommonModule, MatDialogModule,
HttpClientModule, MatButtonModule,
FlexLayoutModule.withConfig({addFlexToParent: false}), MatSnackBarModule,
MatDialogModule, // ngx-translate
MatButtonModule, TranslateModule.forRoot({
MatSnackBarModule, loader: {
provide: TranslateLoader,
// ngx-translate useClass: TranslateDefaultLoader
TranslateModule.forRoot({ },
loader: { missingTranslationHandler: {
provide: TranslateLoader, provide: MissingTranslationHandler,
useClass: TranslateDefaultLoader useClass: TbMissingTranslationHandler
}, },
missingTranslationHandler: { compiler: {
provide: MissingTranslationHandler, provide: TranslateCompiler,
useClass: TbMissingTranslationHandler useClass: TranslateDefaultCompiler
}, },
compiler: { parser: {
provide: TranslateCompiler, provide: TranslateParser,
useClass: TranslateDefaultCompiler useClass: TranslateDefaultParser
}, }
parser: { }),
provide: TranslateParser, HotkeyModule.forRoot(),
useClass: TranslateDefaultParser // ngrx
} StoreModule.forRoot(reducers, { metaReducers,
}), runtimeChecks: {
HotkeyModule.forRoot(), strictStateImmutability: true,
strictActionImmutability: true,
// ngrx strictStateSerializability: true,
StoreModule.forRoot(reducers, strictActionSerializability: true
{ metaReducers, } }),
runtimeChecks: { EffectsModule.forRoot(effects),
strictStateImmutability: true, env.production
strictActionImmutability: true, ? []
strictStateSerializability: true, : StoreDevtoolsModule.instrument({
strictActionSerializability: true name: env.appTitle,
}} connectInZone: true
), })], providers: [
EffectsModule.forRoot(effects), {
env.production provide: HTTP_INTERCEPTORS,
? [] useClass: GlobalHttpInterceptor,
: StoreDevtoolsModule.instrument({ multi: true
name: env.appTitle },
}) {
], provide: HTTP_INTERCEPTORS,
providers: [ useClass: EntityConflictInterceptor,
{ multi: true
provide: HTTP_INTERCEPTORS, },
useClass: GlobalHttpInterceptor, {
multi: true provide: MAT_DIALOG_DEFAULT_OPTIONS,
}, useValue: {
{ ...new MatDialogConfig(),
provide: HTTP_INTERCEPTORS, restoreFocus: false
useClass: EntityConflictInterceptor, }
multi: true },
}, WINDOW_PROVIDERS,
{ provideHttpClient(withInterceptorsFromDi()),
provide: MAT_DIALOG_DEFAULT_OPTIONS, {
useValue: { provide: IMAGE_CONFIG,
...new MatDialogConfig(), useValue: {
restoreFocus: false disableImageSizeWarning: true,
} disableImageLazyLoadWarning: true
}, }
WINDOW_PROVIDERS }
], ] })
exports: []
})
export class CoreModule { export class CoreModule {
} }

4
ui-ngx/src/app/core/guards/auth.guard.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable, NgZone } from '@angular/core'; import { Injectable, NgZone } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
import { AuthService } from '../auth/auth.service'; import { AuthService } from '../auth/auth.service';
import { select, Store } from '@ngrx/store'; import { select, Store } from '@ngrx/store';
import { AppState } from '../core.state'; import { AppState } from '../core.state';
@ -34,7 +34,7 @@ import { MobileService } from '@core/services/mobile.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class AuthGuard implements CanActivate, CanActivateChild { export class AuthGuard {
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private router: Router, private router: Router,

4
ui-ngx/src/app/core/guards/confirm-on-exit.guard.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { UntypedFormGroup } from '@angular/forms'; import { UntypedFormGroup } from '@angular/forms';
import { select, Store } from '@ngrx/store'; import { select, Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
@ -39,7 +39,7 @@ export interface HasDirtyFlag {
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class ConfirmOnExitGuard implements CanDeactivate<HasConfirmForm & HasDirtyFlag> { export class ConfirmOnExitGuard {
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private dialogService: DialogService, private dialogService: DialogService,

23
ui-ngx/src/app/core/http/rule-chain.service.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { ComponentFactory, Injectable } from '@angular/core'; import { Injectable, Type } from '@angular/core';
import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
import { forkJoin, Observable, of } from 'rxjs'; import { forkJoin, Observable, of } from 'rxjs';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
@ -31,11 +31,13 @@ import { ComponentDescriptorService } from './component-descriptor.service';
import { import {
IRuleNodeConfigurationComponent, IRuleNodeConfigurationComponent,
LinkLabel, LinkLabel,
RuleNodeComponentDescriptor, RuleNodeConfiguration, ScriptLanguage, RuleNodeComponentDescriptor,
RuleNodeConfiguration,
ScriptLanguage,
TestScriptInputParams, TestScriptInputParams,
TestScriptResult TestScriptResult
} from '@app/shared/models/rule-node.models'; } from '@app/shared/models/rule-node.models';
import { ResourcesService } from '../services/resources.service'; import { componentTypeBySelector, ResourcesService } from '../services/resources.service';
import { catchError, map, mergeMap } from 'rxjs/operators'; import { catchError, map, mergeMap } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { deepClone, snakeCase } from '@core/utils'; import { deepClone, snakeCase } from '@core/utils';
@ -50,7 +52,7 @@ export class RuleChainService {
private ruleNodeComponentsMap: Map<RuleChainType, Array<RuleNodeComponentDescriptor>> = private ruleNodeComponentsMap: Map<RuleChainType, Array<RuleNodeComponentDescriptor>> =
new Map<RuleChainType, Array<RuleNodeComponentDescriptor>>(); new Map<RuleChainType, Array<RuleNodeComponentDescriptor>>();
private ruleNodeConfigFactories: {[directive: string]: ComponentFactory<IRuleNodeConfigurationComponent>} = {}; private ruleNodeConfigComponents: {[directive: string]: Type<IRuleNodeConfigurationComponent>} = {};
constructor( constructor(
private http: HttpClient, private http: HttpClient,
@ -126,8 +128,8 @@ export class RuleChainService {
} }
} }
public getRuleNodeConfigFactory(directive: string): ComponentFactory<IRuleNodeConfigurationComponent> { public getRuleNodeConfigComponent(directive: string): Type<IRuleNodeConfigurationComponent> {
return this.ruleNodeConfigFactories[directive]; return this.ruleNodeConfigComponents[directive];
} }
public getRuleNodeComponentByClazz(ruleChainType: RuleChainType = RuleChainType.CORE, clazz: string): RuleNodeComponentDescriptor { public getRuleNodeComponentByClazz(ruleChainType: RuleChainType = RuleChainType.CORE, clazz: string): RuleNodeComponentDescriptor {
@ -219,14 +221,13 @@ export class RuleChainService {
}); });
} }
if (moduleResource) { if (moduleResource) {
tasks.push(this.resourcesService.loadFactories(moduleResource, modulesMap).pipe( tasks.push(this.resourcesService.loadModulesWithComponents(moduleResource, modulesMap).pipe(
map((res) => { map((res) => {
if (nodeDefinition.configDirective && nodeDefinition.configDirective.length) { if (nodeDefinition.configDirective && nodeDefinition.configDirective.length) {
const selector = snakeCase(nodeDefinition.configDirective, '-'); const selector = snakeCase(nodeDefinition.configDirective, '-');
const componentFactory = res.factories.find((factory) => const componentType = componentTypeBySelector(res, selector);
factory.selector === selector); if (componentType) {
if (componentFactory) { this.ruleNodeConfigComponents[nodeDefinition.configDirective] = componentType;
this.ruleNodeConfigFactories[nodeDefinition.configDirective] = componentFactory;
} else { } else {
component.configurationDescriptor.nodeDefinition.uiResourceLoadError = component.configurationDescriptor.nodeDefinition.uiResourceLoadError =
this.translate.instant('rulenode.directive-is-not-loaded', this.translate.instant('rulenode.directive-is-not-loaded',

10
ui-ngx/src/app/core/interceptors/entity-conflict.interceptor.ts

@ -15,15 +15,7 @@
/// ///
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpParams, HttpRequest, HttpStatusCode } from '@angular/common/http';
HttpErrorResponse,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpParams,
HttpRequest,
HttpStatusCode
} from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs'; import { Observable, of, throwError } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators'; import { catchError, switchMap } from 'rxjs/operators';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';

10
ui-ngx/src/app/core/services/dynamic-component-factory.service.ts

@ -18,6 +18,7 @@ import { Component, Injectable, Type, ɵComponentDef, ɵNG_COMP_DEF } from '@ang
import { from, Observable, of } from 'rxjs'; import { from, Observable, of } from 'rxjs';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { mergeMap } from 'rxjs/operators'; import { mergeMap } from 'rxjs/operators';
import { guid } from '@core/utils';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -30,14 +31,14 @@ export class DynamicComponentFactoryService {
public createDynamicComponent<T>( public createDynamicComponent<T>(
componentType: Type<T>, componentType: Type<T>,
template: string, template: string,
modules?: Type<any>[], imports?: Type<any>[],
preserveWhitespaces?: boolean, preserveWhitespaces?: boolean,
styles?: string[]): Observable<Type<T>> { styles?: string[]): Observable<Type<T>> {
return from(import('@angular/compiler')).pipe( return from(import('@angular/compiler')).pipe(
mergeMap(() => { mergeMap(() => {
let componentImports: Type<any>[] = [CommonModule]; let componentImports: Type<any>[] = [CommonModule];
if (modules) { if (imports) {
componentImports = [...componentImports, ...modules]; componentImports = [...componentImports, ...imports];
} }
const comp = this.createAndCompileDynamicComponent(componentType, template, componentImports, preserveWhitespaces, styles); const comp = this.createAndCompileDynamicComponent(componentType, template, componentImports, preserveWhitespaces, styles);
return of(comp.type); return of(comp.type);
@ -60,7 +61,8 @@ export class DynamicComponentFactoryService {
imports, imports,
preserveWhitespaces, preserveWhitespaces,
styles, styles,
standalone: true standalone: true,
selector: 'tb-dynamic-component#' + guid()
})(componentType); })(componentType);
// Trigger component compilation // Trigger component compilation
return comp[ɵNG_COMP_DEF]; return comp[ɵNG_COMP_DEF];

209
ui-ngx/src/app/core/services/resources.service.ts

@ -15,16 +15,19 @@
/// ///
import { import {
Compiler, createNgModule,
ComponentFactory,
Inject, Inject,
Injectable, Injectable,
Injector, Injector,
ModuleWithComponentFactories, Type,
Type, ɵNG_MOD_DEF ɵComponentDef,
ɵCssSelectorList,
ɵNG_COMP_DEF,
ɵNG_MOD_DEF,
ɵNgModuleDef
} from '@angular/core'; } from '@angular/core';
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { forkJoin, Observable, ReplaySubject, throwError } from 'rxjs'; import { Observable, ReplaySubject, throwError } from 'rxjs';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { IModulesMap } from '@modules/common/modules-map.models'; import { IModulesMap } from '@modules/common/modules-map.models';
import { TbResourceId } from '@shared/models/id/tb-resource-id'; import { TbResourceId } from '@shared/models/id/tb-resource-id';
@ -36,13 +39,56 @@ import { AppState } from '@core/core.state';
import { map, tap } from 'rxjs/operators'; import { map, tap } from 'rxjs/operators';
import { RequestConfig } from '@core/http/http-utils'; import { RequestConfig } from '@core/http/http-utils';
declare const System; export interface ModuleInfo {
module: ɵNgModuleDef<any>;
components: ɵComponentDef<any>[];
}
export interface ModulesWithComponents {
modules: ModuleInfo[];
standaloneComponents: ɵComponentDef<any>[];
}
export const flatModulesWithComponents = (modulesWithComponentsList: ModulesWithComponents[]): ModulesWithComponents => {
const modulesWithComponents: ModulesWithComponents = {
modules: [],
standaloneComponents: []
};
for (const m of modulesWithComponentsList) {
for (const module of m.modules) {
if (!modulesWithComponents.modules.some(m1 => m1.module === module.module)) {
modulesWithComponents.modules.push(module);
}
}
for (const comp of m.standaloneComponents) {
if (!modulesWithComponents.standaloneComponents.includes(comp)) {
modulesWithComponents.standaloneComponents.push(comp);
}
}
}
return modulesWithComponents;
}
export const modulesWithComponentsToTypes = (modulesWithComponents: ModulesWithComponents): Type<any>[] =>
[...modulesWithComponents.modules.map(m => m.module.type),
...modulesWithComponents.standaloneComponents.map(c => c.type)];
export interface ModulesWithFactories { export const componentTypeBySelector = (modulesWithComponents: ModulesWithComponents, selector: string): Type<any> | undefined => {
modules: Type<any>[]; let found = modulesWithComponents.standaloneComponents.find(c => matchesSelector(c.selectors, selector));
factories: ComponentFactory<any>[]; if (!found) {
for (const m of modulesWithComponents.modules) {
found = m.components.find(c => matchesSelector(c.selectors, selector));
if (found) {
break;
}
}
}
return found?.type;
} }
const matchesSelector = (selectors: ɵCssSelectorList, selector: string) =>
selectors.some(s => s.some(s1 => typeof s1 === 'string' && s1 === selector));
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
@ -50,16 +96,15 @@ export class ResourcesService {
private loadedJsonResources: { [url: string]: ReplaySubject<any> } = {}; private loadedJsonResources: { [url: string]: ReplaySubject<any> } = {};
private loadedResources: { [url: string]: ReplaySubject<void> } = {}; private loadedResources: { [url: string]: ReplaySubject<void> } = {};
private loadedModulesAndFactories: { [url: string]: ReplaySubject<ModulesWithFactories> } = {}; private loadedModulesWithComponents: { [url: string]: ReplaySubject<ModulesWithComponents> } = {};
private anchor = this.document.getElementsByTagName('head')[0] || this.document.getElementsByTagName('body')[0]; private anchor = this.document.getElementsByTagName('head')[0] || this.document.getElementsByTagName('body')[0];
constructor(@Inject(DOCUMENT) private readonly document: any, constructor(@Inject(DOCUMENT) private readonly document: Document,
protected store: Store<AppState>, protected store: Store<AppState>,
private compiler: Compiler,
private http: HttpClient, private http: HttpClient,
private injector: Injector) { private injector: Injector) {
this.store.pipe(select(selectIsAuthenticated)).subscribe(() => this.clearModulesCache()); this.store.pipe(select(selectIsAuthenticated)).subscribe(() => this.clearModulesWithComponentsCache());
} }
public loadJsonResource<T>(url: string, postProcess?: (data: T) => T): Observable<T> { public loadJsonResource<T>(url: string, postProcess?: (data: T) => T): Observable<T> {
@ -93,7 +138,7 @@ export class ResourcesService {
return this.loadedResources[url].asObservable(); return this.loadedResources[url].asObservable();
} }
let fileType; let fileType: string;
const match = /[./](css|less|html|htm|js)?(([?#]).*)?$/.exec(url); const match = /[./](css|less|html|htm|js)?(([?#]).*)?$/.exec(url);
if (match !== null) { if (match !== null) {
fileType = match[1]; fileType = match[1];
@ -137,53 +182,38 @@ export class ResourcesService {
); );
} }
public loadFactories(resourceId: string | TbResourceId, modulesMap: IModulesMap): Observable<ModulesWithFactories> { public loadModulesWithComponents(resourceId: string | TbResourceId, modulesMap: IModulesMap): Observable<ModulesWithComponents> {
const url = this.getDownloadUrl(resourceId); const url = this.getDownloadUrl(resourceId);
if (this.loadedModulesAndFactories[url]) { if (this.loadedModulesWithComponents[url]) {
return this.loadedModulesAndFactories[url].asObservable(); return this.loadedModulesWithComponents[url].asObservable();
} }
modulesMap.init(); modulesMap.init();
const meta = this.getMetaInfo(resourceId); const meta = this.getMetaInfo(resourceId);
const subject = new ReplaySubject<ModulesWithFactories>(); const subject = new ReplaySubject<ModulesWithComponents>();
this.loadedModulesAndFactories[url] = subject; this.loadedModulesWithComponents[url] = subject;
import('@angular/compiler').then( import('@angular/compiler').then(
() => { () => {
// @ts-ignore
System.import(url, undefined, meta).then( System.import(url, undefined, meta).then(
(module) => { (module: any) => {
const modules = this.extractNgModules(module); try {
if (modules.length) { const modulesWithComponents = this.extractModulesWithComponents(module);
const tasks: Promise<ModuleWithComponentFactories<any>>[] = []; if (modulesWithComponents.modules.length || modulesWithComponents.standaloneComponents.length) {
for (const m of modules) { for (const module of modulesWithComponents.modules) {
tasks.push(this.compiler.compileModuleAndAllComponentsAsync(m)); createNgModule(module.module.type, this.injector);
}
forkJoin(tasks).subscribe({
next: (compiled) => {
try {
const componentFactories: ComponentFactory<any>[] = [];
for (const c of compiled) {
c.ngModuleFactory.create(this.injector);
componentFactories.push(...c.componentFactories);
}
const modulesWithFactories: ModulesWithFactories = {
modules,
factories: componentFactories
};
this.loadedModulesAndFactories[url].next(modulesWithFactories);
this.loadedModulesAndFactories[url].complete();
} catch (e) {
this.loadedModulesAndFactories[url].error(new Error(`Unable to init module from url: ${url}`));
}
},
error: (e) => {
this.loadedModulesAndFactories[url].error(new Error(`Unable to compile module from url: ${url}`));
} }
}); this.loadedModulesWithComponents[url].next(modulesWithComponents);
} else { this.loadedModulesWithComponents[url].complete();
this.loadedModulesAndFactories[url].error(new Error(`Module '${url}' doesn't have default export!`)); } else {
this.loadedModulesWithComponents[url].error(new Error(`Module '${url}' doesn't have exported modules or components!`));
}
} catch (e) {
console.log(`Unable to parse module from url: ${url}`, e);
this.loadedModulesWithComponents[url].error(new Error(`Unable to parse module from url: ${url}`));
} }
}, },
(e) => { () => {
this.loadedModulesAndFactories[url].error(new Error(`Unable to load module from url: ${url}`)); this.loadedModulesWithComponents[url].error(new Error(`Unable to load module from url: ${url}`));
} }
); );
} }
@ -192,7 +222,7 @@ export class ResourcesService {
tap({ tap({
next: () => System.delete(url), next: () => System.delete(url),
error: () => { error: () => {
delete this.loadedModulesAndFactories[url]; delete this.loadedModulesWithComponents[url];
System.delete(url); System.delete(url);
}, },
complete: () => System.delete(url) complete: () => System.delete(url)
@ -200,41 +230,66 @@ export class ResourcesService {
); );
} }
private extractNgModules(module: any, modules: Type<any>[] = []): Type<any>[] {
try {
let potentialModules = [module];
let currentScanDepth = 0;
while (potentialModules.length && currentScanDepth < 10) { private extractModulesWithComponents(module: any,
const newPotentialModules = []; modulesWithComponents: ModulesWithComponents = {
for (const potentialModule of potentialModules) { modules: [],
if (potentialModule && (ɵNG_MOD_DEF in potentialModule)) { standaloneComponents: []
modules.push(potentialModule); },
visitedModules: Set<any> = new Set<any>()): ModulesWithComponents {
if (module && ['object', 'function'].includes(typeof module)) {
if (ɵNG_MOD_DEF in module) {
const moduleDef: ɵNgModuleDef<any> = module[ɵNG_MOD_DEF];
if (!visitedModules.has(moduleDef.type)) {
visitedModules.add(moduleDef.type);
const moduleInfo: ModuleInfo = {
module: moduleDef,
components: []
}
modulesWithComponents.modules.push(moduleInfo);
const exportsDecl = moduleDef.exports;
let exports: Type<any>[];
if (Array.isArray(exportsDecl)) {
exports = exportsDecl;
} else { } else {
for (const k of Object.keys(potentialModule)) { exports = exportsDecl();
if (!this.isPrimitive(potentialModule[k])) { }
newPotentialModules.push(potentialModule[k]); for (const element of exports) {
if (ɵNG_COMP_DEF in element) {
const component: ɵComponentDef<any> = element[ɵNG_COMP_DEF];
if (!component.standalone) {
moduleInfo.components.push(component);
} else {
modulesWithComponents.standaloneComponents.push(component);
} }
} else {
this.extractModulesWithComponents(module, modulesWithComponents, visitedModules);
} }
} }
} }
potentialModules = newPotentialModules; } else if (ɵNG_COMP_DEF in module) {
currentScanDepth++; const component: ɵComponentDef<any> = module[ɵNG_COMP_DEF];
if (component.standalone) {
if (!modulesWithComponents.standaloneComponents.includes(component)) {
modulesWithComponents.standaloneComponents.push(component);
}
}
} else {
for (const k of Object.keys(module)) {
const val = module[k];
if (val && ['object', 'function'].includes(typeof val)) {
this.extractModulesWithComponents(val, modulesWithComponents, visitedModules);
}
}
} }
} catch (e) {
console.log('Could not load NgModule', e);
} }
return modules; return modulesWithComponents;
}
private isPrimitive(test) {
return test !== Object(test);
} }
private loadResourceByType(type: 'css' | 'js', url: string): Observable<any> { private loadResourceByType(type: 'css' | 'js', url: string): Observable<any> {
const subject = new ReplaySubject<void>(); const subject = new ReplaySubject<void>();
this.loadedResources[url] = subject; this.loadedResources[url] = subject;
let el; let el: any;
let loaded = false; let loaded = false;
switch (type) { switch (type) {
case 'js': case 'js':
@ -250,7 +305,7 @@ export class ResourcesService {
el.href = url; el.href = url;
break; break;
} }
el.onload = el.onreadystatechange = (e) => { el.onload = el.onreadystatechange = () => {
if (el.readyState && !/^c|loade/.test(el.readyState) || loaded) { return; } if (el.readyState && !/^c|loade/.test(el.readyState) || loaded) { return; }
el.onload = el.onreadystatechange = null; el.onload = el.onreadystatechange = null;
loaded = true; loaded = true;
@ -282,7 +337,7 @@ export class ResourcesService {
} }
} }
private clearModulesCache() { private clearModulesWithComponentsCache() {
this.loadedModulesAndFactories = {}; this.loadedModulesWithComponents = {};
} }
} }

2
ui-ngx/src/app/core/settings/settings.utils.ts

@ -16,7 +16,7 @@
import { environment as env } from '@env/environment'; import { environment as env } from '@env/environment';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import * as _moment from 'moment'; import _moment from 'moment';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
export function updateUserLang(translate: TranslateService, userLang: string, translations = env.supportedLangs): Observable<any> { export function updateUserLang(translate: TranslateService, userLang: string, translations = env.supportedLangs): Observable<any> {

2
ui-ngx/src/app/core/translate/translate-default-compiler.ts

@ -33,7 +33,7 @@ export class TranslateDefaultCompiler extends TranslateMessageFormatCompiler {
super(config); super(config);
} }
public compile(value: string, lang: string): (params: any) => string { public compile(value: string, lang: string): any {
return this.defaultCompile(value, lang); return this.defaultCompile(value, lang);
} }

8
ui-ngx/src/app/modules/common/modules-map.ts

@ -78,7 +78,7 @@ import * as RxJs from 'rxjs';
import * as RxJsOperators from 'rxjs/operators'; import * as RxJsOperators from 'rxjs/operators';
import * as TranslateCore from '@ngx-translate/core'; import * as TranslateCore from '@ngx-translate/core';
import * as MatDateTimePicker from '@mat-datetimepicker/core'; import * as MatDateTimePicker from '@mat-datetimepicker/core';
import * as _moment from 'moment'; import _moment from 'moment';
import * as tslib from 'tslib'; import * as tslib from 'tslib';
import * as TbCore from '@core/public-api'; import * as TbCore from '@core/public-api';
@ -343,8 +343,6 @@ import { TimezoneComponent } from '@shared/components/time/timezone.component';
import { TimezonePanelComponent } from '@shared/components/time/timezone-panel.component'; import { TimezonePanelComponent } from '@shared/components/time/timezone-panel.component';
import { DatapointsLimitComponent } from '@shared/components/time/datapoints-limit.component'; import { DatapointsLimitComponent } from '@shared/components/time/datapoints-limit.component';
declare const System;
class ModulesMap implements IModulesMap { class ModulesMap implements IModulesMap {
private initialized = false; private initialized = false;
@ -681,7 +679,7 @@ class ModulesMap implements IModulesMap {
init() { init() {
if (!this.initialized) { if (!this.initialized) {
System.constructor.prototype.resolve = (id) => { System.constructor.prototype.resolve = (id: string) => {
try { try {
if (this.modulesMap[id]) { if (this.modulesMap[id]) {
return 'app:' + id; return 'app:' + id;
@ -696,7 +694,7 @@ class ModulesMap implements IModulesMap {
System.set('app:' + moduleId, this.modulesMap[moduleId]); System.set('app:' + moduleId, this.modulesMap[moduleId]);
} }
System.constructor.prototype.shouldFetch = (url: string) => url.endsWith('/download'); System.constructor.prototype.shouldFetch = (url: string) => url.endsWith('/download');
System.constructor.prototype.fetch = (url, options: RequestInit & {meta?: any}) => { System.constructor.prototype.fetch = (url: string, options: RequestInit & {meta?: any}) => {
if (options?.meta?.additionalHeaders) { if (options?.meta?.additionalHeaders) {
options.headers = { ...options.headers, ...options.meta.additionalHeaders }; options.headers = { ...options.headers, ...options.meta.additionalHeaders };
} }

4
ui-ngx/src/app/modules/dashboard/dashboard-pages.routing.module.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable, NgModule } from '@angular/core'; import { Injectable, NgModule } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterModule, Routes } from '@angular/router'; import { ActivatedRouteSnapshot, RouterModule, Routes } from '@angular/router';
import { Authority } from '@shared/models/authority.enum'; import { Authority } from '@shared/models/authority.enum';
import { DashboardPageComponent } from '@home/components/dashboard-page/dashboard-page.component'; import { DashboardPageComponent } from '@home/components/dashboard-page/dashboard-page.component';
@ -28,7 +28,7 @@ import { Widget } from '@app/shared/models/widget.models';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
@Injectable() @Injectable()
export class WidgetEditorDashboardResolver implements Resolve<Dashboard> { export class WidgetEditorDashboardResolver {
constructor(private dashboardService: DashboardService, constructor(private dashboardService: DashboardService,
private dashboardUtils: DashboardUtilsService, private dashboardUtils: DashboardUtilsService,

4
ui-ngx/src/app/modules/home/components/alarm/alarm-comment.component.scss

@ -16,8 +16,8 @@
@use '@angular/material' as mat; @use '@angular/material' as mat;
@import '../theme.scss'; @import '../theme.scss';
$primary-color: rgba(mat.get-color-from-palette($tb-primary, 50), 0.4); $primary-color: rgba(mat.m2-get-color-from-palette($tb-primary, 50), 0.4);
$border: 1px solid mat.get-color-from-palette($tb-primary); $border: 1px solid mat.m2-get-color-from-palette($tb-primary);
:host { :host {
.tb-alarm-comments { .tb-alarm-comments {

4
ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.scss

@ -17,7 +17,7 @@
@import '../theme.scss'; @import '../theme.scss';
@import '../scss/constants.scss'; @import '../scss/constants.scss';
$tb-warn: mat.get-color-from-palette(map-get($tb-theme, warn), text); $tb-warn: mat.m2-get-color-from-palette(map-get($tb-theme, warn), text);
:host { :host {
.tb-layout-fixed-container { .tb-layout-fixed-container {
@ -35,7 +35,7 @@ $tb-warn: mat.get-color-from-palette(map-get($tb-theme, warn), text);
.tb-layout-preview { .tb-layout-preview {
width: 100%; width: 100%;
background-color: rgba(mat.get-color-from-palette($tb-primary, 50), 0.6); background-color: rgba(mat.m2-get-color-from-palette($tb-primary, 50), 0.6);
padding: 35px; padding: 35px;
&-container { &-container {

3
ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts

@ -126,8 +126,7 @@ export class StatesComponentDirective implements OnInit, OnDestroy, OnChanges {
} }
const stateControllerInstanceId = this.dashboardCtrl.dashboardCtx.instanceId + '_' + this.statesControllerId; const stateControllerInstanceId = this.dashboardCtrl.dashboardCtx.instanceId + '_' + this.statesControllerId;
const preservedState = this.statesControllerService.withdrawStateControllerState(stateControllerInstanceId); const preservedState = this.statesControllerService.withdrawStateControllerState(stateControllerInstanceId);
const stateControllerFactory = stateControllerData.factory; this.stateControllerComponentRef = this.viewContainerRef.createComponent(stateControllerData.component);
this.stateControllerComponentRef = this.viewContainerRef.createComponent(stateControllerFactory);
this.stateControllerComponent = this.stateControllerComponentRef.instance; this.stateControllerComponent = this.stateControllerComponentRef.instance;
this.dashboardCtrl.dashboardCtx.stateController = this.stateControllerComponent; this.dashboardCtrl.dashboardCtx.stateController = this.stateControllerComponent;
this.dashboardCtrl.dashboardCtx.stateChanged = this.stateChangedSubject.asObservable(); this.dashboardCtrl.dashboardCtx.stateChanged = this.stateChangedSubject.asObservable();

9
ui-ngx/src/app/modules/home/components/dashboard-page/states/states-controller.service.ts

@ -14,12 +14,12 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { ComponentFactory, ComponentFactoryResolver, Injectable, Type } from '@angular/core'; import { Injectable, Type } from '@angular/core';
import { deepClone } from '@core/utils'; import { deepClone } from '@core/utils';
import { IStateControllerComponent } from '@home/components/dashboard-page/states/state-controller.models'; import { IStateControllerComponent } from '@home/components/dashboard-page/states/state-controller.models';
export interface StateControllerData { export interface StateControllerData {
factory: ComponentFactory<IStateControllerComponent>; component: Type<IStateControllerComponent>;
} }
@Injectable() @Injectable()
@ -29,13 +29,12 @@ export class StatesControllerService {
statesControllerStates: {[stateControllerInstanceId: string]: any} = {}; statesControllerStates: {[stateControllerInstanceId: string]: any} = {};
constructor(private componentFactoryResolver: ComponentFactoryResolver) { constructor() {
} }
public registerStatesController(stateControllerId: string, stateControllerComponent: Type<IStateControllerComponent>): void { public registerStatesController(stateControllerId: string, stateControllerComponent: Type<IStateControllerComponent>): void {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(stateControllerComponent);
this.statesControllers[stateControllerId] = { this.statesControllers[stateControllerId] = {
factory: componentFactory component: stateControllerComponent
}; };
} }

6
ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, ComponentFactoryResolver, Inject, Injector, OnInit, SkipSelf, ViewChild } from '@angular/core'; import { Component, Inject, Injector, OnInit, SkipSelf, ViewChild } from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core'; import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
@ -55,7 +55,6 @@ export class AddEntityDialogComponent extends
protected router: Router, protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: AddEntityDialogData<BaseData<HasId>>, @Inject(MAT_DIALOG_DATA) public data: AddEntityDialogData<BaseData<HasId>>,
public dialogRef: MatDialogRef<AddEntityDialogComponent, BaseData<HasId>>, public dialogRef: MatDialogRef<AddEntityDialogComponent, BaseData<HasId>>,
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector, private injector: Injector,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher) { @SkipSelf() private errorStateMatcher: ErrorStateMatcher) {
super(store, router, dialogRef); super(store, router, dialogRef);
@ -66,7 +65,6 @@ export class AddEntityDialogComponent extends
this.translations = this.entitiesTableConfig.entityTranslations; this.translations = this.entitiesTableConfig.entityTranslations;
this.resources = this.entitiesTableConfig.entityResources; this.resources = this.entitiesTableConfig.entityResources;
this.entity = {}; this.entity = {};
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.entitiesTableConfig.entityComponent);
const viewContainerRef = this.entityDetailsFormAnchor.viewContainerRef; const viewContainerRef = this.entityDetailsFormAnchor.viewContainerRef;
viewContainerRef.clear(); viewContainerRef.clear();
const injector: Injector = Injector.create( const injector: Injector = Injector.create(
@ -84,7 +82,7 @@ export class AddEntityDialogComponent extends
parent: this.injector parent: this.injector
} }
); );
const componentRef = viewContainerRef.createComponent(componentFactory, 0, injector); const componentRef = viewContainerRef.createComponent(this.entitiesTableConfig.entityComponent, {index: 0, injector});
this.entityComponent = componentRef.instance; this.entityComponent = componentRef.instance;
this.entityComponent.isEdit = true; this.entityComponent.isEdit = true;
this.detailsForm = this.entityComponent.entityForm; this.detailsForm = this.entityComponent.entityForm;

5
ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts

@ -19,7 +19,6 @@ import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ComponentFactoryResolver,
ElementRef, ElementRef,
EventEmitter, EventEmitter,
Input, NgZone, Input, NgZone,
@ -140,7 +139,6 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
private domSanitizer: DomSanitizer, private domSanitizer: DomSanitizer,
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef,
private router: Router, private router: Router,
private componentFactoryResolver: ComponentFactoryResolver,
private elementRef: ElementRef, private elementRef: ElementRef,
private fb: FormBuilder, private fb: FormBuilder,
private zone: NgZone) { private zone: NgZone) {
@ -193,10 +191,9 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
this.entitiesTableConfig = entitiesTableConfig; this.entitiesTableConfig = entitiesTableConfig;
this.pageMode = this.entitiesTableConfig.pageMode; this.pageMode = this.entitiesTableConfig.pageMode;
if (this.entitiesTableConfig.headerComponent) { if (this.entitiesTableConfig.headerComponent) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.entitiesTableConfig.headerComponent);
const viewContainerRef = this.entityTableHeaderAnchor.viewContainerRef; const viewContainerRef = this.entityTableHeaderAnchor.viewContainerRef;
viewContainerRef.clear(); viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory); const componentRef = viewContainerRef.createComponent(this.entitiesTableConfig.headerComponent);
const headerComponent = componentRef.instance; const headerComponent = componentRef.instance;
headerComponent.entitiesTableConfig = this.entitiesTableConfig; headerComponent.entitiesTableConfig = this.entitiesTableConfig;
} }

5
ui-ngx/src/app/modules/home/components/entity/entity-details-page.component.ts

@ -18,7 +18,6 @@ import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ComponentFactoryResolver,
HostBinding, HostBinding,
Injector, Injector,
OnDestroy, OnDestroy,
@ -30,7 +29,6 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod
import { BaseData, HasId } from '@shared/models/base-data'; import { BaseData, HasId } from '@shared/models/base-data';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { UntypedFormGroup } from '@angular/forms'; import { UntypedFormGroup } from '@angular/forms';
import { AssetId } from '@shared/models/id/asset-id';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { deepClone } from '@core/utils'; import { deepClone } from '@core/utils';
import { BroadcastService } from '@core/services/broadcast.service'; import { BroadcastService } from '@core/services/broadcast.service';
@ -74,12 +72,11 @@ export class EntityDetailsPageComponent extends EntityDetailsPanelComponent impl
private router: Router, private router: Router,
protected injector: Injector, protected injector: Injector,
protected cd: ChangeDetectorRef, protected cd: ChangeDetectorRef,
protected componentFactoryResolver: ComponentFactoryResolver,
private broadcast: BroadcastService, private broadcast: BroadcastService,
private translate: TranslateService, private translate: TranslateService,
private dialogService: DialogService, private dialogService: DialogService,
protected store: Store<AppState>) { protected store: Store<AppState>) {
super(store, injector, cd, componentFactoryResolver); super(store, injector, cd);
this.entitiesTableConfig = this.route.snapshot.data.entitiesTableConfig; this.entitiesTableConfig = this.route.snapshot.data.entitiesTableConfig;
this.backNavigationCommands = this.route.snapshot.data.backNavigationCommands; this.backNavigationCommands = this.route.snapshot.data.backNavigationCommands;
} }

10
ui-ngx/src/app/modules/home/components/entity/entity-details-panel.component.ts

@ -19,7 +19,6 @@ import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ComponentFactoryResolver,
ComponentRef, ComponentRef,
EventEmitter, EventEmitter,
Injector, Injector,
@ -97,8 +96,7 @@ export class EntityDetailsPanelComponent extends PageComponent implements AfterV
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
protected injector: Injector, protected injector: Injector,
protected cd: ChangeDetectorRef, protected cd: ChangeDetectorRef) {
protected componentFactoryResolver: ComponentFactoryResolver) {
super(store); super(store);
} }
@ -167,7 +165,6 @@ export class EntityDetailsPanelComponent extends PageComponent implements AfterV
this.entityComponentRef.destroy(); this.entityComponentRef.destroy();
this.entityComponentRef = null; this.entityComponentRef = null;
} }
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.entitiesTableConfig.entityComponent);
const viewContainerRef = this.entityDetailsFormAnchor.viewContainerRef; const viewContainerRef = this.entityDetailsFormAnchor.viewContainerRef;
viewContainerRef.clear(); viewContainerRef.clear();
const injector: Injector = Injector.create( const injector: Injector = Injector.create(
@ -185,7 +182,7 @@ export class EntityDetailsPanelComponent extends PageComponent implements AfterV
parent: this.injector parent: this.injector
} }
); );
this.entityComponentRef = viewContainerRef.createComponent(componentFactory, 0, injector); this.entityComponentRef = viewContainerRef.createComponent(this.entitiesTableConfig.entityComponent, {index: 0, injector});
this.entityComponent = this.entityComponentRef.instance; this.entityComponent = this.entityComponentRef.instance;
this.entityComponent.isEdit = this.isEdit; this.entityComponent.isEdit = this.isEdit;
this.detailsForm = this.entityComponent.entityForm; this.detailsForm = this.entityComponent.entityForm;
@ -207,8 +204,7 @@ export class EntityDetailsPanelComponent extends PageComponent implements AfterV
viewContainerRef.clear(); viewContainerRef.clear();
this.entityTabsComponent = null; this.entityTabsComponent = null;
if (this.entitiesTableConfig.entityTabsComponent) { if (this.entitiesTableConfig.entityTabsComponent) {
const componentTabsFactory = this.componentFactoryResolver.resolveComponentFactory(this.entitiesTableConfig.entityTabsComponent); this.entityTabsComponentRef = viewContainerRef.createComponent(this.entitiesTableConfig.entityTabsComponent);
this.entityTabsComponentRef = viewContainerRef.createComponent(componentTabsFactory);
this.entityTabsComponent = this.entityTabsComponentRef.instance; this.entityTabsComponent = this.entityTabsComponentRef.instance;
this.entityTabsComponent.isEdit = this.isEdit; this.entityTabsComponent.isEdit = this.isEdit;
this.entityTabsComponent.entitiesTableConfig = this.entitiesTableConfig; this.entityTabsComponent.entitiesTableConfig = this.entitiesTableConfig;

2
ui-ngx/src/app/modules/home/components/notification/notification-bell.component.html

@ -16,5 +16,5 @@
--> -->
<button mat-icon-button #showNotificationButton (click)="showNotification($event, showNotificationButton)"> <button mat-icon-button #showNotificationButton (click)="showNotification($event, showNotificationButton)">
<mat-icon class="material-icons" [matBadge]="(count$ | async)" [matBadgeHidden]="!(count$ | async)" matBadgeColor="warn" matBadgeSize="small">notifications</mat-icon> <mat-icon class="material-icons" aria-hidden="false" [matBadge]="(count$ | async)" [matBadgeHidden]="!(count$ | async)" matBadgeColor="warn" matBadgeSize="small">notifications</mat-icon>
</button> </button>

19
ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts

@ -14,16 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { Component, Inject, ViewChild } from '@angular/core';
AfterViewInit,
Component,
ComponentFactoryResolver,
Inject,
Injector,
SkipSelf,
ViewChild
} from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
@ -68,7 +59,7 @@ export interface AddDeviceProfileDialogData {
styleUrls: ['./add-device-profile-dialog.component.scss'] styleUrls: ['./add-device-profile-dialog.component.scss']
}) })
export class AddDeviceProfileDialogComponent extends export class AddDeviceProfileDialogComponent extends
DialogComponent<AddDeviceProfileDialogComponent, DeviceProfile> implements AfterViewInit { DialogComponent<AddDeviceProfileDialogComponent, DeviceProfile> {
@ViewChild('addDeviceProfileStepper', {static: true}) addDeviceProfileStepper: MatStepper; @ViewChild('addDeviceProfileStepper', {static: true}) addDeviceProfileStepper: MatStepper;
stepperOrientation: Observable<StepperOrientation>; stepperOrientation: Observable<StepperOrientation>;
@ -105,10 +96,7 @@ export class AddDeviceProfileDialogComponent extends
protected router: Router, protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: AddDeviceProfileDialogData, @Inject(MAT_DIALOG_DATA) public data: AddDeviceProfileDialogData,
public dialogRef: MatDialogRef<AddDeviceProfileDialogComponent, DeviceProfile>, public dialogRef: MatDialogRef<AddDeviceProfileDialogComponent, DeviceProfile>,
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
private breakpointObserver: BreakpointObserver, private breakpointObserver: BreakpointObserver,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher,
private deviceProfileService: DeviceProfileService, private deviceProfileService: DeviceProfileService,
private fb: UntypedFormBuilder) { private fb: UntypedFormBuilder) {
super(store, router, dialogRef); super(store, router, dialogRef);
@ -162,9 +150,6 @@ export class AddDeviceProfileDialogComponent extends
{transportConfiguration: createDeviceProfileTransportConfiguration(deviceTransportType)}); {transportConfiguration: createDeviceProfileTransportConfiguration(deviceTransportType)});
} }
ngAfterViewInit(): void {
}
cancel(): void { cancel(): void {
this.dialogRef.close(null); this.dialogRef.close(null);
} }

14
ui-ngx/src/app/modules/home/components/profile/asset-profile-dialog.component.ts

@ -14,20 +14,12 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { AfterViewInit, Component, Inject, SkipSelf, ViewChild } from '@angular/core';
AfterViewInit,
Component,
ComponentFactoryResolver,
Inject,
Injector,
SkipSelf,
ViewChild
} from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core'; import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { UntypedFormControl, FormGroupDirective, NgForm } from '@angular/forms'; import { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { AssetProfile } from '@shared/models/asset.models'; import { AssetProfile } from '@shared/models/asset.models';
@ -59,8 +51,6 @@ export class AssetProfileDialogComponent extends
protected router: Router, protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: AssetProfileDialogData, @Inject(MAT_DIALOG_DATA) public data: AssetProfileDialogData,
public dialogRef: MatDialogRef<AssetProfileDialogComponent, AssetProfile>, public dialogRef: MatDialogRef<AssetProfileDialogComponent, AssetProfile>,
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher, @SkipSelf() private errorStateMatcher: ErrorStateMatcher,
private assetProfileService: AssetProfileService) { private assetProfileService: AssetProfileService) {
super(store, router, dialogRef); super(store, router, dialogRef);

14
ui-ngx/src/app/modules/home/components/profile/device-profile-dialog.component.ts

@ -14,20 +14,12 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { AfterViewInit, Component, Inject, SkipSelf, ViewChild } from '@angular/core';
AfterViewInit,
Component,
ComponentFactoryResolver,
Inject,
Injector,
SkipSelf,
ViewChild
} from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core'; import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { UntypedFormControl, FormGroupDirective, NgForm } from '@angular/forms'; import { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DeviceProfile } from '@shared/models/device.models'; import { DeviceProfile } from '@shared/models/device.models';
@ -59,8 +51,6 @@ export class DeviceProfileDialogComponent extends
protected router: Router, protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: DeviceProfileDialogData, @Inject(MAT_DIALOG_DATA) public data: DeviceProfileDialogData,
public dialogRef: MatDialogRef<DeviceProfileDialogComponent, DeviceProfile>, public dialogRef: MatDialogRef<DeviceProfileDialogComponent, DeviceProfile>,
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher, @SkipSelf() private errorStateMatcher: ErrorStateMatcher,
private deviceProfileService: DeviceProfileService) { private deviceProfileService: DeviceProfileService) {
super(store, router, dialogRef); super(store, router, dialogRef);

14
ui-ngx/src/app/modules/home/components/profile/tenant-profile-dialog.component.ts

@ -14,20 +14,12 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { AfterViewInit, Component, Inject, SkipSelf, ViewChild } from '@angular/core';
AfterViewInit,
Component,
ComponentFactoryResolver,
Inject,
Injector,
SkipSelf,
ViewChild
} from '@angular/core';
import { ErrorStateMatcher } from '@angular/material/core'; import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { UntypedFormControl, FormGroupDirective, NgForm } from '@angular/forms'; import { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { TenantProfile } from '@shared/models/tenant.model'; import { TenantProfile } from '@shared/models/tenant.model';
@ -59,8 +51,6 @@ export class TenantProfileDialogComponent extends
protected router: Router, protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: TenantProfileDialogData, @Inject(MAT_DIALOG_DATA) public data: TenantProfileDialogData,
public dialogRef: MatDialogRef<TenantProfileDialogComponent, TenantProfile>, public dialogRef: MatDialogRef<TenantProfileDialogComponent, TenantProfile>,
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher, @SkipSelf() private errorStateMatcher: ErrorStateMatcher,
private tenantProfileService: TenantProfileService) { private tenantProfileService: TenantProfileService) {
super(store, router, dialogRef); super(store, router, dialogRef);

2
ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts

@ -310,7 +310,7 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange
} }
}), }),
filter((value) => typeof value === 'string'), filter((value) => typeof value === 'string'),
map((value) => value ? (typeof value === 'string' ? value : value.name) : ''), map((value) => value ? value : ''),
mergeMap(name => this.fetchKeys(name) ), mergeMap(name => this.fetchKeys(name) ),
share() share()
); );

16
ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts

@ -15,15 +15,12 @@
/// ///
import { import {
AfterViewInit,
Component, Component,
ComponentFactoryResolver,
ComponentRef, ComponentRef,
forwardRef, forwardRef,
Input, Input,
OnChanges, OnChanges,
OnDestroy, OnDestroy,
OnInit,
SimpleChanges, SimpleChanges,
ViewChild, ViewChild,
ViewContainerRef ViewContainerRef
@ -49,7 +46,6 @@ import { Dashboard } from '@shared/models/dashboard.models';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { IAliasController } from '@core/api/widget-api.models'; import { IAliasController } from '@core/api/widget-api.models';
import { WidgetConfigComponentData } from '@home/models/widget-component.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models';
import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models';
import { WidgetConfigCallbacks } from '@home/components/widget/config/widget-config.component.models'; import { WidgetConfigCallbacks } from '@home/components/widget/config/widget-config.component.models';
@Component({ @Component({
@ -67,7 +63,7 @@ import { WidgetConfigCallbacks } from '@home/components/widget/config/widget-con
multi: true multi: true
}] }]
}) })
export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, OnDestroy, AfterViewInit, OnChanges, Validator { export class WidgetSettingsComponent implements ControlValueAccessor, OnDestroy, OnChanges, Validator {
@ViewChild('definedSettingsContent', {read: ViewContainerRef, static: true}) definedSettingsContainer: ViewContainerRef; @ViewChild('definedSettingsContent', {read: ViewContainerRef, static: true}) definedSettingsContainer: ViewContainerRef;
@ -106,7 +102,6 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On
private propagateChange = (_v: any) => { }; private propagateChange = (_v: any) => { };
constructor(private translate: TranslateService, constructor(private translate: TranslateService,
private cfr: ComponentFactoryResolver,
private widgetService: WidgetService, private widgetService: WidgetService,
private fb: UntypedFormBuilder) { private fb: UntypedFormBuilder) {
this.widgetSettingsFormGroup = this.fb.group({ this.widgetSettingsFormGroup = this.fb.group({
@ -121,9 +116,6 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On
registerOnTouched(fn: any): void { registerOnTouched(fn: any): void {
} }
ngOnInit(): void {
}
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
for (const propName of Object.keys(changes)) { for (const propName of Object.keys(changes)) {
const change = changes[propName]; const change = changes[propName];
@ -164,9 +156,6 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On
} }
} }
ngAfterViewInit(): void {
}
setDisabledState(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled; this.disabled = isDisabled;
if (this.disabled) { if (this.disabled) {
@ -232,8 +221,7 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On
this.changeSubscription = null; this.changeSubscription = null;
} }
this.definedSettingsContainer.clear(); this.definedSettingsContainer.clear();
const factory = this.cfr.resolveComponentFactory(componentType); this.definedSettingsComponentRef = this.definedSettingsContainer.createComponent(componentType);
this.definedSettingsComponentRef = this.definedSettingsContainer.createComponent(factory);
this.definedSettingsComponent = this.definedSettingsComponentRef.instance; this.definedSettingsComponent = this.definedSettingsComponentRef.instance;
this.definedSettingsComponent.aliasController = this.aliasController; this.definedSettingsComponent.aliasController = this.aliasController;
this.definedSettingsComponent.callbacks = this.callbacks; this.definedSettingsComponent.callbacks = this.callbacks;

14
ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.service.ts

@ -35,7 +35,7 @@ import {
@Injectable() @Injectable()
export class CustomDialogService { export class CustomDialogService {
private customModules: Array<Type<any>>; private customImports: Array<Type<any>>;
constructor( constructor(
private dynamicComponentFactoryService: DynamicComponentFactoryService, private dynamicComponentFactoryService: DynamicComponentFactoryService,
@ -47,19 +47,19 @@ export class CustomDialogService {
) { ) {
} }
setAdditionalModules(modules: Array<Type<any>>) { setAdditionalImports(imports: Array<Type<any>>) {
this.customModules = modules; this.customImports = imports;
} }
customDialog(template: string, controller: (instance: CustomDialogComponent) => void, data?: any, customDialog(template: string, controller: (instance: CustomDialogComponent) => void, data?: any,
config?: MatDialogConfig): Observable<any> { config?: MatDialogConfig): Observable<any> {
const modules = [this.sharedModule, CommonModule, this.sharedHomeComponentsModule, this.homeComponentsModule, const imports = [this.sharedModule, CommonModule, this.sharedHomeComponentsModule, this.homeComponentsModule,
this.widgetComponentsModule]; this.widgetComponentsModule];
if (Array.isArray(this.customModules)) { if (Array.isArray(this.customImports)) {
modules.push(...this.customModules); imports.push(...this.customImports);
} }
return this.dynamicComponentFactoryService.createDynamicComponent( return this.dynamicComponentFactoryService.createDynamicComponent(
class CustomDialogComponentInstance extends CustomDialogComponent {}, template, modules).pipe( class CustomDialogComponentInstance extends CustomDialogComponent {}, template, imports).pipe(
mergeMap((componentType) => { mergeMap((componentType) => {
const dialogData: CustomDialogContainerData = { const dialogData: CustomDialogContainerData = {
controller, controller,

10
ui-ngx/src/app/modules/home/components/widget/dialog/embed-dashboard-dialog.component.ts

@ -14,15 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { import { Component, Inject, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
Component,
ComponentFactoryResolver,
Inject,
Injector,
OnInit,
ViewChild,
ViewContainerRef
} from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';

8
ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts

@ -107,9 +107,9 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C
} }
let lowerLeft: number[]; let lowerLeft: number[];
if (offset !== 0 && isNumeric(value)) { if (offset !== 0 && isNumeric(value)) {
lowerLeft = api.coord([startTime, value >= 0 ? Number(value) + offset : offset]); lowerLeft = api.coord([startTime, Number(value) >= 0 ? Number(value) + offset : offset]);
} else { } else {
lowerLeft = api.coord([startTime, value >= 0 ? value : 0]); lowerLeft = api.coord([startTime, value]);
} }
const size = api.size([delta, value]); const size = api.size([delta, value]);
const width = size[0]; const width = size[0];
@ -140,7 +140,7 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C
if (renderCtx.labelOption.show) { if (renderCtx.labelOption.show) {
let position = renderCtx.labelOption.position; let position = renderCtx.labelOption.position;
if (value < 0) { if (Number(value) < 0) {
if (position === 'top') { if (position === 'top') {
position = 'bottom'; position = 'bottom';
} else if (position === 'bottom') { } else if (position === 'bottom') {
@ -164,7 +164,7 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C
} }
let borderRadius: number[]; let borderRadius: number[];
if (value < 0) { if (Number(value) < 0) {
borderRadius = [0, 0, renderCtx.visualSettings.borderRadius, renderCtx.visualSettings.borderRadius]; borderRadius = [0, 0, renderCtx.visualSettings.borderRadius, renderCtx.visualSettings.borderRadius];
} else { } else {
borderRadius = [renderCtx.visualSettings.borderRadius, renderCtx.visualSettings.borderRadius, 0, 0]; borderRadius = [renderCtx.visualSettings.borderRadius, renderCtx.visualSettings.borderRadius, 0, 0];

1
ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts

@ -1012,7 +1012,6 @@ export const createTimeSeriesXAxis = (id: string,
mainType: 'xAxis', mainType: 'xAxis',
show: settings.show, show: settings.show,
type: 'time', type: 'time',
scale: true,
position: settings.position, position: settings.position,
id, id,
name: utils.customTranslation(settings.label, settings.label), name: utils.customTranslation(settings.label, settings.label),

2
ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.component.ts

@ -41,7 +41,7 @@ import {
getFormattedDate getFormattedDate
} from '@home/components/widget/lib/date-range-navigator/date-range-navigator.models'; } from '@home/components/widget/lib/date-range-navigator/date-range-navigator.models';
import { KeyValue } from '@angular/common'; import { KeyValue } from '@angular/common';
import * as _moment from 'moment'; import _moment from 'moment';
import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay'; import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal'; import { ComponentPortal } from '@angular/cdk/portal';
import { MatSelect } from '@angular/material/select'; import { MatSelect } from '@angular/material/select';

2
ui-ngx/src/app/modules/home/components/widget/lib/date-range-navigator/date-range-navigator.models.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import * as _moment from 'moment'; import _moment from 'moment';
export type DateRangeInterval = 'hour' | 'day' | 'week' | 'twoWeeks' | 'month' | 'threeMonths' | 'sixMonths'; export type DateRangeInterval = 'hour' | 'day' | 'week' | 'twoWeeks' | 'month' | 'threeMonths' | 'sixMonths';

2
ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts

@ -54,7 +54,7 @@ import {
TbFlotTicksFormatterFunction, TbFlotTicksFormatterFunction,
TooltipValueFormatFunction TooltipValueFormatFunction
} from './flot-widget.models'; } from './flot-widget.models';
import * as moment_ from 'moment'; import moment_ from 'moment';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { AggregationType, IntervalMath } from '@shared/models/time/time.models'; import { AggregationType, IntervalMath } from '@shared/models/time/time.models';
import { CancelAnimationFrame } from '@core/services/raf.service'; import { CancelAnimationFrame } from '@core/services/raf.service';

7
ui-ngx/src/app/modules/home/components/widget/lib/maps/common-maps-utils.ts

@ -14,7 +14,6 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { MapProviders } from '@home/components/widget/lib/maps/map-models';
import { import {
createLabelFromDatasource, createLabelFromDatasource,
hashCode, hashCode,
@ -58,7 +57,7 @@ export function findAngle(startPoint: FormattedData, endPoint: FormattedData, la
} }
export function getDefCenterPosition(position): [number, number] { export function getDefCenterPosition(position: string | [number, number]): [number, number] {
if (typeof (position) === 'string') { if (typeof (position) === 'string') {
const parts = position.split(','); const parts = position.split(',');
if (parts.length === 2) { if (parts.length === 2) {
@ -258,8 +257,8 @@ export const parseWithTranslation = {
} }
}; };
export function functionValueCalculator(useFunction: boolean, func: (...args: any[]) => any, params = [], defaultValue: any) { export function functionValueCalculator<T>(useFunction: boolean, func: (...args: any[]) => any, params = [], defaultValue: T): T {
let res; let res: T;
if (useFunction && isDefined(func) && isFunction(func)) { if (useFunction && isDefined(func) && isFunction(func)) {
try { try {
res = func(...params); res = func(...params);

50
ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts

@ -14,10 +14,10 @@
/// limitations under the License. /// limitations under the License.
/// ///
import L, { FeatureGroup, LatLngBounds, LatLngTuple, Projection } from 'leaflet'; import L, { FeatureGroup, LatLngBounds, LatLngTuple, PointExpression, Projection } from 'leaflet';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import 'leaflet-providers'; import 'leaflet-providers';
import { MarkerClusterGroup, MarkerClusterGroupOptions } from 'leaflet.markercluster/dist/leaflet.markercluster'; import 'leaflet.markercluster';
import '@geoman-io/leaflet-geoman-free'; import '@geoman-io/leaflet-geoman-free';
import { import {
@ -41,7 +41,8 @@ import {
entitiesParseName, entitiesParseName,
isCutPolygon, isCutPolygon,
isJSON, isJSON,
isValidLatLng isValidLatLng,
LabelSettings
} from '@home/components/widget/lib/maps/maps-utils'; } from '@home/components/widget/lib/maps/maps-utils';
import { checkLngLat, createLoadingDiv } from '@home/components/widget/lib/maps/common-maps-utils'; import { checkLngLat, createLoadingDiv } from '@home/components/widget/lib/maps/common-maps-utils';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
@ -76,7 +77,7 @@ export default abstract class LeafletMap {
options: WidgetUnitedMapSettings; options: WidgetUnitedMapSettings;
bounds: L.LatLngBounds; bounds: L.LatLngBounds;
datasources: FormattedData[]; datasources: FormattedData[];
markersCluster: MarkerClusterGroup; markersCluster: L.MarkerClusterGroup;
points: FeatureGroup; points: FeatureGroup;
markersData: FormattedData[] = []; markersData: FormattedData[] = [];
polygonsData: FormattedData[] = []; polygonsData: FormattedData[] = [];
@ -99,9 +100,7 @@ export default abstract class LeafletMap {
selectedEntity: FormattedData; selectedEntity: FormattedData;
ignoreUpdateBounds = false; ignoreUpdateBounds = false;
initDragModeIgnoreUpdateBoundsSet = false; initDragModeIgnoreUpdateBoundsSet = false;
// eslint-disable-next-line @typescript-eslint/dot-notation
southWest = new L.LatLng(-Projection.SphericalMercator['MAX_LATITUDE'], -180); southWest = new L.LatLng(-Projection.SphericalMercator['MAX_LATITUDE'], -180);
// eslint-disable-next-line @typescript-eslint/dot-notation
northEast = new L.LatLng(Projection.SphericalMercator['MAX_LATITUDE'], 180); northEast = new L.LatLng(Projection.SphericalMercator['MAX_LATITUDE'], 180);
saveLocation: (e: FormattedData, values: {[key: string]: any}) => Observable<any>; saveLocation: (e: FormattedData, values: {[key: string]: any}) => Observable<any>;
saveMarkerLocation: (e: FormattedData, lat?: number, lng?: number) => Observable<any>; saveMarkerLocation: (e: FormattedData, lat?: number, lng?: number) => Observable<any>;
@ -109,7 +108,7 @@ export default abstract class LeafletMap {
translateService: TranslateService; translateService: TranslateService;
tooltipInstances: ITooltipsterInstance[] = []; tooltipInstances: ITooltipsterInstance[] = [];
clusteringSettings: MarkerClusterGroupOptions; clusteringSettings: L.MarkerClusterGroupOptions;
protected constructor(public ctx: WidgetContext, protected constructor(public ctx: WidgetContext,
public $container: HTMLElement, public $container: HTMLElement,
@ -185,13 +184,13 @@ export default abstract class LeafletMap {
if (markerClusteringSettings.maxZoom && markerClusteringSettings.maxZoom >= 0 && markerClusteringSettings.maxZoom < 19) { if (markerClusteringSettings.maxZoom && markerClusteringSettings.maxZoom >= 0 && markerClusteringSettings.maxZoom < 19) {
this.clusteringSettings.disableClusteringAtZoom = Math.floor(markerClusteringSettings.maxZoom); this.clusteringSettings.disableClusteringAtZoom = Math.floor(markerClusteringSettings.maxZoom);
} }
this.markersCluster = new MarkerClusterGroup(this.clusteringSettings); this.markersCluster = new L.MarkerClusterGroup(this.clusteringSettings);
} }
} }
private selectEntityWithoutLocationDialog(shapes: L.PM.SUPPORTED_SHAPES): Observable<FormattedData> { private selectEntityWithoutLocationDialog(shapes: L.PM.SUPPORTED_SHAPES): Observable<FormattedData> {
let entities; let entities: FormattedData[];
let labelSettings; let labelSettings: LabelSettings;
switch (shapes) { switch (shapes) {
case 'Polygon': case 'Polygon':
case 'Rectangle': case 'Rectangle':
@ -244,8 +243,8 @@ export default abstract class LeafletMap {
if (data !== null) { if (data !== null) {
this.selectedEntity = data; this.selectedEntity = data;
this.toggleDrawMode(type); this.toggleDrawMode(type);
let tooltipText; let tooltipText: string;
let customTranslation; let customTranslation: L.PM.Translations;
switch (type) { switch (type) {
case 'tbMarker': case 'tbMarker':
tooltipText = this.translateService.instant('widgets.maps.tooltips.placeMarker', {entityName: data.entityParseName}); tooltipText = this.translateService.instant('widgets.maps.tooltips.placeMarker', {entityName: data.entityParseName});
@ -310,7 +309,7 @@ export default abstract class LeafletMap {
this.map.pm.Toolbar.copyDrawControl('Marker', { this.map.pm.Toolbar.copyDrawControl('Marker', {
name: 'tbMarker', name: 'tbMarker',
afterClick: () => this.selectEntityWithoutLocation('tbMarker'), afterClick: () => this.selectEntityWithoutLocation('tbMarker'),
disabled: true, disabled: false,
actions actions
}); });
} }
@ -336,14 +335,14 @@ export default abstract class LeafletMap {
this.map.pm.Toolbar.copyDrawControl('Rectangle', { this.map.pm.Toolbar.copyDrawControl('Rectangle', {
name: 'tbRectangle', name: 'tbRectangle',
afterClick: () => this.selectEntityWithoutLocation('tbRectangle'), afterClick: () => this.selectEntityWithoutLocation('tbRectangle'),
disabled: true, disabled: false,
actions: rectangleActions actions: rectangleActions
}); });
this.map.pm.Toolbar.copyDrawControl('Polygon', { this.map.pm.Toolbar.copyDrawControl('Polygon', {
name: 'tbPolygon', name: 'tbPolygon',
afterClick: () => this.selectEntityWithoutLocation('tbPolygon'), afterClick: () => this.selectEntityWithoutLocation('tbPolygon'),
disabled: true, disabled: false,
actions: polygonActions actions: polygonActions
}); });
} }
@ -426,7 +425,7 @@ export default abstract class LeafletMap {
switch (e.shape) { switch (e.shape) {
case 'tbMarker': case 'tbMarker':
// @ts-ignore // @ts-ignore
this.saveLocation(this.selectedEntity, this.convertToCustomFormat(e.layer.getLatLng())).subscribe(() => {}); this.saveLocation(this.selectedEntity, this.convertToCustomFormat(e.marker.getLatLng())).subscribe(() => {});
break; break;
case 'tbRectangle': case 'tbRectangle':
case 'tbPolygon': case 'tbPolygon':
@ -567,8 +566,8 @@ export default abstract class LeafletMap {
} }
$(this.ctx.$container) $(this.ctx.$container)
.find('a[role="button"]:not(.leaflet-pm-action)') .find('a[role="button"]:not(.leaflet-pm-action)')
.each((index, element) => { .each((_index, element) => {
let title; let title: string;
if (element.title) { if (element.title) {
title = element.title; title = element.title;
$(element).removeAttr('title'); $(element).removeAttr('title');
@ -589,7 +588,12 @@ export default abstract class LeafletMap {
}, },
side: 'right', side: 'right',
distance: 2, distance: 2,
trackOrigin: true trackOrigin: true,
functionBefore: (instance, helper) => {
if (helper.origin.ariaDisabled === 'true' || helper.origin.parentElement.classList.contains('active')) {
return false;
}
},
} }
); );
this.tooltipInstances.push(tooltip.tooltipster('instance')); this.tooltipInstances.push(tooltip.tooltipster('instance'));
@ -623,7 +627,7 @@ export default abstract class LeafletMap {
return this.map.getCenter(); return this.map.getCenter();
} }
fitBounds(bounds: LatLngBounds, padding?: LatLngTuple) { fitBounds(bounds: LatLngBounds, padding?: PointExpression) {
if (bounds.isValid()) { if (bounds.isValid()) {
this.bounds = !!this.bounds ? this.bounds.extend(bounds) : bounds; this.bounds = !!this.bounds ? this.bounds.extend(bounds) : bounds;
if (!this.options.fitMapBounds && this.options.defaultZoomLevel) { if (!this.options.fitMapBounds && this.options.defaultZoomLevel) {
@ -669,7 +673,7 @@ export default abstract class LeafletMap {
return L.latLng(position.x, position.y) as L.LatLng; return L.latLng(position.x, position.y) as L.LatLng;
} }
convertPosition(data: FormattedData, dsData: FormattedData[]): L.LatLng { convertPosition(data: FormattedData, _dsData: FormattedData[]): L.LatLng {
const position = this.extractPosition(data); const position = this.extractPosition(data);
if (position) { if (position) {
return this.positionToLatLng(position); return this.positionToLatLng(position);
@ -1075,7 +1079,7 @@ export default abstract class LeafletMap {
} }
}); });
const toDelete: string[] = []; const toDelete: string[] = [];
this.polylines.forEach((v, mKey) => { this.polylines.forEach((_v, mKey) => {
if (!keys.includes(mKey)) { if (!keys.includes(mKey)) {
toDelete.push(mKey); toDelete.push(mKey);
} }
@ -1145,7 +1149,7 @@ export default abstract class LeafletMap {
} }
}); });
const toDelete: string[] = []; const toDelete: string[] = [];
this.polygons.forEach((v, mKey) => { this.polygons.forEach((_v, mKey) => {
if (!keys.includes(mKey)) { if (!keys.includes(mKey)) {
toDelete.push(mKey); toDelete.push(mKey);
} }

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts

@ -51,7 +51,7 @@ export interface CircleData {
export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
export type MarkerImageFunction = (data: FormattedData, markerImages: string[], export type MarkerImageFunction = (data: FormattedData, markerImages: string[],
dsData: FormattedData[], dsIndex: number) => MarkerImageInfo; dsData: FormattedData[], dsIndex: number) => MarkerImageInfo;
export type PosFunction = (origXPos, origYPos, data: FormattedData, export type PosFunction = (origXPos: number, origYPos: number, data: FormattedData,
dsData: FormattedData[], dsIndex: number, aspect: number) => { x: number, y: number }; dsData: FormattedData[], dsIndex: number, aspect: number) => { x: number, y: number };
export type MarkerIconReadyFunction = (icon: MarkerIconInfo) => void; export type MarkerIconReadyFunction = (icon: MarkerIconInfo) => void;

6
ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.interface.ts

@ -18,9 +18,9 @@ import LeafletMap from '@home/components/widget/lib/maps/leaflet-map';
export interface MapWidgetInterface { export interface MapWidgetInterface {
map?: LeafletMap; map?: LeafletMap;
resize(); resize(): void;
update(); update(): void;
destroy(); destroy(): void;
} }
export interface MapWidgetStaticInterface { export interface MapWidgetStaticInterface {

4
ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts

@ -150,7 +150,7 @@ export class MapWidgetController implements MapWidgetInterface {
} }
setMarkerLocation(e: FormattedData, lat?: number, lng?: number) { setMarkerLocation(e: FormattedData, lat?: number, lng?: number) {
let markerValue; let markerValue: {[p: string]: any};
if (isDefined(lat) && isDefined(lng)) { if (isDefined(lat) && isDefined(lng)) {
const point = lat != null && lng !== null ? L.latLng(lat, lng) : null; const point = lat != null && lng !== null ? L.latLng(lat, lng) : null;
markerValue = this.map.convertToCustomFormat(point); markerValue = this.map.convertToCustomFormat(point);
@ -169,7 +169,7 @@ export class MapWidgetController implements MapWidgetInterface {
} }
savePolygonLocation(e: FormattedData, coordinates?: Array<any>) { savePolygonLocation(e: FormattedData, coordinates?: Array<any>) {
let polygonValue; let polygonValue: {[p: string]: any};
if (isDefined(coordinates)) { if (isDefined(coordinates)) {
polygonValue = this.map.convertToPolygonFormat(coordinates); polygonValue = this.map.convertToPolygonFormat(coordinates);
} else { } else {

4
ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts

@ -87,14 +87,14 @@ export function isJSON(data: string): boolean {
} }
} }
interface labelSettings { export interface LabelSettings {
showLabel: boolean; showLabel: boolean;
useLabelFunction: boolean; useLabelFunction: boolean;
parsedLabelFunction: GenericFunction; parsedLabelFunction: GenericFunction;
label: string; label: string;
} }
export function entitiesParseName(entities: FormattedData[], labelSettings: labelSettings): FormattedData[] { export function entitiesParseName(entities: FormattedData[], labelSettings: LabelSettings): FormattedData[] {
const div = document.createElement('div'); const div = document.createElement('div');
for (const entity of entities) { for (const entity of entities) {
if (labelSettings?.showLabel) { if (labelSettings?.showLabel) {

18
ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts

@ -30,7 +30,7 @@ export class Marker {
private editing = false; private editing = false;
leafletMarker: L.Marker; leafletMarker: L.Marker;
labelOffset: L.LatLngTuple; labelOffset: L.PointTuple;
tooltipOffset: L.LatLngTuple; tooltipOffset: L.LatLngTuple;
markerOffset: L.LatLngTuple; markerOffset: L.LatLngTuple;
tooltip: L.Popup; tooltip: L.Popup;
@ -40,10 +40,10 @@ export class Marker {
private location: L.LatLng, private location: L.LatLng,
private settings: Partial<WidgetMarkersSettings>, private settings: Partial<WidgetMarkersSettings>,
private data?: FormattedData, private data?: FormattedData,
private dataSources?, private dataSources?: FormattedData[],
private onDragendListener?, private onDragendListener?,
snappable = false) { snappable = false) {
this.leafletMarker = L.marker(location, { this.leafletMarker = L.marker(this.location, {
pmIgnore: !settings.draggableMarker, pmIgnore: !settings.draggableMarker,
snapIgnore: !snappable, snapIgnore: !snappable,
tbMarkerData: this.data tbMarkerData: this.data
@ -78,7 +78,7 @@ export class Marker {
} }
if (settings.draggableMarker && onDragendListener) { if (settings.draggableMarker && onDragendListener) {
this.leafletMarker.on('pm:dragstart', (e) => { this.leafletMarker.on('pm:dragstart', () => {
(this.leafletMarker.dragging as any)._draggable = { _moved: true }; (this.leafletMarker.dragging as any)._draggable = { _moved: true };
(this.leafletMarker.dragging as any)._enabled = true; (this.leafletMarker.dragging as any)._enabled = true;
this.editing = true; this.editing = true;
@ -134,7 +134,7 @@ export class Marker {
} }
} }
updateMarkerColor(color) { updateMarkerColor(color: tinycolor.Instance) {
this.createDefaultMarkerIcon(color, (iconInfo) => { this.createDefaultMarkerIcon(color, (iconInfo) => {
this.leafletMarker.setIcon(iconInfo.icon); this.leafletMarker.setIcon(iconInfo.icon);
}); });
@ -179,8 +179,8 @@ export class Marker {
loadImageWithAspect(this.map.ctx.$injector.get(ImagePipe), currentImage.url).subscribe( loadImageWithAspect(this.map.ctx.$injector.get(ImagePipe), currentImage.url).subscribe(
(aspectImage) => { (aspectImage) => {
if (aspectImage?.aspect) { if (aspectImage?.aspect) {
let width; let width: number;
let height; let height: number;
if (aspectImage.aspect > 1) { if (aspectImage.aspect > 1) {
width = currentImage.size; width = currentImage.size;
height = currentImage.size / aspectImage.aspect; height = currentImage.size / aspectImage.aspect;
@ -263,7 +263,7 @@ export class Marker {
this.leafletMarker.addTo(map))*/ this.leafletMarker.addTo(map))*/
} }
extendBoundsWithMarker(bounds) { extendBoundsWithMarker(bounds: L.LatLngBounds) {
bounds.extend(this.leafletMarker.getLatLng()); bounds.extend(this.leafletMarker.getLatLng());
} }
@ -271,7 +271,7 @@ export class Marker {
return this.leafletMarker.getLatLng(); return this.leafletMarker.getLatLng();
} }
setMarkerPosition(latLng) { setMarkerPosition(latLng: L.LatLngExpression) {
this.leafletMarker.setLatLng(latLng); this.leafletMarker.setLatLng(latLng);
} }
} }

12
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/google-map.ts

@ -31,7 +31,7 @@ interface GmGlobal {
export class GoogleMap extends LeafletMap { export class GoogleMap extends LeafletMap {
private resource: ResourcesService; private resource: ResourcesService;
constructor(ctx: WidgetContext, $container, options: WidgetUnitedMapSettings) { constructor(ctx: WidgetContext, $container: HTMLElement, options: WidgetUnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
this.resource = ctx.$injector.get(ResourcesService); this.resource = ctx.$injector.get(ResourcesService);
this.loadGoogle(() => { this.loadGoogle(() => {
@ -47,20 +47,20 @@ export class GoogleMap extends LeafletMap {
}, options.gmApiKey); }, options.gmApiKey);
} }
private loadGoogle(callback, apiKey = 'AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q') { private loadGoogle(callback: () => void, apiKey = 'AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q') {
if (gmGlobals[apiKey]) { if (gmGlobals[apiKey]) {
callback(); callback();
} else { } else {
this.resource.loadResource(`https://maps.googleapis.com/maps/api/js?key=${apiKey}`).subscribe( this.resource.loadResource(`https://maps.googleapis.com/maps/api/js?key=${apiKey}`).subscribe({
() => { next: () => {
gmGlobals[apiKey] = true; gmGlobals[apiKey] = true;
callback(); callback();
}, },
(error) => { error: (error) => {
gmGlobals[apiKey] = false; gmGlobals[apiKey] = false;
console.error(`Google map api load failed!`, error); console.error(`Google map api load failed!`, error);
} }
); });
} }
} }
} }

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/here-map.ts

@ -21,7 +21,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
import { isDefinedAndNotNull } from '@core/utils'; import { isDefinedAndNotNull } from '@core/utils';
export class HEREMap extends LeafletMap { export class HEREMap extends LeafletMap {
constructor(ctx: WidgetContext, $container, options: WidgetUnitedMapSettings) { constructor(ctx: WidgetContext, $container: HTMLElement, options: WidgetUnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
const map = L.map($container, { const map = L.map($container, {
doubleClickZoom: !this.options.disableDoubleClickZooming, doubleClickZoom: !this.options.disableDoubleClickZooming,

22
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import L, { LatLngBounds, LatLngLiteral, LatLngTuple } from 'leaflet'; import L, { LatLngBounds, LatLngLiteral, LatLngTuple, PointExpression } from 'leaflet';
import LeafletMap from '../leaflet-map'; import LeafletMap from '../leaflet-map';
import { import {
CircleData, CircleData,
@ -24,10 +24,8 @@ import {
WidgetUnitedMapSettings WidgetUnitedMapSettings
} from '../map-models'; } from '../map-models';
import { Observable, of, ReplaySubject, switchMap } from 'rxjs'; import { Observable, of, ReplaySubject, switchMap } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators'; import { catchError } from 'rxjs/operators';
import { import { calculateNewPointCoordinate, loadImageWithAspect } from '@home/components/widget/lib/maps/common-maps-utils';
calculateNewPointCoordinate, loadImageWithAspect
} from '@home/components/widget/lib/maps/common-maps-utils';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { DataSet, DatasourceType, FormattedData, widgetType } from '@shared/models/widget.models'; import { DataSet, DatasourceType, FormattedData, widgetType } from '@shared/models/widget.models';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
@ -135,7 +133,7 @@ export class ImageMap extends LeafletMap {
} }
} }
), ),
catchError((e) => this.imageFromUrl(defaultImageMapProviderSettings.mapImageUrl)) catchError(() => this.imageFromUrl(defaultImageMapProviderSettings.mapImageUrl))
); );
} }
@ -158,13 +156,13 @@ export class ImageMap extends LeafletMap {
return this.imageFromUrl(defaultImageMapProviderSettings.mapImageUrl); return this.imageFromUrl(defaultImageMapProviderSettings.mapImageUrl);
} }
}), }),
catchError((e) => this.imageFromUrl(defaultImageMapProviderSettings.mapImageUrl)) catchError(() => this.imageFromUrl(defaultImageMapProviderSettings.mapImageUrl))
); );
}) })
); );
} }
updateBounds(updateImage?: boolean, lastCenterPos?) { updateBounds(updateImage?: boolean, lastCenterPos?: L.Point) {
const w = this.width; const w = this.width;
const h = this.height; const h = this.height;
this.southWest = this.pointToLatLng(0, h); this.southWest = this.pointToLatLng(0, h);
@ -233,7 +231,7 @@ export class ImageMap extends LeafletMap {
} }
} }
fitBounds(bounds: LatLngBounds, padding?: LatLngTuple) { } fitBounds(_bounds: LatLngBounds, _padding?: PointExpression) { }
initMap(updateImage?: boolean) { initMap(updateImage?: boolean) {
if (!this.map && this.aspect > 0) { if (!this.map && this.aspect > 0) {
@ -271,7 +269,7 @@ export class ImageMap extends LeafletMap {
position.y * this.height); position.y * this.height);
} }
convertPosition(data, dsData: FormattedData[]): L.LatLng { convertPosition(data: FormattedData, dsData: FormattedData[]): L.LatLng {
const position = this.extractPosition(data); const position = this.extractPosition(data);
if (position) { if (position) {
const converted = this.posFunction(position.x, position.y, data, dsData, data.dsIndex, this.aspect) || {x: 0, y: 0}; const converted = this.posFunction(position.x, position.y, data, dsData, data.dsIndex, this.aspect) || {x: 0, y: 0};
@ -296,7 +294,7 @@ export class ImageMap extends LeafletMap {
}).filter(el => !!el); }).filter(el => !!el);
} }
pointToLatLng(x, y): L.LatLng { pointToLatLng(x: number, y: number): L.LatLng {
return L.CRS.Simple.pointToLatLng({ x, y } as L.PointExpression, maxZoom - 1); return L.CRS.Simple.pointToLatLng({ x, y } as L.PointExpression, maxZoom - 1);
} }
@ -304,7 +302,7 @@ export class ImageMap extends LeafletMap {
return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1); return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1);
} }
convertToCustomFormat(position: L.LatLng, offset = 0, width = this.width, height = this.height): {[key: string]: any} { convertToCustomFormat(position: L.LatLng, _offset = 0, width = this.width, height = this.height): {[key: string]: any} {
if (!position) { if (!position) {
return { return {
[this.options.xPosKeyName]: null, [this.options.xPosKeyName]: null,

6
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/openstreet-map.ts

@ -20,17 +20,17 @@ import { DEFAULT_ZOOM_LEVEL, WidgetUnitedMapSettings } from '../map-models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
export class OpenStreetMap extends LeafletMap { export class OpenStreetMap extends LeafletMap {
constructor(ctx: WidgetContext, $container, options: WidgetUnitedMapSettings) { constructor(ctx: WidgetContext, $container: HTMLElement, options: WidgetUnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
const map = L.map($container, { const map = L.map($container, {
doubleClickZoom: !this.options.disableDoubleClickZooming, doubleClickZoom: !this.options.disableDoubleClickZooming,
zoomControl: !this.options.disableZoomControl zoomControl: !this.options.disableZoomControl
}).setView(options?.parsedDefaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL); }).setView(options?.parsedDefaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
let tileLayer; let tileLayer: L.TileLayer;
if (options.useCustomProvider) { if (options.useCustomProvider) {
tileLayer = L.tileLayer(options.customProviderTileUrl); tileLayer = L.tileLayer(options.customProviderTileUrl);
} else { } else {
tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik'); tileLayer = L.tileLayer.provider(options.mapProvider || 'OpenStreetMap.Mapnik');
} }
tileLayer.addTo(map); tileLayer.addTo(map);
super.setMap(map); super.setMap(map);

6
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/tencent-map.ts

@ -21,9 +21,9 @@ import { DEFAULT_ZOOM_LEVEL, WidgetUnitedMapSettings } from '../map-models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
export class TencentMap extends LeafletMap { export class TencentMap extends LeafletMap {
constructor(ctx: WidgetContext, $container, options: WidgetUnitedMapSettings) { constructor(ctx: WidgetContext, $container: HTMLElement, options: WidgetUnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0'; const txUrl = 'https://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0';
const map = L.map($container, { const map = L.map($container, {
doubleClickZoom: !this.options.disableDoubleClickZooming, doubleClickZoom: !this.options.disableDoubleClickZooming,
zoomControl: !this.options.disableZoomControl zoomControl: !this.options.disableZoomControl
@ -31,7 +31,7 @@ export class TencentMap extends LeafletMap {
const txLayer = L.tileLayer(txUrl, { const txLayer = L.tileLayer(txUrl, {
subdomains: '0123', subdomains: '0123',
tms: true, tms: true,
attribution: '&copy;2021 Tencent - GS(2020)2236号- Data&copy; NavInfo' attribution: '&copy;2024 Tencent - GS(2023)1171号'
}).addTo(map); }).addTo(map);
txLayer.addTo(map); txLayer.addTo(map);
super.setMap(map); super.setMap(map);

2
ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts

@ -33,7 +33,7 @@ import {
isUndefined isUndefined
} from '@core/utils'; } from '@core/utils';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import * as _moment from 'moment'; import _moment from 'moment';
import { UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators } from '@angular/forms';
import { RequestConfig } from '@core/http/http-utils'; import { RequestConfig } from '@core/http/http-utils';
import { AttributeService } from '@core/http/attribute.service'; import { AttributeService } from '@core/http/attribute.service';

11
ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { AfterViewInit, Component, ElementRef, Input, OnDestroy, ViewChild } from '@angular/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
@ -55,11 +55,11 @@ interface SwitchSettings {
templateUrl: './switch.component.html', templateUrl: './switch.component.html',
styleUrls: ['./switch.component.scss'] styleUrls: ['./switch.component.scss']
}) })
export class SwitchComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy { export class SwitchComponent extends PageComponent implements AfterViewInit, OnDestroy {
@ViewChild('switch', {static: false}) switchElementRef: ElementRef<HTMLElement>; @ViewChild('switch', {static: false}) switchElementRef: ElementRef<HTMLElement>;
@ViewChild('switchContainer', {static: false}) switchContainerRef: ElementRef<HTMLElement>; @ViewChild('switchContainer', {static: false}) switchContainerRef: ElementRef<HTMLElement>;
@ViewChild('matSlideToggle', {static: false}) matSlideToggleRef: MatSlideToggle; @ViewChild('matSlideToggle', {static: false, read: ElementRef}) matSlideToggleRef: ElementRef<HTMLElement>;
@ViewChild('onoffContainer', {static: false}) onoffContainerRef: ElementRef<HTMLElement>; @ViewChild('onoffContainer', {static: false}) onoffContainerRef: ElementRef<HTMLElement>;
@ViewChild('onLabel', {static: false}) onLabelRef: ElementRef<HTMLElement>; @ViewChild('onLabel', {static: false}) onLabelRef: ElementRef<HTMLElement>;
@ViewChild('offLabel', {static: false}) offLabelRef: ElementRef<HTMLElement>; @ViewChild('offLabel', {static: false}) offLabelRef: ElementRef<HTMLElement>;
@ -119,14 +119,11 @@ export class SwitchComponent extends PageComponent implements OnInit, AfterViewI
super(store); super(store);
} }
ngOnInit(): void {
}
ngAfterViewInit() { ngAfterViewInit() {
if (this.switchType === 'switch') { if (this.switchType === 'switch') {
this.switchElement = $(this.switchElementRef.nativeElement); this.switchElement = $(this.switchElementRef.nativeElement);
this.switchContainer = $(this.switchContainerRef.nativeElement); this.switchContainer = $(this.switchContainerRef.nativeElement);
this.matSlideToggle = $(this.matSlideToggleRef._elementRef.nativeElement); this.matSlideToggle = $(this.matSlideToggleRef.nativeElement);
this.onoffContainer = $(this.onoffContainerRef.nativeElement); this.onoffContainer = $(this.onoffContainerRef.nativeElement);
this.onLabel = $(this.onLabelRef.nativeElement); this.onLabel = $(this.onLabelRef.nativeElement);
this.offLabel = $(this.offLabelRef.nativeElement); this.offLabel = $(this.offLabelRef.nativeElement);

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html

@ -17,7 +17,7 @@
--> -->
<ng-container [formGroup]="axisSettingsFormGroup"> <ng-container [formGroup]="axisSettingsFormGroup">
<div class="tb-form-panel stroked tb-slide-toggle"> <div class="tb-form-panel stroked tb-slide-toggle">
<mat-expansion-panel class="tb-settings" [(expanded)]="alwaysExpanded || settingsExpanded" <mat-expansion-panel class="tb-settings" [expanded]="alwaysExpanded || settingsExpanded"
[disabled]="alwaysExpanded || !axisSettingsFormGroup.get('show').value"> [disabled]="alwaysExpanded || !axisSettingsFormGroup.get('show').value">
<mat-expansion-panel-header fxLayout="row wrap"> <mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title> <mat-panel-title>

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.ts

@ -194,7 +194,7 @@ export class DataKeyInputComponent implements ControlValueAccessor, OnInit, OnCh
} }
}), }),
filter((value) => typeof value === 'string'), filter((value) => typeof value === 'string'),
map((value) => value ? (typeof value === 'string' ? value : value.name) : ''), map((value) => value ? value : ''),
mergeMap(name => this.fetchKeys(name) ), mergeMap(name => this.fetchKeys(name) ),
share() share()
); );

58
ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { ComponentFactory, Inject, Injectable, Optional, Type } from '@angular/core'; import { Inject, Injectable, Optional, Type } from '@angular/core';
import { DynamicComponentFactoryService } from '@core/services/dynamic-component-factory.service'; import { DynamicComponentFactoryService } from '@core/services/dynamic-component-factory.service';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { forkJoin, from, Observable, of, ReplaySubject, Subject, throwError } from 'rxjs'; import { forkJoin, from, Observable, of, ReplaySubject, Subject, throwError } from 'rxjs';
@ -28,7 +28,13 @@ import {
} from '@home/models/widget-component.models'; } from '@home/models/widget-component.models';
import cssjs from '@core/css/css'; import cssjs from '@core/css/css';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { ModulesWithFactories, ResourcesService } from '@core/services/resources.service'; import {
componentTypeBySelector,
flatModulesWithComponents,
ModulesWithComponents,
modulesWithComponentsToTypes,
ResourcesService
} from '@core/services/resources.service';
import { import {
IWidgetSettingsComponent, IWidgetSettingsComponent,
Widget, Widget,
@ -55,7 +61,6 @@ import { HOME_COMPONENTS_MODULE_TOKEN } from '@home/components/tokens';
import { widgetSettingsComponentsMap } from '@home/components/widget/lib/settings/widget-settings.module'; import { widgetSettingsComponentsMap } from '@home/components/widget/lib/settings/widget-settings.module';
import { basicWidgetConfigComponentsMap } from '@home/components/widget/config/basic/basic-widget-config.module'; import { basicWidgetConfigComponentsMap } from '@home/components/widget/config/basic/basic-widget-config.module';
import { IBasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models'; import { IBasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models';
import { TbTimeSeriesChart } from '@home/components/widget/lib/chart/time-series-chart';
@Injectable() @Injectable()
export class WidgetComponentService { export class WidgetComponentService {
@ -323,12 +328,12 @@ export class WidgetComponentService {
this.cssParser.cssPreviewNamespace = widgetNamespace; this.cssParser.cssPreviewNamespace = widgetNamespace;
this.cssParser.createStyleElement(widgetNamespace, widgetInfo.templateCss); this.cssParser.createStyleElement(widgetNamespace, widgetInfo.templateCss);
const resourceTasks: Observable<string>[] = []; const resourceTasks: Observable<string>[] = [];
const modulesTasks: Observable<ModulesWithFactories | string>[] = []; const modulesTasks: Observable<ModulesWithComponents | string>[] = [];
if (widgetInfo.resources.length > 0) { if (widgetInfo.resources.length > 0) {
widgetInfo.resources.filter(r => r.isModule).forEach( widgetInfo.resources.filter(r => r.isModule).forEach(
(resource) => { (resource) => {
modulesTasks.push( modulesTasks.push(
this.resources.loadFactories(resource.url, this.modulesMap).pipe( this.resources.loadModulesWithComponents(resource.url, this.modulesMap).pipe(
catchError((e: Error) => of(e?.message ? e.message : `Failed to load widget resource module: '${resource.url}'`)) catchError((e: Error) => of(e?.message ? e.message : `Failed to load widget resource module: '${resource.url}'`))
) )
); );
@ -345,7 +350,7 @@ export class WidgetComponentService {
} }
); );
let modulesObservable: Observable<string | ModulesWithFactories>; let modulesObservable: Observable<string | ModulesWithComponents>;
if (modulesTasks.length) { if (modulesTasks.length) {
modulesObservable = forkJoin(modulesTasks).pipe( modulesObservable = forkJoin(modulesTasks).pipe(
map(res => { map(res => {
@ -353,20 +358,13 @@ export class WidgetComponentService {
if (msg) { if (msg) {
return msg as string; return msg as string;
} else { } else {
const modulesWithFactoriesList = res as ModulesWithFactories[]; const modulesWithComponentsList = res as ModulesWithComponents[];
const resModulesWithFactories: ModulesWithFactories = { return flatModulesWithComponents(modulesWithComponentsList);
modules: modulesWithFactoriesList.map(mf => mf.modules).flat(),
factories: modulesWithFactoriesList.map(mf => mf.factories).flat()
};
if (modules && modules.length) {
resModulesWithFactories.modules = resModulesWithFactories.modules.concat(modules);
}
return resModulesWithFactories;
} }
}) })
); );
} else { } else {
modulesObservable = modules && modules.length ? of({modules, factories: []}) : of({modules: [], factories: []}); modulesObservable = of({modules: [], standaloneComponents: []});
} }
resourceTasks.push( resourceTasks.push(
@ -375,11 +373,15 @@ export class WidgetComponentService {
if (typeof resolvedModules === 'string') { if (typeof resolvedModules === 'string') {
return of(resolvedModules); return of(resolvedModules);
} else { } else {
this.registerWidgetSettingsForms(widgetInfo, resolvedModules.factories); this.registerWidgetSettingsForms(widgetInfo, resolvedModules);
let imports = modulesWithComponentsToTypes(resolvedModules);
if (modules && modules.length) {
imports = imports.concat(modules);
}
return this.dynamicComponentFactoryService.createDynamicComponent( return this.dynamicComponentFactoryService.createDynamicComponent(
class DynamicWidgetComponentInstance extends DynamicWidgetComponent {}, class DynamicWidgetComponentInstance extends DynamicWidgetComponent {},
widgetInfo.templateHtml, widgetInfo.templateHtml,
resolvedModules.modules imports
).pipe( ).pipe(
map((componentType) => { map((componentType) => {
widgetInfo.componentType = componentType; widgetInfo.componentType = componentType;
@ -401,7 +403,7 @@ export class WidgetComponentService {
errors = msgs.filter(msg => msg && msg.length > 0); errors = msgs.filter(msg => msg && msg.length > 0);
} }
if (errors && errors.length) { if (errors && errors.length) {
return throwError(errors); return throwError(() => errors);
} else { } else {
return of(null); return of(null);
} }
@ -409,7 +411,7 @@ export class WidgetComponentService {
)); ));
} }
private registerWidgetSettingsForms(widgetInfo: WidgetInfo, factories: ComponentFactory<any>[]) { private registerWidgetSettingsForms(widgetInfo: WidgetInfo, modulesWithComponents: ModulesWithComponents) {
const directives: string[] = []; const directives: string[] = [];
const basicDirectives: string[] = []; const basicDirectives: string[] = [];
if (widgetInfo.settingsDirective && widgetInfo.settingsDirective.length) { if (widgetInfo.settingsDirective && widgetInfo.settingsDirective.length) {
@ -425,17 +427,19 @@ export class WidgetComponentService {
basicDirectives.push(widgetInfo.basicModeDirective); basicDirectives.push(widgetInfo.basicModeDirective);
} }
this.expandSettingComponentMap(widgetSettingsComponentsMap, directives, factories); this.expandSettingComponentMap(widgetSettingsComponentsMap, directives, modulesWithComponents);
this.expandSettingComponentMap(basicWidgetConfigComponentsMap, basicDirectives, factories); this.expandSettingComponentMap(basicWidgetConfigComponentsMap, basicDirectives, modulesWithComponents);
} }
private expandSettingComponentMap(settingsComponentsMap: {[key: string]: Type<IWidgetSettingsComponent | IBasicWidgetConfigComponent>}, private expandSettingComponentMap(settingsComponentsMap: {[key: string]: Type<IWidgetSettingsComponent | IBasicWidgetConfigComponent>},
directives: string[], factories: ComponentFactory<any>[]): void { directives: string[], modulesWithComponents: ModulesWithComponents): void {
if (directives.length) { if (directives.length) {
factories.filter((factory) => directives.includes(factory.selector)) directives.forEach(selector => {
.forEach((foundFactory) => { const compType = componentTypeBySelector(modulesWithComponents, selector);
settingsComponentsMap[foundFactory.selector] = foundFactory.componentType; if (compType) {
}); settingsComponentsMap[selector] = compType;
}
});
} }
} }

5
ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts

@ -17,7 +17,6 @@
import { import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ComponentFactoryResolver,
ComponentRef, ComponentRef,
forwardRef, forwardRef,
Input, Input,
@ -212,7 +211,6 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
private entityService: EntityService, private entityService: EntityService,
private dialog: MatDialog, private dialog: MatDialog,
public translate: TranslateService, public translate: TranslateService,
private cfr: ComponentFactoryResolver,
private fb: UntypedFormBuilder, private fb: UntypedFormBuilder,
private cd: ChangeDetectorRef) { private cd: ChangeDetectorRef) {
super(store); super(store);
@ -444,10 +442,9 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
this.basicModeDirectiveError = this.translate.instant('widget-config.settings-component-not-found', this.basicModeDirectiveError = this.translate.instant('widget-config.settings-component-not-found',
{selector: this.modelValue.basicModeDirective}); {selector: this.modelValue.basicModeDirective});
} else { } else {
const factory = this.cfr.resolveComponentFactory(componentType);
this.createBasicModeComponentTimeout = setTimeout(() => { this.createBasicModeComponentTimeout = setTimeout(() => {
this.createBasicModeComponentTimeout = null; this.createBasicModeComponentTimeout = null;
this.basicModeComponentRef = this.basicModeContainer.createComponent(factory); this.basicModeComponentRef = this.basicModeContainer.createComponent(componentType);
this.basicModeComponent = this.basicModeComponentRef.instance; this.basicModeComponent = this.basicModeComponentRef.instance;
this.basicModeComponent.isAdd = isAdd; this.basicModeComponent.isAdd = isAdd;
this.basicModeComponent.widgetConfig = this.modelValue; this.basicModeComponent.widgetConfig = this.modelValue;

45
ui-ngx/src/app/modules/home/components/widget/widget.component.ts

@ -15,7 +15,6 @@
/// ///
import { import {
AfterViewInit,
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
@ -39,7 +38,8 @@ import {
} from '@angular/core'; } from '@angular/core';
import { DashboardWidget } from '@home/models/dashboard-component.models'; import { DashboardWidget } from '@home/models/dashboard-component.models';
import { import {
Widget, WidgetAction, Widget,
WidgetAction,
WidgetActionDescriptor, WidgetActionDescriptor,
widgetActionSources, widgetActionSources,
WidgetActionType, WidgetActionType,
@ -57,7 +57,8 @@ import { WidgetService } from '@core/http/widget.service';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { forkJoin, Observable, of, ReplaySubject, Subscription, throwError } from 'rxjs'; import { forkJoin, Observable, of, ReplaySubject, Subscription, throwError } from 'rxjs';
import { import {
deepClone, guid, deepClone,
guid,
insertVariable, insertVariable,
isDefined, isDefined,
isNotEmptyStr, isNotEmptyStr,
@ -87,7 +88,12 @@ import {
import { EntityId } from '@shared/models/id/entity-id'; import { EntityId } from '@shared/models/id/entity-id';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import cssjs from '@core/css/css'; import cssjs from '@core/css/css';
import { ModulesWithFactories, ResourcesService } from '@core/services/resources.service'; import {
flatModulesWithComponents,
ModulesWithComponents,
modulesWithComponentsToTypes,
ResourcesService
} from '@core/services/resources.service';
import { catchError, map, switchMap } from 'rxjs/operators'; import { catchError, map, switchMap } from 'rxjs/operators';
import { ActionNotificationShow } from '@core/notification/notification.actions'; import { ActionNotificationShow } from '@core/notification/notification.actions';
import { TimeService } from '@core/services/time.service'; import { TimeService } from '@core/services/time.service';
@ -122,7 +128,7 @@ import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class WidgetComponent extends PageComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy { export class WidgetComponent extends PageComponent implements OnInit, OnChanges, OnDestroy {
@Input() @Input()
widgetTitlePanel: TemplateRef<any>; widgetTitlePanel: TemplateRef<any>;
@ -326,9 +332,6 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
} }
} }
ngAfterViewInit(): void {
}
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
for (const propName of Object.keys(changes)) { for (const propName of Object.keys(changes)) {
const change = changes[propName]; const change = changes[propName];
@ -1129,7 +1132,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
} }
const customActionPrettyFunction = new Function('$event', 'widgetContext', 'entityId', const customActionPrettyFunction = new Function('$event', 'widgetContext', 'entityId',
'entityName', 'htmlTemplate', 'additionalParams', 'entityLabel', customPrettyFunction); 'entityName', 'htmlTemplate', 'additionalParams', 'entityLabel', customPrettyFunction);
this.widgetContext.customDialog.setAdditionalModules(descriptor.customModules); this.widgetContext.customDialog.setAdditionalImports(descriptor.customImports);
customActionPrettyFunction($event, this.widgetContext, entityId, entityName, htmlTemplate, additionalParams, entityLabel); customActionPrettyFunction($event, this.widgetContext, entityId, entityName, htmlTemplate, additionalParams, entityLabel);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@ -1459,7 +1462,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
private loadCustomActionResources(actionNamespace: string, customCss: string, customResources: Array<WidgetResource>, private loadCustomActionResources(actionNamespace: string, customCss: string, customResources: Array<WidgetResource>,
actionDescriptor: WidgetAction): Observable<any> { actionDescriptor: WidgetAction): Observable<any> {
const resourceTasks: Observable<string>[] = []; const resourceTasks: Observable<string>[] = [];
const modulesTasks: Observable<ModulesWithFactories | string>[] = []; const modulesTasks: Observable<ModulesWithComponents | string>[] = [];
if (isDefined(customCss) && customCss.length > 0) { if (isDefined(customCss) && customCss.length > 0) {
this.cssParser.cssPreviewNamespace = actionNamespace; this.cssParser.cssPreviewNamespace = actionNamespace;
@ -1470,7 +1473,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
customResources.forEach(resource => { customResources.forEach(resource => {
if (resource.isModule) { if (resource.isModule) {
modulesTasks.push( modulesTasks.push(
this.resources.loadFactories(resource.url, this.modulesMap).pipe( this.resources.loadModulesWithComponents(resource.url, this.modulesMap).pipe(
catchError((e: Error) => of(e?.message ? e.message : `Failed to load custom action resource module: '${resource.url}'`)) catchError((e: Error) => of(e?.message ? e.message : `Failed to load custom action resource module: '${resource.url}'`))
) )
); );
@ -1484,28 +1487,24 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
}); });
if (modulesTasks.length) { if (modulesTasks.length) {
const modulesObservable: Observable<string | Type<any>[]> = forkJoin(modulesTasks).pipe( const importsObservable: Observable<string | Type<any>[]> = forkJoin(modulesTasks).pipe(
map(res => { map(res => {
const msg = res.find(r => typeof r === 'string'); const msg = res.find(r => typeof r === 'string');
if (msg) { if (msg) {
return msg as string; return msg as string;
} else { } else {
const modulesWithFactoriesList = res as ModulesWithFactories[]; const modulesWithComponents = flatModulesWithComponents(res as ModulesWithComponents[]);
const resModulesWithFactories: ModulesWithFactories = { return modulesWithComponentsToTypes(modulesWithComponents);
modules: modulesWithFactoriesList.map(mf => mf.modules).flat(),
factories: modulesWithFactoriesList.map(mf => mf.factories).flat()
};
return resModulesWithFactories.modules;
} }
}) })
); );
resourceTasks.push(modulesObservable.pipe( resourceTasks.push(importsObservable.pipe(
map((resolvedModules) => { map((resolvedImports) => {
if (typeof resolvedModules === 'string') { if (typeof resolvedImports === 'string') {
return resolvedModules; return resolvedImports;
} else { } else {
actionDescriptor.customModules = resolvedModules; actionDescriptor.customImports = resolvedImports;
return null; return null;
} }
}))); })));

10
ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts

@ -15,15 +15,7 @@
/// ///
import { inject, NgModule } from '@angular/core'; import { inject, NgModule } from '@angular/core';
import { import { ActivatedRouteSnapshot, ResolveFn, Router, RouterModule, RouterStateSnapshot, Routes } from '@angular/router';
ActivatedRouteSnapshot,
Resolve,
ResolveFn,
Router,
RouterModule,
RouterStateSnapshot,
Routes
} from '@angular/router';
import { MailServerComponent } from '@modules/home/pages/admin/mail-server.component'; import { MailServerComponent } from '@modules/home/pages/admin/mail-server.component';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';

3
ui-ngx/src/app/modules/home/pages/admin/mail-server.component.scss

@ -97,6 +97,9 @@
line-height: 24px; line-height: 24px;
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
.mat-pseudo-checkbox {
display: none;
}
} }
.mat-button-toggle-checked.mat-button-toggle-appearance-standard:not(.mat-button-toggle-disabled):hover .mat-button-toggle-focus-overlay { .mat-button-toggle-checked.mat-button-toggle-appearance-standard:not(.mat-button-toggle-disabled):hover .mat-button-toggle-focus-overlay {

4
ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/clients-table-config.resolver.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
import { import {
DateEntityTableColumn, DateEntityTableColumn,
EntityTableColumn, EntityTableColumn,
@ -37,7 +37,7 @@ import { Direction } from '@shared/models/page/sort-order';
import { PageLink } from '@shared/models/page/page-link'; import { PageLink } from '@shared/models/page/page-link';
@Injectable() @Injectable()
export class ClientsTableConfigResolver implements Resolve<EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo>> { export class ClientsTableConfigResolver {
private readonly config: EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo> = private readonly config: EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo> =
new EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo>(); new EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo>();

4
ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain-table-config.resolver.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { ActivatedRouteSnapshot } from '@angular/router';
import { import {
DateEntityTableColumn, DateEntityTableColumn,
EntityActionTableColumn, EntityActionTableColumn,
@ -36,7 +36,7 @@ import { Direction } from '@app/shared/models/page/sort-order';
import { map, Observable, of, mergeMap } from 'rxjs'; import { map, Observable, of, mergeMap } from 'rxjs';
@Injectable() @Injectable()
export class DomainTableConfigResolver implements Resolve<EntityTableConfig<DomainInfo>> { export class DomainTableConfigResolver {
private readonly config: EntityTableConfig<DomainInfo> = new EntityTableConfig<DomainInfo>(); private readonly config: EntityTableConfig<DomainInfo> = new EntityTableConfig<DomainInfo>();

4
ui-ngx/src/app/modules/home/pages/admin/oauth2/mobile-apps/mobile-app-table-config.resolver.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { ActivatedRouteSnapshot } from '@angular/router';
import { import {
CellActionDescriptorType, CellActionDescriptorType,
DateEntityTableColumn, DateEntityTableColumn,
@ -36,7 +36,7 @@ import { MobileAppTableHeaderComponent } from '@home/pages/admin/oauth2/mobile-a
import { map, Observable, of, mergeMap } from 'rxjs'; import { map, Observable, of, mergeMap } from 'rxjs';
@Injectable() @Injectable()
export class MobileAppTableConfigResolver implements Resolve<EntityTableConfig<MobileAppInfo>> { export class MobileAppTableConfigResolver {
private readonly config: EntityTableConfig<MobileAppInfo> = new EntityTableConfig<MobileAppInfo>(); private readonly config: EntityTableConfig<MobileAppInfo> = new EntityTableConfig<MobileAppInfo>();

4
ui-ngx/src/app/modules/home/pages/admin/oauth2/oauth2-routing.module.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable, NgModule } from '@angular/core'; import { Injectable, NgModule } from '@angular/core';
import { Resolve, RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { RouterTabsComponent } from '@home/components/router-tabs.component'; import { RouterTabsComponent } from '@home/components/router-tabs.component';
import { Authority } from '@shared/models/authority.enum'; import { Authority } from '@shared/models/authority.enum';
import { EntitiesTableComponent } from '@home/components/entity/entities-table.component'; import { EntitiesTableComponent } from '@home/components/entity/entities-table.component';
@ -30,7 +30,7 @@ import { MobileAppTableConfigResolver } from '@home/pages/admin/oauth2/mobile-ap
import { MenuId } from '@core/services/menu.models'; import { MenuId } from '@core/services/menu.models';
@Injectable() @Injectable()
export class OAuth2LoginProcessingUrlResolver implements Resolve<string> { export class OAuth2LoginProcessingUrlResolver {
constructor(private oauth2Service: OAuth2Service) { constructor(private oauth2Service: OAuth2Service) {
} }

4
ui-ngx/src/app/modules/home/pages/admin/queue/queues-table-config.resolver.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; import { ActivatedRouteSnapshot, Router } from '@angular/router';
import { EntityTableColumn, EntityTableConfig } from '@home/models/entity/entities-table-config.models'; import { EntityTableColumn, EntityTableConfig } from '@home/models/entity/entities-table-config.models';
import { import {
QueueInfo, QueueInfo,
@ -39,7 +39,7 @@ import { selectAuthUser } from '@core/auth/auth.selectors';
import { EntityAction } from '@home/models/entity/entity-component.models'; import { EntityAction } from '@home/models/entity/entity-component.models';
@Injectable() @Injectable()
export class QueuesTableConfigResolver implements Resolve<EntityTableConfig<QueueInfo>> { export class QueuesTableConfigResolver {
readonly queueType = ServiceType.TB_RULE_ENGINE; readonly queueType = ServiceType.TB_RULE_ENGINE;

4
ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts

@ -21,7 +21,7 @@ import {
EntityTableColumn, EntityTableColumn,
EntityTableConfig EntityTableConfig
} from '@home/models/entity/entities-table-config.models'; } from '@home/models/entity/entities-table-config.models';
import { Resolve, Router } from '@angular/router'; import { Router } from '@angular/router';
import { Resource, ResourceInfo, ResourceType, ResourceTypeTranslationMap } from '@shared/models/resource.models'; import { Resource, ResourceInfo, ResourceType, ResourceTypeTranslationMap } from '@shared/models/resource.models';
import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models'; import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models';
import { NULL_UUID } from '@shared/models/id/has-uuid'; import { NULL_UUID } from '@shared/models/id/has-uuid';
@ -39,7 +39,7 @@ import { map } from 'rxjs/operators';
import { ResourcesTableHeaderComponent } from '@home/pages/admin/resource/resources-table-header.component'; import { ResourcesTableHeaderComponent } from '@home/pages/admin/resource/resources-table-header.component';
@Injectable() @Injectable()
export class ResourcesLibraryTableConfigResolver implements Resolve<EntityTableConfig<Resource, PageLink, ResourceInfo>> { export class ResourcesLibraryTableConfigResolver {
private readonly config: EntityTableConfig<Resource, PageLink, ResourceInfo> = new EntityTableConfig<Resource, PageLink, ResourceInfo>(); private readonly config: EntityTableConfig<Resource, PageLink, ResourceInfo> = new EntityTableConfig<Resource, PageLink, ResourceInfo>();
private readonly resourceTypesTranslationMap = ResourceTypeTranslationMap; private readonly resourceTypesTranslationMap = ResourceTypeTranslationMap;

4
ui-ngx/src/app/modules/home/pages/alarm/alarm-routing.module.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable, NgModule } from '@angular/core'; import { Injectable, NgModule } from '@angular/core';
import { Resolve, RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { Authority } from '@shared/models/authority.enum'; import { Authority } from '@shared/models/authority.enum';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { OAuth2Service } from '@core/http/oauth2.service'; import { OAuth2Service } from '@core/http/oauth2.service';
@ -24,7 +24,7 @@ import { AlarmsMode } from '@shared/models/alarm.models';
import { MenuId } from '@core/services/menu.models'; import { MenuId } from '@core/services/menu.models';
@Injectable() @Injectable()
export class OAuth2LoginProcessingUrlResolver implements Resolve<string> { export class OAuth2LoginProcessingUrlResolver {
constructor(private oauth2Service: OAuth2Service) { constructor(private oauth2Service: OAuth2Service) {
} }

4
ui-ngx/src/app/modules/home/pages/asset-profile/asset-profiles-table-config.resolver.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Resolve, Router } from '@angular/router'; import { Router } from '@angular/router';
import { import {
checkBoxCell, checkBoxCell,
DateEntityTableColumn, DateEntityTableColumn,
@ -37,7 +37,7 @@ import { AssetProfileComponent } from '@home/components/profile/asset-profile.co
import { AssetProfileTabsComponent } from './asset-profile-tabs.component'; import { AssetProfileTabsComponent } from './asset-profile-tabs.component';
@Injectable() @Injectable()
export class AssetProfilesTableConfigResolver implements Resolve<EntityTableConfig<AssetProfile>> { export class AssetProfilesTableConfigResolver {
private readonly config: EntityTableConfig<AssetProfile> = new EntityTableConfig<AssetProfile>(); private readonly config: EntityTableConfig<AssetProfile> = new EntityTableConfig<AssetProfile>();

4
ui-ngx/src/app/modules/home/pages/asset/assets-table-config.resolver.ts

@ -16,7 +16,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; import { ActivatedRouteSnapshot, Router } from '@angular/router';
import { import {
CellActionDescriptor, CellActionDescriptor,
checkBoxCell, checkBoxCell,
@ -65,7 +65,7 @@ import {
} from '@home/dialogs/add-entities-to-edge-dialog.component'; } from '@home/dialogs/add-entities-to-edge-dialog.component';
@Injectable() @Injectable()
export class AssetsTableConfigResolver implements Resolve<EntityTableConfig<AssetInfo>> { export class AssetsTableConfigResolver {
private readonly config: EntityTableConfig<AssetInfo> = new EntityTableConfig<AssetInfo>(); private readonly config: EntityTableConfig<AssetInfo> = new EntityTableConfig<AssetInfo>();

4
ui-ngx/src/app/modules/home/pages/customer/customers-table-config.resolver.ts

@ -16,7 +16,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Resolve, Router } from '@angular/router'; import { Router } from '@angular/router';
import { import {
DateEntityTableColumn, DateEntityTableColumn,
@ -37,7 +37,7 @@ import { AppState } from '@core/core.state';
import { HomeDialogsService } from '@home/dialogs/home-dialogs.service'; import { HomeDialogsService } from '@home/dialogs/home-dialogs.service';
@Injectable() @Injectable()
export class CustomersTableConfigResolver implements Resolve<EntityTableConfig<Customer>> { export class CustomersTableConfigResolver {
private readonly config: EntityTableConfig<Customer> = new EntityTableConfig<Customer>(); private readonly config: EntityTableConfig<Customer> = new EntityTableConfig<Customer>();

4
ui-ngx/src/app/modules/home/pages/dashboard/dashboard-routing.module.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable, NgModule } from '@angular/core'; import { Injectable, NgModule } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterModule, Routes } from '@angular/router'; import { ActivatedRouteSnapshot, RouterModule, Routes } from '@angular/router';
import { EntitiesTableComponent } from '../../components/entity/entities-table.component'; import { EntitiesTableComponent } from '../../components/entity/entities-table.component';
import { Authority } from '@shared/models/authority.enum'; import { Authority } from '@shared/models/authority.enum';
@ -36,7 +36,7 @@ import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
import { MenuId } from '@core/services/menu.models'; import { MenuId } from '@core/services/menu.models';
@Injectable() @Injectable()
export class DashboardResolver implements Resolve<Dashboard> { export class DashboardResolver {
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private dashboardService: DashboardService, private dashboardService: DashboardService,

4
ui-ngx/src/app/modules/home/pages/dashboard/dashboards-table-config.resolver.ts

@ -16,7 +16,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; import { ActivatedRouteSnapshot, Router } from '@angular/router';
import { import {
CellActionDescriptor, CellActionDescriptor,
checkBoxCell, checkBoxCell,
@ -79,7 +79,7 @@ import {
} from '@home/components/alias/entity-aliases-dialog.component'; } from '@home/components/alias/entity-aliases-dialog.component';
@Injectable() @Injectable()
export class DashboardsTableConfigResolver implements Resolve<EntityTableConfig<DashboardInfo | Dashboard>> { export class DashboardsTableConfigResolver {
private readonly config: EntityTableConfig<DashboardInfo | Dashboard> = new EntityTableConfig<DashboardInfo | Dashboard>(); private readonly config: EntityTableConfig<DashboardInfo | Dashboard> = new EntityTableConfig<DashboardInfo | Dashboard>();

4
ui-ngx/src/app/modules/home/pages/device-profile/device-profiles-table-config.resolver.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Resolve, Router } from '@angular/router'; import { Router } from '@angular/router';
import { import {
checkBoxCell, checkBoxCell,
DateEntityTableColumn, DateEntityTableColumn,
@ -45,7 +45,7 @@ import { ImportExportService } from '@shared/import-export/import-export.service
import { HomeDialogsService } from '@home/dialogs/home-dialogs.service'; import { HomeDialogsService } from '@home/dialogs/home-dialogs.service';
@Injectable() @Injectable()
export class DeviceProfilesTableConfigResolver implements Resolve<EntityTableConfig<DeviceProfile>> { export class DeviceProfilesTableConfigResolver {
private readonly config: EntityTableConfig<DeviceProfile> = new EntityTableConfig<DeviceProfile>(); private readonly config: EntityTableConfig<DeviceProfile> = new EntityTableConfig<DeviceProfile>();

4
ui-ngx/src/app/modules/home/pages/device/devices-table-config.resolver.ts

@ -16,7 +16,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRoute, ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; import { ActivatedRoute, ActivatedRouteSnapshot, Router } from '@angular/router';
import { import {
CellActionDescriptor, CellActionDescriptor,
checkBoxCell, checkBoxCell,
@ -91,7 +91,7 @@ interface DevicePageQueryParams extends PageQueryParam {
} }
@Injectable() @Injectable()
export class DevicesTableConfigResolver implements Resolve<EntityTableConfig<DeviceInfo>> { export class DevicesTableConfigResolver {
private readonly config: EntityTableConfig<DeviceInfo> = new EntityTableConfig<DeviceInfo>(); private readonly config: EntityTableConfig<DeviceInfo> = new EntityTableConfig<DeviceInfo>();

4
ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts

@ -16,7 +16,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; import { ActivatedRouteSnapshot, Router } from '@angular/router';
import { import {
CellActionDescriptor, CellActionDescriptor,
checkBoxCell, checkBoxCell,
@ -65,7 +65,7 @@ import {
import { AddEntityDialogComponent } from '@home/components/entity/add-entity-dialog.component'; import { AddEntityDialogComponent } from '@home/components/entity/add-entity-dialog.component';
@Injectable() @Injectable()
export class EdgesTableConfigResolver implements Resolve<EntityTableConfig<EdgeInfo>> { export class EdgesTableConfigResolver {
private readonly config: EntityTableConfig<EdgeInfo> = new EntityTableConfig<EdgeInfo>(); private readonly config: EntityTableConfig<EdgeInfo> = new EntityTableConfig<EdgeInfo>();
private customerId: string; private customerId: string;

4
ui-ngx/src/app/modules/home/pages/entity-view/entity-views-table-config.resolver.ts

@ -16,7 +16,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; import { ActivatedRouteSnapshot, Router } from '@angular/router';
import { import {
CellActionDescriptor, CellActionDescriptor,
checkBoxCell, checkBoxCell,
@ -63,7 +63,7 @@ import {
} from '@home/dialogs/add-entities-to-edge-dialog.component'; } from '@home/dialogs/add-entities-to-edge-dialog.component';
@Injectable() @Injectable()
export class EntityViewsTableConfigResolver implements Resolve<EntityTableConfig<EntityViewInfo>> { export class EntityViewsTableConfigResolver {
private readonly config: EntityTableConfig<EntityViewInfo> = new EntityTableConfig<EntityViewInfo>(); private readonly config: EntityTableConfig<EntityViewInfo> = new EntityTableConfig<EntityViewInfo>();

4
ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-table-config.resolver.ts

@ -38,11 +38,11 @@ import {
InboxNotificationDialogData InboxNotificationDialogData
} from '@home/pages/notification/inbox/inbox-notification-dialog.component'; } from '@home/pages/notification/inbox/inbox-notification-dialog.component';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { ActivatedRouteSnapshot } from '@angular/router';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
@Injectable() @Injectable()
export class InboxTableConfigResolver implements Resolve<EntityTableConfig<Notification>> { export class InboxTableConfigResolver {
private readonly config: EntityTableConfig<Notification> = new EntityTableConfig<Notification>(); private readonly config: EntityTableConfig<Notification> = new EntityTableConfig<Notification>();

3
ui-ngx/src/app/modules/home/pages/notification/inbox/inbox-table-header.component.scss

@ -63,6 +63,9 @@
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
letter-spacing: .25px; letter-spacing: .25px;
.mat-pseudo-checkbox {
display: none;
}
} }
.mat-button-toggle-checked.mat-button-toggle-appearance-standard:not(.mat-button-toggle-disabled):hover .mat-button-toggle-focus-overlay { .mat-button-toggle-checked.mat-button-toggle-appearance-standard:not(.mat-button-toggle-disabled):hover .mat-button-toggle-focus-overlay {

4
ui-ngx/src/app/modules/home/pages/notification/recipient/recipient-table-config.resolver.ts

@ -32,12 +32,12 @@ import {
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { EntityAction } from '@home/models/entity/entity-component.models'; import { EntityAction } from '@home/models/entity/entity-component.models';
import { RecipientTableHeaderComponent } from '@home/pages/notification/recipient/recipient-table-header.component'; import { RecipientTableHeaderComponent } from '@home/pages/notification/recipient/recipient-table-header.component';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { ActivatedRouteSnapshot } from '@angular/router';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
@Injectable() @Injectable()
export class RecipientTableConfigResolver implements Resolve<EntityTableConfig<NotificationTarget>> { export class RecipientTableConfigResolver {
private readonly config: EntityTableConfig<NotificationTarget> = new EntityTableConfig<NotificationTarget>(); private readonly config: EntityTableConfig<NotificationTarget> = new EntityTableConfig<NotificationTarget>();

4
ui-ngx/src/app/modules/home/pages/notification/rule/rule-table-config.resolver.ts

@ -32,12 +32,12 @@ import {
RuleNotificationDialogComponent, RuleNotificationDialogComponent,
RuleNotificationDialogData RuleNotificationDialogData
} from '@home/pages/notification/rule/rule-notification-dialog.component'; } from '@home/pages/notification/rule/rule-notification-dialog.component';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { ActivatedRouteSnapshot } from '@angular/router';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
@Injectable() @Injectable()
export class RuleTableConfigResolver implements Resolve<EntityTableConfig<NotificationRule>> { export class RuleTableConfigResolver {
private readonly config: EntityTableConfig<NotificationRule> = new EntityTableConfig<NotificationRule>(); private readonly config: EntityTableConfig<NotificationRule> = new EntityTableConfig<NotificationRule>();

4
ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts

@ -45,11 +45,11 @@ import {
NotificationRequestErrorDialogData, NotificationRequestErrorDialogData,
SentErrorDialogComponent SentErrorDialogComponent
} from '@home/pages/notification/sent/sent-error-dialog.component'; } from '@home/pages/notification/sent/sent-error-dialog.component';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { ActivatedRouteSnapshot } from '@angular/router';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
@Injectable() @Injectable()
export class SentTableConfigResolver implements Resolve<EntityTableConfig<NotificationRequest, PageLink, NotificationRequestInfo>> { export class SentTableConfigResolver {
private readonly config: EntityTableConfig<NotificationRequest, PageLink, NotificationRequestInfo> = private readonly config: EntityTableConfig<NotificationRequest, PageLink, NotificationRequestInfo> =
new EntityTableConfig<NotificationRequest, PageLink, NotificationRequestInfo>(); new EntityTableConfig<NotificationRequest, PageLink, NotificationRequestInfo>();

11
ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts

@ -84,15 +84,16 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co
tinyMceOptions: Record<string, any> = { tinyMceOptions: Record<string, any> = {
base_url: '/assets/tinymce', base_url: '/assets/tinymce',
suffix: '.min', suffix: '.min',
plugins: ['link table image imagetools code fullscreen'], plugins: ['link', 'table', 'image', 'lists', 'code', 'fullscreen'],
menubar: 'edit insert tools view format table', menubar: 'edit insert tools view format table',
toolbar: 'fontselect fontsizeselect | formatselect | bold italic strikethrough forecolor backcolor ' + toolbar: 'undo redo | fontfamily fontsize blocks | bold italic strikethrough | forecolor backcolor ' +
'| link | table | image | alignleft aligncenter alignright alignjustify ' + '| link table image | alignleft aligncenter alignright alignjustify ' +
'| numlist bullist outdent indent | removeformat | code | fullscreen', '| numlist bullist | outdent indent | removeformat | code | fullscreen',
toolbar_mode: 'sliding', toolbar_mode: 'sliding',
height: 400, height: 400,
autofocus: false, autofocus: false,
branding: false branding: false,
promotion: false
}; };
private propagateChange = null; private propagateChange = null;

4
ui-ngx/src/app/modules/home/pages/notification/template/template-table-config.resolver.ts

@ -33,11 +33,11 @@ import {
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { TemplateTableHeaderComponent } from '@home/pages/notification/template/template-table-header.component'; import { TemplateTableHeaderComponent } from '@home/pages/notification/template/template-table-header.component';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { ActivatedRouteSnapshot } from '@angular/router';
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
@Injectable() @Injectable()
export class TemplateTableConfigResolver implements Resolve<EntityTableConfig<NotificationTemplate>> { export class TemplateTableConfigResolver {
private readonly config: EntityTableConfig<NotificationTemplate> = new EntityTableConfig<NotificationTemplate>(); private readonly config: EntityTableConfig<NotificationTemplate> = new EntityTableConfig<NotificationTemplate>();

4
ui-ngx/src/app/modules/home/pages/ota-update/ota-update-table-config.resolve.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Resolve, Router } from '@angular/router'; import { Router } from '@angular/router';
import { import {
CellActionDescriptorType, CellActionDescriptorType,
DateEntityTableColumn, DateEntityTableColumn,
@ -40,7 +40,7 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
@Injectable() @Injectable()
export class OtaUpdateTableConfigResolve implements Resolve<EntityTableConfig<OtaPackage, PageLink, OtaPackageInfo>> { export class OtaUpdateTableConfigResolve {
private readonly config: EntityTableConfig<OtaPackage, PageLink, OtaPackageInfo> = private readonly config: EntityTableConfig<OtaPackage, PageLink, OtaPackageInfo> =
new EntityTableConfig<OtaPackage, PageLink, OtaPackageInfo>(); new EntityTableConfig<OtaPackage, PageLink, OtaPackageInfo>();

4
ui-ngx/src/app/modules/home/pages/profile/profile-routing.module.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable, NgModule } from '@angular/core'; import { Injectable, NgModule } from '@angular/core';
import { Resolve, RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { ProfileComponent } from './profile.component'; import { ProfileComponent } from './profile.component';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
@ -28,7 +28,7 @@ import { getCurrentAuthUser } from '@core/auth/auth.selectors';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
@Injectable() @Injectable()
export class UserProfileResolver implements Resolve<User> { export class UserProfileResolver {
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private userService: UserService) { private userService: UserService) {

22
ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts

@ -15,14 +15,12 @@
/// ///
import { import {
AfterViewInit,
Component, Component,
ComponentRef, ComponentRef,
EventEmitter, EventEmitter,
forwardRef, forwardRef,
Input, Input,
OnDestroy, OnDestroy,
OnInit,
Output, Output,
ViewChild, ViewChild,
ViewContainerRef ViewContainerRef
@ -42,7 +40,6 @@ import {
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { RuleChainService } from '@core/http/rule-chain.service'; import { RuleChainService } from '@core/http/rule-chain.service';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { TranslateService } from '@ngx-translate/core';
import { JsonObjectEditComponent } from '@shared/components/json-object-edit.component'; import { JsonObjectEditComponent } from '@shared/components/json-object-edit.component';
import { deepClone } from '@core/utils'; import { deepClone } from '@core/utils';
import { RuleChainType } from '@shared/models/rule-chain.models'; import { RuleChainType } from '@shared/models/rule-chain.models';
@ -57,7 +54,7 @@ import { RuleChainType } from '@shared/models/rule-chain.models';
multi: true multi: true
}] }]
}) })
export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, OnDestroy, AfterViewInit { export class RuleNodeConfigComponent implements ControlValueAccessor, OnDestroy {
@ViewChild('definedConfigContent', {read: ViewContainerRef, static: true}) definedConfigContainer: ViewContainerRef; @ViewChild('definedConfigContent', {read: ViewContainerRef, static: true}) definedConfigContainer: ViewContainerRef;
@ -121,10 +118,9 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On
private configuration: RuleNodeConfiguration; private configuration: RuleNodeConfiguration;
private propagateChange = (v: any) => { }; private propagateChange = (_v: any) => { };
constructor(private translate: TranslateService, constructor(private ruleChainService: RuleChainService,
private ruleChainService: RuleChainService,
private fb: UntypedFormBuilder) { private fb: UntypedFormBuilder) {
this.ruleNodeConfigFormGroup = this.fb.group({ this.ruleNodeConfigFormGroup = this.fb.group({
configuration: [null, Validators.required] configuration: [null, Validators.required]
@ -135,10 +131,7 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On
this.propagateChange = fn; this.propagateChange = fn;
} }
registerOnTouched(fn: any): void { registerOnTouched(_fn: any): void {
}
ngOnInit(): void {
} }
ngOnDestroy(): void { ngOnDestroy(): void {
@ -155,9 +148,6 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On
} }
} }
ngAfterViewInit(): void {
}
setDisabledState(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled; this.disabled = isDisabled;
if (this.disabled) { if (this.disabled) {
@ -218,8 +208,8 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnInit, On
this.changeSubscription = null; this.changeSubscription = null;
} }
this.definedConfigContainer.clear(); this.definedConfigContainer.clear();
const factory = this.ruleChainService.getRuleNodeConfigFactory(this.nodeDefinition.configDirective); const component = this.ruleChainService.getRuleNodeConfigComponent(this.nodeDefinition.configDirective);
this.definedConfigComponentRef = this.definedConfigContainer.createComponent(factory); this.definedConfigComponentRef = this.definedConfigContainer.createComponent(component);
this.definedConfigComponent = this.definedConfigComponentRef.instance; this.definedConfigComponent = this.definedConfigComponentRef.instance;
this.definedConfigComponent.ruleNodeId = this.ruleNodeId; this.definedConfigComponent.ruleNodeId = this.ruleNodeId;
this.definedConfigComponent.ruleChainId = this.ruleChainId; this.definedConfigComponent.ruleChainId = this.ruleChainId;

2
ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.scss

@ -345,7 +345,7 @@
} }
} }
.tb-rule-chain-context-menu.mat-mdc-menu-panel.mdc-menu-surface { .tb-rule-chain-context-menu.mat-mdc-menu-panel {
min-width: 320px; min-width: 320px;
max-height: 404px; max-height: 404px;
border-radius: 8px; border-radius: 8px;

21
ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts

@ -15,16 +15,7 @@
/// ///
import { Inject, Injectable, NgModule, Optional } from '@angular/core'; import { Inject, Injectable, NgModule, Optional } from '@angular/core';
import { import { ActivatedRouteSnapshot, Router, RouterModule, RouterStateSnapshot, Routes, UrlTree } from '@angular/router';
ActivatedRouteSnapshot,
CanActivate,
Resolve,
Router,
RouterModule,
RouterStateSnapshot,
Routes,
UrlTree
} from '@angular/router';
import { EntitiesTableComponent } from '../../components/entity/entities-table.component'; import { EntitiesTableComponent } from '../../components/entity/entities-table.component';
import { Authority } from '@shared/models/authority.enum'; import { Authority } from '@shared/models/authority.enum';
@ -44,7 +35,7 @@ import { MODULES_MAP } from '@shared/public-api';
import { IModulesMap } from '@modules/common/modules-map.models'; import { IModulesMap } from '@modules/common/modules-map.models';
@Injectable() @Injectable()
export class RuleChainResolver implements Resolve<RuleChain> { export class RuleChainResolver {
constructor(private ruleChainService: RuleChainService) { constructor(private ruleChainService: RuleChainService) {
} }
@ -56,7 +47,7 @@ export class RuleChainResolver implements Resolve<RuleChain> {
} }
@Injectable() @Injectable()
export class RuleChainMetaDataResolver implements Resolve<RuleChainMetaData> { export class RuleChainMetaDataResolver {
constructor(private ruleChainService: RuleChainService) { constructor(private ruleChainService: RuleChainService) {
} }
@ -68,7 +59,7 @@ export class RuleChainMetaDataResolver implements Resolve<RuleChainMetaData> {
} }
@Injectable() @Injectable()
export class RuleNodeComponentsResolver implements Resolve<Array<RuleNodeComponentDescriptor>> { export class RuleNodeComponentsResolver {
constructor(private ruleChainService: RuleChainService, constructor(private ruleChainService: RuleChainService,
@Optional() @Inject(MODULES_MAP) private modulesMap: IModulesMap) { @Optional() @Inject(MODULES_MAP) private modulesMap: IModulesMap) {
@ -80,7 +71,7 @@ export class RuleNodeComponentsResolver implements Resolve<Array<RuleNodeCompone
} }
@Injectable() @Injectable()
export class TooltipsterResolver implements Resolve<any> { export class TooltipsterResolver {
constructor() { constructor() {
} }
@ -91,7 +82,7 @@ export class TooltipsterResolver implements Resolve<any> {
} }
@Injectable() @Injectable()
export class RuleChainImportGuard implements CanActivate { export class RuleChainImportGuard {
constructor(private itembuffer: ItemBufferService, constructor(private itembuffer: ItemBufferService,
private router: Router) { private router: Router) {

4
ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts

@ -16,7 +16,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router'; import { ActivatedRouteSnapshot, Router } from '@angular/router';
import { import {
CellActionDescriptor, CellActionDescriptor,
checkBoxCell, checkBoxCell,
@ -53,7 +53,7 @@ import { PageData } from '@shared/models/page/page-data';
import { HomeDialogsService } from '@home/dialogs/home-dialogs.service'; import { HomeDialogsService } from '@home/dialogs/home-dialogs.service';
@Injectable() @Injectable()
export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<RuleChain>> { export class RuleChainsTableConfigResolver {
private readonly config: EntityTableConfig<RuleChain> = new EntityTableConfig<RuleChain>(); private readonly config: EntityTableConfig<RuleChain> = new EntityTableConfig<RuleChain>();
private edge: Edge; private edge: Edge;

1
ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol.component.ts

@ -78,7 +78,6 @@ import {
SaveWidgetTypeAsDialogResult SaveWidgetTypeAsDialogResult
} from '@home/pages/widget/save-widget-type-as-dialog.component'; } from '@home/pages/widget/save-widget-type-as-dialog.component';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { de } from 'date-fns/locale';
@Component({ @Component({
selector: 'tb-scada-symbol', selector: 'tb-scada-symbol',

6
ui-ngx/src/app/modules/home/pages/security/security-routing.module.ts

@ -15,7 +15,7 @@
/// ///
import { Injectable, NgModule } from '@angular/core'; import { Injectable, NgModule } from '@angular/core';
import { Resolve, RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { SecurityComponent } from './security.component'; import { SecurityComponent } from './security.component';
import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard'; import { ConfirmOnExitGuard } from '@core/guards/confirm-on-exit.guard';
@ -30,7 +30,7 @@ import { TwoFactorAuthProviderType } from '@shared/models/two-factor-auth.models
import { TwoFactorAuthenticationService } from '@core/http/two-factor-authentication.service'; import { TwoFactorAuthenticationService } from '@core/http/two-factor-authentication.service';
@Injectable() @Injectable()
export class UserProfileResolver implements Resolve<User> { export class UserProfileResolver {
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private userService: UserService) { private userService: UserService) {
@ -43,7 +43,7 @@ export class UserProfileResolver implements Resolve<User> {
} }
@Injectable() @Injectable()
export class UserTwoFAProvidersResolver implements Resolve<Array<TwoFactorAuthProviderType>> { export class UserTwoFAProvidersResolver {
constructor(private twoFactorAuthService: TwoFactorAuthenticationService) { constructor(private twoFactorAuthService: TwoFactorAuthenticationService) {
} }

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save