This is an automated email from the ASF dual-hosted git repository. nealsun pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/helix.git
The following commit(s) were added to refs/heads/master by this push: new 3ad6c4ee2 Update UI for Node Ideal State [helix-front] (#2162) 3ad6c4ee2 is described below commit 3ad6c4ee29b850c59221327f4e0384d7331a97dc Author: Micah Stubbs <micah.stu...@gmail.com> AuthorDate: Tue Jun 21 14:30:26 2022 -0700 Update UI for Node Ideal State [helix-front] (#2162) Enable Ideal State updates through the Helix UI. --- helix-front/angular.json | 39 +++++++- helix-front/assemble/{package.sh => assemble.sh} | 0 helix-front/client/app/app.component.html | 2 +- .../client/app/resource/shared/resource.model.ts | 2 +- .../client/app/resource/shared/resource.service.ts | 13 +++ .../shared/input-inline/input-inline.component.ts | 2 +- .../shared/node-viewer/node-viewer.component.html | 9 +- .../node-viewer/node-viewer.component.spec.ts | 4 + .../shared/node-viewer/node-viewer.component.ts | 102 ++++++++++++++------ helix-front/client/app/shared/shared.module.ts | 2 + helix-front/package.json | 33 ++++--- helix-front/pom.xml | 2 +- helix-front/proxy.conf.json | 2 +- helix-front/yarn.lock | 106 +++++++++++++-------- 14 files changed, 225 insertions(+), 93 deletions(-) diff --git a/helix-front/angular.json b/helix-front/angular.json index c6e0f92a7..9ffd4f108 100644 --- a/helix-front/angular.json +++ b/helix-front/angular.json @@ -17,9 +17,25 @@ "main": "client/main.ts", "tsConfig": "client/tsconfig.app.json", "polyfills": "client/polyfills.ts", - "assets": ["client/assets", "client/favicon.ico"], + "assets": [ + "client/assets", + "client/favicon.ico", + { + "glob": "**/*", + "input": "node_modules/ace-builds/src-min/", + "output": "/" + } + ], "styles": ["client/styles.scss", "client/theme.scss"], - "scripts": [], + "scripts": [ + "node_modules/ace-builds/src-min/ace.js", + "node_modules/ace-builds/src-min/theme-eclipse.js", + "node_modules/ace-builds/src-min/theme-chrome.js", + "node_modules/ace-builds/src-min/mode-javascript.js", + "node_modules/ace-builds/src-min/mode-html.js", + "node_modules/ace-builds/src-min/mode-css.js", + "node_modules/ace-builds/src-min/mode-json.js" + ], "vendorChunk": true, "extractLicenses": false, "buildOptimizer": false, @@ -81,9 +97,24 @@ "tsConfig": "client/tsconfig.spec.json", "polyfills": ["client/polyfills.ts"], "no-cache": true, - "scripts": [], + "scripts": [ + "node_modules/ace-builds/src-min/ace.js", + "node_modules/ace-builds/src-min/theme-eclipse.js", + "node_modules/ace-builds/src-min/mode-javascript.js", + "node_modules/ace-builds/src-min/mode-html.js", + "node_modules/ace-builds/src-min/mode-css.js", + "node_modules/ace-builds/src-min/mode-json.js" + ], "styles": ["client/styles.scss", "client/theme.scss"], - "assets": ["client/assets", "client/favicon.ico"] + "assets": [ + "client/assets", + "client/favicon.ico", + { + "glob": "worker-html.js", + "input": "node_modules/ace-builds/src-min/", + "output": "/" + } + ] } }, "lint": { diff --git a/helix-front/assemble/package.sh b/helix-front/assemble/assemble.sh similarity index 100% rename from helix-front/assemble/package.sh rename to helix-front/assemble/assemble.sh diff --git a/helix-front/client/app/app.component.html b/helix-front/client/app/app.component.html index f1656dac7..bc4b8f36c 100644 --- a/helix-front/client/app/app.component.html +++ b/helix-front/client/app/app.component.html @@ -47,6 +47,6 @@ fxLayout="row" fxLayoutAlign="center center" > - <span>© 2018 Helix. All rights reserved.</span> + <span>© 2022 Helix. All rights reserved.</span> </section> </section> diff --git a/helix-front/client/app/resource/shared/resource.model.ts b/helix-front/client/app/resource/shared/resource.model.ts index 496482584..e1b2ea0b3 100644 --- a/helix-front/client/app/resource/shared/resource.model.ts +++ b/helix-front/client/app/resource/shared/resource.model.ts @@ -79,7 +79,7 @@ export class Resource { for (const partitionName in externalView.mapFields) { const partition = new Partition(partitionName); - // in FULL_ATUO mode, externalView is more important + // in FULL_AUTO mode, externalView is more important // if preferences list exists, fetch instances from it, else whatever if ( this.rebalanceMode != 'FULL_AUTO' && diff --git a/helix-front/client/app/resource/shared/resource.service.ts b/helix-front/client/app/resource/shared/resource.service.ts index 8e7356cde..601a62ff0 100644 --- a/helix-front/client/app/resource/shared/resource.service.ts +++ b/helix-front/client/app/resource/shared/resource.service.ts @@ -6,6 +6,7 @@ import * as _ from 'lodash'; import { HelixService } from '../../core/helix.service'; import { Resource } from './resource.model'; import { Cluster } from '../../cluster/shared/cluster.model'; +import { Node } from '../../shared/models/node.model'; @Injectable() export class ResourceService extends HelixService { @@ -109,4 +110,16 @@ export class ResourceService extends HelixService { public remove(clusterName: string, resourceName: string) { return this.delete(`/clusters/${clusterName}/resources/${resourceName}`); } + + public setIdealState( + clusterName: string, + resourceName: string, + idealState: Node + ) { + return this.post( + `/clusters/${clusterName}/resources/${resourceName}/idealState?command=update`, + JSON.stringify(idealState) + ); + } } + diff --git a/helix-front/client/app/shared/input-inline/input-inline.component.ts b/helix-front/client/app/shared/input-inline/input-inline.component.ts index b89cc0024..2aa609344 100644 --- a/helix-front/client/app/shared/input-inline/input-inline.component.ts +++ b/helix-front/client/app/shared/input-inline/input-inline.component.ts @@ -88,7 +88,7 @@ export class InputInlineComponent implements ControlValueAccessor, OnInit { this.lastValue = value; this.editing = true; setTimeout((_) => { - this.inputControl.nativeElement.focus(); + this.inputControl?.nativeElement.focus(); }); } diff --git a/helix-front/client/app/shared/node-viewer/node-viewer.component.html b/helix-front/client/app/shared/node-viewer/node-viewer.component.html index c498660f7..9e9b95ff0 100644 --- a/helix-front/client/app/shared/node-viewer/node-viewer.component.html +++ b/helix-front/client/app/shared/node-viewer/node-viewer.component.html @@ -29,10 +29,15 @@ ></mat-progress-bar> <mat-button-toggle-group #group="matButtonToggleGroup" value="table"> <mat-button-toggle value="table"> Table View </mat-button-toggle> + <mat-button-toggle value="tree"> Tree View </mat-button-toggle> <mat-button-toggle value="json"> JSON View </mat-button-toggle> </mat-button-toggle-group> <section class="viewer" [ngSwitch]="group.value" fxFlexFill> - <ngx-json-viewer *ngSwitchCase="'json'" [json]="obj"></ngx-json-viewer> + <ngx-json-viewer *ngSwitchCase="'tree'" [json]="obj"></ngx-json-viewer> + <ace-editor *ngSwitchCase="'json'" [(text)]="objString" mode="json" theme="chrome" + [options]="{useWorker: false}" style="min-height:300px;" + #editor> + </ace-editor> <section *ngSwitchCase="'table'"> <!-- TODO vxu: use mat-simple-table when it's available --> @@ -47,9 +52,9 @@ /> </mat-form-field> <span fxFlex="1 1 auto"></span> + <!-- *ngIf="unlockable" --> <button mat-button - *ngIf="unlockable" (click)="editable = !editable" [matTooltip]=" editable diff --git a/helix-front/client/app/shared/node-viewer/node-viewer.component.spec.ts b/helix-front/client/app/shared/node-viewer/node-viewer.component.spec.ts index eb493f373..519ff3bab 100644 --- a/helix-front/client/app/shared/node-viewer/node-viewer.component.spec.ts +++ b/helix-front/client/app/shared/node-viewer/node-viewer.component.spec.ts @@ -28,4 +28,8 @@ describe('NodeViewerComponent', () => { it('should be created', () => { expect(component).toBeTruthy(); }); + + it('should render the locked button', () => { + expect(component).toContain('Locked'); + }); }); diff --git a/helix-front/client/app/shared/node-viewer/node-viewer.component.ts b/helix-front/client/app/shared/node-viewer/node-viewer.component.ts index e79cdaa32..de98a1c76 100644 --- a/helix-front/client/app/shared/node-viewer/node-viewer.component.ts +++ b/helix-front/client/app/shared/node-viewer/node-viewer.component.ts @@ -11,21 +11,41 @@ import { ActivatedRoute } from '@angular/router'; import { MatDialog } from '@angular/material/dialog'; import * as _ from 'lodash'; - +// import * as ace from 'ace-builds/src-noconflict/ace'; +import 'ace-builds'; +import 'ace-builds/webpack-resolver'; +import 'ace-builds/src-noconflict/mode-json'; +import 'ace-builds/src-noconflict/theme-chrome'; +import { config } from 'ace-builds'; + +import { ResourceService } from '../../resource/shared/resource.service'; +import { HelperService } from '../../shared/helper.service'; import { Node } from '../models/node.model'; import { Settings } from '../../core/settings'; import { InputDialogComponent } from '../dialog/input-dialog/input-dialog.component'; import { ConfirmDialogComponent } from '../dialog/confirm-dialog/confirm-dialog.component'; +config.set( + 'basePath', + 'https://cdn.jsdelivr.net/npm/ace-builds@1.6.0/src-noconflict/' +); +config.setModuleUrl( + 'ace/mode/javascript_worker', + 'https://cdn.jsdelivr.net/npm/ace-builds@1.6.0/src-noconflict/worker-json.js' +); @Component({ selector: 'hi-node-viewer', templateUrl: './node-viewer.component.html', styleUrls: ['./node-viewer.component.scss'], + providers: [ResourceService], // Since we are importing external styles in this component // we will not use Shadow DOM at all to make sure the styles apply encapsulation: ViewEncapsulation.None, }) export class NodeViewerComponent implements OnInit { + isLoading = true; + clusterName: string; + resourceName: string; @ViewChild('simpleTable', { static: true }) simpleTable; @ViewChild('listTable', { static: true }) listTable; @ViewChild('mapTable', { static: true }) mapTable; @@ -82,7 +102,7 @@ export class NodeViewerComponent implements OnInit { // MODE 1: use directly in components @Input() set obj(value: any) { - if (value != null) { + if (value !== null) { this._obj = value; this.node = new Node(value); } @@ -90,6 +110,18 @@ export class NodeViewerComponent implements OnInit { get obj(): any { return this._obj; } + set objString(value: string | null) { + let parsedValue = null; + if (value && value !== null) { + parsedValue = JSON.parse(value); + } + + this.obj = parsedValue; + this.node = new Node(parsedValue); + } + get objString(): string { + return JSON.stringify(this.obj, null, 2); + } set editable(value: boolean) { this._editable = value; this.columns.simpleConfigs[1].editable = this._editable; @@ -138,7 +170,12 @@ export class NodeViewerComponent implements OnInit { : []; } - constructor(protected dialog: MatDialog, protected route: ActivatedRoute) {} + public constructor( + protected dialog: MatDialog, + protected route: ActivatedRoute, + protected resourceService: ResourceService, + protected helper: HelperService + ) {} ngOnInit() { // MODE 2: use in router @@ -152,6 +189,15 @@ export class NodeViewerComponent implements OnInit { // try self data then this.obj = _.get(this.route.snapshot.data, path); } + + this.objString = JSON.stringify(this.obj, null, 2); + } + + if (this.route.parent) { + this.clusterName = + this.route.parent.snapshot.params.name || + this.route.parent.snapshot.params.cluster_name; + this.resourceName = this.route.parent.snapshot.params.resource_name; } } @@ -254,16 +300,12 @@ export class NodeViewerComponent implements OnInit { case 'list': if (key) { const entry = _.find(this.node.listFields, { name: key }); - // Property 'value' does not exist on type 'number | ListFieldObject | ((searchElement: ListFieldObject, fromIndex?: number) => boolean) | ((...'. - // Property 'value' does not exist on type 'number'.ts(2339) - // @ts-ignore + entry.value.push({ name: '', value: data.value.value, }); - // Argument of type 'number | ListFieldObject | ((searchElement: ListFieldObject, fromIndex?: number) => boolean) | ((...' is not assignable to parameter of type 'ListFieldObject'. - // Type 'number' is not assignable to type 'ListFieldObject'.ts(2345) - // @ts-ignore + newNode.listFields.push(entry); } break; @@ -271,12 +313,11 @@ export class NodeViewerComponent implements OnInit { case 'map': if (key) { const entry = _.find(this.node.mapFields, { name: key }); - // Property 'value' does not exist on type 'number | MapFieldObject | ((searchElement: MapFieldObject, fromIndex?: number) => boolean) | (() ...'. - // Property 'value' does not exist on type 'number'.ts(2339) - // @ts-ignore + _.forEach(entry.value, (item: any) => { newNode.appendMapField(key, item.name, item.value); }); + newNode.appendMapField(key, data.name.value, data.value.value); } break; @@ -300,24 +341,14 @@ export class NodeViewerComponent implements OnInit { case 'list': if (key) { const entry = _.find(this.node.listFields, { name: key }); - // Property 'value' does not exist on type 'number | ListFieldObject | ((searchElement: ListFieldObject, fromIndex?: number) => boolean) | ((...'. - // Property 'value' does not exist on type 'number'.ts(2339) - // @ts-ignore const index = _.findIndex(entry.value, { value: row.value }); + if (isDeleting) { - // Property 'value' does not exist on type 'number | ListFieldObject | ((searchElement: ListFieldObject, fromIndex?: number) => boolean) | ((...'. - // Property 'value' does not exist on type 'number'.ts(2339) - // @ts-ignore entry.value.splice(index, 1); } else { - // Property 'value' does not exist on type 'number | ListFieldObject | ((searchElement: ListFieldObject, fromIndex?: number) => boolean) | ((...'. - // Property 'value' does not exist on type 'number'.ts(2339) - // @ts-ignore entry.value[index].value = value; } - // Argument of type 'number | ListFieldObject | ((searchElement: ListFieldObject, fromIndex?: number) => boolean) | ((...' is not assignable to parameter of type 'ListFieldObject'. - // Type 'number' is not assignable to type 'ListFieldObject'.ts(2345) - // @ts-ignore + newNode.listFields.push(entry); } break; @@ -328,9 +359,6 @@ export class NodeViewerComponent implements OnInit { const entry = _.find(this.node.mapFields, { name: key }); newNode.mapFields = [{ name: key, value: [] }]; - // Property 'value' does not exist on type 'number | MapFieldObject | ((searchElement: MapFieldObject, fromIndex?: number) => boolean) | (() ...'. - // Property 'value' does not exist on type 'number'.ts(2339) - // @ts-ignore _.forEach(entry.value, (item: any) => { if (item.name === row.name) { if (!isDeleting) { @@ -344,6 +372,26 @@ export class NodeViewerComponent implements OnInit { break; } + const path = this?.route?.snapshot?.data?.path; + if (path && path === 'idealState') { + const observer = this.resourceService.setIdealState( + this.clusterName, + this.resourceName, + newNode + ); + + if (observer) { + this.isLoading = true; + observer.subscribe( + () => { + this.helper.showSnackBar('Ideal State updated!'); + }, + (error) => this.helper.showError(error), + () => (this.isLoading = false) + ); + } + } + this.change.emit(newNode); } } diff --git a/helix-front/client/app/shared/shared.module.ts b/helix-front/client/app/shared/shared.module.ts index 6921a339d..9f18ecee1 100644 --- a/helix-front/client/app/shared/shared.module.ts +++ b/helix-front/client/app/shared/shared.module.ts @@ -6,6 +6,7 @@ import { FormsModule } from '@angular/forms'; import { NgxDatatableModule } from '@swimlane/ngx-datatable'; import { NgxJsonViewerModule } from 'ngx-json-viewer'; +import { AceEditorModule } from 'ng2-ace-editor'; import { MaterialModule } from './material.module'; import { HelperService } from './helper.service'; @@ -33,6 +34,7 @@ import { DisabledLabelComponent } from './disabled-label/disabled-label.componen FormsModule, NgxDatatableModule, NgxJsonViewerModule, + AceEditorModule ], declarations: [ InputDialogComponent, diff --git a/helix-front/package.json b/helix-front/package.json index d5e4fd1a6..a547787a2 100644 --- a/helix-front/package.json +++ b/helix-front/package.json @@ -14,7 +14,8 @@ "scripts": { "ng": "ng", "build": "rm -rf dist && mkdir dist && ng build --aot --configuration production && tsc -p server", - "start": "tsc -p server && concurrently -r \"ng serve\" \"tsc -w -p server\" \"nodemon dist/server/app.js\"", + "build:dev": "rm -rf dist && mkdir dist && ng build --aot --configuration development && tsc -p server", + "start": "concurrently -r \"ng serve\" \"tsc -w -p server\" \"nodemon dist/server/app.js\"", "prod": "npm run build && node dist/server/app.js", "test": "ng test", "cypress:open": "cypress open --e2e --browser chrome", @@ -30,7 +31,7 @@ "format": "yarn prettier --write ." }, "engines": { - "node": "14.17.6", + "node": "~14.17.5", "yarn": "^1.22.18" }, "browserslist": [ @@ -40,18 +41,18 @@ "Chrome > 60" ], "dependencies": { - "@angular/animations": "^13.3.9", - "@angular/cdk": "^13.3.7", - "@angular/common": "^13.3.9", - "@angular/compiler": "^13.3.9", - "@angular/core": "^13.3.9", - "@angular/flex-layout": "^13.0.0-beta.38", - "@angular/forms": "^13.3.9", - "@angular/material": "^13.3.7", - "@angular/platform-browser": "^13.3.9", - "@angular/platform-browser-dynamic": "^13.3.9", - "@angular/platform-server": "^13.3.9", - "@angular/router": "^13.3.9", + "@angular/animations": "13.3.9", + "@angular/cdk": "13.3.9", + "@angular/common": "13.3.9", + "@angular/compiler": "13.3.9", + "@angular/core": "13.3.9", + "@angular/flex-layout": "13.0.0-beta.38", + "@angular/forms": "13.3.9", + "@angular/material": "13.3.9", + "@angular/platform-browser": "13.3.9", + "@angular/platform-browser-dynamic": "13.3.9", + "@angular/platform-server": "13.3.9", + "@angular/router": "13.3.9", "@egjs/hammerjs": "^2.0.17", "@swimlane/ngx-charts": "^16.0.0", "@swimlane/ngx-datatable": "^20.0.0", @@ -70,6 +71,7 @@ "lodash": "^4.17.12", "moment": "^2.29.2", "morgan": "^1.8.2", + "ng2-ace-editor": "^0.3.9", "ngx-clipboard": "^12.1.2", "ngx-json-viewer": "^2.3.0", "ngx-vis": "^3.1.0", @@ -105,8 +107,8 @@ "@types/request": "^2.0.0", "@typescript-eslint/eslint-plugin": "5.17.0", "@typescript-eslint/parser": "5.17.0", - "canvas": "^2.9.1", "ajv-formats": "^2.1.1", + "canvas": "^2.9.1", "concurrently": "^3.5.0", "cypress": "^10.0.3", "eslint": "^8.12.0", @@ -114,6 +116,7 @@ "eslint-plugin-import": "latest", "eslint-plugin-jsdoc": "^39.3.0", "eslint-plugin-prefer-arrow": "latest", + "file-loader": "^6.2.0", "jest": "^28.1.1", "jest-html-reporters": "^3.0.9", "jest-preset-angular": "^12.1.0", diff --git a/helix-front/pom.xml b/helix-front/pom.xml index 30f5c1ce8..79a9081e6 100644 --- a/helix-front/pom.xml +++ b/helix-front/pom.xml @@ -135,7 +135,7 @@ <goal>exec</goal> </goals> <configuration> - <executable>assemble/package.sh</executable> + <executable>assemble/assemble.sh</executable> </configuration> </execution> </executions> diff --git a/helix-front/proxy.conf.json b/helix-front/proxy.conf.json index 63dd62750..54dc57121 100644 --- a/helix-front/proxy.conf.json +++ b/helix-front/proxy.conf.json @@ -1,6 +1,6 @@ { "/api": { - "target": "http://localhost:3000", + "target": "http://localhost:4200", "secure": false } } diff --git a/helix-front/yarn.lock b/helix-front/yarn.lock index c250ab234..8420bba93 100644 --- a/helix-front/yarn.lock +++ b/helix-front/yarn.lock @@ -237,14 +237,14 @@ "@angular-eslint/bundled-angular-compiler" "13.2.1" "@typescript-eslint/experimental-utils" "5.17.0" -"@angular/animations@^13.3.9": - version "13.3.11" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-13.3.11.tgz#13a7afa3d7d7076874f6ac62da5158ec4ae009f0" - integrity sha512-KE/3RuvixHIk9YTSwaUsezsUm9Ig9Y8rZMpHOT/8bRtzPiJ5ld2GnDHjrJgyZn7TdoP4wz4YCta5eC4ycu+KCw== +"@angular/animations@13.3.9": + version "13.3.9" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-13.3.9.tgz#2c8683986d15003394e72ed4ae329406d9dab537" + integrity sha512-PIspkNm1r7Uq1F3/c24mTQjCbKvl84Iy5kRmKOtjxp9uBGg1Dy+akw29hJt2FAqKa5yKFustBFCgWKypqgSoUQ== dependencies: tslib "^2.3.0" -"@angular/cdk@^13.3.7": +"@angular/cdk@13.3.9": version "13.3.9" resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-13.3.9.tgz#a177196e872e29be3f84d3a50f778d361c689ff7" integrity sha512-XCuCbeuxWFyo3EYrgEYx7eHzwl76vaWcxtWXl00ka8d+WAOtMQ6Tf1D98ybYT5uwF9889fFpXAPw98mVnlo3MA== @@ -278,10 +278,10 @@ symbol-observable "4.0.0" uuid "8.3.2" -"@angular/common@^13.3.9": - version "13.3.11" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-13.3.11.tgz#bcd42bb078ffd3712625be35dc6ec7b6ab828df7" - integrity sha512-gPMwDYIAag1izXm2tRQ6EOIx9FVEUqLdr+qYtRVoQtoBmfkoTSLGcpeBXqqlPVxVPbA6Li1WZZT5wxLLlLAN+Q== +"@angular/common@13.3.9": + version "13.3.9" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-13.3.9.tgz#3fbc00e58ac9d6f1e34febaa6b9d5ad4c3e328ab" + integrity sha512-+bTleNL1XGlzuxLbVbsol82/33IW2pJasQN8ViraxKIElT2F8ooBJevIBMCSIcdvxvMBGAjn4ayQJr6tkPqPaw== dependencies: tslib "^2.3.0" @@ -301,68 +301,68 @@ tslib "^2.3.0" yargs "^17.2.1" -"@angular/compiler@^13.3.9": - version "13.3.11" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-13.3.11.tgz#1268a3f82bd9693eaf17c2a8764d917efdd624a0" - integrity sha512-EV6JCBbXdHDHbPShWmymvuoxFYG0KVc8sDJpYp47WLHCY2zgZaXhvWs//Hrls3fmi+TGTekgRa2jOBBNce/Ggg== +"@angular/compiler@13.3.9": + version "13.3.9" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-13.3.9.tgz#3b31e4e12f04f9b88bcde37da1cb341670ffed8f" + integrity sha512-fXmcN9PIUTJ9Vw2QyQE9vtW95K5ML9bVI7409Zf3DAQJEo4IhX2eUjgiGF3RtSn9Kdjj3tZY0xSbGGwp1hTBIA== dependencies: tslib "^2.3.0" -"@angular/core@^13.3.9": - version "13.3.11" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-13.3.11.tgz#e5d56560028b3c99c6814989cba7ad61339968ea" - integrity sha512-9BmE2CxyV0g+AkBeuc8IwjSOiJ8Y+kptXnqD/J8EAFT3B0/fLGVnjFdZC6Sev9L0SNZb6qdzebpfIOLqbUjReQ== +"@angular/core@13.3.9": + version "13.3.9" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-13.3.9.tgz#6be6f79efd7d85bbd014d100da4227fe43d5ae75" + integrity sha512-LaY3yBDgN/efG11x/cwVeuC4gUG3YUMmk/sgAP3L1VGawYOiKoJ76decFpy6y4UgYPShQQRzpZQEVXF405jrLg== dependencies: tslib "^2.3.0" -"@angular/flex-layout@^13.0.0-beta.38": +"@angular/flex-layout@13.0.0-beta.38": version "13.0.0-beta.38" resolved "https://registry.yarnpkg.com/@angular/flex-layout/-/flex-layout-13.0.0-beta.38.tgz#b0993a255ba51d2cfd16537ba8a8d88c3adf6587" integrity sha512-kcWb7CcoHbvw7fjo/knizWVmSSmvaTnr8v1ML6zOdxu1PK9UPPOcOS8RTm6fy61zoC2LABivP1/6Z2jF5XfpdQ== dependencies: tslib "^2.3.0" -"@angular/forms@^13.3.9": - version "13.3.11" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-13.3.11.tgz#f63aa99a2b3bd4638fb3429417b4e432ddc0f113" - integrity sha512-iMgTNB+Qc3TsfAZSk1FnUE6MVoddPzxhG9AKCfSlvpjFh8VmXkIjxPL3dun7J8OjayT3X+B8f7LZ9AkKNXtBKw== +"@angular/forms@13.3.9": + version "13.3.9" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-13.3.9.tgz#b8114426764d87527b9a9a1dd4d0ca085b11504a" + integrity sha512-eNOsqMVrMsBceoAJ9pS+2qQDWsgwt62q7abqfYdzSdkjWbnLrtaIPP6iYMGQke1pIcdUSyoun29VsdQTSXXksg== dependencies: tslib "^2.3.0" -"@angular/material@^13.3.7": +"@angular/material@13.3.9": version "13.3.9" resolved "https://registry.yarnpkg.com/@angular/material/-/material-13.3.9.tgz#efd8ab5800b654df01e36426391d31531e412425" integrity sha512-FU8lcMgo+AL8ckd27B4V097ZPoIZNRHiCe3wpgkImT1qC0YwcyXZVn0MqQTTFSdC9a/aI8wPm3AbTClJEVw5Vw== dependencies: tslib "^2.3.0" -"@angular/platform-browser-dynamic@^13.3.9": - version "13.3.11" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-13.3.11.tgz#779b4042d009c6eb3f16410bdfcba1909bbb2b83" - integrity sha512-xM0VRC1Nw//SHO3gkghUHyjCaaQbk1UYMq4vIu3iKVq9KLqOSZgccv0NcOKHzXXN3S5RgX2auuyOUOCD6ny1Pg== +"@angular/platform-browser-dynamic@13.3.9": + version "13.3.9" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-13.3.9.tgz#681083b281a0a24e56193c5ceb2b18d32a0b09a7" + integrity sha512-flyfoJG9vBSj3rmH/jUNaOPGfGlGHSj4v34OL16Qjk3M5bxbQKxBYNrDAUwk0Ve4S4qUfXF7ZDE0v1vUvn+3MA== dependencies: tslib "^2.3.0" -"@angular/platform-browser@^13.3.9": - version "13.3.11" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-13.3.11.tgz#689334ae5b8a77b0cc8c0dc8bd9d0746dc73f362" - integrity sha512-PG3chCErARb6wNzkOed2NsZmgvTmbumRx/6sMXqGkDKXYQm0JULnl4X42Rn+JCgJ9DLJi5/jrd1dbcBCrKk9Vg== +"@angular/platform-browser@13.3.9": + version "13.3.9" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-13.3.9.tgz#2c6235a03c6081b63241507df27c2c120e2f7074" + integrity sha512-1l0IVYFbKCEfACR60bfLjH35BYP69CerIW9Ok58pedp0MIUsvPttBzUjM5HhW+3jhvNyO0cCMaK4r5kKTRMo4w== dependencies: tslib "^2.3.0" -"@angular/platform-server@^13.3.9": - version "13.3.11" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-13.3.11.tgz#ee7a6784c309d32ae7f942efac026a6e614dc797" - integrity sha512-Mm6UEYw+mn3pvxH/YeWO1D6DWMWMC8tInLdqEBrlPu/8oXQBrDCp+zpaT1v0uA5gzBltZ8QihLwsABifnSClaQ== +"@angular/platform-server@13.3.9": + version "13.3.9" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-13.3.9.tgz#dbc6174dfa9764dd298036bed40620aeb86ebf41" + integrity sha512-FgkOpVrH6d3DlZd4hAoFQg9dgVSFnLRxKtNSxcauAz1ulPqjENIQz8zJDrnXE060ECqBm//R7G+g8v7HpP7zng== dependencies: domino "^2.1.2" tslib "^2.3.0" xhr2 "^0.2.0" -"@angular/router@^13.3.9": - version "13.3.11" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-13.3.11.tgz#5a74a10d4317d6bde8ee4f57055da10065ce6d87" - integrity sha512-bJTcxDYKEyoqtsi1kJcDJWLmEN+dXpwhU07SsqUwfyN4V5fYF1ApDhpJ4c17hNdjEqe106srT9tiHXhmWayhmQ== +"@angular/router@13.3.9": + version "13.3.9" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-13.3.9.tgz#68d1100061811c4dcdfb615d9128146fcfb84baf" + integrity sha512-M9j3ZscdRLsTnOLware1Yyw87JlRw/axoeZcN8JnTs3ltCc0+UMEJ22q0s8ud6j9GmYiA0+kmaM35OsEoHX72g== dependencies: tslib "^2.3.0" @@ -2599,6 +2599,11 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" +ace-builds@^1.4.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.6.0.tgz#4e1652a0e33c4ae262dc841b1254dd2ad0beb5da" + integrity sha512-qdkx965G/TA12IK7Zk+iCVDtA9wvhxIGivGc2rsID4UYbY2Bpatwep3ZrBZwj1IB2miU6FodDMqM9Kc1lqDlLg== + acorn-globals@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" @@ -3247,6 +3252,11 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" +brace@^0.11.1: + version "0.11.1" + resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58" + integrity sha512-Fc8Ne62jJlKHiG/ajlonC4Sd66Pq68fFwK4ihJGNZpGqboc324SQk+lRvMzpPRuJOmfrJefdG8/7JdWX4bzJ2Q== + braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -5540,6 +5550,14 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + filelist@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" @@ -8072,6 +8090,14 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +ng2-ace-editor@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/ng2-ace-editor/-/ng2-ace-editor-0.3.9.tgz#5ae68712e9ca49591eda31df8fe02eca1c3634e1" + integrity sha512-e8Q4YCirlL/OEiekewmzupG+zV3prYsiYmQnRzQzd0wNgsPjOLOdb0it7cCbzFfIXKGyIIHKTW5584WxPr2LnQ== + dependencies: + ace-builds "^1.4.2" + brace "^0.11.1" + ngx-clipboard@^12.1.2: version "12.3.1" resolved "https://registry.yarnpkg.com/ngx-clipboard/-/ngx-clipboard-12.3.1.tgz#565d73b946b10719242e532e748ad912cf8bc97a" @@ -9679,7 +9705,7 @@ schema-utils@^2.6.5: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.1.0, schema-utils@^3.1.1: +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==