Browse Source

Merge pull request #11985 from thingsboard/develop/esbuild

Switch to angular esbuild
pull/11990/head
Igor Kulikov 2 years ago
committed by GitHub
parent
commit
7c201d0a79
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 67
      ui-ngx/angular.json
  2. 104
      ui-ngx/esbuild/tb-esbuild-plugins.ts
  3. 100
      ui-ngx/extra-webpack.config.js
  4. 19
      ui-ngx/package.json
  5. 43
      ui-ngx/patches/@angular+build+18.2.10.patch
  6. 14
      ui-ngx/patches/jquery.terminal+2.43.1.patch
  7. 8
      ui-ngx/src/app/core/utils.ts
  8. 2
      ui-ngx/src/app/modules/common/modules-map.ts
  9. 2
      ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts
  10. 20
      ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.component.ts
  11. 77
      ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts
  12. 4
      ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts
  13. 4
      ui-ngx/src/app/modules/home/components/widget/lib/qrcode-widget.component.ts
  14. 6
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action.models.ts
  15. 15
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-provider-settings.component.ts
  16. 26
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-settings.component.ts
  17. 28
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-widget-settings.component.ts
  18. 8
      ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
  19. 10
      ui-ngx/src/app/modules/home/components/widget/widget.component.ts
  20. 6
      ui-ngx/src/app/modules/home/models/widget-component.models.ts
  21. 2
      ui-ngx/src/app/modules/home/pages/security/authentication-dialog/backup-code-auth-dialog.component.ts
  22. 3
      ui-ngx/src/app/modules/home/pages/security/authentication-dialog/totp-auth-dialog.component.ts
  23. 8
      ui-ngx/src/app/shared/components/json-form/json-form.component.ts
  24. 7
      ui-ngx/src/app/shared/components/json-form/react/json-form-ace-editor.tsx
  25. 7
      ui-ngx/src/app/shared/components/json-form/react/json-form-schema-form.tsx
  26. 6
      ui-ngx/src/app/shared/components/page.component.ts
  27. 1
      ui-ngx/src/app/shared/decorators/public-api.ts
  28. 23
      ui-ngx/src/app/shared/decorators/tb-inject.ts
  29. 9
      ui-ngx/src/app/shared/models/ace/ace.models.ts
  30. 4
      ui-ngx/src/app/shared/models/beautify.models.ts
  31. 5
      ui-ngx/src/main.ts
  32. 4
      ui-ngx/src/styles.scss
  33. 4
      ui-ngx/src/tsconfig.app.json
  34. 6
      ui-ngx/src/typings/rawloader.typings.d.ts
  35. 1
      ui-ngx/tsconfig.json
  36. 189
      ui-ngx/yarn.lock

67
ui-ngx/angular.json

@ -18,12 +18,20 @@
},
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"builder": "@angular-builders/custom-esbuild:application",
"options": {
"outputPath": "target/generated-resources/public",
"plugins": ["./esbuild/tb-esbuild-plugins.ts"],
"loader": {
".raw": "text"
},
"outputPath": {
"base": "target/generated-resources/public",
"media": ".",
"browser": ""
},
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"browser": "src/main.ts",
"polyfills": ["src/polyfills.ts"],
"tsConfig": "src/tsconfig.app.json",
"aot": true,
"assets": [
@ -122,49 +130,8 @@
"node_modules/prismjs/components/prism-typescript.min.js",
"node_modules/prismjs/plugins/line-numbers/prism-line-numbers.min.js"
],
"customWebpackConfig": {
"path": "./extra-webpack.config.js"
},
"allowedCommonJsDependencies": [
"hammerjs",
"react",
"react-dom",
"reactcss",
"react-ace",
"schema-inspector",
"@flowjs/flow.js",
"@material-ui/icons/Add",
"@material-ui/icons/Clear",
"js-beautify",
"mousetrap",
"prop-types",
"react-is",
"hoist-non-react-statics",
"classnames",
"raf",
"moment-timezone",
"tinycolor2",
"json-schema-defaults",
"leaflet-providers",
"lodash",
"jquery",
"jquery.terminal",
"tooltipster",
"jstree",
"qrcode",
"wcwidth",
"leaflet-polylinedecorator",
"ace-diff",
"messageformat-parser",
"html2canvas",
"jszip",
"moment",
"ace",
"ace-builds",
"diff-match-patch",
"tv4",
"@messageformat/parser",
"sorted-btree"
"*"
]
},
"configurations": {
@ -187,8 +154,6 @@
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": false,
"budgets": [
{
"type": "initial",
@ -198,7 +163,6 @@
]
},
"development": {
"buildOptimizer": false,
"optimization": {
"scripts": false,
"styles": {
@ -207,7 +171,6 @@
},
"fonts": false
},
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
@ -215,7 +178,7 @@
}
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"builder": "@angular-builders/custom-esbuild:dev-server",
"options": {
"buildTarget": "thingsboard:build",
"proxyConfig": "proxy.conf.js"
@ -231,7 +194,7 @@
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"builder": "@angular/build:extract-i18n",
"options": {
"buildTarget": "thingsboard:build"
}

104
ui-ngx/esbuild/tb-esbuild-plugins.ts

@ -0,0 +1,104 @@
///
/// 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 type { Plugin, PluginBuild, OutputFile } from 'esbuild';
import dirTree from 'directory-tree';
import * as packageJson from '../package.json';
import { gzip } from 'node:zlib';
import * as path from 'node:path';
const defineTbVariablesPlugin: Plugin = {
name: 'tb-define-variables',
setup(build: PluginBuild) {
const options = build.initialOptions;
const langs: string[] = [];
dirTree("./src/assets/locale/", {extensions: /\.json$/}, (item) => {
/* It is expected what the name of a locale file has the following format: */
/* 'locale.constant-LANG_CODE[_REGION_CODE].json', e.g. locale.constant-es.json or locale.constant-zh_CN.json*/
langs.push(item.name.slice(item.name.lastIndexOf("-") + 1, -5));
});
options.define.TB_VERSION = JSON.stringify(packageJson.version);
options.define.SUPPORTED_LANGS = JSON.stringify(langs);
options.define.ngJitMode = 'true';
},
};
const resolveJQueryPlugin: Plugin = {
name: 'tb-resolve-jquery-plugin',
setup(build: PluginBuild) {
if (isProduction()) {
const jQueryPath = require.resolve('jquery');
build.onResolve({filter: /^(jquery|\$)$/}, () => {
return {path: jQueryPath};
})
}
}
};
const compressFileTypes = ['.js', '.css', '.html', '.svg', '.png', '.jpg', '.ttf', '.gif', '.woff', '.woff2', '.eot', '.json'];
const compressThreshold = 10240;
const compressorPlugin: Plugin = {
name: 'tb-compressor-plugin',
setup(build) {
build.onEnd(async result => {
if (!result.outputFiles || !isProduction()) return;
const outputExt = '.gz';
const gzippedFiles: OutputFile[] = [];
for (const file of result.outputFiles) {
if (!compressFileTypes.some((ext) => ext === path.extname(file.path))) continue;
if (file.contents.byteLength <= compressThreshold) continue;
const compressedContent = await gzipContent(file.contents);
const compressedFilePath = `${file.path}${outputExt}`;
gzippedFiles.push(
{
path: compressedFilePath,
hash: file.hash,
contents: new Uint8Array(compressedContent),
text: '',
}
);
}
result.outputFiles.push(...gzippedFiles);
});
},
};
async function gzipContent(content): Promise<Buffer> {
return new Promise((resolve, reject) => {
gzip(content, (error, result) => {
if (error) {
reject(error);
} else {
resolve(result);
}
});
});
}
function isProduction(): boolean {
const configurationIndex = process.argv.indexOf('--configuration');
let production = false;
if (configurationIndex > -1) {
const configurationValue = process.argv[configurationIndex + 1];
production = configurationValue === 'production';
}
return production;
}
export default [defineTbVariablesPlugin, resolveJQueryPlugin, compressorPlugin];

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

@ -1,100 +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.
*/
const CompressionPlugin = require("compression-webpack-plugin");
const JavaScriptOptimizerPlugin = require("@angular-devkit/build-angular/src/tools/webpack/plugins/javascript-optimizer-plugin").JavaScriptOptimizerPlugin;
const webpack = require("webpack");
const dirTree = require("directory-tree");
const ngWebpack = require('@ngtools/webpack');
const keysTransformer = require('ts-transformer-keys/transformer').default;
var langs = [];
dirTree("./src/assets/locale/", {extensions: /\.json$/}, (item) => {
/* It is expected what the name of a locale file has the following format: */
/* 'locale.constant-LANG_CODE[_REGION_CODE].json', e.g. locale.constant-es.json or locale.constant-zh_CN.json*/
langs.push(item.name.slice(item.name.lastIndexOf("-") + 1, -5));
});
module.exports = (config, options) => {
config.ignoreWarnings.push(/Usage of '~' in imports is deprecated/);
config.ignoreWarnings.push(/Did you mean "left" instead?/);
config.ignoreWarnings.push(/autoprefixer/);
config.plugins.push(
new webpack.DefinePlugin({
TB_VERSION: JSON.stringify(require("./package.json").version),
SUPPORTED_LANGS: JSON.stringify(langs),
})
);
config.plugins.push(
new webpack.ProvidePlugin(
{
$: "jquery"
}
)
);
config.plugins.push(
new CompressionPlugin({
filename: "[path][base].gz[query]",
algorithm: "gzip",
test: /\.js$|\.css$|\.html$|\.svg?.+$|\.jpg$|\.ttf?.+$|\.woff?.+$|\.eot?.+$|\.json$/,
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false,
})
);
config.plugins.push(
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
})
);
config.module.rules[2].use[0].options.aot = false;
const index = config.plugins.findIndex(p => p instanceof ngWebpack.AngularWebpackPlugin);
let angularWebpackPlugin = config.plugins[index];
if (config.mode === 'production') {
const angularCompilerOptions = angularWebpackPlugin.pluginOptions;
angularCompilerOptions.emitClassMetadata = true;
angularCompilerOptions.emitNgModuleScope = true;
config.plugins.splice(index, 1);
angularWebpackPlugin = new ngWebpack.AngularWebpackPlugin(angularCompilerOptions);
config.plugins.push(angularWebpackPlugin);
const javascriptOptimizerOptions = config.optimization.minimizer[0].options;
delete javascriptOptimizerOptions.define.ngJitMode;
config.optimization.minimizer.splice(0, 1);
config.optimization.minimizer.unshift(new JavaScriptOptimizerPlugin(javascriptOptimizerOptions));
}
addTransformerToAngularWebpackPlugin(angularWebpackPlugin, keysTransformer);
return config;
};
function addTransformerToAngularWebpackPlugin(plugin, transformer) {
const originalCreateFileEmitter = plugin.createFileEmitter; // private method
plugin.createFileEmitter = function (program, transformers, getExtraDependencies, onAfterEmit) {
if (!transformers) {
transformers = {};
}
if (!transformers.before) {
transformers = { before: [] };
}
transformers.before.push(transformer(program.getProgram()));
return originalCreateFileEmitter.apply(plugin, [program, transformers, getExtraDependencies, onAfterEmit]);
};
}

