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>&copy; 2018 Helix. All rights reserved.</span>
+    <span>&copy; 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==

Reply via email to