19
ui-ngx/package.json

@ -5,7 +5,7 @@
"ng": "ng",
"start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --configuration development --host 0.0.0.0 --open",
"build": "ng build",
"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",
"build:types": "node generate-types.js",
"build:icon-metadata": "node generate-icon-metadata.js",
"lint": "ng lint",
@ -105,26 +105,25 @@
"tinycolor2": "^1.6.0",
"tinymce": "~6.8.5",
"tooltipster": "^4.2.8",
"ts-transformer-keys": "^0.4.4",
"tslib": "^2.7.0",
"tv4": "^1.3.0",
"typeface-roboto": "^1.1.13",
"zone.js": "~0.14.10"
},
"devDependencies": {
"@angular-builders/custom-webpack": "~18.0.0",
"@angular-devkit/build-angular": "18.2.7",
"@angular-devkit/core": "18.2.7",
"@angular-devkit/schematics": "18.2.7",
"@angular-builders/custom-esbuild": "18.0.0",
"@angular-devkit/build-angular": "18.2.10",
"@angular-devkit/core": "18.2.10",
"@angular-devkit/schematics": "18.2.10",
"@angular-eslint/builder": "18.3.1",
"@angular-eslint/eslint-plugin": "18.3.1",
"@angular-eslint/eslint-plugin-template": "18.3.1",
"@angular-eslint/schematics": "18.3.1",
"@angular-eslint/template-parser": "18.3.1",
"@angular/cli": "18.2.7",
"@angular/compiler-cli": "18.2.6",
"@angular/language-service": "18.2.6",
"@ngtools/webpack": "18.2.7",
"@angular/build": "18.2.10",
"@angular/cli": "18.2.10",
"@angular/compiler-cli": "18.2.9",
"@angular/language-service": "18.2.9",
"@types/ace-diff": "^2.1.4",
"@types/canvas-gauges": "^2.1.8",
"@types/flot": "^0.0.36",

43
ui-ngx/patches/@angular+build+18.2.10.patch

@ -0,0 +1,43 @@
diff --git a/node_modules/@angular/build/src/tools/angular/compilation/angular-compilation.js b/node_modules/@angular/build/src/tools/angular/compilation/angular-compilation.js
index 625c621..4fc8bd8 100755
--- a/node_modules/@angular/build/src/tools/angular/compilation/angular-compilation.js
+++ b/node_modules/@angular/build/src/tools/angular/compilation/angular-compilation.js
@@ -68,8 +68,6 @@ class AngularCompilation {
allowEmptyCodegenFiles: false,
annotationsAs: 'decorators',
enableResourceInlining: false,
- supportTestBed: false,
- supportJitMode: false,
}));
}
async diagnoseFiles(modes = DiagnosticModes.All) {
diff --git a/node_modules/@angular/build/src/tools/esbuild/angular/compiler-plugin.js b/node_modules/@angular/build/src/tools/esbuild/angular/compiler-plugin.js
index b1bb6ea..c76b4c6 100755
--- a/node_modules/@angular/build/src/tools/esbuild/angular/compiler-plugin.js
+++ b/node_modules/@angular/build/src/tools/esbuild/angular/compiler-plugin.js
@@ -79,7 +79,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
sourcemap: !!pluginOptions.sourcemap,
thirdPartySourcemaps: pluginOptions.thirdPartySourcemaps,
advancedOptimizations: pluginOptions.advancedOptimizations,
- jit: pluginOptions.jit,
+ jit: true, // pluginOptions.jit,
}, environment_options_1.maxWorkers, cacheStore?.createCache('jstransformer'));
// Setup defines based on the values used by the Angular compiler-cli
build.initialOptions.define ??= {};
@@ -377,12 +377,14 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
async function hasSideEffects(path) {
if (!pluginOptions.advancedOptimizations) {
return undefined;
+ } else {
+ return true;
}
- const { sideEffects } = await build.resolve(path, {
+ /*const { sideEffects } = await build.resolve(path, {
kind: 'import-statement',
resolveDir: build.initialOptions.absWorkingDir ?? '',
});
- return sideEffects;
+ return sideEffects;*/
}
},
};

14
ui-ngx/patches/jquery.terminal+2.43.1.patch

File diff suppressed because one or more lines are too long

8
ui-ngx/src/app/core/utils.ts

@ -894,3 +894,11 @@ export const camelCase = (str: string): string => {
export const convertKeysToCamelCase = (obj: Record<string, any>): Record<string, any> => {
return _.mapKeys(obj, (value, key) => _.camelCase(key));
};
export const unwrapModule = (module: any) : any => {
if ('default' in module && Object.keys(module).length === 1) {
return module.default;
} else {
return module;
}
};

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

@ -100,7 +100,6 @@ import * as TruncateWithTooltipDirective from '@shared/directives/truncate-with-
import * as coercion from '@shared/decorators/coercion';
import * as enumerable from '@shared/decorators/enumerable';
import * as TbInject from '@shared/decorators/tb-inject';
import * as FooterComponent from '@shared/components/footer.component';
import * as LogoComponent from '@shared/components/logo.component';
@ -432,7 +431,6 @@ class ModulesMap implements IModulesMap {
'@shared/decorators/coercion': coercion,
'@shared/decorators/enumerable': enumerable,
'@shared/decorators/tb-inject': TbInject,
'@shared/import-export/import-export.service': ImportExportService,
'@shared/import-export/import-dialog.component': ImportDialogComponent,

2
ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts

@ -121,7 +121,7 @@ export class EntityVersionDiffComponent extends PageComponent implements OnInit,
this.popoverComponent.updatePosition();
}
setTimeout(() => {
this.differ = new aceDiff.default(
this.differ = new aceDiff(
{
element: this.diffViewerElmRef.nativeElement,
mode: 'ace/mode/json',

20
ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.component.ts

@ -15,16 +15,13 @@
///
import { MatDialogRef } from '@angular/material/dialog';
import { Directive, InjectionToken } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { Directive, inject, InjectionToken } from '@angular/core';
import { Router } from '@angular/router';
import { PageComponent } from '@shared/components/page.component';
import { CustomDialogContainerComponent } from './custom-dialog-container.component';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { TbInject } from '@shared/decorators/tb-inject';
export const CUSTOM_DIALOG_DATA = new InjectionToken<any>('ConfigDialogData');
export const CUSTOM_DIALOG_DATA = new InjectionToken<CustomDialogData>('ConfigDialogData');
export interface CustomDialogData {
controller: (instance: CustomDialogComponent) => void;
@ -37,12 +34,13 @@ export class CustomDialogComponent extends PageComponent {
[key: string]: any;
constructor(@TbInject(Store) protected store: Store<AppState>,
@TbInject(Router) protected router: Router,
@TbInject(MatDialogRef) public dialogRef: MatDialogRef<CustomDialogContainerComponent>,
@TbInject(UntypedFormBuilder) public fb: UntypedFormBuilder,
@TbInject(CUSTOM_DIALOG_DATA) public data: CustomDialogData) {
super(store);
protected router = inject(Router);
public dialogRef = inject(MatDialogRef<CustomDialogContainerComponent>);
public data = inject(CUSTOM_DIALOG_DATA);
public fb = inject(UntypedFormBuilder);
constructor() {
super();
// @ts-ignore
this.validators = Validators;
this.data.controller(this);

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

@ -15,10 +15,13 @@
///
import { PageComponent } from '@shared/components/page.component';
import { Directive, Injector, OnDestroy, OnInit, TemplateRef } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { IDynamicWidgetComponent, WidgetContext } from '@home/models/widget-component.models';
import { Directive, inject, Injector, OnDestroy, OnInit } from '@angular/core';
import {
IDynamicWidgetComponent,
widgetContextToken,
widgetErrorMessagesToken,
widgetTitlePanelToken
} from '@home/models/widget-component.models';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { RafService } from '@core/services/raf.service';
import {
@ -45,7 +48,6 @@ import { DatePipe } from '@angular/common';
import { TranslateService } from '@ngx-translate/core';
import { DomSanitizer } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { TbInject } from '@shared/decorators/tb-inject';
import { MillisecondsToTimeStringPipe } from '@shared/pipe/milliseconds-to-time-string.pipe';
import { UserSettingsService } from '@core/http/user-settings.service';
import { ImagePipe } from '@shared/pipe/image.pipe';
@ -64,38 +66,39 @@ export class DynamicWidgetComponent extends PageComponent implements IDynamicWid
validators = Validators;
constructor(@TbInject(RafService) public raf: RafService,
@TbInject(Store) protected store: Store<AppState>,
@TbInject(UntypedFormBuilder) public fb: UntypedFormBuilder,
@TbInject(Injector) public readonly $injector: Injector,
@TbInject('widgetContext') public readonly ctx: WidgetContext,
@TbInject('errorMessages') public readonly errorMessages: string[],
@TbInject('widgetTitlePanel') public readonly widgetTitlePanel: TemplateRef<any>) {
super(store);
this.ctx.$injector = $injector;
this.ctx.deviceService = $injector.get(DeviceService);
this.ctx.assetService = $injector.get(AssetService);
this.ctx.entityViewService = $injector.get(EntityViewService);
this.ctx.customerService = $injector.get(CustomerService);
this.ctx.dashboardService = $injector.get(DashboardService);
this.ctx.userService = $injector.get(UserService);
this.ctx.attributeService = $injector.get(AttributeService);
this.ctx.entityRelationService = $injector.get(EntityRelationService);
this.ctx.entityService = $injector.get(EntityService);
this.ctx.authService = $injector.get(AuthService);
this.ctx.dialogs = $injector.get(DialogService);
this.ctx.customDialog = $injector.get(CustomDialogService);
this.ctx.resourceService = $injector.get(ResourceService);
this.ctx.userSettingsService = $injector.get(UserSettingsService);
this.ctx.utilsService = $injector.get(UtilsService);
this.ctx.telemetryWsService = $injector.get(TelemetryWebsocketService);
this.ctx.date = $injector.get(DatePipe);
this.ctx.imagePipe = $injector.get(ImagePipe);
this.ctx.milliSecondsToTimeString = $injector.get(MillisecondsToTimeStringPipe);
this.ctx.translate = $injector.get(TranslateService);
this.ctx.http = $injector.get(HttpClient);
this.ctx.sanitizer = $injector.get(DomSanitizer);
this.ctx.router = $injector.get(Router);
public raf = inject(RafService);
public fb = inject(UntypedFormBuilder);
public readonly $injector = inject(Injector);
public readonly ctx = inject(widgetContextToken);
public readonly errorMessages = inject(widgetErrorMessagesToken);
public readonly widgetTitlePanel = inject(widgetTitlePanelToken);
constructor() {
super();
this.ctx.$injector = this.$injector;
this.ctx.deviceService = this.$injector.get(DeviceService);
this.ctx.assetService = this.$injector.get(AssetService);
this.ctx.entityViewService = this.$injector.get(EntityViewService);
this.ctx.customerService = this.$injector.get(CustomerService);
this.ctx.dashboardService = this.$injector.get(DashboardService);
this.ctx.userService = this.$injector.get(UserService);
this.ctx.attributeService = this.$injector.get(AttributeService);
this.ctx.entityRelationService = this.$injector.get(EntityRelationService);
this.ctx.entityService = this.$injector.get(EntityService);
this.ctx.authService = this.$injector.get(AuthService);
this.ctx.dialogs = this.$injector.get(DialogService);
this.ctx.customDialog = this.$injector.get(CustomDialogService);
this.ctx.resourceService = this.$injector.get(ResourceService);
this.ctx.userSettingsService = this.$injector.get(UserSettingsService);
this.ctx.utilsService = this.$injector.get(UtilsService);
this.ctx.telemetryWsService = this.$injector.get(TelemetryWebsocketService);
this.ctx.date = this.$injector.get(DatePipe);
this.ctx.imagePipe = this.$injector.get(ImagePipe);
this.ctx.milliSecondsToTimeString = this.$injector.get(MillisecondsToTimeStringPipe);
this.ctx.translate = this.$injector.get(TranslateService);
this.ctx.http = this.$injector.get(HttpClient);
this.ctx.sanitizer = this.$injector.get(DomSanitizer);
this.ctx.router = this.$injector.get(Router);
this.ctx.$scope = this;
if (this.ctx.defaultSubscription) {

4
ui-ngx/src/app/modules/home/components/widget/lib/mobile-app-qrcode-widget.component.ts

@ -24,7 +24,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
import { UtilsService } from '@core/services/utils.service';
import { Observable, Subject } from 'rxjs';
import { MINUTE } from '@shared/models/time/time.models';
import { isDefinedAndNotNull, mergeDeep } from '@core/utils';
import { isDefinedAndNotNull, mergeDeep, unwrapModule } from '@core/utils';
import { backgroundStyle, ComponentStyle, overlayStyle } from '@shared/models/widget-settings.models';
import { ImagePipe } from '@shared/pipe/image.pipe';
import { DomSanitizer } from '@angular/platform-browser';
@ -157,7 +157,7 @@ export class MobileAppQrcodeWidgetComponent extends PageComponent implements OnI
private updateQRCode(link: string) {
import('qrcode').then((QRCode) => {
QRCode.toString(link, (err, string) => {
unwrapModule(QRCode).toString(link, (err, string) => {
this.qrCodeSVG = string;
this.cd.markForCheck();
})

4
ui-ngx/src/app/modules/home/components/widget/lib/qrcode-widget.component.ts

@ -28,7 +28,7 @@ import {
isNumber,
isObject,
parseFunction,
safeExecute
safeExecute, unwrapModule
} from '@core/utils';
interface QrCodeWidgetSettings {
@ -124,7 +124,7 @@ export class QrCodeWidgetComponent extends PageComponent implements OnInit, Afte
private updateCanvas() {
if (this.viewInited) {
import('qrcode').then((QRCode) => {
QRCode.toCanvas(this.canvasRef.nativeElement, this.qrCodeText);
unwrapModule(QRCode).toCanvas(this.canvasRef.nativeElement, this.qrCodeText);
this.canvasRef.nativeElement.style.width = 'auto';
this.canvasRef.nativeElement.style.height = 'auto';
});

6
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action.models.ts

@ -19,9 +19,9 @@ import { widgetContextCompletions } from '@shared/models/ace/widget-completion.m
import { entityIdHref, entityTypeHref, serviceCompletions } from '@shared/models/ace/service-completion.models';
import { CustomActionDescriptor, WidgetAction } from '@shared/models/widget.models';
import { deepClone, isDefined, isUndefined } from '@core/utils';
import customSampleJs from '!raw-loader!./custom-sample-js.raw';
import customSampleCss from '!raw-loader!./custom-sample-css.raw';
import customSampleHtml from '!raw-loader!./custom-sample-html.raw';
import customSampleJs from './custom-sample-js.raw';
import customSampleCss from './custom-sample-css.raw';
import customSampleHtml from './custom-sample-html.raw';
const customActionCompletions: TbEditorCompletions = {
...{

15
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-provider-settings.component.ts

@ -29,6 +29,10 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core';
import {
defaultGoogleMapProviderSettings,
defaultHereMapProviderSettings,
defaultImageMapProviderSettings,
defaultOpenStreetMapProviderSettings, defaultTencentMapProviderSettings,
GoogleMapProviderSettings,
HereMapProviderSettings,
ImageMapProviderSettings,
@ -39,7 +43,6 @@ import {
TencentMapProviderSettings
} from '@home/components/widget/lib/maps/map-models';
import { extractType } from '@core/utils';
import { keys } from 'ts-transformer-keys';
import { IAliasController } from '@core/api/widget-api.models';
@Component({
@ -128,11 +131,11 @@ export class MapProviderSettingsComponent extends PageComponent implements OnIni
writeValue(value: MapProviderSettings): void {
this.modelValue = value;
const provider = value?.provider;
const googleProviderSettings = extractType<GoogleMapProviderSettings>(value, keys<GoogleMapProviderSettings>());
const openstreetProviderSettings = extractType<OpenStreetMapProviderSettings>(value, keys<OpenStreetMapProviderSettings>());
const hereProviderSettings = extractType<HereMapProviderSettings>(value, keys<HereMapProviderSettings>());
const imageMapProviderSettings = extractType<ImageMapProviderSettings>(value, keys<ImageMapProviderSettings>());
const tencentMapProviderSettings = extractType<TencentMapProviderSettings>(value, keys<TencentMapProviderSettings>());
const googleProviderSettings = extractType<GoogleMapProviderSettings>(value, Object.keys(defaultGoogleMapProviderSettings) as (keyof GoogleMapProviderSettings)[]);
const openstreetProviderSettings = extractType<OpenStreetMapProviderSettings>(value, Object.keys(defaultOpenStreetMapProviderSettings) as (keyof OpenStreetMapProviderSettings)[]);
const hereProviderSettings = extractType<HereMapProviderSettings>(value, Object.keys(defaultHereMapProviderSettings) as (keyof HereMapProviderSettings)[]);
const imageMapProviderSettings = extractType<ImageMapProviderSettings>(value, Object.keys(defaultImageMapProviderSettings) as (keyof ImageMapProviderSettings)[]);
const tencentMapProviderSettings = extractType<TencentMapProviderSettings>(value, Object.keys(defaultTencentMapProviderSettings) as (keyof TencentMapProviderSettings)[]);
this.providerSettingsFormGroup.patchValue(
{
provider,

26
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-settings.component.ts

@ -17,11 +17,11 @@
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import {
ControlValueAccessor,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
UntypedFormBuilder,
UntypedFormControl,
UntypedFormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
Validator
} from '@angular/forms';
import { PageComponent } from '@shared/components/page.component';
@ -31,6 +31,13 @@ import { TranslateService } from '@ngx-translate/core';
import {
CircleSettings,
CommonMapSettings,
defaultCircleSettings,
defaultCommonMapSettings,
defaultMapEditorSettings,
defaultMapProviderSettings,
defaultMarkerClusteringSettings,
defaultMarkersSettings,
defaultPolygonSettings,
MapEditorSettings,
MapProviders,
MapProviderSettings,
@ -41,7 +48,6 @@ import {
UnitedMapSettings
} from '@home/components/widget/lib/maps/map-models';
import { extractType } from '@core/utils';
import { keys } from 'ts-transformer-keys';
import { IAliasController } from '@core/api/widget-api.models';
import { Widget } from '@shared/models/widget.models';
@ -140,12 +146,12 @@ export class MapSettingsComponent extends PageComponent implements OnInit, Contr
writeValue(value: UnitedMapSettings): void {
this.modelValue = value;
const mapProviderSettings = extractType<MapProviderSettings>(value, keys<MapProviderSettings>());
const commonMapSettings = extractType<CommonMapSettings>(value, keys<CommonMapSettings>());
const markersSettings = extractType<MarkersSettings>(value, keys<MarkersSettings>());
const polygonSettings = extractType<PolygonSettings>(value, keys<PolygonSettings>());
const circleSettings = extractType<CircleSettings>(value, keys<CircleSettings>());
const mapEditorSettings = extractType<MapEditorSettings>(value, keys<MapEditorSettings>());
const mapProviderSettings = extractType<MapProviderSettings>(value, Object.keys(defaultMapProviderSettings) as (keyof MapProviderSettings)[]);
const commonMapSettings = extractType<CommonMapSettings>(value, Object.keys(defaultCommonMapSettings) as (keyof CommonMapSettings)[]);
const markersSettings = extractType<MarkersSettings>(value, Object.keys(defaultMarkersSettings) as (keyof MarkersSettings)[]);
const polygonSettings = extractType<PolygonSettings>(value, Object.keys(defaultPolygonSettings) as (keyof PolygonSettings)[]);
const circleSettings = extractType<CircleSettings>(value, Object.keys(defaultCircleSettings) as (keyof CircleSettings)[]);
const mapEditorSettings = extractType<MapEditorSettings>(value, Object.keys(defaultMapEditorSettings) as (keyof MapEditorSettings)[]);
const formValue = {
mapProviderSettings,
commonMapSettings,
@ -157,7 +163,7 @@ export class MapSettingsComponent extends PageComponent implements OnInit, Contr
if (this.routeMap) {
formValue.routeMapSettings = extractType<PolylineSettings>(value, ['strokeWeight', 'strokeOpacity']);
} else {
formValue.markerClusteringSettings = extractType<MarkerClusteringSettings>(value, keys<MarkerClusteringSettings>());
formValue.markerClusteringSettings = extractType<MarkerClusteringSettings>(value, Object.keys(defaultMarkerClusteringSettings) as (keyof MarkerClusteringSettings)[]);
}
this.mapSettingsFormGroup.patchValue( formValue, {emitEvent: false} );
this.updateValidators(false);

28
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-widget-settings.component.ts

@ -21,16 +21,22 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import {
CircleSettings,
CommonMapSettings,
defaultCircleSettings,
defaultCommonMapSettings,
defaultMapProviderSettings,
defaultMarkersSettings,
defaultPolygonSettings,
defaultTripAnimationPathSettings,
defaultTripAnimationPointSettings,
defaultTripAnimationSettings,
MapProviderSettings,
MarkersSettings,
PointsSettings,
PolygonSettings,
PolylineSettings,
TripAnimationCommonSettings,
TripAnimationMarkerSettings
PolylineSettings
} from 'src/app/modules/home/components/widget/lib/maps/map-models';
import { extractType } from '@core/utils';
import { keys } from 'ts-transformer-keys';
@Component({
selector: 'tb-trip-animation-widget-settings',
@ -69,13 +75,13 @@ export class TripAnimationWidgetSettingsComponent extends WidgetSettingsComponen
}
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
const mapProviderSettings = extractType<MapProviderSettings>(settings, keys<MapProviderSettings>());
const commonMapSettings = extractType<TripAnimationCommonSettings>(settings, keys<TripAnimationCommonSettings>());
const markersSettings = extractType<TripAnimationMarkerSettings>(settings, keys<TripAnimationMarkerSettings>());
const pathSettings = extractType<PolylineSettings>(settings, keys<PolylineSettings>());
const pointSettings = extractType<PointsSettings>(settings, keys<PointsSettings>());
const polygonSettings = extractType<PolygonSettings>(settings, keys<PolygonSettings>());
const circleSettings = extractType<CircleSettings>(settings, keys<CircleSettings>());
const mapProviderSettings = extractType<MapProviderSettings>(settings, Object.keys(defaultMapProviderSettings) as (keyof MapProviderSettings)[]);
const commonMapSettings = extractType<CommonMapSettings>(settings, Object.keys(defaultCommonMapSettings) as (keyof CommonMapSettings)[]);
const markersSettings = extractType<MarkersSettings>(settings, Object.keys(defaultMarkersSettings) as (keyof MarkersSettings)[]);
const pathSettings = extractType<PolylineSettings>(settings, Object.keys(defaultTripAnimationPathSettings) as (keyof PolylineSettings)[]);
const pointSettings = extractType<PointsSettings>(settings, Object.keys(defaultTripAnimationPointSettings) as (keyof PointsSettings)[]);
const polygonSettings = extractType<PolygonSettings>(settings, Object.keys(defaultPolygonSettings) as (keyof PolygonSettings)[]);
const circleSettings = extractType<CircleSettings>(settings, Object.keys(defaultCircleSettings) as (keyof CircleSettings)[]);
return {
mapProviderSettings,
commonMapSettings,

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

@ -129,11 +129,13 @@ export class WidgetComponentService {
w.tinycolor = tinycolor;
w.cssjs = cssjs;
w.moment = moment;
w.$ = $;
w.jQuery = $;
const widgetModulesTasks: Observable<any>[] = [];
widgetModulesTasks.push(from(import('jquery.terminal')));
widgetModulesTasks.push(from(import('jquery.terminal')).pipe(
tap((mod) => {
mod.default(window, $);
})
));
widgetModulesTasks.push(from(import('flot/src/jquery.flot.js')).pipe(
mergeMap(() => {

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

@ -70,9 +70,9 @@ import {
IDynamicWidgetComponent,
ShowWidgetHeaderActionFunction,
updateEntityParams,
WidgetContext,
WidgetContext, widgetContextToken, widgetErrorMessagesToken,
WidgetHeaderAction,
WidgetInfo,
WidgetInfo, widgetTitlePanelToken,
WidgetTypeInstance
} from '@home/models/widget-component.models';
import {
@ -743,15 +743,15 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
{
providers: [
{
provide: 'widgetContext',
provide: widgetContextToken,
useValue: this.widgetContext
},
{
provide: 'errorMessages',
provide: widgetErrorMessagesToken,
useValue: this.errorMessages
},
{
provide: 'widgetTitlePanel',
provide: widgetTitlePanelToken,
useValue: this.widgetTitlePanel
}
],

6
ui-ngx/src/app/modules/home/models/widget-component.models.ts

@ -47,7 +47,7 @@ import {
WidgetActionsApi,
WidgetSubscriptionApi
} from '@core/api/widget-api.models';
import { ChangeDetectorRef, Injector, NgZone, Type } from '@angular/core';
import { ChangeDetectorRef, InjectionToken, Injector, NgZone, TemplateRef, Type } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { RafService } from '@core/services/raf.service';
import { WidgetTypeId } from '@shared/models/id/widget-type-id';
@ -538,6 +538,10 @@ export class LabelVariablePattern {
}
}
export const widgetContextToken = new InjectionToken<WidgetContext>('widgetContext');
export const widgetErrorMessagesToken = new InjectionToken<string[]>('errorMessages');
export const widgetTitlePanelToken = new InjectionToken<TemplateRef<any>>('widgetTitlePanel');
export interface IDynamicWidgetComponent {
readonly ctx: WidgetContext;
readonly errorMessages: string[];

2
ui-ngx/src/app/modules/home/pages/security/authentication-dialog/backup-code-auth-dialog.component.ts

@ -31,7 +31,7 @@ import { mergeMap, tap } from 'rxjs/operators';
import { ImportExportService } from '@shared/import-export/import-export.service';
import { deepClone } from '@core/utils';
import printTemplate from '!raw-loader!./backup-code-print-template.raw';
import printTemplate from './backup-code-print-template.raw';
@Component({
selector: 'tb-backup-code-auth-dialog',

3
ui-ngx/src/app/modules/home/pages/security/authentication-dialog/totp-auth-dialog.component.ts

@ -28,6 +28,7 @@ import {
TwoFactorAuthProviderType
} from '@shared/models/two-factor-auth.models';
import { MatStepper } from '@angular/material/stepper';
import { unwrapModule } from '@core/utils';
@Component({
selector: 'tb-totp-auth-dialog',
@ -56,7 +57,7 @@ export class TotpAuthDialogComponent extends DialogComponent<TotpAuthDialogCompo
this.totpAuthURL = this.authAccountConfig.authUrl;
this.authAccountConfig.useByDefault = true;
import('qrcode').then((QRCode) => {
QRCode.toCanvas(this.canvasRef.nativeElement, this.totpAuthURL);
unwrapModule(QRCode).toCanvas(this.canvasRef.nativeElement, this.totpAuthURL);
this.canvasRef.nativeElement.style.width = 'auto';
this.canvasRef.nativeElement.style.height = 'auto';
});

8
ui-ngx/src/app/shared/components/json-form/json-form.component.ts

@ -31,7 +31,7 @@ import { ControlValueAccessor, UntypedFormControl, NG_VALIDATORS, NG_VALUE_ACCES
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { deepClone, isString } from '@app/core/utils';
import { deepClone, isString, unwrapModule } from '@app/core/utils';
import { JsonFormProps } from './react/json-form.models';
import inspector from 'schema-inspector';
import tinycolor from 'tinycolor2';
@ -270,9 +270,9 @@ export class JsonFormComponent implements ControlValueAccessor, Validator, OnCha
];
forkJoin(reactSchemaFormObservables).subscribe(
(modules) => {
const react = modules[0];
const reactDomClient = modules[2];
const jsonFormReact = modules[3].default;
const react = unwrapModule(modules[0]);
const reactDomClient = unwrapModule(modules[2]);
const jsonFormReact = unwrapModule(modules[3]);
this.reactRoot = reactDomClient.createRoot(this.reactRootElmRef.nativeElement);
this.reactRoot.render(react.createElement(jsonFormReact, this.formProps));
}

7
ui-ngx/src/app/shared/components/json-form/react/json-form-ace-editor.tsx

@ -20,18 +20,21 @@ import reactCSS from 'reactcss';
import Button from '@mui/material/Button';
import { JsonFormFieldProps, JsonFormFieldState } from '@shared/components/json-form/react/json-form.models';
import { IEditorProps } from 'react-ace/src/types';
import { mergeMap } from 'rxjs/operators';
import { map, mergeMap } from 'rxjs/operators';
import { getAce } from '@shared/models/ace/ace.models';
import { from, lastValueFrom } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import { CircularProgress, IconButton } from '@mui/material';
import { MouseEvent } from 'react';
import { Help, HelpOutline } from '@mui/icons-material';
import { unwrapModule } from '@core/utils';
const ReactAce = React.lazy(() => {
return lastValueFrom(getAce().pipe(
mergeMap(() => {
return from(import('react-ace'));
return from(import('react-ace')).pipe(
map((module) => unwrapModule(module)
));
})
));
});

7
ui-ngx/src/app/shared/components/json-form/react/json-form-schema-form.tsx

@ -51,6 +51,7 @@ import { MouseEvent, ReactNode } from 'react';
class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
private hasConditions: boolean;
private conditionFunction: Function;
private readonly mapper: {[type: string]: any};
constructor(props: JsonFormProps) {
@ -130,8 +131,10 @@ class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
}
if (form.condition) {
this.hasConditions = true;
// tslint:disable-next-line:no-eval
if (eval(form.condition) === false) {
if (!this.conditionFunction) {
this.conditionFunction = new Function('form', 'model', 'index', `return ${form.condition};`);
}
if (this.conditionFunction(form, model, index) === false) {
return null;
}
}

6
ui-ngx/src/app/shared/components/page.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Directive, OnDestroy } from '@angular/core';
import { Directive, inject, OnDestroy } from '@angular/core';
import { select, Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { Observable, Subscription } from 'rxjs';
@ -25,13 +25,15 @@ import { AbstractControl } from '@angular/forms';
@Directive()
export abstract class PageComponent implements OnDestroy {
protected store: Store<AppState> = inject(Store<AppState>);
isLoading$: Observable<boolean>;
loadingSubscription: Subscription;
disabledOnLoadFormControls: Array<AbstractControl> = [];
showMainLoadingBar = true;
protected constructor(protected store: Store<AppState>) {
protected constructor(...args: unknown[]) {
this.isLoading$ = this.store.pipe(delay(0), select(selectIsLoading), share());
}

1
ui-ngx/src/app/shared/decorators/public-api.ts

@ -16,4 +16,3 @@
export * from './coercion';
export * from './enumerable';
export * from './tb-inject';

23
ui-ngx/src/app/shared/decorators/tb-inject.ts

@ -1,23 +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 { Inject, Type } from '@angular/core';
export function TbInject<T>(token: any): (target: Type<T>, key: any, paramIndex: number) => void {
return (target: Type<T>, key: any, paramIndex: number) => {
Inject(token)(target, key, paramIndex);
};
}

9
ui-ngx/src/app/shared/models/ace/ace.models.ts

@ -18,6 +18,7 @@ import { Ace } from 'ace-builds';
import { Observable } from 'rxjs/internal/Observable';
import { forkJoin, from, of } from 'rxjs';
import { map, mergeMap, tap } from 'rxjs/operators';
import { unwrapModule } from '@core/utils';
let aceDependenciesLoaded = false;
let aceModule: any;
@ -67,10 +68,10 @@ export function getAce(): Observable<any> {
if (aceModule) {
return of(aceModule);
} else {
return from(import('ace')).pipe(
return from(import('ace-builds/src-noconflict/ace')).pipe(
mergeMap((module) => {
return loadAceDependencies().pipe(
map(() => module)
map(() => unwrapModule(module))
);
}),
tap((module) => {
@ -86,7 +87,9 @@ export function getAceDiff(): Observable<any> {
} else {
return getAce().pipe(
mergeMap((ace) => {
return from(import('ace-diff'));
return from(import('ace-diff')).pipe(
map((module) => unwrapModule(module))
);
}),
tap((module) => {
aceDiffModule = module;

4
ui-ngx/src/app/shared/models/beautify.models.ts

@ -17,6 +17,7 @@
import { Observable } from 'rxjs/internal/Observable';
import { from, of } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { unwrapModule } from '@core/utils';
let jsBeautifyModule: any;
let htmlBeautifyModule: any;
@ -27,6 +28,7 @@ function loadJsBeautify(): Observable<any> {
return of(jsBeautifyModule);
} else {
return from(import('js-beautify/js/lib/beautify.js')).pipe(
map((module) => unwrapModule(module)),
tap((module) => {
jsBeautifyModule = module;
})
@ -39,6 +41,7 @@ function loadHtmlBeautify(): Observable<any> {
return of(htmlBeautifyModule);
} else {
return from(import('js-beautify/js/lib/beautify-html.js')).pipe(
map((module) => unwrapModule(module)),
tap((module) => {
htmlBeautifyModule = module;
})
@ -51,6 +54,7 @@ function loadCssBeautify(): Observable<any> {
return of(cssBeautifyModule);
} else {
return from(import('js-beautify/js/lib/beautify-css.js')).pipe(
map((module) => unwrapModule(module)),
tap((module) => {
cssBeautifyModule = module;
})

5
ui-ngx/src/main.ts

@ -22,6 +22,11 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from '@app/app.module';
import { environment } from '@env/environment';
import $ from 'jquery';
(window as any).jQuery = $;
(window as any).$ = $;
if (environment.production) {
enableProdMode();
}

4
ui-ngx/src/styles.scss

@ -15,8 +15,8 @@
*/
/* You can add global styles to this file, and also import other style files */
@import '~typeface-roboto/index.css';
@import '~font-awesome/css/font-awesome.min.css';
@import 'typeface-roboto/index.css';
@import 'font-awesome/css/font-awesome.min.css';
@import 'theme.scss';
@import './scss/constants';
@import './scss/animations';

4
ui-ngx/src/tsconfig.app.json

@ -6,7 +6,9 @@
"react", "react-dom", "raphael", "canvas-gauges", "systemjs"]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true
"fullTemplateTypeCheck": true,
"supportTestBed": true,
"supportJitMode": true
},
"files": [
"main.ts",

6
ui-ngx/src/typings/rawloader.typings.d.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
declare module '!raw-loader!*' {
const contents: string;
export = contents;
declare module '*.raw' {
const content: string;
export default content;
}

1
ui-ngx/tsconfig.json

@ -15,6 +15,7 @@
"module": "es2020",
"emitDecoratorMetadata": true,
"jsx": "react",
"resolveJsonModule": true,
"typeRoots": [
"node_modules/@types",
"src/typings"

189
ui-ngx/yarn.lock

@ -24,36 +24,34 @@
ts-node "^10.0.0"
tsconfig-paths "^4.1.0"
"@angular-builders/custom-webpack@~18.0.0":
"@angular-builders/custom-esbuild@18.0.0":
version "18.0.0"
resolved "https://registry.yarnpkg.com/@angular-builders/custom-webpack/-/custom-webpack-18.0.0.tgz#b51f8b03d6fff4955f63cbe9e090e0366acc90d2"
integrity sha512-XSynPSXHq5+nrh7J2snfrcbvm6YGwUGQRzr7OuO3wURJ6CHOD9C+xEAmvEUWW8c1YjEslVNG7aLtCGz7LA4ymw==
resolved "https://registry.yarnpkg.com/@angular-builders/custom-esbuild/-/custom-esbuild-18.0.0.tgz#7da11ce47cfa0bbab1e5e07a9bdefb8a6afe8ed8"
integrity sha512-SdAGatJMJJjPYrdkUupdRazid3xe1sIj/CAHDdDVP094vZ9CrZs6fgcsOF17waAo6uMxrQCWmPDrTjNgR3CvMQ==
dependencies:
"@angular-builders/common" "2.0.0"
"@angular-devkit/architect" ">=0.1800.0 < 0.1900.0"
"@angular-devkit/build-angular" "^18.0.0"
"@angular-devkit/core" "^18.0.0"
lodash "^4.17.15"
webpack-merge "^5.7.3"
"@angular-devkit/architect@0.1802.7", "@angular-devkit/architect@>=0.1800.0 < 0.1900.0":
version "0.1802.7"
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1802.7.tgz#eb69e6b94473c3ca3428b71c5f31ee418724a8e5"
integrity sha512-kpcgXnepEXcoxDTbqbGj7Hg1WJLWj1HLR3/FKmC5TbpBf1xiLxiqfkQNwz3BbE/W9JWMLdrXr3GI9O3O2gWPLg==
"@angular-devkit/architect@0.1802.10", "@angular-devkit/architect@>=0.1800.0 < 0.1900.0":
version "0.1802.10"
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1802.10.tgz#1ae877263261e33a86fb3a047c3741ab09a9c599"
integrity sha512-/xudcHK2s4J/GcL6qyobmGaWMHQcYLSMqCaWMT+nK6I6tu9VEAj/p3R83Tzx8B/eKi31Pz499uHw9pmqdtbafg==
dependencies:
"@angular-devkit/core" "18.2.7"
"@angular-devkit/core" "18.2.10"
rxjs "7.8.1"
"@angular-devkit/build-angular@18.2.7", "@angular-devkit/build-angular@^18.0.0":
version "18.2.7"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-18.2.7.tgz#21b72596f270e4a5a16d38224b38e46a609aad80"
integrity sha512-u8PriYdgddK7k+OS/pOFPD1v4Iu5bztUJZXZVcGeXBZFFdnGFFzKmQw9mfcyGvTMJp2ABgBuuJT0YqYgNfAhzw==
"@angular-devkit/build-angular@18.2.10", "@angular-devkit/build-angular@^18.0.0":
version "18.2.10"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-18.2.10.tgz#7eab5b31856f8d3ce02e89771e3966328d13268f"
integrity sha512-47XgJ5fdIqlZUFWAo/XtNsh3y597DtLZWvfsnwShw6/TgyiV0rbL1Z24Rn2TCV1D/b3VhLutAIIZ/i5O5BirxQ==
dependencies:
"@ampproject/remapping" "2.3.0"
"@angular-devkit/architect" "0.1802.7"
"@angular-devkit/build-webpack" "0.1802.7"
"@angular-devkit/core" "18.2.7"
"@angular/build" "18.2.7"
"@angular-devkit/architect" "0.1802.10"
"@angular-devkit/build-webpack" "0.1802.10"
"@angular-devkit/core" "18.2.10"
"@angular/build" "18.2.10"
"@babel/core" "7.25.2"
"@babel/generator" "7.25.0"
"@babel/helper-annotate-as-pure" "7.24.7"
@ -64,7 +62,7 @@
"@babel/preset-env" "7.25.3"
"@babel/runtime" "7.25.0"
"@discoveryjs/json-ext" "0.6.1"
"@ngtools/webpack" "18.2.7"
"@ngtools/webpack" "18.2.10"
"@vitejs/plugin-basic-ssl" "1.1.0"
ansi-colors "4.1.3"
autoprefixer "10.4.20"
@ -75,7 +73,7 @@
css-loader "7.1.2"
esbuild-wasm "0.23.0"
fast-glob "3.3.2"
http-proxy-middleware "3.0.0"
http-proxy-middleware "3.0.3"
https-proxy-agent "7.0.5"
istanbul-lib-instrument "6.0.3"
jsonc-parser "3.3.1"
@ -114,18 +112,18 @@
optionalDependencies:
esbuild "0.23.0"
"@angular-devkit/build-webpack@0.1802.7":
version "0.1802.7"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1802.7.tgz#07c64d2763b10bedacff29795b778c81e888ca2c"
integrity sha512-VrtbrhZ+dht3f0GjtfRLRGRN4XHN/W+/bA9DqckdxVS6SydsrCWNHonvEPmOs4jJmGIGXIu6tUBMcWleTao2sg==
"@angular-devkit/build-webpack@0.1802.10":
version "0.1802.10"
resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1802.10.tgz#cf55fd2bee8a7d86b91bfeb0c8af9c22957c6727"
integrity sha512-WRftK/RJ9rBDDmkx5IAtIpyNo0DJiMfgGUTuZNpNUaJfSfGeaSZYgC7o1++axMchID8pncmI3Hr8L8gaP94WQg==
dependencies:
"@angular-devkit/architect" "0.1802.7"
"@angular-devkit/architect" "0.1802.10"
rxjs "7.8.1"
"@angular-devkit/core@18.2.7", "@angular-devkit/core@^18.0.0":
version "18.2.7"
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-18.2.7.tgz#f7133c9c50eb1916f8862370be975e4e2b84cca3"
integrity sha512-1ZTi4A6tEC2bkJ/puCIdIPYhesnlCVOMSDJL/lZAd0hC6X22T4pwu0AEvue7mcP5NbXpQDiBaXOZ3MmCA8PwOA==
"@angular-devkit/core@18.2.10", "@angular-devkit/core@^18.0.0":
version "18.2.10"
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-18.2.10.tgz#7565f0c7bf0fa3318d08c4a696e890ab0b670032"
integrity sha512-LFqiNdraBujg8e1lhuB0bkFVAoIbVbeXXwfoeROKH60OPbP8tHdgV6sFTqU7UGBKA+b+bYye70KFTG2Ys8QzKQ==
dependencies:
ajv "8.17.1"
ajv-formats "3.0.1"
@ -134,12 +132,12 @@
rxjs "7.8.1"
source-map "0.7.4"
"@angular-devkit/schematics@18.2.7":
version "18.2.7"
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-18.2.7.tgz#348cb0d790720a66e8183d6876effc262571086c"
integrity sha512-j7198lpkOXMG+Gyfln/5aDgBZV7m4pWMzHFhkO3+w3cbCNUN1TVZW0SyJcF+CYaxANzTbuumfvpsYc/fTeAGLw==
"@angular-devkit/schematics@18.2.10":
version "18.2.10"
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-18.2.10.tgz#2ca7dde6f8c9062c3ef8254a12edeffdd180272e"
integrity sha512-EIm/yCYg3ZYPsPYJxXRX5F6PofJCbNQ5rZEuQEY09vy+ZRTqGezH0qoUP5WxlYeJrjiRLYqADI9WtVNzDyaD4w==
dependencies:
"@angular-devkit/core" "18.2.7"
"@angular-devkit/core" "18.2.10"
jsonc-parser "3.3.1"
magic-string "0.30.11"
ora "5.4.1"
@ -206,13 +204,13 @@
dependencies:
tslib "^2.3.0"
"@angular/build@18.2.7":
version "18.2.7"
resolved "https://registry.yarnpkg.com/@angular/build/-/build-18.2.7.tgz#3bdb7c18e8f3bee00c0ce12a48216ce2df15f87c"
integrity sha512-oq6JsVxLP9/w9F2IjKroJwPB9CdlMblu2Xhfq/qQZRSUuM8Ppt1svr2FBTo1HrLIbosqukkVcSSdmKYDneo+cg==
"@angular/build@18.2.10":
version "18.2.10"
resolved "https://registry.yarnpkg.com/@angular/build/-/build-18.2.10.tgz#98eb7f1ced225483693280964482e617eba3eb1b"
integrity sha512-YFBKvAyC5sH17yRYcx7VHCtJ4KUg7xCjCQ4Pe16kiTvW6vuYsgU6Btyti0Qgewd7XaWpTM8hk8N6hE4Z0hpflw==
dependencies:
"@ampproject/remapping" "2.3.0"
"@angular-devkit/architect" "0.1802.7"
"@angular-devkit/architect" "0.1802.10"
"@babel/core" "7.25.2"
"@babel/helper-annotate-as-pure" "7.24.7"
"@babel/helper-split-export-declaration" "7.24.7"
@ -246,17 +244,17 @@
optionalDependencies:
parse5 "^7.1.2"
"@angular/cli@18.2.7":
version "18.2.7"
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-18.2.7.tgz#b5fe23d6d9d65d37ba580f1860c8a09c7578bc69"
integrity sha512-KoWgSvhRsU05A2m6B7jw1kdpyoS+Ce5GGLW6xcnX7VF2AckW54vYd/8ZkgpzQrKfvIpVblYd4KJGizKoaLZ5jA==
"@angular/cli@18.2.10":
version "18.2.10"
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-18.2.10.tgz#29ab1344bb496122b2689ebbb862f2b44fb31848"
integrity sha512-qW/F3XVZMzzenFzbn+7FGpw8GOt9qW8UxBtYya7gUNdWlcsgGUk+ZaGC2OLbfI5gX6pchW4TOPMsDSMeaCEI2Q==
dependencies:
"@angular-devkit/architect" "0.1802.7"
"@angular-devkit/core" "18.2.7"
"@angular-devkit/schematics" "18.2.7"
"@angular-devkit/architect" "0.1802.10"
"@angular-devkit/core" "18.2.10"
"@angular-devkit/schematics" "18.2.10"
"@inquirer/prompts" "5.3.8"
"@listr2/prompt-adapter-inquirer" "2.0.15"
"@schematics/angular" "18.2.7"
"@schematics/angular" "18.2.10"
"@yarnpkg/lockfile" "1.1.0"
ini "4.1.3"
jsonc-parser "3.3.1"
@ -276,14 +274,14 @@
dependencies:
tslib "^2.3.0"
"@angular/compiler-cli@18.2.6":
version "18.2.6"
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-18.2.6.tgz#84d94852ec5088107a9ffa81908b38c51c576bd5"
integrity sha512-b5x9STfjNiNM/S0D+CnqRP9UOxPtSz1+RlCH5WdOMiW/p8j5p6dBix8YYgTe6Wg3OD7eItD2pnFQKgF/dWiopA==
"@angular/compiler-cli@18.2.9":
version "18.2.9"
resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-18.2.9.tgz#637f40e0fbb210ccd8d4ff464ddb6628ffa0fc46"
integrity sha512-4iMoRvyMmq/fdI/4Gob9HKjL/jvTlCjbS4kouAYHuGO9w9dmUhi1pY1z+mALtCEl9/Q8CzU2W8e5cU2xtV4nVg==
dependencies:
"@babel/core" "7.25.2"
"@jridgewell/sourcemap-codec" "^1.4.14"
chokidar "^3.0.0"
chokidar "^4.0.0"
convert-source-map "^1.5.1"
reflect-metadata "^0.2.0"
semver "^7.0.0"
@ -318,10 +316,10 @@
dependencies:
tslib "^2.3.0"
"@angular/language-service@18.2.6":
version "18.2.6"
resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-18.2.6.tgz#c1cd36e40579b5bacaf0d666477c138577d2a6dd"
integrity sha512-GBvBvS2llh+/l2YhO7UO5o3GftlvQQoXnw3v0hcNoHKwcnvqXV4CCi+T2WOaZyK0iB8Is4QRbMrpJUC66HokZg==
"@angular/language-service@18.2.9":
version "18.2.9"
resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-18.2.9.tgz#f24f5e7e53036f6c9c4968113a3ea9ea827048f7"
integrity sha512-vC9la5VpvfX27ept36rlc42nGxDak7YfbWtSoZUageyZJUWyIEAvW8rNNPEvoO86RLi011/HmyyIr2GSQLKvxA==
"@angular/material@18.2.6":
version "18.2.6"
@ -2535,10 +2533,10 @@
dependencies:
tslib "^2.0.0"
"@ngtools/webpack@18.2.7":
version "18.2.7"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-18.2.7.tgz#2e8e7a3753ccdf49a3f350e082bdf79c7550db44"
integrity sha512-BmnFxss6zGobGyq9Mi7736golbK8RLgF+zYCQZ+4/OfMMA1jKVoELnyJqNyAx+DQn3m1qKVBjtGEL7pTNpPzOw==
"@ngtools/webpack@18.2.10":
version "18.2.10"
resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-18.2.10.tgz#6fd94d33a9de0b5f48f8b900a9d32e4f8c89872e"
integrity sha512-CGYr8rdM5ntdb4kLUAhrLBPrhJQ4KBPo3KMT6qJE/S+jJJn5zHzedpuGFOCVhC1Siw+n1pOBSI8leTRJIW/eCQ==
"@ngx-translate/core@^15.0.0":
version "15.0.0"
@ -2855,13 +2853,13 @@
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
"@schematics/angular@18.2.7":
version "18.2.7"
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-18.2.7.tgz#0b6caf0491618c2e9b24506cc68fb629845b6c6c"
integrity sha512-WOBzO11qstznHbC9tZXQf6/8+PqmaRI6QYcdTspqXNh9q9nNglvi43Xn4tSIpEhW8aSHea9hgWZV8sG+i/4W9Q==
"@schematics/angular@18.2.10":
version "18.2.10"
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-18.2.10.tgz#8ef1e67d266c334e71bac38cdef4cefab141f244"
integrity sha512-2pDHT4aSzfs8Up4RQmHHuFd5FeuUebS1ZJwyt46MfXzRMFtzUZV/JKsIvDqyMwnkvFfLvgJyTCkl8JGw5jQObg==
dependencies:
"@angular-devkit/core" "18.2.7"
"@angular-devkit/schematics" "18.2.7"
"@angular-devkit/core" "18.2.10"
"@angular-devkit/schematics" "18.2.10"
jsonc-parser "3.3.1"
"@sigstore/bundle@^2.3.2":
@ -3273,7 +3271,7 @@
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f"
integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==
"@types/http-proxy@^1.17.10", "@types/http-proxy@^1.17.8":
"@types/http-proxy@^1.17.15", "@types/http-proxy@^1.17.8":
version "1.17.15"
resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.15.tgz#12118141ce9775a6499ecb4c01d02f90fc839d36"
integrity sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==
@ -4354,7 +4352,7 @@ chevrotain@~11.0.3:
"@chevrotain/utils" "11.0.3"
lodash-es "4.17.21"
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.5.3, chokidar@^3.6.0:
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3, chokidar@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
@ -4369,6 +4367,13 @@ chevrotain@~11.0.3:
optionalDependencies:
fsevents "~2.3.2"
chokidar@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.1.tgz#4a6dff66798fb0f72a94f616abbd7e1a19f31d41"
integrity sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==
dependencies:
readdirp "^4.0.1"
chownr@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
@ -6515,17 +6520,17 @@ http-proxy-agent@^7.0.0:
agent-base "^7.1.0"
debug "^4.3.4"
http-proxy-middleware@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-3.0.0.tgz#550790357d6f92a9b82ab2d63e07343a791cf26b"
integrity sha512-36AV1fIaI2cWRzHo+rbcxhe3M3jUDCNzc4D5zRl57sEWRAxdXYtw7FSQKYY6PDKssiAKjLYypbssHk+xs/kMXw==
http-proxy-middleware@3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz#dc1313c75bd00d81e103823802551ee30130ebd1"
integrity sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==
dependencies:
"@types/http-proxy" "^1.17.10"
debug "^4.3.4"
"@types/http-proxy" "^1.17.15"
debug "^4.3.6"
http-proxy "^1.18.1"
is-glob "^4.0.1"
is-plain-obj "^3.0.0"
micromatch "^4.0.5"
is-glob "^4.0.3"
is-plain-object "^5.0.0"
micromatch "^4.0.8"
http-proxy-middleware@^2.0.3:
version "2.0.6"
@ -6860,6 +6865,11 @@ is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
is-plain-object@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
is-regex@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
@ -7524,7 +7534,7 @@ lodash.merge@^4.6.2:
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
lodash@4.17.21, lodash@^4.0.1, lodash@^4.17.14, lodash@^4.17.15:
lodash@4.17.21, lodash@^4.0.1, lodash@^4.17.14:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@ -7685,7 +7695,7 @@ methods@~1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
@ -9079,6 +9089,11 @@ readable-stream@^3.0.6, readable-stream@^3.4.0:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readdirp@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.0.2.tgz#388fccb8b75665da3abffe2d8f8ed59fe74c230a"
integrity sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
@ -10224,11 +10239,6 @@ ts-node@^10.0.0, ts-node@^10.9.2:
v8-compile-cache-lib "^3.0.1"
yn "3.1.1"
ts-transformer-keys@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/ts-transformer-keys/-/ts-transformer-keys-0.4.4.tgz#c185508b3ae9b79236aac58f788c85ca3ac807d7"
integrity sha512-LrqgvaFvar01/5mbunRyeLTSIkqoC2xfcpL/90aDY6vR07DGyH+UaYGdIEsUudnlAw2Sr0pxFgdZvE0QIyI4qA==
tsconfig-paths@^3.15.0:
version "3.15.0"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4"
@ -10646,15 +10656,6 @@ webpack-merge@6.0.1:
flat "^5.0.2"
wildcard "^2.0.1"
webpack-merge@^5.7.3:
version "5.10.0"
resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177"
integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==
dependencies:
clone-deep "^4.0.1"
flat "^5.0.2"
wildcard "^2.0.0"
webpack-sources@^3.0.0, webpack-sources@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
@ -10780,7 +10781,7 @@ which@^4.0.0:
dependencies:
isexe "^3.1.1"
wildcard@^2.0.0, wildcard@^2.0.1:
wildcard@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67"
integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==

Loading…
Cancel
Save