summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INFO.yaml37
-rw-r--r--mod/bpgenerator/pom.xml72
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/common/blueprint/BlueprintHelper.java4
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Appconfig.java15
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Blueprint.java122
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Imports.java15
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Interfaces.java4
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Properties.java17
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/ResourceConfig.java19
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Start.java8
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/StartInputs.java13
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapInfo.java8
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapObj.java16
-rw-r--r--mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/dmaapbp/DmaapBlueprint.java185
-rw-r--r--mod/bpgenerator/src/test/java/org/onap/blueprintgenerator/models/dmaapbp/DmaapBlueprintTest.java244
-rw-r--r--mod/bpgenerator/version.properties4
-rw-r--r--mod2/auth-service/Dockerfile11
-rw-r--r--mod2/auth-service/pom.xml171
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java40
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java97
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java171
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java58
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java96
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java52
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java34
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java34
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java34
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java34
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java40
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java50
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java43
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java75
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java50
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java53
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java47
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java37
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java40
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java92
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java51
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java81
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java90
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java127
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java100
-rw-r--r--mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java56
-rw-r--r--mod2/auth-service/src/main/resources/application.properties32
-rw-r--r--mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/AuthObjectMother.java85
-rw-r--r--mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/RoleObjectMother.java56
-rw-r--r--mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/UserObjectMother.java100
-rw-r--r--mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/util/TestUtil.java60
-rw-r--r--mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/AuthControllerTest.java149
-rw-r--r--mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/RoleControllerTest.java109
-rw-r--r--mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/UserControllerTest.java168
-rw-r--r--mod2/auth-service/src/test/resources/application.properties1
-rw-r--r--mod2/auth-service/src/test/resources/http/requests/AuthLoginRequest.json4
-rw-r--r--mod2/auth-service/src/test/resources/http/requests/AuthSignupRequest.json6
-rw-r--r--mod2/auth-service/src/test/resources/specification/componentSpec_hello_world-with-dmaap.json149
-rw-r--r--mod2/auth-service/src/test/resources/specification/policy_json_sample_3.json28
-rw-r--r--mod2/ui/.editorconfig13
-rw-r--r--mod2/ui/.gitignore46
-rw-r--r--mod2/ui/Dockerfile26
-rw-r--r--mod2/ui/Jenkinsfile3
-rw-r--r--mod2/ui/README.md27
-rw-r--r--mod2/ui/angular.json128
-rw-r--r--mod2/ui/browserslist12
-rw-r--r--mod2/ui/dependenciesFile0
-rw-r--r--mod2/ui/e2e/protractor.conf.js50
-rw-r--r--mod2/ui/e2e/src/app.e2e-spec.ts41
-rw-r--r--mod2/ui/e2e/src/app.po.ts29
-rw-r--r--mod2/ui/e2e/tsconfig.json13
-rw-r--r--mod2/ui/extra-webpack.config.js29
-rw-r--r--mod2/ui/healthcheck.sh20
-rw-r--r--mod2/ui/karma.conf.js50
-rw-r--r--mod2/ui/package-lock.json10747
-rw-r--r--mod2/ui/package.json64
-rw-r--r--mod2/ui/pipelineConfig.json21
-rw-r--r--mod2/ui/pom.xml72
-rw-r--r--mod2/ui/proxy.conf.json11
-rw-r--r--mod2/ui/src/app/app-routing.module.ts55
-rw-r--r--mod2/ui/src/app/app.component.css173
-rw-r--r--mod2/ui/src/app/app.component.html136
-rw-r--r--mod2/ui/src/app/app.component.spec.ts90
-rw-r--r--mod2/ui/src/app/app.component.ts218
-rw-r--r--mod2/ui/src/app/app.module.ts172
-rw-r--r--mod2/ui/src/app/blueprints/blueprints.component.css142
-rw-r--r--mod2/ui/src/app/blueprints/blueprints.component.html283
-rw-r--r--mod2/ui/src/app/blueprints/blueprints.component.spec.ts153
-rw-r--r--mod2/ui/src/app/blueprints/blueprints.component.ts602
-rw-r--r--mod2/ui/src/app/comp-spec-add/comp-spec-add.component.css43
-rw-r--r--mod2/ui/src/app/comp-spec-add/comp-spec-add.component.html64
-rw-r--r--mod2/ui/src/app/comp-spec-add/comp-spec-add.component.spec.ts77
-rw-r--r--mod2/ui/src/app/comp-spec-add/comp-spec-add.component.ts180
-rw-r--r--mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.css73
-rw-r--r--mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.html108
-rw-r--r--mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.spec.ts132
-rw-r--r--mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.ts145
-rw-r--r--mod2/ui/src/app/comp-specs/comp-specs.component.css121
-rw-r--r--mod2/ui/src/app/comp-specs/comp-specs.component.html189
-rw-r--r--mod2/ui/src/app/comp-specs/comp-specs.component.spec.ts133
-rw-r--r--mod2/ui/src/app/comp-specs/comp-specs.component.ts211
-rw-r--r--mod2/ui/src/app/guards/auth.guard.spec.ts44
-rw-r--r--mod2/ui/src/app/guards/auth.guard.ts62
-rw-r--r--mod2/ui/src/app/guards/login.guard.spec.ts41
-rw-r--r--mod2/ui/src/app/guards/login.guard.ts52
-rw-r--r--mod2/ui/src/app/guards/role.guard.spec.ts44
-rw-r--r--mod2/ui/src/app/guards/role.guard.ts61
-rw-r--r--mod2/ui/src/app/home/home.component.css50
-rw-r--r--mod2/ui/src/app/home/home.component.html93
-rw-r--r--mod2/ui/src/app/home/home.component.ts64
-rw-r--r--mod2/ui/src/app/login/login.component.css25
-rw-r--r--mod2/ui/src/app/login/login.component.html58
-rw-r--r--mod2/ui/src/app/login/login.component.spec.ts59
-rw-r--r--mod2/ui/src/app/login/login.component.ts65
-rw-r--r--mod2/ui/src/app/material-elevation.directive.ts64
-rw-r--r--mod2/ui/src/app/microservices/microservices.component.css121
-rw-r--r--mod2/ui/src/app/microservices/microservices.component.html185
-rw-r--r--mod2/ui/src/app/microservices/microservices.component.spec.ts134
-rw-r--r--mod2/ui/src/app/microservices/microservices.component.ts311
-rw-r--r--mod2/ui/src/app/models/AuthResponse.ts28
-rw-r--r--mod2/ui/src/app/models/Authority.enum.ts22
-rw-r--r--mod2/ui/src/app/models/User.ts25
-rw-r--r--mod2/ui/src/app/ms-add-change/ms-add-change.component.css57
-rw-r--r--mod2/ui/src/app/ms-add-change/ms-add-change.component.html109
-rw-r--r--mod2/ui/src/app/ms-add-change/ms-add-change.component.spec.ts67
-rw-r--r--mod2/ui/src/app/ms-add-change/ms-add-change.component.ts180
-rw-r--r--mod2/ui/src/app/ms-instance-add/ms-instance-add.component.css48
-rw-r--r--mod2/ui/src/app/ms-instance-add/ms-instance-add.component.html93
-rw-r--r--mod2/ui/src/app/ms-instance-add/ms-instance-add.component.spec.ts71
-rw-r--r--mod2/ui/src/app/ms-instance-add/ms-instance-add.component.ts189
-rw-r--r--mod2/ui/src/app/msInstances/msInstances.component.css148
-rw-r--r--mod2/ui/src/app/msInstances/msInstances.component.html221
-rw-r--r--mod2/ui/src/app/msInstances/msInstances.component.spec.ts127
-rw-r--r--mod2/ui/src/app/msInstances/msInstances.component.ts511
-rw-r--r--mod2/ui/src/app/onboarding-tools/onboarding-tools.component.css27
-rw-r--r--mod2/ui/src/app/onboarding-tools/onboarding-tools.component.html23
-rw-r--r--mod2/ui/src/app/onboarding-tools/onboarding-tools.component.spec.ts48
-rw-r--r--mod2/ui/src/app/onboarding-tools/onboarding-tools.component.ts52
-rw-r--r--mod2/ui/src/app/register/register.component.css18
-rw-r--r--mod2/ui/src/app/register/register.component.html62
-rw-r--r--mod2/ui/src/app/register/register.component.spec.ts61
-rw-r--r--mod2/ui/src/app/register/register.component.ts99
-rw-r--r--mod2/ui/src/app/reset-password/reset-password.component.css18
-rw-r--r--mod2/ui/src/app/reset-password/reset-password.component.html64
-rw-r--r--mod2/ui/src/app/reset-password/reset-password.component.spec.ts58
-rw-r--r--mod2/ui/src/app/reset-password/reset-password.component.ts78
-rw-r--r--mod2/ui/src/app/services/auth.service.spec.ts43
-rw-r--r--mod2/ui/src/app/services/auth.service.ts95
-rw-r--r--mod2/ui/src/app/services/base-microservice.service.spec.ts42
-rw-r--r--mod2/ui/src/app/services/base-microservice.service.ts35
-rw-r--r--mod2/ui/src/app/services/breadcrumb.service.ts73
-rw-r--r--mod2/ui/src/app/services/comp-spec-add.service.spec.ts42
-rw-r--r--mod2/ui/src/app/services/comp-spec-add.service.ts45
-rw-r--r--mod2/ui/src/app/services/comp-specs-service.service.spec.ts43
-rw-r--r--mod2/ui/src/app/services/comp-specs-service.service.ts43
-rw-r--r--mod2/ui/src/app/services/deployment-artifact.service.spec.ts43
-rw-r--r--mod2/ui/src/app/services/deployment-artifact.service.ts71
-rw-r--r--mod2/ui/src/app/services/download.service.spec.ts41
-rw-r--r--mod2/ui/src/app/services/download.service.ts85
-rw-r--r--mod2/ui/src/app/services/global-filters.service.spec.ts30
-rw-r--r--mod2/ui/src/app/services/global-filters.service.ts55
-rw-r--r--mod2/ui/src/app/services/jwt-interceptor.service.spec.ts30
-rw-r--r--mod2/ui/src/app/services/jwt-interceptor.service.ts40
-rw-r--r--mod2/ui/src/app/services/microservice-instance.service.spec.ts41
-rw-r--r--mod2/ui/src/app/services/microservice-instance.service.ts46
-rw-r--r--mod2/ui/src/app/services/ms-add.service.spec.ts42
-rw-r--r--mod2/ui/src/app/services/ms-add.service.ts52
-rw-r--r--mod2/ui/src/app/services/spec-validation.service.spec.ts41
-rw-r--r--mod2/ui/src/app/services/spec-validation.service.ts53
-rw-r--r--mod2/ui/src/app/services/user.service.spec.ts44
-rw-r--r--mod2/ui/src/app/services/user.service.ts53
-rw-r--r--mod2/ui/src/app/shared/shared-module.ts61
-rw-r--r--mod2/ui/src/app/user-management/user-management.component.css54
-rw-r--r--mod2/ui/src/app/user-management/user-management.component.html89
-rw-r--r--mod2/ui/src/app/user-management/user-management.component.spec.ts63
-rw-r--r--mod2/ui/src/app/user-management/user-management.component.ts149
-rw-r--r--mod2/ui/src/assets/.gitkeep0
-rw-r--r--mod2/ui/src/assets/env.js17
-rw-r--r--mod2/ui/src/environments/environment.prod.ts22
-rw-r--r--mod2/ui/src/environments/environment.ts35
-rw-r--r--mod2/ui/src/favicon.icobin0 -> 5430 bytes
-rw-r--r--mod2/ui/src/index.html36
-rw-r--r--mod2/ui/src/main.ts31
-rw-r--r--mod2/ui/src/polyfills.ts81
-rw-r--r--mod2/ui/src/styles.css33
-rw-r--r--mod2/ui/src/test.ts38
-rw-r--r--mod2/ui/tsconfig.app.json14
-rw-r--r--mod2/ui/tsconfig.json33
-rw-r--r--mod2/ui/tsconfig.spec.json18
-rw-r--r--mod2/ui/tslint.json92
-rw-r--r--mod2/ui/typings.d.ts32
-rw-r--r--releases/1.1.0-distributorapi-container.yaml9
-rw-r--r--releases/1.5.0-blueprint-generator.yaml4
-rw-r--r--releases/2.12.3-onboardingapi-container.yaml9
192 files changed, 24356 insertions, 325 deletions
diff --git a/INFO.yaml b/INFO.yaml
index d2301c0..abd7c37 100644
--- a/INFO.yaml
+++ b/INFO.yaml
@@ -1,7 +1,8 @@
+---
project: 'dcaegen2-platform'
project_creation_date: '2017-06-28'
project_category: ''
-lifecycle_state: 'Incubation'
+lifecycle_state: 'Mature'
project_lead: &onap_dcaegen2_ptl
name: 'Vijay Venkatesh Kumar'
email: 'vv770d@att.com'
@@ -30,26 +31,31 @@ repositories:
- 'dcaegen2/platform'
committers:
- <<: *onap_dcaegen2_ptl
- - name: 'Lusheng Ji'
- email: 'lji@research.att.com'
- company: 'ATT'
- id: 'wrider'
- timezone: 'America/New_York'
- name: 'Tony Hansen'
email: 'tony@att.com'
company: 'ATT'
id: 'TonyLHansen'
timezone: 'America/New_York'
- - name: 'Jack Lucas'
- email: 'jflucas@research.att.com'
- company: 'ATT'
- id: 'jackl'
- timezone: 'America/New_York'
- name: 'Joseph O Leary'
email: 'joseph.o.leary@est.tech'
company: 'EST'
id: 'JoeOLeary'
timezone: 'Ireland/UTC'
+ - name: 'Kornel Janiak'
+ email: 'kornel.janiak@nokia.com'
+ company: 'Nokia'
+ id: 'kjaniak'
+ timezone: 'Europe/Warsaw'
+ - name: 'Jack Lucas'
+ email: 'jflos@sonoris.net'
+ company: 'IC'
+ id: 'jackl'
+ timezone: 'America/New_York'
+ - name: 'Remigiusz Janeczek'
+ email: 'remigiusz.janeczek@nokia.com'
+ company: 'Nokia'
+ id: 'rjanecze'
+ timezone: 'Europe/Warsaw'
tsc:
approval: 'https://lists.onap.org/pipermail/onap-tsc'
changes:
@@ -65,3 +71,12 @@ tsc:
- type: 'Removal'
name: 'Xinhui Li'
link: 'https://lists.onap.org/g/onap-tsc/message/6814'
+ - type: 'Addition'
+ name: 'Kornel Janiak'
+ link: 'https://lists.onap.org/g/onap-tsc/message/7026'
+ - type: 'Removal'
+ name: 'Lusheng Ji'
+ link: 'https://lists.onap.org/g/onap-tsc/message/7026'
+ - type: 'Addition'
+ name: 'Remigiusz Janeczek'
+ link: 'https://lists.onap.org/g/onap-tsc/message/7026'
diff --git a/mod/bpgenerator/pom.xml b/mod/bpgenerator/pom.xml
index 96ceb41..aaf9713 100644
--- a/mod/bpgenerator/pom.xml
+++ b/mod/bpgenerator/pom.xml
@@ -29,17 +29,12 @@
</parent>
<groupId>org.onap.dcaegen2.platform.mod</groupId>
<artifactId>blueprint-generator</artifactId>
- <version>1.4.0-SNAPSHOT</version>
+ <version>1.5.1-SNAPSHOT</version>
<properties>
- <maven.compiler.source>1.6</maven.compiler.source>
- <maven.compiler.target>1.6</maven.compiler.target>
-
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <sonar.core.codeCoveragePlugin>cobertura</sonar.core.codeCoveragePlugin>
- <sonar.java.coveragePlugin>cobertura</sonar.java.coveragePlugin>
<sonar.junit.reportsPath>${project.basedir}/target/surefire-reports</sonar.junit.reportsPath>
<sonar.surefire.reportsPath>${project.basedir}/target/surefire-reports</sonar.surefire.reportsPath>
- <sonar.cobertura.reportPaths>${project.basedir}/target/site/cobertura/coverage.xml</sonar.cobertura.reportPaths>
+ <sonar.coverage.jacoco.xmlReportPaths>${project.basedir}/target/site/jacoco-ut/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
<shade.main>org.onap.blueprintgenerator.core.App</shade.main>
<shade.transformer>org.apache.maven.plugins.shade.resource.ManifestResourceTransformer</shade.transformer>
</properties>
@@ -70,47 +65,6 @@
</plugin>
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>cobertura-maven-plugin</artifactId>
- <version>2.7</version>
- <configuration>
- <instrumentation>
- <includes>
- <include>**/*.class</include>
- </includes>
- </instrumentation>
- <encoding>UTF-8</encoding>
- </configuration>
-
- <executions>
-
- <execution>
- <id>clean</id>
- <!-- > <phase>pre-site</phase> -->
- <phase>pre-site</phase>
- <goals>
- <goal>cobertura</goal>
- </goals>
- </execution>
-
-
- <execution>
- <id>instrument</id>
- <phase>site</phase>
- <goals>
- <goal>instrument</goal>
- <goal>cobertura</goal>
- </goals>
- <configuration>
- <encoding>UTF-8</encoding>
- </configuration>
- </execution>
-
- </executions>
-
- </plugin>
-
- <plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.0.2</version>
@@ -141,31 +95,13 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <source>8</source>
- <target>8</target>
+ <source>11</source>
+ <target>11</target>
</configuration>
</plugin>
</plugins>
-
</build>
- <reporting>
- <plugins>
- <plugin>
- <!-- use mvn cobertura:cobertura to generate cobertura reports -->
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>cobertura-maven-plugin</artifactId>
- <version>2.7</version>
- <configuration>
- <formats>
- <format>xml</format>
- </formats>
- </configuration>
- </plugin>
- </plugins>
- </reporting>
-
-
<dependencies>
<dependency>
<groupId>junit</groupId>
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/common/blueprint/BlueprintHelper.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/common/blueprint/BlueprintHelper.java
index 16eca51..451988f 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/common/blueprint/BlueprintHelper.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/common/blueprint/BlueprintHelper.java
@@ -34,4 +34,8 @@ public class BlueprintHelper {
inputMap.put("default", defaultValue);
return inputMap;
}
+
+ public static String joinUnderscore(String firstValue, String secondValue){
+ return firstValue + "_" + secondValue;
+ }
}
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Appconfig.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Appconfig.java
index b39a8ec..75864be 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Appconfig.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Appconfig.java
@@ -52,8 +52,7 @@ public class Appconfig {
public TreeMap<String, LinkedHashMap<String, Object>> createAppconfig(TreeMap<String, LinkedHashMap<String, Object>> inps, ComponentSpec cs, String override,
boolean isDmaap) {
- TreeMap<String, LinkedHashMap<String, Object>> retInputs = new TreeMap<String, LinkedHashMap<String, Object>>();
- retInputs = inps;
+ TreeMap<String, LinkedHashMap<String, Object>> retInputs = inps;
//set service calls
CallsObj[] call = new CallsObj[0];
@@ -83,7 +82,7 @@ public class Appconfig {
}
//set the stream publishes
- TreeMap<String, DmaapObj> streamSubscribes = new TreeMap<String, DmaapObj>();
+ TreeMap<String, DmaapObj> streamSubscribes = new TreeMap<>();
if(cs.getStreams().getSubscribes().length != 0) {
for(Subscribes s: cs.getStreams().getSubscribes()) {
@@ -110,7 +109,7 @@ public class Appconfig {
this.setStreams_subscribes(streamSubscribes);
//set the parameters into the appconfig
- TreeMap<String, Object> parameters = new TreeMap<String, Object>();
+ TreeMap<String, Object> parameters = new TreeMap<>();
for(Parameters p: cs.getParameters()) {
String pName = p.getName();
if(p.isSourced_at_deployment()) {
@@ -119,17 +118,17 @@ public class Appconfig {
parameters.put(pName, paramInput);
if(!p.getValue().equals("")) {
- LinkedHashMap<String, Object> inputs = new LinkedHashMap<String, Object>();
+ LinkedHashMap<String, Object> inputs = new LinkedHashMap<>();
inputs.put("type", "string");
inputs.put("default", p.getValue());
retInputs.put(pName, inputs);
} else {
- LinkedHashMap<String, Object> inputs = new LinkedHashMap<String, Object>();
+ LinkedHashMap<String, Object> inputs = new LinkedHashMap<>();
inputs.put("type", "string");
retInputs.put(pName, inputs);
}
} else {
- if(p.getType() == "string") {
+ if("string".equals(p.getType())) {
String val =(String) p.getValue();
val = '"' + val + '"';
parameters.put(pName, val);
@@ -143,7 +142,7 @@ public class Appconfig {
GetInput ov = new GetInput();
ov.setBpInputName("service_component_name_override");
parameters.put("service_component_name_override", ov);
- LinkedHashMap<String, Object> over = new LinkedHashMap<String, Object>();
+ LinkedHashMap<String, Object> over = new LinkedHashMap<>();
over.put("type", "string");
over.put("default", override);
retInputs.put("service_component_name_override", over);
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Blueprint.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Blueprint.java
index c043a9e..f2ef7aa 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Blueprint.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Blueprint.java
@@ -20,35 +20,27 @@
package org.onap.blueprintgenerator.models.blueprint;
-import java.io.*;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.TreeMap;
import java.util.regex.Pattern;
-
+import lombok.Getter;
+import lombok.Setter;
import org.onap.blueprintgenerator.core.Fixes;
import org.onap.blueprintgenerator.models.componentspec.ComponentSpec;
-import org.onap.blueprintgenerator.models.componentspec.Parameters;
-import org.onap.blueprintgenerator.models.componentspec.Publishes;
-import org.onap.blueprintgenerator.models.componentspec.Subscribes;
import org.onap.blueprintgenerator.models.dmaapbp.DmaapBlueprint;
import org.onap.blueprintgenerator.models.onapbp.OnapBlueprint;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.core.JsonProcessingException;
-//import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
-import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.yaml.snakeyaml.Yaml;
-
-
@Getter @Setter
@JsonInclude(JsonInclude.Include.NON_NULL)
@@ -100,93 +92,43 @@ public class Blueprint {
public void blueprintToYaml(String outputPath, String bluePrintName, ComponentSpec cs) {
File outputFile;
-
- if(bluePrintName.equals("")) {
- String name = cs.getSelf().getName();
- if(name.contains(".")) {
- name = name.replaceAll(Pattern.quote("."), "_");
- }
- if(name.contains(" ")) {
- name = name.replaceAll(" ", "");
- }
- String file = name + ".yaml";
-
-
- outputFile = new File(outputPath, file);
- outputFile.getParentFile().mkdirs();
- try {
- outputFile.createNewFile();
- } catch (IOException e) {
-
- throw new RuntimeException(e);
- }
- } else {
- if(bluePrintName.contains(" ") || bluePrintName.contains(".")) {
- bluePrintName = bluePrintName.replaceAll(Pattern.quote("."), "_");
- bluePrintName = bluePrintName.replaceAll(" ", "");
- }
- String file = bluePrintName + ".yaml";
- outputFile = new File(outputPath, file);
- outputFile.getParentFile().mkdirs();
- try {
- outputFile.createNewFile();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ String name = bluePrintName.equals("") ? cs.getSelf().getName() : bluePrintName;
+ if(name.contains(".")) {
+ name = name.replaceAll(Pattern.quote("."), "_");
+ }
+ if(name.contains(" ")) {
+ name = name.replaceAll(" ", "");
+ }
+ String file = name + ".yaml";
+ outputFile = new File(outputPath, file);
+ outputFile.getParentFile().mkdirs();
+ try {
+ outputFile.createNewFile();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
String version = "#blueprint_version: " + cs.getSelf().getVersion() + '\n';
String description = "#description: " + cs.getSelf().getDescription() + '\n';
- BufferedWriter writer = null;
- try {
- writer = new BufferedWriter(new FileWriter(outputFile, false));
+ try(BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile, false))) {
+ writer.write(description);
+ writer.write(version);
} catch (IOException e1) {
throw new RuntimeException(e1);
}
- if(writer != null) {
- try {
- writer.write(description);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- try {
- writer.write(version);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- try {
- writer.close();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
//read the translated blueprint into the file
ObjectMapper blueprintMapper = new ObjectMapper(new YAMLFactory().configure(YAMLGenerator.Feature.MINIMIZE_QUOTES, true));
- PrintWriter out = null;
- try {
- out = new PrintWriter(new BufferedWriter(new FileWriter(outputFile, true)));
+ try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(outputFile, true)))) {
+ blueprintMapper.writeValue(out, this);
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
- if(out != null) {
- blueprintMapper.writeValue(out, this);
- out.close();
- }
- } catch (IOException e) {
-
- throw new RuntimeException(e);
- }
-
-
- Fixes fix = new Fixes();
- try {
- fix.fixSingleQuotes(outputFile);
+ Fixes.fixSingleQuotes(outputFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Imports.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Imports.java
index b17b045..139790a 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Imports.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Imports.java
@@ -21,21 +21,16 @@
package org.onap.blueprintgenerator.models.blueprint;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-
-
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
-import lombok.AllArgsConstructor;
-import lombok.Getter; import lombok.Setter;
-import lombok.NoArgsConstructor;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import lombok.Getter;
+import lombok.Setter;
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Interfaces.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Interfaces.java
index a3404f6..435059e 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Interfaces.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Interfaces.java
@@ -31,11 +31,9 @@ import lombok.Getter; import lombok.Setter;
public class Interfaces {
private Start start;
public TreeMap<String, LinkedHashMap<String, Object>> createInterface(TreeMap<String, LinkedHashMap<String, Object>> inps, ComponentSpec cs){
- TreeMap<String, LinkedHashMap<String, Object>> retInputs = new TreeMap<String, LinkedHashMap<String, Object>>();
- retInputs = inps;
//create the start object
Start start = new Start();
- retInputs = start.createOnapStart(retInputs, cs);
+ TreeMap<String, LinkedHashMap<String, Object>> retInputs = start.createOnapStart(inps, cs);
this.setStart(start);
return retInputs;
}
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Properties.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Properties.java
index d32d6f4..6edbe5c 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Properties.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Properties.java
@@ -47,6 +47,8 @@ import org.onap.blueprintgenerator.models.dmaapbp.DmaapStreams;
@JsonInclude(value = Include.NON_NULL)
public class Properties {
+ ArrayList<DmaapStreams> streams_publishes;
+ ArrayList<DmaapStreams> streams_subscribes;
private Appconfig application_config;
private Auxilary docker_config;
private Object image;
@@ -58,8 +60,6 @@ public class Properties {
private String name;
private GetInput topic_name;
private GetInput feed_name;
- ArrayList<DmaapStreams> streams_publishes;
- ArrayList<DmaapStreams> streams_subscribes;
private TlsInfo tls_info;
private ExternalTlsInfo external_cert;
private ResourceConfig resource_config;
@@ -155,8 +155,7 @@ public class Properties {
public TreeMap<String, LinkedHashMap<String, Object>> createDmaapProperties(
TreeMap<String, LinkedHashMap<String, Object>> inps, ComponentSpec cs, String override) {
- TreeMap<String, LinkedHashMap<String, Object>> retInputs = new TreeMap<String, LinkedHashMap<String, Object>>();
- retInputs = inps;
+ TreeMap<String, LinkedHashMap<String, Object>> retInputs = inps;
//set the image
GetInput image = new GetInput();
@@ -171,7 +170,7 @@ public class Properties {
GetInput location = new GetInput();
location.setBpInputName("location_id");
this.setLocation_id(location);
- LinkedHashMap<String, Object> locMap = new LinkedHashMap();
+ LinkedHashMap<String, Object> locMap = new LinkedHashMap<>();
locMap.put("type", "string");
locMap.put("default", "");
retInputs.put("location_id", locMap);
@@ -219,7 +218,7 @@ public class Properties {
this.setApplication_config(app);
//set the stream publishes
- ArrayList<DmaapStreams> pubStreams = new ArrayList();
+ ArrayList<DmaapStreams> pubStreams = new ArrayList<>();
if (cs.getStreams().getPublishes() != null) {
for (Publishes p : cs.getStreams().getPublishes()) {
if (p.getType().equals("message_router") || p.getType().equals("message router")) {
@@ -239,7 +238,7 @@ public class Properties {
}
//set the stream subscribes
- ArrayList<DmaapStreams> subStreams = new ArrayList();
+ ArrayList<DmaapStreams> subStreams = new ArrayList<>();
if (cs.getStreams().getSubscribes() != null) {
for (Subscribes s : cs.getStreams().getSubscribes()) {
if (s.getType().equals("message_router") || s.getType().equals("message router")) {
@@ -258,10 +257,10 @@ public class Properties {
}
}
- if (pubStreams.size() != 0) {
+ if (!pubStreams.isEmpty()) {
this.setStreams_publishes(pubStreams);
}
- if (subStreams.size() != 0) {
+ if (!subStreams.isEmpty()) {
this.setStreams_subscribes(subStreams);
}
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/ResourceConfig.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/ResourceConfig.java
index 13aa0d0..6595a67 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/ResourceConfig.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/ResourceConfig.java
@@ -71,13 +71,12 @@ public class ResourceConfig {
* @return the tree map
*/
public TreeMap<String, LinkedHashMap<String, Object>> createResourceConfig(TreeMap<String, LinkedHashMap<String, Object>> inps, String name){
- TreeMap<String, LinkedHashMap<String, Object>> retInputs = inps;
- LinkedHashMap<String, Object> mi = new LinkedHashMap<String, Object>();
+ LinkedHashMap<String, Object> mi = new LinkedHashMap<>();
mi.put("type", "string");
mi.put("default", "128Mi");
- LinkedHashMap<String, Object> m = new LinkedHashMap<String, Object>();
+ LinkedHashMap<String, Object> m = new LinkedHashMap<>();
m.put("type", "string");
m.put("default", "250m");
@@ -87,7 +86,7 @@ public class ResourceConfig {
}
//set the limits
- TreeMap<String, GetInput> lim = new TreeMap<String, GetInput>();
+ TreeMap<String, GetInput> lim = new TreeMap<>();
GetInput cpu = new GetInput();
cpu.setBpInputName(name + "cpu_limit");
@@ -97,13 +96,13 @@ public class ResourceConfig {
memL.setBpInputName(name + "memory_limit");
lim.put("memory", memL);
- retInputs.put(name + "cpu_limit", m);
- retInputs.put(name + "memory_limit", mi);
+ inps.put(name + "cpu_limit", m);
+ inps.put(name + "memory_limit", mi);
this.setLimits(lim);
//set the requests
- TreeMap<String, GetInput> req = new TreeMap<String, GetInput>();
+ TreeMap<String, GetInput> req = new TreeMap<>();
GetInput cpuR = new GetInput();
cpuR.setBpInputName(name + "cpu_request");
@@ -113,12 +112,12 @@ public class ResourceConfig {
memR.setBpInputName(name + "memory_request");
req.put("memory", memR);
- retInputs.put(name + "cpu_request", m);
- retInputs.put(name + "memory_request", mi);
+ inps.put(name + "cpu_request", m);
+ inps.put(name + "memory_request", mi);
this.setRequests(req);
- return retInputs;
+ return inps;
}
}
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Start.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Start.java
index d9c885d..0b03777 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Start.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/Start.java
@@ -36,14 +36,12 @@ public class Start {
private LinkedHashMap<String, Object> envs;
public TreeMap<String, LinkedHashMap<String, Object>> createOnapStart(TreeMap<String, LinkedHashMap<String, Object>> inps, ComponentSpec cs) {
- TreeMap<String, LinkedHashMap<String, Object>> retInputs = inps;
- retInputs = inps;
-
+
//create the start inputs
StartInputs inputs = new StartInputs();
- inputs.createOnapStartInputs(retInputs, cs);
+ inputs.createOnapStartInputs(inps, cs);
this.setInputs(inputs);
- return retInputs;
+ return inps;
}
}
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/StartInputs.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/StartInputs.java
index 1055fbd..a0cfe20 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/StartInputs.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/StartInputs.java
@@ -41,10 +41,9 @@ public class StartInputs {
private Object envs;
public TreeMap<String, LinkedHashMap<String, Object>> createOnapStartInputs(TreeMap<String, LinkedHashMap<String, Object>> inps, ComponentSpec cs){
- TreeMap<String, LinkedHashMap<String, Object>> retInputs = inps;
int count = 0;
- ArrayList<String> portList = new ArrayList();
+ ArrayList<String> portList = new ArrayList<>();
Auxilary aux = cs.getAuxilary();
if (aux.getPorts() != null) {
@@ -56,10 +55,10 @@ public class StartInputs {
, ports[0], count);
portList.add(internal);
- LinkedHashMap<String, Object> portType = new LinkedHashMap();
+ LinkedHashMap<String, Object> portType = new LinkedHashMap<>();
portType.put("type", "string");
portType.put("default", ports[1]);
- retInputs.put("external_port_" + count, portType);
+ inps.put("external_port_" + count, portType);
count++;
}
@@ -98,7 +97,7 @@ public class StartInputs {
// }
//set the envs
- LinkedHashMap<String, Object> eMap = new LinkedHashMap();
+ LinkedHashMap<String, Object> eMap = new LinkedHashMap<>();
if(cs.getAuxilary().getDatabases() != null){
//set db env variables
LinkedHashMap<String, Object> envVars = PgaasNodeBuilder.getEnvVariables(cs.getAuxilary().getDatabases());
@@ -111,9 +110,9 @@ public class StartInputs {
this.setEnvs(env);
eMap.put("default", "{}");
}
- retInputs.put("envs", eMap);
+ inps.put("envs", eMap);
- return retInputs;
+ return inps;
}
}
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapInfo.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapInfo.java
index 464fc4a..0cec284 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapInfo.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapInfo.java
@@ -46,9 +46,7 @@ public class DmaapInfo {
public TreeMap<String, LinkedHashMap<String, Object>> createOnapDmaapMRInfo(
TreeMap<String, LinkedHashMap<String, Object>> inps, String config, char type) {
- TreeMap<String, LinkedHashMap<String, Object>> retInputs = new TreeMap<String, LinkedHashMap<String, Object>>();
- retInputs = inps;
- LinkedHashMap<String, Object> stringType = new LinkedHashMap<String, Object>();
+ LinkedHashMap<String, Object> stringType = new LinkedHashMap<>();
stringType.put("type", "string");
config = config.replaceAll("-", "_");
@@ -62,9 +60,9 @@ public class DmaapInfo {
topic.setBpInputName(config);
this.setTopic_url(topic);
- retInputs.put(config, stringType);
+ inps.put(config, stringType);
- return retInputs;
+ return inps;
}
public TreeMap<String, LinkedHashMap<String, Object>> createOnapDmaapDRInfo(
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapObj.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapObj.java
index 6af69e5..30f59e2 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapObj.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/blueprint/dmaap/DmaapObj.java
@@ -40,10 +40,8 @@ public class DmaapObj {
public TreeMap<String, LinkedHashMap<String, Object>> createOnapDmaapMRObj(TreeMap<String, LinkedHashMap<String, Object>> inps,
String config, char type, String n, String num, boolean isDmaap) {
- TreeMap<String, LinkedHashMap<String, Object>> retInputs = new TreeMap<String, LinkedHashMap<String, Object>>();
- LinkedHashMap<String, Object> stringType = new LinkedHashMap();
+ LinkedHashMap<String, Object> stringType = new LinkedHashMap<>();
stringType.put("type", "string");
- retInputs = inps;
//set the dmaapinfo
DmaapInfo info = new DmaapInfo();
@@ -58,20 +56,18 @@ public class DmaapObj {
GetInput u = new GetInput();
u.setBpInputName(config + "_" + num +"_aaf_username");
this.setUser(u);
- retInputs.put(config + "_" + num +"_aaf_username", stringType);
+ inps.put(config + "_" + num +"_aaf_username", stringType);
//set password
GetInput p = new GetInput();
p.setBpInputName(config + "_" + num +"_aaf_password");
this.setPass(p);
- retInputs.put(config + "_" + num +"_aaf_password", stringType);
+ inps.put(config + "_" + num +"_aaf_password", stringType);
}
- return retInputs;
+ return inps;
}
public TreeMap<String, LinkedHashMap<String, Object>> createOnapDmaapDRObj(TreeMap<String, LinkedHashMap<String, Object>> inps, String config, char type, String n, String num, boolean isDmaap) {
- TreeMap<String, LinkedHashMap<String, Object>> retInputs = new TreeMap<String, LinkedHashMap<String, Object>>();
- retInputs = inps;
-
+
//set the dmaapinfo
DmaapInfo info = new DmaapInfo();
if(!isDmaap){
@@ -82,6 +78,6 @@ public class DmaapObj {
String infoType = "<<" + n + ">>";
this.setDmaap_info(infoType);
}
- return retInputs;
+ return inps;
}
}
diff --git a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/dmaapbp/DmaapBlueprint.java b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/dmaapbp/DmaapBlueprint.java
index c4cc663..2774abb 100644
--- a/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/dmaapbp/DmaapBlueprint.java
+++ b/mod/bpgenerator/src/main/java/org/onap/blueprintgenerator/models/dmaapbp/DmaapBlueprint.java
@@ -1,4 +1,4 @@
-/**============LICENSE_START=======================================================
+/*============LICENSE_START=======================================================
org.onap.dcae
================================================================================
Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
@@ -8,16 +8,16 @@
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.
============LICENSE_END=========================================================
-
+
*/
package org.onap.blueprintgenerator.models.dmaapbp;
@@ -28,92 +28,103 @@ import java.util.TreeMap;
import org.onap.blueprintgenerator.core.PgaasNodeBuilder;
import org.onap.blueprintgenerator.core.PolicyNodeBuilder;
import org.onap.blueprintgenerator.models.blueprint.Blueprint;
-import org.onap.blueprintgenerator.models.blueprint.Imports;
import org.onap.blueprintgenerator.models.blueprint.Node;
import org.onap.blueprintgenerator.models.componentspec.ComponentSpec;
import org.onap.blueprintgenerator.models.componentspec.Publishes;
import org.onap.blueprintgenerator.models.componentspec.Subscribes;
-public class DmaapBlueprint extends Blueprint{
- public Blueprint createDmaapBlueprint(ComponentSpec cs, String importPath, String override) {
- Blueprint bp = new Blueprint();
-
- //set tosca definition
- bp.setTosca_definitions_version("cloudify_dsl_1_3");
-
- //set the description
- bp.setDescription(cs.getSelf().getDescription());
-
- //create the inpus object that will be added to over the creation of the blueprint
- TreeMap<String, LinkedHashMap<String, Object>> inps = new TreeMap<String, LinkedHashMap<String, Object>>();
-
- //set the imports
- Imports imps = new Imports();
- if(importPath.equals("")) {
- bp.setImports(imps.createDmaapImports());
- }
- else {
- bp.setImports(imps.createImportsFromFile(importPath));
- }
-
- //bp.setImports(imps.getImports());
-
- //set and create the node templates
- TreeMap<String, Node> nodeTemplate = new TreeMap();
-
- //create and add the main dmaap node
- DmaapNode dmaap = new DmaapNode();
- inps = dmaap.createDmaapNode(cs, inps, override);
- nodeTemplate.put(cs.getSelf().getName(), dmaap);
-
- //create and add the topic/feed nodes
-
- //go through the streams publishes
- if(cs.getStreams().getPublishes() != null) {
- for(Publishes p: cs.getStreams().getPublishes()) {
- if(p.getType().equals("message_router") || p.getType().equals("message router")) {
- String topic = p.getConfig_key() + "_topic";
- DmaapNode topicNode = new DmaapNode();
- inps = topicNode.createTopicNode(cs, inps, topic);
- nodeTemplate.put(topic, topicNode);
- } else if(p.getType().equals("data_router") || p.getType().equals("data router")) {
- String feed = p.getConfig_key() + "_feed";
- DmaapNode feedNode = new DmaapNode();
- inps = feedNode.createFeedNode(cs, inps, feed);
- nodeTemplate.put(feed, feedNode);
- }
- }
- }
- //go through the stream subscribes
- if(cs.getStreams().getSubscribes() != null) {
- for(Subscribes s: cs.getStreams().getSubscribes()) {
- if(s.getType().equals("message_router") || s.getType().equals("message router")) {
- String topic = s.getConfig_key() + "_topic";
- DmaapNode topicNode = new DmaapNode();
- inps = topicNode.createTopicNode(cs, inps, topic);
- nodeTemplate.put(topic, topicNode);
- } else if(s.getType().equals("data_router") || s.getType().equals("data router")) {
- String feed = s.getConfig_key() + "_feed";
- DmaapNode feedNode = new DmaapNode();
- inps = feedNode.createFeedNode(cs, inps, feed);
- nodeTemplate.put(feed, feedNode);
- }
- }
- }
-
- //if present in component spec, populate policyNodes information in the blueprint
- if(cs.getPolicyInfo() != null){
- PolicyNodeBuilder.addPolicyNodesAndInputs(cs, nodeTemplate, inps);
- }
-
- //if present in component spec, populate pgaasNodes information in the blueprint
- if(cs.getAuxilary().getDatabases() != null){
- PgaasNodeBuilder.addPgaasNodesAndInputs(cs, nodeTemplate, inps);
- }
-
- bp.setNode_templates(nodeTemplate);
-
- bp.setInputs(inps);
- return bp;
- }
+import static org.onap.blueprintgenerator.common.blueprint.BlueprintHelper.joinUnderscore;
+import static org.onap.blueprintgenerator.models.blueprint.Imports.createDmaapImports;
+import static org.onap.blueprintgenerator.models.blueprint.Imports.createImportsFromFile;
+
+public class DmaapBlueprint extends Blueprint {
+
+ private static final String TOPIC = "topic";
+ private static final String FEED = "feed";
+
+ public Blueprint createDmaapBlueprint(ComponentSpec componentSpec, String importPath, String override) {
+ Blueprint blueprint = new Blueprint();
+
+ //set tosca definition
+ blueprint.setTosca_definitions_version("cloudify_dsl_1_3");
+
+ //set the description
+ blueprint.setDescription(componentSpec.getSelf().getDescription());
+
+ //create the inpus object that will be added to over the creation of the blueprint
+ TreeMap<String, LinkedHashMap<String, Object>> inps = new TreeMap<>();
+
+ //set the imports
+ if (importPath.equals("")) {
+ blueprint.setImports(createDmaapImports());
+ } else {
+ blueprint.setImports(createImportsFromFile(importPath));
+ }
+
+ //set and create the node templates
+ TreeMap<String, Node> nodeTemplate = new TreeMap();
+
+ //create and add the main dmaap node
+ DmaapNode dmaap = new DmaapNode();
+ inps = dmaap.createDmaapNode(componentSpec, inps, override);
+ nodeTemplate.put(componentSpec.getSelf().getName(), dmaap);
+
+ //create and add the topic/feed nodes
+
+ //go through the streams publishes
+ if (componentSpec.getStreams().getPublishes() != null) {
+ for (Publishes publisher : componentSpec.getStreams().getPublishes()) {
+ if (isMessageRouter(publisher.getType())) {
+ String topic = joinUnderscore(publisher.getConfig_key(), TOPIC);
+ DmaapNode topicNode = new DmaapNode();
+ inps = topicNode.createTopicNode(componentSpec, inps, topic);
+ nodeTemplate.put(topic, topicNode);
+ } else if (isDataRouter(publisher.getType())) {
+ String feed = joinUnderscore(publisher.getConfig_key(), FEED);
+ DmaapNode feedNode = new DmaapNode();
+ inps = feedNode.createFeedNode(componentSpec, inps, feed);
+ nodeTemplate.put(feed, feedNode);
+ }
+ }
+ }
+ //go through the stream subscribes
+ if (componentSpec.getStreams().getSubscribes() != null) {
+ for (Subscribes subscriber : componentSpec.getStreams().getSubscribes()) {
+ if (isMessageRouter(subscriber.getType())) {
+ String topic = joinUnderscore(subscriber.getConfig_key(), TOPIC);
+ DmaapNode topicNode = new DmaapNode();
+ inps = topicNode.createTopicNode(componentSpec, inps, topic);
+ nodeTemplate.put(topic, topicNode);
+ } else if (isDataRouter(subscriber.getType())) {
+ String feed = joinUnderscore(subscriber.getConfig_key(), FEED);
+ DmaapNode feedNode = new DmaapNode();
+ inps = feedNode.createFeedNode(componentSpec, inps, feed);
+ nodeTemplate.put(feed, feedNode);
+ }
+ }
+ }
+
+ //if present in component spec, populate policyNodes information in the blueprint
+ if (componentSpec.getPolicyInfo() != null) {
+ PolicyNodeBuilder.addPolicyNodesAndInputs(componentSpec, nodeTemplate, inps);
+ }
+
+ //if present in component spec, populate pgaasNodes information in the blueprint
+ if (componentSpec.getAuxilary().getDatabases() != null) {
+ PgaasNodeBuilder.addPgaasNodesAndInputs(componentSpec, nodeTemplate, inps);
+ }
+
+ blueprint.setNode_templates(nodeTemplate);
+
+ blueprint.setInputs(inps);
+ return blueprint;
+ }
+
+ private boolean isDataRouter(String type) {
+ return type.equals("data_router") || type.equals("data router");
+ }
+
+ private boolean isMessageRouter(String type) {
+ return type.equals("message_router") || type.equals("message router");
+ }
}
diff --git a/mod/bpgenerator/src/test/java/org/onap/blueprintgenerator/models/dmaapbp/DmaapBlueprintTest.java b/mod/bpgenerator/src/test/java/org/onap/blueprintgenerator/models/dmaapbp/DmaapBlueprintTest.java
new file mode 100644
index 0000000..820082e
--- /dev/null
+++ b/mod/bpgenerator/src/test/java/org/onap/blueprintgenerator/models/dmaapbp/DmaapBlueprintTest.java
@@ -0,0 +1,244 @@
+/*============LICENSE_START=======================================================
+ org.onap.dcae
+ ================================================================================
+ Copyright (c) 2020 Nokia. All rights reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ */
+
+
+package org.onap.blueprintgenerator.models.dmaapbp;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.onap.blueprintgenerator.models.blueprint.Blueprint;
+import org.onap.blueprintgenerator.models.componentspec.Artifacts;
+import org.onap.blueprintgenerator.models.componentspec.Auxilary;
+import org.onap.blueprintgenerator.models.componentspec.ComponentSpec;
+import org.onap.blueprintgenerator.models.componentspec.Parameters;
+import org.onap.blueprintgenerator.models.componentspec.Publishes;
+import org.onap.blueprintgenerator.models.componentspec.Self;
+import org.onap.blueprintgenerator.models.componentspec.Streams;
+import org.onap.blueprintgenerator.models.componentspec.Subscribes;
+
+public class DmaapBlueprintTest {
+
+ private static final String MOCKED_NAME = "sample.name";
+ private static final String MESSAGE_ROUTER_TYPE_1 = "message_router";
+ private static final String MESSAGE_ROUTER_TYPE_2 = "message router";
+ private static final String DATA_ROUTER_TYPE_1 = "data_router";
+ private static final String DATA_ROUTER_TYPE_2 = "data router";
+ private static final String CONFIG_KEY_1 = "Configkey1";
+ private static final String CONFIG_KEY_2 = "Configkey2";
+
+ private static final String TOPIC_NODE_1 = CONFIG_KEY_1 + "_topic";
+ private static final String TOPIC_NODE_2 = CONFIG_KEY_2 + "_topic";
+ private static final String FEED_NODE_1 = CONFIG_KEY_1 + "_feed";
+ private static final String FEED_NODE_2 = CONFIG_KEY_2 + "_feed";
+
+ private static final String SAMPLE_FORMAT = "Format";
+ private static final String SAMPLE_VERSION = "1.0.0";
+ private static final String SAMPLE_ROUTE = "SampleRoute";
+ private static final String SAMPLE_DESCRIPTION = "sample description";
+ private static final String SAMPLE_PORTS = "8080:8080";
+ private static final String SAMPLE_ARTIFACT_TYPE = "test";
+ private static final String SAMPLE_ARTIFACT_URI = "test_uri";
+
+ @Test
+ public void dmaapBlueprintShouldHaveNodeTemplateWithDmaapNode() {
+
+ //given
+ ComponentSpec componentSpec = getMockedComponentSpec();
+ DmaapBlueprint dmaapBlueprint = new DmaapBlueprint();
+
+ //when
+ Blueprint resultBlueprint = dmaapBlueprint.createDmaapBlueprint(componentSpec, "", "");
+
+ //then
+ assertTrue(resultBlueprint.getNode_templates().get(MOCKED_NAME) instanceof DmaapNode);
+ }
+
+ @Test
+ public void nodeTemplateHasTopicNodeWhenAddMessageRouterAsPublishes() {
+ //given
+ ComponentSpec componentSpec = getMockedComponentSpec();
+ Streams streams = new Streams();
+ streams.setPublishes(getMessageRouterPublishes());
+ streams.setSubscribes(new Subscribes[0]);
+
+ when(componentSpec.getStreams()).thenReturn(streams);
+ DmaapBlueprint dmaapBlueprint = new DmaapBlueprint();
+
+ //when
+ Blueprint resultBlueprint = dmaapBlueprint.createDmaapBlueprint(componentSpec, "", "");
+
+ //then
+ assertNotNull(resultBlueprint.getNode_templates().get(TOPIC_NODE_1));
+ assertNotNull(resultBlueprint.getNode_templates().get(TOPIC_NODE_2));
+
+ }
+
+ @Test
+ public void nodeTemplateHasTopicNodeWhenAddMessageRouterAsSubscribes() {
+ //given
+ ComponentSpec componentSpec = getMockedComponentSpec();
+ Streams streams = new Streams();
+ streams.setPublishes(new Publishes[0]);
+ streams.setSubscribes(getMessageRouterSubscribes());
+
+ when(componentSpec.getStreams()).thenReturn(streams);
+ DmaapBlueprint dmaapBlueprint = new DmaapBlueprint();
+
+ //when
+ Blueprint resultBlueprint = dmaapBlueprint.createDmaapBlueprint(componentSpec, "", "");
+
+ //then
+ assertNotNull(resultBlueprint.getNode_templates().get(TOPIC_NODE_1));
+ assertNotNull(resultBlueprint.getNode_templates().get(TOPIC_NODE_2));
+
+ }
+
+ @Test
+ public void nodeTemplateHasFeedNodeWhenAddDataRouterAsPublishes() {
+ //given
+ ComponentSpec componentSpec = getMockedComponentSpec();
+ Streams streams = new Streams();
+ streams.setPublishes(getDataRouterPublishes());
+ streams.setSubscribes(new Subscribes[0]);
+
+ when(componentSpec.getStreams()).thenReturn(streams);
+ DmaapBlueprint dmaapBlueprint = new DmaapBlueprint();
+
+ //when
+ Blueprint resultBlueprint = dmaapBlueprint.createDmaapBlueprint(componentSpec, "", "");
+
+ //then
+ assertNotNull(resultBlueprint.getNode_templates().get(FEED_NODE_1));
+ assertNotNull(resultBlueprint.getNode_templates().get(FEED_NODE_2));
+
+ }
+
+ @Test
+ public void nodeTemplateHasFeedNodeWhenAddDataRouterAsSubscribes() {
+ //given
+ ComponentSpec componentSpec = getMockedComponentSpec();
+ Streams streams = new Streams();
+ streams.setPublishes(new Publishes[0]);
+ streams.setSubscribes(getDataRouterSubscribes());
+
+ when(componentSpec.getStreams()).thenReturn(streams);
+ DmaapBlueprint dmaapBlueprint = new DmaapBlueprint();
+
+ //when
+ Blueprint resultBlueprint = dmaapBlueprint.createDmaapBlueprint(componentSpec, "", "");
+
+ //then
+ assertNotNull(resultBlueprint.getNode_templates().get(FEED_NODE_1));
+ assertNotNull(resultBlueprint.getNode_templates().get(FEED_NODE_2));
+
+ }
+
+ private Publishes[] getMessageRouterPublishes() {
+ List<Publishes> publishesList = new ArrayList<>();
+
+ publishesList.add(createSamplePublishes(MESSAGE_ROUTER_TYPE_1, CONFIG_KEY_1));
+ publishesList.add(createSamplePublishes(MESSAGE_ROUTER_TYPE_2, CONFIG_KEY_2));
+ return publishesList.toArray(new Publishes[0]);
+ }
+
+ private Subscribes[] getMessageRouterSubscribes() {
+ List<Subscribes> subscribesList = new ArrayList<>();
+
+ subscribesList.add(createSampleSubscribes(MESSAGE_ROUTER_TYPE_1, CONFIG_KEY_1));
+ subscribesList.add(createSampleSubscribes(MESSAGE_ROUTER_TYPE_2, CONFIG_KEY_2));
+ return subscribesList.toArray(new Subscribes[0]);
+ }
+
+ private Publishes[] getDataRouterPublishes() {
+ List<Publishes> publishesList = new ArrayList<>();
+
+ publishesList.add(createSamplePublishes(DATA_ROUTER_TYPE_1, CONFIG_KEY_1));
+ publishesList.add(createSamplePublishes(DATA_ROUTER_TYPE_2, CONFIG_KEY_2));
+ return publishesList.toArray(new Publishes[0]);
+ }
+
+ private Subscribes[] getDataRouterSubscribes() {
+ List<Subscribes> subscribesList = new ArrayList<>();
+
+ subscribesList.add(createSampleSubscribes(DATA_ROUTER_TYPE_1, CONFIG_KEY_1));
+ subscribesList.add(createSampleSubscribes(DATA_ROUTER_TYPE_2, CONFIG_KEY_2));
+ return subscribesList.toArray(new Subscribes[0]);
+ }
+
+ private Publishes createSamplePublishes(String type, String key) {
+ Publishes publishes = new Publishes();
+
+ publishes.setType(type);
+ publishes.setConfig_key(key);
+ publishes.setFormat(SAMPLE_FORMAT);
+ publishes.setVersion(SAMPLE_VERSION);
+ publishes.setRoute(SAMPLE_ROUTE);
+
+ return publishes;
+ }
+
+ private Subscribes createSampleSubscribes(String type, String key) {
+ Subscribes subscribes = new Subscribes();
+
+ subscribes.setType(type);
+ subscribes.setConfig_key(key);
+ subscribes.setFormat(SAMPLE_FORMAT);
+ subscribes.setVersion(SAMPLE_FORMAT);
+ subscribes.setRoute(SAMPLE_ROUTE);
+
+ return subscribes;
+ }
+
+ private ComponentSpec getMockedComponentSpec() {
+ Self self = mock(Self.class);
+ when(self.getDescription()).thenReturn(SAMPLE_DESCRIPTION);
+ when(self.getName()).thenReturn(MOCKED_NAME);
+
+ Auxilary auxilary = mock(Auxilary.class);
+ ArrayList<Object> ports = new ArrayList<>();
+ ports.add(SAMPLE_PORTS);
+ when(auxilary.getPorts()).thenReturn(ports);
+
+ Streams streams = mock(Streams.class);
+ when(streams.getPublishes()).thenReturn(new Publishes[0]);
+ when(streams.getSubscribes()).thenReturn(new Subscribes[0]);
+
+ Artifacts artifact = new Artifacts();
+ artifact.setType(SAMPLE_ARTIFACT_TYPE);
+ artifact.setUri(SAMPLE_ARTIFACT_URI);
+
+ Artifacts[] arrayArtifacts = new Artifacts[10];
+ arrayArtifacts[0] = artifact;
+
+ ComponentSpec componentSpec = mock(ComponentSpec.class);
+ when(componentSpec.getSelf()).thenReturn(self);
+ when(componentSpec.getAuxilary()).thenReturn(auxilary);
+ when(componentSpec.getStreams()).thenReturn(streams);
+ when(componentSpec.getArtifacts()).thenReturn(arrayArtifacts);
+ when(componentSpec.getParameters()).thenReturn(new Parameters[0]);
+ return componentSpec;
+ }
+}
diff --git a/mod/bpgenerator/version.properties b/mod/bpgenerator/version.properties
index 9e0d73d..303a703 100644
--- a/mod/bpgenerator/version.properties
+++ b/mod/bpgenerator/version.properties
@@ -1,6 +1,6 @@
major=1
-minor=4
-patch=0
+minor=5
+patch=1
base_version=${major}.${minor}.${patch}
release_version=${base_version}
snapshot_version=${base_version}-SNAPSHOT
diff --git a/mod2/auth-service/Dockerfile b/mod2/auth-service/Dockerfile
new file mode 100644
index 0000000..c427bda
--- /dev/null
+++ b/mod2/auth-service/Dockerfile
@@ -0,0 +1,11 @@
+FROM onap/integration-java11:7.1.0
+WORKDIR /usr/app
+VOLUME /tmp
+
+ADD target/auth-service-1.0.0-SNAPSHOT.jar auth-service-1.0.0-SNAPSHOT.jar
+
+EXPOSE 8082
+
+ENTRYPOINT ["java", \
+ "-Djava.security.egd=file:/dev/./urandom", \
+ "-jar", "auth-service-1.0.0-SNAPSHOT.jar"] \ No newline at end of file
diff --git a/mod2/auth-service/pom.xml b/mod2/auth-service/pom.xml
new file mode 100644
index 0000000..1fd4f02
--- /dev/null
+++ b/mod2/auth-service/pom.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ /*
+ ~ * ============LICENSE_START=======================================================
+ ~ * org.onap.dcae
+ ~ * ================================================================================
+ ~ * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ ~ * ================================================================================
+ ~ * 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.
+ ~ * ============LICENSE_END=========================================================
+ ~ */
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.oparent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>2.0.0</version>
+ </parent>
+ <groupId>org.onap.dcaegen2.platform.mod</groupId>
+ <artifactId>auth-service</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <name>auth-service</name>
+ <description>REST APIs to serve Auth Service</description>
+
+ <properties>
+ <java.version>11</java.version>
+ <maven.compiler.source>${java.version}</maven.compiler.source>
+ <maven.compiler.target>${java.version}</maven.compiler.target>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-mongodb</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.8.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt</artifactId>
+ <version>0.9.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-webflux</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ </dependency>
+ <!-- CODE GENERATION -->
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>okhttp</artifactId>
+ <version>4.0.1</version>
+ </dependency>
+
+ <!--TEST DEPENDENCIES-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.junit.vintage</groupId>
+ <artifactId>junit-vintage-engine</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <version>4.0.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>2.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <!-- Import dependency management from Spring Boot -->
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>2.2.5.RELEASE</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>2.2.5.RELEASE</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.22.2</version>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java
new file mode 100644
index 0000000..5b147bf
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/AuthServiceApplication.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Auth Service Application
+ */
+@SpringBootApplication
+public class AuthServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(AuthServiceApplication.class, args);
+ }
+
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java
new file mode 100644
index 0000000..959b450
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/DataLoader.java
@@ -0,0 +1,97 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod;
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * To Initialize Roles and create Default Admin User
+ */
+@Component
+public class DataLoader implements ApplicationRunner {
+
+ @Autowired
+ private RoleRepository roleRepository;
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ PasswordEncoder passwordEncoder;
+
+ @Override
+ public void run(ApplicationArguments args) throws Exception {
+ populateRoles();
+ populateAdminUser();
+ }
+
+ private void populateRoles() {
+ List<Role> roles = createRoles();
+ roles.forEach((role) -> {
+ boolean roleNotPresent = !roleRepository.findByName(role.getName()).isPresent();
+ if(roleNotPresent)
+ roleRepository.save(role);
+ });
+
+ }
+
+ private List<Role> createRoles() {
+ Role admin = new Role("ROLE_ADMIN");
+ Role user = new Role("ROLE_USER");
+ Role developer = new Role("ROLE_DEVELOPER");
+ return Arrays.asList(admin, user, developer);
+ }
+
+ private void populateAdminUser() {
+ boolean adminNotPresent = !userRepository.findByUsername("admin").isPresent();
+ if(adminNotPresent) {
+ ModUser admin = createAdmin();
+ userRepository.save(admin);
+ }
+ }
+
+ private ModUser createAdmin() {
+ ModUser admin = new ModUser();
+ admin.setUsername("admin");
+ admin.setFullName("Admin");
+ admin.setPassword(passwordEncoder.encode("admin@mod"));
+ HashSet<Role> roleAdmin = new HashSet<>();
+ roleAdmin.add(roleRepository.findByName("ROLE_ADMIN").get());
+ admin.setRoles(roleAdmin);
+ return admin;
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java
new file mode 100644
index 0000000..6612138
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/AuthController.java
@@ -0,0 +1,171 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.controllers;
+
+import org.onap.dcaegen2.platform.mod.exceptions.RoleNotExistsException;
+import org.onap.dcaegen2.platform.mod.exceptions.UserAlreadyExistsException;
+import org.onap.dcaegen2.platform.mod.models.LoginRequest;
+import org.onap.dcaegen2.platform.mod.models.JwtResponse;
+import org.onap.dcaegen2.platform.mod.models.SignupRequest;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.GenericResponse;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+
+import javax.validation.Valid;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Authentication Operations
+ */
+@RestController
+@RequestMapping("/api/auth")
+@CrossOrigin(origins = "*")
+public class AuthController {
+
+ @Autowired
+ AuthenticationManager authenticationManager;
+
+ @Autowired
+ UserRepository userRepository;
+
+ @Autowired
+ RoleRepository roleRepository;
+
+ @Autowired
+ PasswordEncoder passwordEncoder;
+
+ @Autowired
+ JwtUtils jwtUtils;
+
+ @PreAuthorize("isAuthenticated()")
+ @PostMapping("/validate-token")
+ public ResponseEntity<?> validateToken() {
+ return new ResponseEntity("true", HttpStatus.OK);
+ }
+
+ @PostMapping("/signin")
+ public ResponseEntity<?> authenticateUser(@RequestBody @Valid LoginRequest loginRequest) {
+ Authentication authentication = authenticateLoginRequest(loginRequest);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ String jwt = jwtUtils.generateJwtToken(authentication);
+ return setUserContext(authentication, jwt);
+ }
+
+ private Authentication authenticateLoginRequest(@RequestBody @Valid LoginRequest loginRequest) {
+ return authenticationManager.authenticate(
+ new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
+ );
+ }
+
+ private ResponseEntity<?> setUserContext(Authentication authentication, String jwt) {
+ UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
+ List<String> roles = setRolesFromUserDetails(userDetails);
+ return buildUserContext(jwt, userDetails, roles);
+ }
+
+ private List<String> setRolesFromUserDetails(UserDetailsImpl userDetails) {
+ return userDetails.getAuthorities().stream()
+ .map(item -> ((GrantedAuthority) item).getAuthority())
+ .collect(Collectors.toList());
+ }
+
+ private ResponseEntity<JwtResponse> buildUserContext(String jwt, UserDetailsImpl userDetails, List<String> roles) {
+ return ResponseEntity.ok(JwtResponse.builder()
+ .id(userDetails.getId())
+ .roles(roles)
+ .username(userDetails.getUsername())
+ .token(jwt)
+ .fullName(userDetails.getFullName())
+ .build()
+ );
+ }
+
+ @PreAuthorize("hasRole('ADMIN')")
+ @PostMapping("/signup")
+ public ResponseEntity<?> registerUser(@RequestBody @Valid SignupRequest request) {
+ checkIfUserExists(request);
+ ModUser user = createNewUser(request);
+ userRepository.save(user);
+ return ResponseEntity.ok(new GenericResponse("User registered successfully!"));
+ }
+
+ private void checkIfUserExists(@RequestBody @Valid SignupRequest signUpRequest) {
+ if (userRepository.existsByUsername(signUpRequest.getUsername()))
+ throw new UserAlreadyExistsException("Username already exists!");
+ }
+
+ private ModUser createNewUser(@RequestBody @Valid SignupRequest request) {
+ ModUser user = new ModUser();
+ user.setUsername(request.getUsername());
+ user.setFullName(request.getFullName());
+ user.setPassword(getEncodedPassword(request));
+ Set<Role> roles = createRoles(request.getRoles());
+ user.setRoles(roles);
+ return user;
+ }
+
+ private String getEncodedPassword(@RequestBody @Valid SignupRequest request) {
+ return passwordEncoder.encode(request.getPassword());
+ }
+
+ public Set<Role> createRoles(Set<String> roleStrings) {
+ Set<Role> roles = new HashSet<>();
+ for (String roleStr : roleStrings) {
+ roles.add(getRole(roleStr));
+ }
+ return roles;
+ }
+
+ private Role getRole(String roleStr) {
+ return roleRepository.findByName(roleStr).orElseThrow(
+ () -> new RoleNotExistsException(String.format("Role %s does not exist", roleStr)));
+ }
+}
+
+
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java
new file mode 100644
index 0000000..e129cda
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/RoleController.java
@@ -0,0 +1,58 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.controllers;
+
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Role Operations
+ */
+@RestController
+@RequestMapping("/api/roles")
+@CrossOrigin(origins = "*")
+public class RoleController {
+
+ @Autowired
+ RoleRepository roleRepository;
+
+ @GetMapping
+ @ResponseStatus(HttpStatus.OK)
+ public List<String> getRoles(){
+ return roleRepository.findAll()
+ .stream()
+ .map(role -> role.getName())
+ .collect(Collectors.toList());
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java
new file mode 100644
index 0000000..90e7b62
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/controllers/UserController.java
@@ -0,0 +1,96 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.controllers;
+
+import org.onap.dcaegen2.platform.mod.exceptions.UserNotFoundException;
+import org.onap.dcaegen2.platform.mod.models.GenericResponse;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.onap.dcaegen2.platform.mod.services.MODUserDetailService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+
+/**
+ * @author
+ * @date 09/08/2020
+ * User Operations
+ */
+@RestController
+@RequestMapping("/api/users")
+@CrossOrigin(origins = "*")
+public class UserController {
+
+ @Autowired
+ private MODUserDetailService modUserDetailService;
+
+ @Autowired
+ private UserDetailsServiceImpl userDetailsService;
+
+ @PreAuthorize("hasRole('ADMIN')")
+ @GetMapping("/getAll")
+ @ResponseStatus(HttpStatus.OK)
+ public List<ModUser> getAllUsers() {
+ return modUserDetailService.findAll();
+ }
+
+ @PreAuthorize("hasRole('ADMIN') or hasRole('USER')")
+ @GetMapping("/{username}")
+ public UserDetails getUser(@PathVariable String username) {
+ return userDetailsService.loadUserByUsername(username);
+ }
+
+ @PreAuthorize("hasRole('ADMIN')")
+ @PatchMapping("/admin/{username}")
+ public ModUser adminUpdateUserProfile(@PathVariable String username, @RequestBody @Valid UpdateUserRequest
+ userRequest, @RequestHeader (name="Authorization") String token) {
+ return userDetailsService.adminUpdateUser(username, userRequest, token);
+ }
+
+ @PreAuthorize("hasRole('USER') or hasRole('DEVELOPER')")
+ @PatchMapping("/user/{username}")
+ public ModUser userUpdateOwnProfile(@PathVariable String username, @RequestBody @Valid UpdateUserRequest
+ userRequest, @RequestHeader (name="Authorization") String token) {
+ return userDetailsService.userUpdateOwnProfile(username, userRequest, token);
+ }
+
+ @PreAuthorize("hasRole('ADMIN')")
+ @DeleteMapping("/{username}")
+ public ResponseEntity<?> deleteUser(@PathVariable String username) {
+ modUserDetailService.deleteUserByUsername(username);
+ return ResponseEntity.ok(new GenericResponse("User " + username + " was removed"));
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public void userNotFoundHandler(UserNotFoundException ex) {
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java
new file mode 100644
index 0000000..e029e69
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/AppExceptionHandler.java
@@ -0,0 +1,52 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+import org.onap.dcaegen2.platform.mod.models.GenericResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception handler for the Auth Service Application
+ */
+@ControllerAdvice
+@Slf4j
+public class AppExceptionHandler {
+
+ @ExceptionHandler
+ public ResponseEntity<GenericResponse> resolveRuntimeException(UserAlreadyExistsException ex){
+ log.error(ex.getMessage());
+ return new ResponseEntity<>(new GenericResponse(ex.getMessage()), HttpStatus.CONFLICT);
+ }
+
+ @ExceptionHandler
+ public ResponseEntity<GenericResponse> resolveRoleNotFoundException(RoleNotExistsException ex){
+ log.error(ex.getMessage());
+ return new ResponseEntity<>(new GenericResponse(ex.getMessage()), HttpStatus.BAD_REQUEST);
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java
new file mode 100644
index 0000000..4a5837a
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/IllegalUserOperationException.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception for Illegal Operation
+ */
+public class IllegalUserOperationException extends RuntimeException {
+ public IllegalUserOperationException(String s) {
+ super(s);
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java
new file mode 100644
index 0000000..dfa6efb
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/RoleNotExistsException.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception for Role not exist
+ */
+public class RoleNotExistsException extends RuntimeException {
+ public RoleNotExistsException(String message) {
+ super(message);
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java
new file mode 100644
index 0000000..475dc44
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserAlreadyExistsException.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception for User already exists
+ */
+public class UserAlreadyExistsException extends RuntimeException {
+ public UserAlreadyExistsException(String message) {
+ super(message);
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java
new file mode 100644
index 0000000..95c6a70
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/exceptions/UserNotFoundException.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.exceptions;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Exception for User Not Found
+ */
+public class UserNotFoundException extends RuntimeException {
+ public UserNotFoundException(String s) {
+ super(s);
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java
new file mode 100644
index 0000000..c4625a4
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/GenericResponse.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Generic Response for the Auth Service Request
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+public class GenericResponse {
+
+ private String message;
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java
new file mode 100644
index 0000000..8855245
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/JwtResponse.java
@@ -0,0 +1,50 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * JWT Response for the Auth Service Request
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class JwtResponse {
+
+ private String token;
+ private String type = "Bearer";
+ private String id;
+ private String username;
+ private String fullName;
+ private List<String> roles;
+
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java
new file mode 100644
index 0000000..af0f710
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/LoginRequest.java
@@ -0,0 +1,43 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Login request
+ */
+@Data
+public class LoginRequest {
+
+ @NotBlank
+ private String username;
+
+ @NotBlank
+ private String password;
+
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java
new file mode 100644
index 0000000..4da5c98
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/ModUser.java
@@ -0,0 +1,75 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Assigning Roles to User
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Document(collection = "users")
+public class ModUser implements Serializable {
+
+ @Id
+ public String _id;
+
+ @NotBlank
+ @Size(max = 10)
+ private String username;
+
+ @NotBlank
+ private String password;
+
+ @NotBlank
+ private String fullName;
+
+ @DBRef
+ private Set<Role> roles = new HashSet<>();
+
+ public ModUser(@NotBlank @Size(max = 10) String username, @NotBlank String password, @NotBlank String fullName) {
+ this.username = username;
+ this.password = password;
+ this.fullName=fullName;
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java
new file mode 100644
index 0000000..8cce344
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/Role.java
@@ -0,0 +1,50 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Roles
+ */
+@Document(collection = "roles")
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Role {
+
+ @Id
+ private String id;
+
+ private String name;
+
+ public Role(String name) {
+ this.name = name;
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java
new file mode 100644
index 0000000..f705d76
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/SignupRequest.java
@@ -0,0 +1,53 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * To validate User enter Details
+ */
+@Data
+public class SignupRequest {
+
+ @NotBlank(message = "username must not be blank")
+ @Size(min = 5, max = 10, message = "username must be between 5 and 10 characters.")
+ private String username;
+
+ @NotNull(message = "username must not be null")
+ @Size(min = 1, message = "At least 1 role must be passed")
+ private Set<String> roles;
+
+ @NotBlank(message = "password must not be blank")
+ private String password;
+
+ @NotBlank(message = "Full name must not be blank")
+ private String fullName;
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java
new file mode 100644
index 0000000..6e3abf6
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/models/UpdateUserRequest.java
@@ -0,0 +1,47 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.models;
+
+import lombok.Data;
+
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * To update User Details of Name and Password
+ */
+@Data
+public class UpdateUserRequest {
+
+ @Size(min = 1, message = "At least 1 role must be passed")
+ private Set<String> roles;
+
+ @Pattern(regexp = "^(?!\\s*$).+", message = "password must not be blank")
+ private String password;
+
+ @Pattern(regexp = "^(?!\\s*$).+", message = "fullName must not be blank")
+ private String fullName;
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java
new file mode 100644
index 0000000..6efad17
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/RoleRepository.java
@@ -0,0 +1,37 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.repositories;
+
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+import java.util.Optional;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Interface to find user exists or not
+ */
+public interface RoleRepository extends MongoRepository<Role, String> {
+ Optional<Role> findByName(String name);
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java
new file mode 100644
index 0000000..442ebf1
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/repositories/UserRepository.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.repositories;
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+import java.util.Optional;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Interface to Find/Valid/Delete user
+ */
+public interface UserRepository extends MongoRepository<ModUser, String>{
+ Optional<ModUser> findByUsername(String username);
+ Boolean existsByUsername(String username);
+ void deleteByUsername(String username);
+}
+
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java
new file mode 100644
index 0000000..cfccce4
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/WebSecurityConfigurer.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security;
+
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthEntryPointJwt;
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthTokenFilter;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Allows customization to the Spring WebSecurity
+ */
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ UserDetailsServiceImpl userDetailsService;
+
+ @Autowired
+ private AuthEntryPointJwt unauthorizedHandler;
+
+ @Bean
+ public AuthTokenFilter authenticationJwtTokenFilter(){
+ return new AuthTokenFilter();
+ }
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
+ authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
+ }
+
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception{
+ return super.authenticationManagerBean();
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.cors().and().csrf().disable()
+ .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+ .authorizeRequests().antMatchers("/api/auth/**").permitAll()
+ .antMatchers("/api/users/**").permitAll()
+ .anyRequest().authenticated();
+
+ http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java
new file mode 100644
index 0000000..310d487
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthEntryPointJwt.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.jwt;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * JWT Authentication Entry Point
+ */
+
+@Slf4j
+@Component
+public class AuthEntryPointJwt implements AuthenticationEntryPoint {
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException authException) throws IOException, ServletException {
+ log.error("Unauthorized error: {}", authException.getMessage());
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java
new file mode 100644
index 0000000..012c333
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/AuthTokenFilter.java
@@ -0,0 +1,81 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.jwt;
+
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * Authentication Token Filter
+ */
+@Slf4j
+public class AuthTokenFilter extends OncePerRequestFilter {
+
+ @Autowired
+ private JwtUtils jwtUtils;
+
+ @Autowired
+ private UserDetailsServiceImpl userDetailsService;
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
+ try{
+ String jwt = parseJwt(httpServletRequest);
+ if (jwt != null && jwtUtils.validateJwtToken(jwt)){
+ String username = jwtUtils.getUserNameFromJwtToken(jwt);
+ UserDetails userDetails = userDetailsService.loadUserByUsername(username);
+ UsernamePasswordAuthenticationToken authenticationToken =
+ new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
+ authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
+ SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+ }
+ }catch (Exception e){
+ logger.error("Cannot set user authentication: {}", e);
+ }
+ filterChain.doFilter(httpServletRequest, httpServletResponse);
+ }
+
+ private String parseJwt(HttpServletRequest httpServletRequest) {
+ String headerAuth = httpServletRequest.getHeader("Authorization");
+
+ if(StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")){
+ return headerAuth.substring(7, headerAuth.length());
+ }
+ return null;
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java
new file mode 100644
index 0000000..3b6d311
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/jwt/JwtUtils.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.jwt;
+
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.SignatureException;
+import io.jsonwebtoken.MalformedJwtException;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.UnsupportedJwtException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * JWT Utils
+ */
+@Slf4j
+@Component
+public class JwtUtils {
+
+ @Value("${mod-portal.jwt.secret}")
+ private String jwtSecret;
+
+ @Value("${mod-portal.jwt.jwtExpirationMs}")
+ private int jwtExpirationMs;
+
+ public String generateJwtToken(Authentication authentication) {
+
+ UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
+
+ return Jwts.builder()
+ .setSubject((userPrincipal.getUsername()))
+ .claim("roles", userPrincipal.getAuthoritiesAsList())
+ .claim("fullName", userPrincipal.getFullName())
+ .setIssuedAt(new Date())
+ .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
+ .signWith(SignatureAlgorithm.HS512, jwtSecret)
+ .compact();
+ }
+
+ public String getUserNameFromJwtToken(String token) {
+ return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
+ }
+
+ public boolean validateJwtToken(String authToken) {
+ try {
+ Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
+ return true;
+ } catch (SignatureException e) {
+ log.error("Invalid JWT signature: {}", e.getMessage());
+ } catch (MalformedJwtException e) {
+ log.error("Invalid JWT token: {}", e.getMessage());
+ } catch (ExpiredJwtException e) {
+ log.error("JWT token is expired: {}", e.getMessage());
+ } catch (UnsupportedJwtException e) {
+ log.error("JWT token is unsupported: {}", e.getMessage());
+ } catch (IllegalArgumentException e) {
+ log.error("JWT claims string is empty: {}", e.getMessage());
+ }
+
+ return false;
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java
new file mode 100644
index 0000000..82cb577
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsImpl.java
@@ -0,0 +1,127 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.services;
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.EqualsAndHashCode;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * User Details Implementation
+ */
+@EqualsAndHashCode
+public class UserDetailsImpl implements UserDetails{
+
+ private static final long serialVersionUID = 1L;
+
+ private String id;
+
+ private String username;
+
+ private String fullName;
+
+ @JsonIgnore
+ private String password;
+
+ private Collection<? extends GrantedAuthority> authorities;
+
+ public UserDetailsImpl(String id, String username, String fullName, String password, Collection<?
+ extends GrantedAuthority> authorities) {
+ this.id = id;
+ this.username = username;
+ this.fullName = fullName;
+ this.password = password;
+ this.authorities = authorities;
+ }
+
+ public static UserDetails build(ModUser user) {
+ List<GrantedAuthority> authorities = user.getRoles().stream()
+ .map(role -> new SimpleGrantedAuthority(role.getName()))
+ .collect(Collectors.toList());
+
+ return new UserDetailsImpl(
+ user.get_id(),
+ user.getUsername(),
+ user.getFullName(),
+ user.getPassword(),
+ authorities
+ );
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public Collection<? extends GrantedAuthority> getAuthorities() {
+ return authorities;
+ }
+
+ public List<String> getAuthoritiesAsList(){
+ return authorities.stream().map(GrantedAuthority::getAuthority)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public String getPassword() {
+ return password;
+ }
+
+ @Override
+ public String getUsername() {
+ return username;
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java
new file mode 100644
index 0000000..5c13e11
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/security/services/UserDetailsServiceImpl.java
@@ -0,0 +1,100 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.security.services;
+
+import org.onap.dcaegen2.platform.mod.controllers.AuthController;
+import org.onap.dcaegen2.platform.mod.exceptions.UserNotFoundException;
+import org.onap.dcaegen2.platform.mod.exceptions.IllegalUserOperationException;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import lombok.Setter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * User Details Service
+ */
+@Service
+public class UserDetailsServiceImpl implements UserDetailsService {
+
+ @Autowired
+ @Setter
+ UserRepository userRepository;
+
+ @Autowired
+ PasswordEncoder passwordEncoder;
+
+ @Autowired
+ AuthController authController;
+
+ @Autowired
+ private JwtUtils jwtUtils;
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ ModUser user = userRepository.findByUsername(username)
+ .orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));
+
+ return UserDetailsImpl.build(user);
+ }
+
+ public ModUser adminUpdateUser(String username, UpdateUserRequest userRequest, String token) {
+ return updateUserProfile(username, userRequest);
+ }
+
+ public ModUser userUpdateOwnProfile(String username, UpdateUserRequest userRequest, String token) {
+ String usernameFromToken = jwtUtils.getUserNameFromJwtToken(token.substring(7));
+ if (usernameFromToken.equals(username)) {
+ return updateUserProfile(username, userRequest);
+ } else {
+ throw new IllegalUserOperationException("Permission denied to update user profile of " + username);
+ }
+ }
+
+ private ModUser updateUserProfile(String username, UpdateUserRequest userRequest) {
+ ModUser modUser = userRepository.findByUsername(username).orElseThrow(() -> new UserNotFoundException(String.format("User %s not found", username)));
+ modUser = updateUserFields(modUser, userRequest);
+ return userRepository.save(modUser);
+ }
+
+ private ModUser updateUserFields(ModUser modUser, UpdateUserRequest userRequest) {
+ if (userRequest.getFullName() != null) modUser.setFullName(userRequest.getFullName());
+ if (userRequest.getPassword() != null) modUser.setPassword(passwordEncoder.encode(userRequest.getPassword()));
+ if (userRequest.getRoles() != null) {
+ Set<Role> roles = authController.createRoles(userRequest.getRoles());
+ modUser.setRoles(roles);
+ }
+ return modUser;
+ }
+}
diff --git a/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java
new file mode 100644
index 0000000..a6a6de5
--- /dev/null
+++ b/mod2/auth-service/src/main/java/org/onap/dcaegen2/platform/mod/services/MODUserDetailService.java
@@ -0,0 +1,56 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.services;
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author
+ * @date 09/08/2020
+ * This Service provides APIs to manage User Entity
+ */
+
+@Service
+public class MODUserDetailService {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ public MODUserDetailService(UserRepository userRepository) {
+ this.userRepository = userRepository;
+ }
+
+ public List<ModUser> findAll() {
+ return userRepository.findAll();
+ }
+
+ public void deleteUserByUsername(String username) {
+ userRepository.deleteByUsername(username);
+ }
+
+}
diff --git a/mod2/auth-service/src/main/resources/application.properties b/mod2/auth-service/src/main/resources/application.properties
new file mode 100644
index 0000000..f3f5d37
--- /dev/null
+++ b/mod2/auth-service/src/main/resources/application.properties
@@ -0,0 +1,32 @@
+#
+# /*
+# * ============LICENSE_START=======================================================
+# * org.onap.dcae
+# * ================================================================================
+# * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+# * ================================================================================
+# * 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.
+# * ============LICENSE_END=========================================================
+# */
+#
+
+server.port=8082
+
+#spring.data.mongodb.host=mongo_db
+spring.data.mongodb.host=localhost
+#spring.data.mongodb.host=zlecdyh2bdcc1s2dokr05.ec53e7.dyh2b.tci.att.com
+spring.data.mongodb.port=27017
+spring.data.mongodb.database=dcae_mod
+
+mod-portal.jwt.secret=mod2020!
+mod-portal.jwt.jwtExpirationMs=43200000 \ No newline at end of file
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/AuthObjectMother.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/AuthObjectMother.java
new file mode 100644
index 0000000..3a22af3
--- /dev/null
+++ b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/AuthObjectMother.java
@@ -0,0 +1,85 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.objectmothers;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.onap.dcaegen2.platform.mod.models.LoginRequest;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.models.SignupRequest;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl;
+import org.onap.dcaegen2.platform.mod.util.TestUtil;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock for AuthenticationController Test Case
+ */
+
+public class AuthObjectMother {
+ public static final String LOGIN_REQUEST = "src/test/resources/http/requests/AuthLoginRequest.json";
+ public static final String SIGNUP_REQUEST = "src/test/resources/http/requests/AuthSignupRequest.json";
+
+ public static String asJsonString(final Object object) {
+ try {
+ return new ObjectMapper().writeValueAsString(object);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static LoginRequest getLoginRequest() {
+ return TestUtil.deserializeJsonFileToModel(LOGIN_REQUEST, LoginRequest.class);
+ }
+
+ public static SignupRequest getSignupRequest() {
+ return TestUtil.deserializeJsonFileToModel(SIGNUP_REQUEST, SignupRequest.class);
+ }
+
+ public static UserDetailsImpl getUserDetailsImpl() {
+ SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_ADMIN");
+ List authorities = new ArrayList();
+ authorities.add(simpleGrantedAuthority);
+ return new UserDetailsImpl("admin123", "admin123", "admin123", "admin123", authorities);
+ }
+
+ public static ModUser getModUser() {
+ ModUser user = new ModUser();
+ user.setUsername("test");
+ user.setFullName("test");
+ user.setPassword("password");
+ Set<Role> roles = new HashSet<>();
+ Role role = new Role();
+ role.setName("test");
+ role.setId("123");
+ roles.add(role);
+ user.setRoles(roles);
+ return user;
+ }
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/RoleObjectMother.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/RoleObjectMother.java
new file mode 100644
index 0000000..68002ac
--- /dev/null
+++ b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/RoleObjectMother.java
@@ -0,0 +1,56 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.objectmothers;
+
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock for RoleController Test Case
+ */
+public class RoleObjectMother {
+
+ public static List<Role> getRoles() {
+ List<Role> roles = new ArrayList();
+ Role role1 = new Role();
+ role1.setId("123");
+ role1.setName("Admin123");
+
+ Role role2 = new Role();
+ role2.setId("1234");
+ role2.setName("Admin1234");
+
+ roles.add(role1);
+ roles.add(role2);
+
+ return roles;
+ }
+
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/UserObjectMother.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/UserObjectMother.java
new file mode 100644
index 0000000..301b81f
--- /dev/null
+++ b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/objectmothers/UserObjectMother.java
@@ -0,0 +1,100 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.objectmothers;
+
+
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsImpl;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock for UserController Test Case
+ */
+public class UserObjectMother {
+
+ public static final String userId = "admin";
+
+ public static List<ModUser> getUsers() {
+ List<ModUser> users = new ArrayList();
+ ModUser modUser1 = new ModUser();
+ modUser1.set_id("123");
+ modUser1.setFullName("Admin123");
+ modUser1.setPassword("Admin123");
+ Set<Role> roles = new HashSet<>();
+ Role role = new Role();
+ role.setName("test");
+ role.setId("123");
+ roles.add(role);
+ modUser1.setRoles(roles);
+
+ ModUser modUser2 = new ModUser();
+ modUser2.set_id("1234");
+ modUser2.setFullName("Admin1234");
+ modUser2.setPassword("Admin1234");
+ Set<Role> roles1 = new HashSet<>();
+ Role role1 = new Role();
+ role.setName("test1");
+ role.setId("1234");
+ roles.add(role1);
+ modUser2.setRoles(roles1);
+
+ users.add(modUser1);
+ users.add(modUser2);
+
+ return users;
+ }
+
+ public static ModUser getModUser() {
+ ModUser user = new ModUser();
+ user.setUsername("test");
+ user.setFullName("test");
+ user.setPassword("password");
+ Set<Role> roles = new HashSet<>();
+ Role role = new Role();
+ role.setName("test");
+ role.setId("123");
+ roles.add(role);
+ user.setRoles(roles);
+ return user;
+ }
+
+ public static UpdateUserRequest getUpdateUserRequest(){
+ UpdateUserRequest user = new UpdateUserRequest();
+ user.setFullName("test");
+ user.setPassword("password");
+ Set<String> roles = new HashSet<>();
+ roles.add("ROLE_PST");
+ user.setRoles(roles);
+ return user;
+ }
+
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/util/TestUtil.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/util/TestUtil.java
new file mode 100644
index 0000000..111653f
--- /dev/null
+++ b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/util/TestUtil.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.util;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * TestUtils for test cases
+ */
+public class TestUtil {
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private TestUtil() {}
+
+ public static Map<String, Object> readJsonFileAsObjectMap(String filePath) {
+ try {
+ return MAPPER.readValue(new File(filePath), new TypeReference<Map<String, Object>>() {});
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new RuntimeException();
+ }
+ }
+
+ public static <T> T deserializeJsonFileToModel(String filePath, Class<T> modelClass) {
+ try {
+ return MAPPER.readValue(new File(filePath), modelClass);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new RuntimeException();
+ }
+ }
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/AuthControllerTest.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/AuthControllerTest.java
new file mode 100644
index 0000000..2aad289
--- /dev/null
+++ b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/AuthControllerTest.java
@@ -0,0 +1,149 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.onap.dcaegen2.platform.mod.controllers.AuthController;
+import org.onap.dcaegen2.platform.mod.models.*;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthEntryPointJwt;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.*;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.web.client.RestTemplate;
+import org.testng.annotations.BeforeTest;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.mockito.Mockito.*;
+import static org.onap.dcaegen2.platform.mod.objectmothers.AuthObjectMother.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock Test cases for AuthenticationController
+ */
+@WebMvcTest(AuthController.class)
+public class AuthControllerTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @MockBean
+ JwtUtils jwtUtils;
+
+ @MockBean
+ AuthenticationManager authenticationManager;
+
+ @MockBean
+ UserRepository userRepository;
+
+ @MockBean
+ RoleRepository roleRepository;
+
+ @MockBean
+ PasswordEncoder passwordEncoder;
+
+ @MockBean
+ UserDetailsServiceImpl userDetailsService;
+
+ @MockBean
+ AuthEntryPointJwt authEntryPointJwt;
+
+ @Mock
+ Authentication authentication;
+
+ @BeforeEach
+ void setUp() {
+ }
+
+
+ @Test
+ void test_signin_returnsSuccessResponse() throws Exception {
+
+ LoginRequest loginRequest = getLoginRequest();
+
+ when(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()))).thenReturn(authentication);
+ when(authentication.getPrincipal()).thenReturn(getUserDetailsImpl());
+ when(jwtUtils.generateJwtToken(any())).thenReturn("Demo");
+
+ mockMvc.perform(post("/api/auth/signin")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(loginRequest)).accept(MediaType.APPLICATION_JSON))
+ .andExpect(jsonPath("$.token", notNullValue()))
+ .andExpect(status().isOk());
+
+ verify(authenticationManager, times(1)).authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
+ verify(jwtUtils, times(1)).generateJwtToken(any());
+ }
+
+
+ @WithMockUser(roles="ADMIN")
+ @Test
+ void test_signup_returnsSuccessResponse() throws Exception {
+
+ SignupRequest signUpRequest = getSignupRequest();
+
+ when(userRepository.existsByUsername(signUpRequest.getUsername())).thenReturn(false);
+ when(passwordEncoder.encode(signUpRequest.getPassword())).thenReturn("password");
+ when(roleRepository.findByName(anyString())).thenReturn(Optional.of(new Role()));
+ when(userRepository.save(any())).thenReturn(getModUser());
+
+ mockMvc.perform(post("/api/auth/signup")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(signUpRequest)).accept(MediaType.APPLICATION_JSON))
+ .andExpect(jsonPath("$.message", notNullValue()))
+ .andExpect(status().isOk());
+
+ verify(userRepository, times(1)).existsByUsername(signUpRequest.getUsername());
+ verify(passwordEncoder, times(1)).encode(signUpRequest.getPassword());
+ verify(roleRepository, times(1)).findByName(anyString());
+ verify(userRepository, times(1)).save(any());
+ }
+
+
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/RoleControllerTest.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/RoleControllerTest.java
new file mode 100644
index 0000000..48b5d4b
--- /dev/null
+++ b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/RoleControllerTest.java
@@ -0,0 +1,109 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.web;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.onap.dcaegen2.platform.mod.controllers.RoleController;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.Role;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthEntryPointJwt;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.Authentication;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.onap.dcaegen2.platform.mod.objectmothers.AuthObjectMother.asJsonString;
+import static org.onap.dcaegen2.platform.mod.objectmothers.RoleObjectMother.getRoles;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock Test cases for RoleController
+ */
+@WebMvcTest(RoleController.class)
+public class RoleControllerTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @MockBean
+ RoleRepository roleRepository;
+
+ @MockBean
+ UserDetailsServiceImpl userDetailsService;
+
+ @MockBean
+ AuthEntryPointJwt authEntryPointJwt;
+
+ @MockBean
+ JwtUtils jwtUtils;
+
+ @Mock
+ Authentication authentication;
+
+ @BeforeEach
+ void setUp() {
+ }
+
+
+ @Test
+ void test_getRoles() throws Exception {
+
+ Mockito.when(roleRepository.findAll()).thenReturn(getRoles());
+
+ MvcResult result = mockMvc.perform(get("/api/roles")
+ .contentType(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk()).andReturn();
+
+ Assert.assertNotNull(result.getResponse().getContentAsString());
+
+ }
+
+}
diff --git a/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/UserControllerTest.java b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/UserControllerTest.java
new file mode 100644
index 0000000..1374e0e
--- /dev/null
+++ b/mod2/auth-service/src/test/java/org/onap/dcaegen2/platform/mod/web/UserControllerTest.java
@@ -0,0 +1,168 @@
+/*
+ *
+ * * ============LICENSE_START=======================================================
+ * * org.onap.dcae
+ * * ================================================================================
+ * * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * * ================================================================================
+ * * 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.
+ * * ============LICENSE_END=========================================================
+ *
+ */
+
+package org.onap.dcaegen2.platform.mod.web;
+
+import org.apache.tools.ant.taskdefs.optional.extension.Specification;
+import org.junit.Assert;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.runner.Request;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.onap.dcaegen2.platform.mod.controllers.RoleController;
+import org.onap.dcaegen2.platform.mod.controllers.UserController;
+import org.onap.dcaegen2.platform.mod.models.LoginRequest;
+import org.onap.dcaegen2.platform.mod.models.ModUser;
+import org.onap.dcaegen2.platform.mod.models.UpdateUserRequest;
+import org.onap.dcaegen2.platform.mod.repositories.RoleRepository;
+import org.onap.dcaegen2.platform.mod.repositories.UserRepository;
+import org.onap.dcaegen2.platform.mod.security.jwt.AuthEntryPointJwt;
+import org.onap.dcaegen2.platform.mod.security.jwt.JwtUtils;
+import org.onap.dcaegen2.platform.mod.security.services.UserDetailsServiceImpl;
+import org.onap.dcaegen2.platform.mod.services.MODUserDetailService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.web.client.RequestMatcher;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.ResultMatcher;
+
+import java.util.Optional;
+
+import static org.hamcrest.Matchers.notNullValue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+import static org.onap.dcaegen2.platform.mod.objectmothers.AuthObjectMother.asJsonString;
+import static org.onap.dcaegen2.platform.mod.objectmothers.AuthObjectMother.getModUser;
+import static org.onap.dcaegen2.platform.mod.objectmothers.RoleObjectMother.getRoles;
+import static org.onap.dcaegen2.platform.mod.objectmothers.UserObjectMother.*;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * @author
+ * @date 09/22/2020
+ * Mock Test cases for UserController
+ */
+@WebMvcTest(UserController.class)
+public class UserControllerTest {
+
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @MockBean
+ UserDetailsServiceImpl userDetailsService;
+
+ @MockBean
+ UserRepository userRepository;
+
+ @MockBean
+ MODUserDetailService modUserDetailService;
+
+ @MockBean
+ RoleRepository roleRepository;
+
+ @MockBean
+ AuthEntryPointJwt authEntryPointJwt;
+
+ @MockBean
+ JwtUtils jwtUtils;
+
+ @Mock
+ Authentication authentication;
+
+
+ @BeforeEach
+ void setUp() {
+ }
+
+ @WithMockUser(roles="ADMIN")
+ @Test
+ void test_getUsername() throws Exception {
+
+ when(userRepository.findByUsername(any())).thenReturn(Optional.of(new ModUser()));
+
+ MvcResult result = mockMvc.perform(get("/api/users/" + userId)
+ .contentType(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk()).andReturn();
+
+ Assert.assertNotNull(result.getResponse().getContentAsString());
+ verify(userRepository, times(1)).findByUsername(any());
+ }
+
+ @Test
+ void test_getAllUsers() throws Exception {
+
+ when(modUserDetailService.findAll()).thenReturn(getUsers());
+
+ MvcResult result = mockMvc.perform(get("/api/users/getAll")
+ .contentType(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk()).andReturn();
+
+ Assert.assertNotNull(result.getResponse().getContentAsString());
+ verify(modUserDetailService, times(1)).findAll();
+ }
+
+
+ @WithMockUser(roles="ADMIN")
+ @Test
+ void test_deleteUser() throws Exception {
+
+ doNothing().when(modUserDetailService).deleteUserByUsername(any(String.class));
+
+ MvcResult result = mockMvc.perform(delete("/api/users/" + userId)
+ .contentType(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk()).andReturn();
+
+ Assert.assertNotNull(result.getResponse().getContentAsString());
+ verify(modUserDetailService, times(1)).deleteUserByUsername(any(String.class));
+ }
+
+
+ @WithMockUser(username="ADMIN")
+ @Test
+ void test_userUpdateOwnProfile_returnsSuccessResponse() throws Exception {
+ //arrange
+ UpdateUserRequest updateUserRequest = getUpdateUserRequest();
+
+ when(userDetailsService.adminUpdateUser(userId,updateUserRequest,"token")).thenReturn(getModUser());
+
+ mockMvc.perform(patch("/api/users/admin/" + userId)
+ //.header("Authorization", "token")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(asJsonString(updateUserRequest)).accept(MediaType.APPLICATION_JSON))
+ //.andExpect(jsonPath("$.message", notNullValue()))
+ .andExpect(status().isOk()).andReturn();
+
+ verify(userDetailsService, times(1)).adminUpdateUser(anyString(),updateUserRequest,anyString());
+ }
+
+
+} \ No newline at end of file
diff --git a/mod2/auth-service/src/test/resources/application.properties b/mod2/auth-service/src/test/resources/application.properties
new file mode 100644
index 0000000..d6a913c
--- /dev/null
+++ b/mod2/auth-service/src/test/resources/application.properties
@@ -0,0 +1 @@
+#spring.data.mongodb.port=0 \ No newline at end of file
diff --git a/mod2/auth-service/src/test/resources/http/requests/AuthLoginRequest.json b/mod2/auth-service/src/test/resources/http/requests/AuthLoginRequest.json
new file mode 100644
index 0000000..fbdc4a9
--- /dev/null
+++ b/mod2/auth-service/src/test/resources/http/requests/AuthLoginRequest.json
@@ -0,0 +1,4 @@
+{
+ "username": "admin",
+ "password": "admin@mod"
+}
diff --git a/mod2/auth-service/src/test/resources/http/requests/AuthSignupRequest.json b/mod2/auth-service/src/test/resources/http/requests/AuthSignupRequest.json
new file mode 100644
index 0000000..25be086
--- /dev/null
+++ b/mod2/auth-service/src/test/resources/http/requests/AuthSignupRequest.json
@@ -0,0 +1,6 @@
+{
+ "username": "admin1",
+ "fullName": "Administrator",
+ "password": "admin@mod",
+ "roles": ["ROLE_PST"]
+} \ No newline at end of file
diff --git a/mod2/auth-service/src/test/resources/specification/componentSpec_hello_world-with-dmaap.json b/mod2/auth-service/src/test/resources/specification/componentSpec_hello_world-with-dmaap.json
new file mode 100644
index 0000000..0ad6b6e
--- /dev/null
+++ b/mod2/auth-service/src/test/resources/specification/componentSpec_hello_world-with-dmaap.json
@@ -0,0 +1,149 @@
+{
+ "self": {
+ "component_type": "docker",
+ "description": "Hello World mS for subscribing the data from local DMaaP, DR or MR, processing them and publishing them as PM files to local DMaaP DR",
+ "name": "dcae-collectors-vcc-helloworld-pm",
+ "version": "1.0.1"
+ },
+
+ "services": {
+ "calls": [],
+ "provides": []
+ },
+
+ "streams": {
+ "publishes": [{
+ "config_key": "DCAE-HELLO-WORLD-PUB-DR",
+ "format": "dataformat_Hello_World_PM",
+ "type": "data_router",
+ "version": "1.0.0"
+ },
+ {
+ "config_key": "DCAE-HELLO-WORLD-PUB-MR",
+ "format": "dataformat_Hello_World_PM",
+ "type": "message_router",
+ "version": "1.0.0"
+ }
+ ],
+
+ "subscribes": [{
+ "config_key": "DCAE-HELLO-WORLD-SUB-MR",
+ "format": "dataformat_Hello_World_PM",
+ "route": "/DCAE_HELLO_WORLD_SUB_MR",
+ "type": "message_router",
+ "version": "1.0.0"
+ },
+ {
+ "config_key": "DCAE-HELLO-WORLD-SUB-DR",
+ "format": "dataformat_Hello_World_PM",
+ "route": "/DCAE-HELLO-WORLD-SUB-DR",
+ "type": "data_router",
+ "version": "1.0.0"
+ }
+ ]
+ },
+
+ "parameters":
+ [
+ {
+ "name": "vcc_hello_name",
+ "value": "120",
+ "type": "integer",
+ "description": "the name entered for specific person",
+ "sourced_at_deployment": false,
+ "designer_editable": false,
+ "policy_editable": false
+ },
+
+ {
+ "name": "useDtiConfig",
+ "value": false,
+ "type" : "boolean",
+ "description": "component depends on configuration from dti.",
+ "sourced_at_deployment": false,
+ "designer_editable": true,
+ "policy_editable": false,
+ "required" : true
+ },
+
+ {
+ "name": "isSelfServeComponent",
+ "value": false,
+ "type": "boolean",
+ "description": "Is this used as self serve component.",
+ "sourced_at_deployment": false,
+ "designer_editable": true,
+ "policy_editable": false,
+ "required" : true
+ }
+ ],
+
+ "auxilary": {
+ "healthcheck": {
+ "interval": "60s",
+ "initialDelaySeconds": "120s",
+ "timeout": "20s",
+ "script": "/opt/app/vcc/bin/common/HealthCheck_HelloWorld.sh",
+ "type": "docker"
+ },
+ "livehealthcheck": {
+ "interval": "60s",
+ "initialDelaySeconds": "120s",
+ "timeout": "20s",
+ "script": "/opt/app/vcc/bin/common/HealthCheck_HelloWorld.sh",
+ "type": "docker"
+ },
+ "reconfigs":{
+ "app_reconfig" : "abc"
+ },
+
+ "volumes": [
+ {
+ "container": {
+ "bind": "/opt/app/dcae-certificate"
+ },
+ "host": {
+ "path": "/opt/app/dcae-certificate"
+ }
+ },
+ {
+ "container": {
+ "bind": "/opt/logs/DCAE/dmd/AGENT"
+ },
+ "host": {
+ "path": "/opt/logs/DCAE/helloworldpm/dmd/AGENT"
+ }
+ },
+ {
+ "container": {
+ "bind": "/opt/logs/DCAE/dmd/WATCHER"
+ },
+ "host": {
+ "path": "/opt/logs/DCAE/helloworldpm/dmd/WATCHER"
+ }
+ },
+ {
+ "container": {
+ "bind": "/opt/app/vcc/logs/DCAE"
+ },
+ "host": {
+ "path": "/opt/logs/DCAE/helloworldpm/vcc-logs"
+ }
+ },
+ {
+ "container": {
+ "bind": "/opt/app/vcc/archive/data"
+ },
+ "host": {
+ "path": "/opt/data/DCAE/helloworldpm/vcc-archive"
+ }
+ }
+
+ ]
+
+ },
+ "artifacts": [{
+ "type": "docker image",
+ "uri": "dockercentral.it.att.com:5100/com.att.sample/dcae-controller-vcc-helloworld-pm:18.02-001"
+ }]
+} \ No newline at end of file
diff --git a/mod2/auth-service/src/test/resources/specification/policy_json_sample_3.json b/mod2/auth-service/src/test/resources/specification/policy_json_sample_3.json
new file mode 100644
index 0000000..4a8c76f
--- /dev/null
+++ b/mod2/auth-service/src/test/resources/specification/policy_json_sample_3.json
@@ -0,0 +1,28 @@
+{
+ "policies": [
+ {
+ "configAttributes": "",
+ "configName": "",
+ "onapName": "DCAE",
+ "policyName": "DCAE.Config_",
+ "unique": false
+ },
+ {
+ "onapName": "DCAE",
+ "policyName": "DCAE.Config_",
+ "unique": true
+ },
+ {
+ "configAttributes": "",
+ "configName": "",
+ "onapName": "DCAE",
+ "policyName": "DCAE.Config_*",
+ "unique": false
+ }
+ ],
+ "policy": [
+ {
+ "policy_id" : "id_0"
+ }
+ ]
+} \ No newline at end of file
diff --git a/mod2/ui/.editorconfig b/mod2/ui/.editorconfig
new file mode 100644
index 0000000..e89330a
--- /dev/null
+++ b/mod2/ui/.editorconfig
@@ -0,0 +1,13 @@
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/mod2/ui/.gitignore b/mod2/ui/.gitignore
new file mode 100644
index 0000000..f4f46a5
--- /dev/null
+++ b/mod2/ui/.gitignore
@@ -0,0 +1,46 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/tmp
+/out-tsc
+# Only exists if Bazel was run
+/bazel-out
+
+# dependencies
+/node_modules
+
+# profiling files
+chrome-profiler-events.json
+speed-measure-plugin.json
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.history/*
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage
+/libpeerconnection.log
+npm-debug.log
+yarn-error.log
+testem.log
+/typings
+
+# System Files
+.DS_Store
+Thumbs.db
diff --git a/mod2/ui/Dockerfile b/mod2/ui/Dockerfile
new file mode 100644
index 0000000..67744d4
--- /dev/null
+++ b/mod2/ui/Dockerfile
@@ -0,0 +1,26 @@
+# ---- Base Node ----
+FROM alpine:12.4.0 AS base
+
+#RUN fs.inotify.max_user_watches=524288
+
+WORKDIR /app
+
+#run in prod mode
+# RUN ng build --prod
+
+# copy project file
+COPY . .
+
+#to make healthcheck executable
+RUN chmod +x healthcheck.sh
+
+# COPY package.json /app
+RUN npm install -g @angular/cli@8.0.6
+
+#to install all dev dependencies explicitly
+RUN npm i --only=dev
+RUN npm install --save-dev @angular-devkit/build-angular
+
+# RUN npm run build --prod
+EXPOSE 4200
+CMD ng serve --host 0.0.0.0 --disableHostCheck --proxy-config proxy.conf.json
diff --git a/mod2/ui/Jenkinsfile b/mod2/ui/Jenkinsfile
new file mode 100644
index 0000000..d51287f
--- /dev/null
+++ b/mod2/ui/Jenkinsfile
@@ -0,0 +1,3 @@
+// @Library('common@develop') _
+
+pythonPipeline() \ No newline at end of file
diff --git a/mod2/ui/README.md b/mod2/ui/README.md
new file mode 100644
index 0000000..e08fb38
--- /dev/null
+++ b/mod2/ui/README.md
@@ -0,0 +1,27 @@
+# DcaeModFe
+
+This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.0.1.
+
+## Development server
+
+Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+
+## Code scaffolding
+
+Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
+
+## Build
+
+Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
+
+## Running unit tests
+
+Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
+
+## Running end-to-end tests
+
+Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
+
+## Further help
+
+To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
diff --git a/mod2/ui/angular.json b/mod2/ui/angular.json
new file mode 100644
index 0000000..48a973b
--- /dev/null
+++ b/mod2/ui/angular.json
@@ -0,0 +1,128 @@
+{
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+ "version": 1,
+ "newProjectRoot": "projects",
+ "projects": {
+ "dcae-mod-fe": {
+ "projectType": "application",
+ "schematics": {},
+ "root": "",
+ "sourceRoot": "src",
+ "prefix": "app",
+ "architect": {
+ "build": {
+ "builder": "@angular-builders/custom-webpack:browser",
+ "options": {
+ "customWebpackConfig": {
+ "path": "extra-webpack.config.js"
+ },
+ "outputPath": "dist/dcae-mod-fe",
+ "index": "src/index.html",
+ "main": "src/main.ts",
+ "polyfills": "src/polyfills.ts",
+ "tsConfig": "tsconfig.app.json",
+ "assets": [
+ "src/favicon.ico",
+ "src/assets"
+ ],
+ "styles": [
+ "./node_modules/@angular/material/prebuilt-themes/purple-green.css",
+ "src/styles.css",
+ "./node_modules/primeng/resources/primeng.min.css",
+ "./node_modules/primeng/resources/themes/nova-light/theme.css",
+ "./node_modules/primeicons/primeicons.css"
+ ],
+ "scripts": []
+ },
+ "configurations": {
+ "production": {
+ "fileReplacements": [
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.prod.ts"
+ }
+ ],
+ "optimization": true,
+ "outputHashing": "all",
+ "sourceMap": false,
+ "extractCss": true,
+ "namedChunks": false,
+ "aot": true,
+ "extractLicenses": true,
+ "vendorChunk": false,
+ "buildOptimizer": true,
+ "budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "2mb",
+ "maximumError": "5mb"
+ }
+ ]
+ }
+ }
+ },
+ "serve": {
+ "builder": "@angular-builders/custom-webpack:dev-server",
+ "options": {
+ "browserTarget": "dcae-mod-fe:build"
+ },
+ "configurations": {
+ "production": {
+ "browserTarget": "dcae-mod-fe:build:production"
+ }
+ }
+ },
+ "extract-i18n": {
+ "builder": "@angular-devkit/build-angular:extract-i18n",
+ "options": {
+ "browserTarget": "dcae-mod-fe:build"
+ }
+ },
+ "test": {
+ "builder": "@angular-devkit/build-angular:karma",
+ "options": {
+ "main": "src/test.ts",
+ "polyfills": "src/polyfills.ts",
+ "tsConfig": "tsconfig.spec.json",
+ "karmaConfig": "karma.conf.js",
+ "assets": [
+ "src/favicon.ico",
+ "src/assets"
+ ],
+ "styles": [
+ "./node_modules/@angular/material/prebuilt-themes/purple-green.css",
+ "src/styles.css"
+ ],
+ "scripts": []
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": [
+ "tsconfig.app.json",
+ "tsconfig.spec.json",
+ "e2e/tsconfig.json"
+ ],
+ "exclude": [
+ "**/node_modules/**"
+ ]
+ }
+ },
+ "e2e": {
+ "builder": "@angular-devkit/build-angular:protractor",
+ "options": {
+ "protractorConfig": "e2e/protractor.conf.js",
+ "devServerTarget": "dcae-mod-fe:serve"
+ },
+ "configurations": {
+ "production": {
+ "devServerTarget": "dcae-mod-fe:serve:production"
+ }
+ }
+ }
+ }
+ }
+ },
+ "defaultProject": "dcae-mod-fe"
+} \ No newline at end of file
diff --git a/mod2/ui/browserslist b/mod2/ui/browserslist
new file mode 100644
index 0000000..8084853
--- /dev/null
+++ b/mod2/ui/browserslist
@@ -0,0 +1,12 @@
+# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
+# For additional information regarding the format and rule options, please see:
+# https://github.com/browserslist/browserslist#queries
+
+# You can see what browsers were selected by your queries by running:
+# npx browserslist
+
+> 0.5%
+last 2 versions
+Firefox ESR
+not dead
+not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file
diff --git a/mod2/ui/dependenciesFile b/mod2/ui/dependenciesFile
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mod2/ui/dependenciesFile
diff --git a/mod2/ui/e2e/protractor.conf.js b/mod2/ui/e2e/protractor.conf.js
new file mode 100644
index 0000000..ff9b518
--- /dev/null
+++ b/mod2/ui/e2e/protractor.conf.js
@@ -0,0 +1,50 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+// @ts-check
+// Protractor configuration file, see link for more information
+// https://github.com/angular/protractor/blob/master/lib/config.ts
+
+const { SpecReporter } = require('jasmine-spec-reporter');
+
+/**
+ * @type { import("protractor").Config }
+ */
+exports.config = {
+ allScriptsTimeout: 11000,
+ specs: [
+ './src/**/*.e2e-spec.ts'
+ ],
+ capabilities: {
+ 'browserName': 'chrome'
+ },
+ directConnect: true,
+ baseUrl: 'http://localhost:4200/',
+ framework: 'jasmine',
+ jasmineNodeOpts: {
+ showColors: true,
+ defaultTimeoutInterval: 30000,
+ print: function() {}
+ },
+ onPrepare() {
+ require('ts-node').register({
+ project: require('path').join(__dirname, './tsconfig.json')
+ });
+ jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
+ }
+}; \ No newline at end of file
diff --git a/mod2/ui/e2e/src/app.e2e-spec.ts b/mod2/ui/e2e/src/app.e2e-spec.ts
new file mode 100644
index 0000000..f25e135
--- /dev/null
+++ b/mod2/ui/e2e/src/app.e2e-spec.ts
@@ -0,0 +1,41 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { AppPage } from './app.po';
+import { browser, logging } from 'protractor';
+
+describe('workspace-project App', () => {
+ let page: AppPage;
+
+ beforeEach(() => {
+ page = new AppPage();
+ });
+
+ it('should display welcome message', () => {
+ page.navigateTo();
+ expect(page.getTitleText()).toEqual('Welcome to dcae-mod-fe!');
+ });
+
+ afterEach(async () => {
+ // Assert that there are no errors emitted from the browser
+ const logs = await browser.manage().logs().get(logging.Type.BROWSER);
+ expect(logs).not.toContain(jasmine.objectContaining({
+ level: logging.Level.SEVERE,
+ } as logging.Entry));
+ });
+});
diff --git a/mod2/ui/e2e/src/app.po.ts b/mod2/ui/e2e/src/app.po.ts
new file mode 100644
index 0000000..b26c21a
--- /dev/null
+++ b/mod2/ui/e2e/src/app.po.ts
@@ -0,0 +1,29 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { browser, by, element } from 'protractor';
+
+export class AppPage {
+ navigateTo() {
+ return browser.get(browser.baseUrl) as Promise<any>;
+ }
+
+ getTitleText() {
+ return element(by.css('app-root h1')).getText() as Promise<string>;
+ }
+}
diff --git a/mod2/ui/e2e/tsconfig.json b/mod2/ui/e2e/tsconfig.json
new file mode 100644
index 0000000..39b800f
--- /dev/null
+++ b/mod2/ui/e2e/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/e2e",
+ "module": "commonjs",
+ "target": "es5",
+ "types": [
+ "jasmine",
+ "jasminewd2",
+ "node"
+ ]
+ }
+}
diff --git a/mod2/ui/extra-webpack.config.js b/mod2/ui/extra-webpack.config.js
new file mode 100644
index 0000000..dd85485
--- /dev/null
+++ b/mod2/ui/extra-webpack.config.js
@@ -0,0 +1,29 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+const webpack = require('webpack')
+
+module.exports = {
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env': {
+ DCAE_HOSTNAME: JSON.stringify(process.env.DCAE_HOSTNAME)
+ }
+ })
+ ]
+} \ No newline at end of file
diff --git a/mod2/ui/healthcheck.sh b/mod2/ui/healthcheck.sh
new file mode 100644
index 0000000..d36705b
--- /dev/null
+++ b/mod2/ui/healthcheck.sh
@@ -0,0 +1,20 @@
+__='
+* # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+'
+
+#!/bin/bash
+exit 0 \ No newline at end of file
diff --git a/mod2/ui/karma.conf.js b/mod2/ui/karma.conf.js
new file mode 100644
index 0000000..13d1962
--- /dev/null
+++ b/mod2/ui/karma.conf.js
@@ -0,0 +1,50 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/1.0/config/configuration-file.html
+
+module.exports = function (config) {
+ config.set({
+ basePath: '',
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
+ plugins: [
+ require('karma-jasmine'),
+ require('karma-chrome-launcher'),
+ require('karma-jasmine-html-reporter'),
+ require('karma-coverage-istanbul-reporter'),
+ require('@angular-devkit/build-angular/plugins/karma')
+ ],
+ client: {
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
+ },
+ coverageIstanbulReporter: {
+ dir: require('path').join(__dirname, './coverage/dcae-mod-fe'),
+ reports: ['html', 'lcovonly', 'text-summary'],
+ fixWebpackSourcePaths: true
+ },
+ reporters: ['progress', 'kjhtml'],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: ['Chrome'],
+ singleRun: false,
+ restartOnFileChange: true
+ });
+};
diff --git a/mod2/ui/package-lock.json b/mod2/ui/package-lock.json
new file mode 100644
index 0000000..f744c0b
--- /dev/null
+++ b/mod2/ui/package-lock.json
@@ -0,0 +1,10747 @@
+{
+ "name": "dcae-mod-fe",
+ "version": "0.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@angular-builders/custom-webpack": {
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-8.4.1.tgz",
+ "integrity": "sha512-FbBt4mFbAxETdYLb6tTX869pIpm8nMiCpT34jROejuqLtsljymdqXhSCEWogWlel8ULAYus6BNdzZyRLyAkfqQ==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.10",
+ "ts-node": "^8.5.2",
+ "webpack-merge": "^4.2.1"
+ },
+ "dependencies": {
+ "diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.18",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.18.tgz",
+ "integrity": "sha512-9luZr/BZ2QeU6tO2uG8N2aZpVSli4TSAOAqFOyTO51AJcD9P99c0K1h6dD6r6qo5dyT44BR5exweOaLLeldTkQ==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "ts-node": {
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.9.0.tgz",
+ "integrity": "sha512-rwkXfOs9zmoHrV8xE++dmNd6ZIS+nmHHCxcV53ekGJrxFLMbp+pizpPS07ARvhwneCIECPppOwbZHvw9sQtU4w==",
+ "dev": true,
+ "requires": {
+ "arg": "^4.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "source-map-support": "^0.5.17",
+ "yn": "3.1.1"
+ }
+ },
+ "yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true
+ }
+ }
+ },
+ "@angular-builders/dev-server": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/@angular-builders/dev-server/-/dev-server-7.3.1.tgz",
+ "integrity": "sha512-rFr0NyFcwTb4RkkboYQN5JeR9ZraOkfUrQYljMSe/O01MM3SJvE8LYJbsyMwGtp71Rc8T6JrpdxaNEeYCV/4PA==",
+ "dev": true
+ },
+ "@angular-devkit/architect": {
+ "version": "0.800.6",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.800.6.tgz",
+ "integrity": "sha512-946ceRci/1yx09g8iRvULLoVihcB2RW9nhpCCMum4L9wheip8t4FWso3pd3JtPQGJV9dmsnwPzR9s12bncmj3g==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.0.6",
+ "rxjs": "6.4.0"
+ }
+ },
+ "@angular-devkit/build-angular": {
+ "version": "0.803.24",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.803.24.tgz",
+ "integrity": "sha512-uA789spMVghXehwAhl5zK0loY/wfxblUiL+y21T24LMCJc15a9QX5dwbXH72ioHz7qdzb/agXk7AK+foc2/0Hw==",
+ "requires": {
+ "@angular-devkit/architect": "0.803.24",
+ "@angular-devkit/build-optimizer": "0.803.24",
+ "@angular-devkit/build-webpack": "0.803.24",
+ "@angular-devkit/core": "8.3.24",
+ "@babel/core": "7.8.3",
+ "@babel/preset-env": "7.8.3",
+ "@ngtools/webpack": "8.3.24",
+ "ajv": "6.10.2",
+ "autoprefixer": "9.6.1",
+ "browserslist": "4.8.3",
+ "cacache": "12.0.2",
+ "caniuse-lite": "1.0.30001019",
+ "circular-dependency-plugin": "5.2.0",
+ "clean-css": "4.2.1",
+ "copy-webpack-plugin": "5.1.1",
+ "core-js": "3.6.4",
+ "coverage-istanbul-loader": "2.0.3",
+ "file-loader": "4.2.0",
+ "find-cache-dir": "3.0.0",
+ "glob": "7.1.4",
+ "jest-worker": "24.9.0",
+ "karma-source-map-support": "1.4.0",
+ "less": "3.9.0",
+ "less-loader": "5.0.0",
+ "license-webpack-plugin": "2.1.2",
+ "loader-utils": "1.2.3",
+ "mini-css-extract-plugin": "0.8.0",
+ "minimatch": "3.0.4",
+ "open": "6.4.0",
+ "parse5": "4.0.0",
+ "postcss": "7.0.17",
+ "postcss-import": "12.0.1",
+ "postcss-loader": "3.0.0",
+ "raw-loader": "3.1.0",
+ "regenerator-runtime": "0.13.3",
+ "rxjs": "6.4.0",
+ "sass": "1.22.9",
+ "sass-loader": "7.2.0",
+ "semver": "6.3.0",
+ "source-map": "0.7.3",
+ "source-map-loader": "0.2.4",
+ "source-map-support": "0.5.13",
+ "speed-measure-webpack-plugin": "1.3.1",
+ "style-loader": "1.0.0",
+ "stylus": "0.54.5",
+ "stylus-loader": "3.0.2",
+ "terser": "4.6.3",
+ "terser-webpack-plugin": "1.4.3",
+ "tree-kill": "1.2.2",
+ "webpack": "4.39.2",
+ "webpack-dev-middleware": "3.7.2",
+ "webpack-dev-server": "3.9.0",
+ "webpack-merge": "4.2.1",
+ "webpack-sources": "1.4.3",
+ "webpack-subresource-integrity": "1.1.0-rc.6",
+ "worker-plugin": "3.2.0"
+ },
+ "dependencies": {
+ "@angular-devkit/architect": {
+ "version": "0.803.24",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.24.tgz",
+ "integrity": "sha512-ONY/Ppzyvtb0tqgwnzQvlGlexb5nTyy58ljgL1aQLTO3cNTkpl4IQYUCTdvn61gGA+FWPAXMCCbNqOPZMsOZCQ==",
+ "requires": {
+ "@angular-devkit/core": "8.3.24",
+ "rxjs": "6.4.0"
+ }
+ },
+ "@angular-devkit/core": {
+ "version": "8.3.24",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.24.tgz",
+ "integrity": "sha512-xpT5yg+ddGDnifryBv2sRSYtq5F3iZIS+lN/K2AhhEa50B7Z+QaCVlEzoV/IfrGd6sLArdnKYwjLHFZ0LElUuw==",
+ "requires": {
+ "ajv": "6.10.2",
+ "fast-json-stable-stringify": "2.0.0",
+ "magic-string": "0.25.3",
+ "rxjs": "6.4.0",
+ "source-map": "0.7.3"
+ }
+ },
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "cacache": {
+ "version": "12.0.2",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.2.tgz",
+ "integrity": "sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==",
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "infer-owner": "^1.0.3",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "magic-string": {
+ "version": "0.25.3",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz",
+ "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==",
+ "requires": {
+ "sourcemap-codec": "^1.4.4"
+ }
+ },
+ "open": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz",
+ "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==",
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ },
+ "source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "webpack-merge": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz",
+ "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==",
+ "requires": {
+ "lodash": "^4.17.5"
+ }
+ }
+ }
+ },
+ "@angular-devkit/build-optimizer": {
+ "version": "0.803.24",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.803.24.tgz",
+ "integrity": "sha512-Z+d7M+WpBq7AWWRwbxzb1l9O9qkylxnDRKxXvq3Tzjn43g+2WyspE91dMyrg1ISc+p8jgX6xKSblRLvtWqpA8w==",
+ "requires": {
+ "loader-utils": "1.2.3",
+ "source-map": "0.7.3",
+ "tslib": "1.10.0",
+ "typescript": "3.5.3",
+ "webpack-sources": "1.4.3"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+ },
+ "typescript": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz",
+ "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g=="
+ }
+ }
+ },
+ "@angular-devkit/build-webpack": {
+ "version": "0.803.24",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.803.24.tgz",
+ "integrity": "sha512-Bbd5KUGaE+edN0sp8K3azuqS/JTBmeWXIumdBEtqWyL6VsohX7fL+toJlSvRkj8lg02LVyozAFetXKnyaBkfCQ==",
+ "requires": {
+ "@angular-devkit/architect": "0.803.24",
+ "@angular-devkit/core": "8.3.24",
+ "rxjs": "6.4.0"
+ },
+ "dependencies": {
+ "@angular-devkit/architect": {
+ "version": "0.803.24",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.24.tgz",
+ "integrity": "sha512-ONY/Ppzyvtb0tqgwnzQvlGlexb5nTyy58ljgL1aQLTO3cNTkpl4IQYUCTdvn61gGA+FWPAXMCCbNqOPZMsOZCQ==",
+ "requires": {
+ "@angular-devkit/core": "8.3.24",
+ "rxjs": "6.4.0"
+ }
+ },
+ "@angular-devkit/core": {
+ "version": "8.3.24",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.24.tgz",
+ "integrity": "sha512-xpT5yg+ddGDnifryBv2sRSYtq5F3iZIS+lN/K2AhhEa50B7Z+QaCVlEzoV/IfrGd6sLArdnKYwjLHFZ0LElUuw==",
+ "requires": {
+ "ajv": "6.10.2",
+ "fast-json-stable-stringify": "2.0.0",
+ "magic-string": "0.25.3",
+ "rxjs": "6.4.0",
+ "source-map": "0.7.3"
+ }
+ },
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "magic-string": {
+ "version": "0.25.3",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz",
+ "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==",
+ "requires": {
+ "sourcemap-codec": "^1.4.4"
+ }
+ }
+ }
+ },
+ "@angular-devkit/core": {
+ "version": "8.0.6",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.0.6.tgz",
+ "integrity": "sha512-gbKEVsQuYqBJPzgaxEitvs0aN9NwmUHhTkum28mRyPbS3witay/q8+3ls48M2W+98Da/PQbfndxFY4OCa+qHEA==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.10.0",
+ "fast-json-stable-stringify": "2.0.0",
+ "magic-string": "0.25.2",
+ "rxjs": "6.4.0",
+ "source-map": "0.7.3"
+ }
+ },
+ "@angular-devkit/schematics": {
+ "version": "8.0.6",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.0.6.tgz",
+ "integrity": "sha512-FGPcVKxNvtdFB0A6oHyxtWeugL83nW+kPATlAimgh1hu7TCP94dDpflCV9o/lgZlH817xTYXrhToXJaMZSnDPw==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.0.6",
+ "rxjs": "6.4.0"
+ }
+ },
+ "@angular/animations": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.0.3.tgz",
+ "integrity": "sha512-9zciJ4YRR0bodFSYgsgXdYMz8wKKyVjch7XZADGkWubXT8mGuwlpdPMlQ6n9Cwj8Ebu0u52WxMeQsX76K9RlYA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/cdk": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-8.2.3.tgz",
+ "integrity": "sha512-ZwO5Sn720RA2YvBqud0JAHkZXjmjxM0yNzCO8RVtRE9i8Gl26Wk0j0nQeJkVm4zwv2QO8MwbKUKGTMt8evsokA==",
+ "requires": {
+ "parse5": "^5.0.0",
+ "tslib": "^1.7.1"
+ },
+ "dependencies": {
+ "parse5": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
+ "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
+ "optional": true
+ }
+ }
+ },
+ "@angular/cli": {
+ "version": "8.0.6",
+ "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.0.6.tgz",
+ "integrity": "sha512-COBpeoXyLt8FiOhsmoEnDfQcm0aTdUSUHsH3zNkVTcyxpRzZVspTDGzxhK0UsCpddXS/MMjJiXph6SJ1el3qaQ==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/architect": "0.800.6",
+ "@angular-devkit/core": "8.0.6",
+ "@angular-devkit/schematics": "8.0.6",
+ "@schematics/angular": "8.0.6",
+ "@schematics/update": "0.800.6",
+ "@yarnpkg/lockfile": "1.1.0",
+ "debug": "^4.1.1",
+ "ini": "1.3.5",
+ "inquirer": "6.3.1",
+ "npm-package-arg": "6.1.0",
+ "open": "6.2.0",
+ "pacote": "9.5.0",
+ "read-package-tree": "5.2.2",
+ "semver": "6.0.0",
+ "symbol-observable": "1.2.0",
+ "universal-analytics": "^0.4.20",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@angular/common": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.0.3.tgz",
+ "integrity": "sha512-2YLYGVUf9eJZcocRmD3/9UHj4qFHt2t4ftDWJmrFM9zo2PZF+G5O9fASO7qoBbwpx3KFZtQO4dprKl2dFugRjg==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/compiler": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.0.3.tgz",
+ "integrity": "sha512-1/vF8D6l1O6IfWiDtaj6nC+B8CtkVtFgXgooDzLBO6XAkaCuJCnhKT1HnpWG5GtVsGaY9MGoTl1vE9ZMDbRQjg==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/compiler-cli": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-8.0.3.tgz",
+ "integrity": "sha512-6nckvBnnp1YnrxwCB8UKvhHAMcUa1WvGjbYMEqhgiBreiRT4ub+tKVPNzrRtQFPpcXtY1wlgOWqYHWhHRtcLlg==",
+ "dev": true,
+ "requires": {
+ "canonical-path": "1.0.0",
+ "chokidar": "^2.1.1",
+ "convert-source-map": "^1.5.1",
+ "dependency-graph": "^0.7.2",
+ "magic-string": "^0.25.0",
+ "minimist": "^1.2.0",
+ "reflect-metadata": "^0.1.2",
+ "shelljs": "^0.8.1",
+ "source-map": "^0.6.1",
+ "tslib": "^1.9.0",
+ "yargs": "13.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "yargs": {
+ "version": "13.1.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.1.0.tgz",
+ "integrity": "sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "os-locale": "^3.1.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
+ "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "@angular/core": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.0.3.tgz",
+ "integrity": "sha512-IIxrtIPNuv2+HudER9J1nmPGiGJ4aRpeiFM9V4lSiSFv50RzuaoG60XqYIpUyuBdgvyKigcrfSbu9+x1vyN0hw==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/forms": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.0.3.tgz",
+ "integrity": "sha512-22s82QDRQ72K4vMYuNh3NAN+da9uanwoydnfKlp2rb9dZAb2QVX9NN6gSoMrkSSr2O9KTP6pWiw6A3/MW8sGRA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/language-service": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-8.0.3.tgz",
+ "integrity": "sha512-04XojOo9FJgEQE/rZafnaJQxPEU+//TSzTgpGoIVzCSMx+joCY/ZSSwJZPWxiHlOE57W/zX02ZY+TwcM81oTdw==",
+ "dev": true
+ },
+ "@angular/material": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-8.2.3.tgz",
+ "integrity": "sha512-SOczkIaqes+r+9XF/UUiokidfFKBpHkOPIaFK857sFD0FBNPvPEpOr5oHKCG3feERRwAFqHS7Wo2ohVEWypb5A==",
+ "requires": {
+ "tslib": "^1.7.1"
+ }
+ },
+ "@angular/platform-browser": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.0.3.tgz",
+ "integrity": "sha512-ceAPP2Ijmk2sZ1rnOU/WNlE3DtT6K6ljpjO9oUfXKMoSMdWirJKAraT3m/BAzmYwMSXpPBxA7c3paZjiLL6t5A==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/platform-browser-dynamic": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.0.3.tgz",
+ "integrity": "sha512-ZjQjSYslSQAKzM4llvyMFxnSjFpbhT1U9FOdKwscPe475zAKX0087qsHrP2CRwkJRfwtdcmj9wMUQIPlzMpHLA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/router": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.0.3.tgz",
+ "integrity": "sha512-CU5pLTfQVUnTN93mdIKJrVjXiNldUkk30DPz4lpdxpZjYOqFGXeeSeQWmToHSofLPodNcAB4kkZ41VyXvlBu7w==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@auth0/angular-jwt": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-4.0.0.tgz",
+ "integrity": "sha512-CHvk1zJ9jpQupl0f5y7EmTvYAwugyFvC4ztLsZKr7ZC7anNVaDd1+pDFJYS+ZEU9jLWzE74+AfVKfigImADJuw==",
+ "requires": {
+ "url": "^0.11.0"
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
+ "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
+ "requires": {
+ "@babel/highlight": "^7.8.3"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.8.0.tgz",
+ "integrity": "sha512-ixPUWJpnd9hHvRkyIE3mJ6PY5DEWmR08UkcpdqI5kV5g/d6knT8Wth1LE5v5sVTIJkm9dGpQsXnhwxcf2/PjAg==",
+ "requires": {
+ "browserslist": "^4.8.2",
+ "invariant": "^2.2.4",
+ "semver": "^7.1.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
+ }
+ }
+ },
+ "@babel/core": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.3.tgz",
+ "integrity": "sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==",
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/generator": "^7.8.3",
+ "@babel/helpers": "^7.8.3",
+ "@babel/parser": "^7.8.3",
+ "@babel/template": "^7.8.3",
+ "@babel/traverse": "^7.8.3",
+ "@babel/types": "^7.8.3",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.1",
+ "json5": "^2.1.0",
+ "lodash": "^4.17.13",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "json5": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+ "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz",
+ "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==",
+ "requires": {
+ "@babel/types": "^7.8.3",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ }
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz",
+ "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==",
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz",
+ "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==",
+ "requires": {
+ "@babel/helper-explode-assignable-expression": "^7.8.3",
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.8.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz",
+ "integrity": "sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==",
+ "requires": {
+ "browserslist": "^4.9.1",
+ "invariant": "^2.2.4",
+ "levenary": "^1.1.1",
+ "semver": "^5.5.0"
+ },
+ "dependencies": {
+ "browserslist": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz",
+ "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001043",
+ "electron-to-chromium": "^1.3.413",
+ "node-releases": "^1.1.53",
+ "pkg-up": "^2.0.0"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001045",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001045.tgz",
+ "integrity": "sha512-Y8o2Iz1KPcD6FjySbk1sPpvJqchgxk/iow0DABpGyzA1UeQAuxh63Xh0Enj5/BrsYbXtCN32JmR4ZxQTCQ6E6A=="
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ }
+ }
+ },
+ "@babel/helper-create-regexp-features-plugin": {
+ "version": "7.8.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz",
+ "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.8.3",
+ "@babel/helper-regex": "^7.8.3",
+ "regexpu-core": "^4.7.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+ },
+ "regexpu-core": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz",
+ "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==",
+ "requires": {
+ "regenerate": "^1.4.0",
+ "regenerate-unicode-properties": "^8.2.0",
+ "regjsgen": "^0.5.1",
+ "regjsparser": "^0.6.4",
+ "unicode-match-property-ecmascript": "^1.0.4",
+ "unicode-match-property-value-ecmascript": "^1.2.0"
+ }
+ },
+ "regjsgen": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz",
+ "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg=="
+ },
+ "regjsparser": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz",
+ "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==",
+ "requires": {
+ "jsesc": "~0.5.0"
+ }
+ }
+ }
+ },
+ "@babel/helper-define-map": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz",
+ "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==",
+ "requires": {
+ "@babel/helper-function-name": "^7.8.3",
+ "@babel/types": "^7.8.3",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-explode-assignable-expression": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz",
+ "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==",
+ "requires": {
+ "@babel/traverse": "^7.8.3",
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz",
+ "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==",
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.8.3",
+ "@babel/template": "^7.8.3",
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz",
+ "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==",
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz",
+ "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==",
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz",
+ "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==",
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz",
+ "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==",
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz",
+ "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.8.3",
+ "@babel/helper-replace-supers": "^7.8.6",
+ "@babel/helper-simple-access": "^7.8.3",
+ "@babel/helper-split-export-declaration": "^7.8.3",
+ "@babel/template": "^7.8.6",
+ "@babel/types": "^7.9.0",
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "@babel/parser": {
+ "version": "7.9.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz",
+ "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA=="
+ },
+ "@babel/template": {
+ "version": "7.8.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
+ "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==",
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/parser": "^7.8.6",
+ "@babel/types": "^7.8.6"
+ }
+ },
+ "@babel/types": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz",
+ "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.9.5",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz",
+ "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==",
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz",
+ "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ=="
+ },
+ "@babel/helper-regex": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz",
+ "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==",
+ "requires": {
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz",
+ "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.8.3",
+ "@babel/helper-wrap-function": "^7.8.3",
+ "@babel/template": "^7.8.3",
+ "@babel/traverse": "^7.8.3",
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.8.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz",
+ "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==",
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.8.3",
+ "@babel/helper-optimise-call-expression": "^7.8.3",
+ "@babel/traverse": "^7.8.6",
+ "@babel/types": "^7.8.6"
+ },
+ "dependencies": {
+ "@babel/generator": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz",
+ "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==",
+ "requires": {
+ "@babel/types": "^7.9.5",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+ "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.8.3",
+ "@babel/template": "^7.8.3",
+ "@babel/types": "^7.9.5"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.9.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz",
+ "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA=="
+ },
+ "@babel/traverse": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz",
+ "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==",
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/generator": "^7.9.5",
+ "@babel/helper-function-name": "^7.9.5",
+ "@babel/helper-split-export-declaration": "^7.8.3",
+ "@babel/parser": "^7.9.0",
+ "@babel/types": "^7.9.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz",
+ "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.9.5",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ }
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz",
+ "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==",
+ "requires": {
+ "@babel/template": "^7.8.3",
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz",
+ "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==",
+ "requires": {
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz",
+ "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g=="
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz",
+ "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==",
+ "requires": {
+ "@babel/helper-function-name": "^7.8.3",
+ "@babel/template": "^7.8.3",
+ "@babel/traverse": "^7.8.3",
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.9.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz",
+ "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==",
+ "requires": {
+ "@babel/template": "^7.8.3",
+ "@babel/traverse": "^7.9.0",
+ "@babel/types": "^7.9.0"
+ },
+ "dependencies": {
+ "@babel/generator": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz",
+ "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==",
+ "requires": {
+ "@babel/types": "^7.9.5",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+ "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.8.3",
+ "@babel/template": "^7.8.3",
+ "@babel/types": "^7.9.5"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.9.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz",
+ "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA=="
+ },
+ "@babel/traverse": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz",
+ "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==",
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/generator": "^7.9.5",
+ "@babel/helper-function-name": "^7.9.5",
+ "@babel/helper-split-export-declaration": "^7.8.3",
+ "@babel/parser": "^7.9.0",
+ "@babel/types": "^7.9.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/types": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz",
+ "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.9.5",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ }
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
+ "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
+ "requires": {
+ "chalk": "^2.0.0",
+ "esutils": "^2.0.2",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ }
+ }
+ },
+ "@babel/parser": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz",
+ "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw=="
+ },
+ "@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz",
+ "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-remap-async-to-generator": "^7.8.3",
+ "@babel/plugin-syntax-async-generators": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz",
+ "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz",
+ "integrity": "sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-transform-parameters": "^7.9.5"
+ }
+ },
+ "@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-optional-chaining": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz",
+ "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.0"
+ }
+ },
+ "@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.8.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz",
+ "integrity": "sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.8.8",
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-top-level-await": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz",
+ "integrity": "sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-arrow-functions": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz",
+ "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz",
+ "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==",
+ "requires": {
+ "@babel/helper-module-imports": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-remap-async-to-generator": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz",
+ "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-block-scoping": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz",
+ "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/plugin-transform-classes": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz",
+ "integrity": "sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.8.3",
+ "@babel/helper-define-map": "^7.8.3",
+ "@babel/helper-function-name": "^7.9.5",
+ "@babel/helper-optimise-call-expression": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-replace-supers": "^7.8.6",
+ "@babel/helper-split-export-declaration": "^7.8.3",
+ "globals": "^11.1.0"
+ },
+ "dependencies": {
+ "@babel/helper-function-name": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz",
+ "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==",
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.8.3",
+ "@babel/template": "^7.8.3",
+ "@babel/types": "^7.9.5"
+ }
+ },
+ "@babel/types": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz",
+ "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==",
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.9.5",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
+ }
+ },
+ "@babel/plugin-transform-computed-properties": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz",
+ "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-destructuring": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz",
+ "integrity": "sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-dotall-regex": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz",
+ "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-duplicate-keys": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz",
+ "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz",
+ "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==",
+ "requires": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-for-of": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz",
+ "integrity": "sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-function-name": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz",
+ "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==",
+ "requires": {
+ "@babel/helper-function-name": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-literals": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz",
+ "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-member-expression-literals": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz",
+ "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz",
+ "integrity": "sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.9.0",
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "babel-plugin-dynamic-import-node": "^2.3.0"
+ }
+ },
+ "@babel/plugin-transform-modules-commonjs": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz",
+ "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.9.0",
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-simple-access": "^7.8.3",
+ "babel-plugin-dynamic-import-node": "^2.3.0"
+ }
+ },
+ "@babel/plugin-transform-modules-systemjs": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz",
+ "integrity": "sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ==",
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.8.3",
+ "@babel/helper-module-transforms": "^7.9.0",
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "babel-plugin-dynamic-import-node": "^2.3.0"
+ }
+ },
+ "@babel/plugin-transform-modules-umd": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz",
+ "integrity": "sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ==",
+ "requires": {
+ "@babel/helper-module-transforms": "^7.9.0",
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz",
+ "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-new-target": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz",
+ "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-object-super": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz",
+ "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-replace-supers": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-parameters": {
+ "version": "7.9.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz",
+ "integrity": "sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA==",
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-property-literals": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz",
+ "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-regenerator": {
+ "version": "7.8.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz",
+ "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==",
+ "requires": {
+ "regenerator-transform": "^0.14.2"
+ }
+ },
+ "@babel/plugin-transform-reserved-words": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz",
+ "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-shorthand-properties": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz",
+ "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz",
+ "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-sticky-regex": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz",
+ "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/helper-regex": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-template-literals": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz",
+ "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-typeof-symbol": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz",
+ "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==",
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-transform-unicode-regex": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz",
+ "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==",
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/preset-env": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.8.3.tgz",
+ "integrity": "sha512-Rs4RPL2KjSLSE2mWAx5/iCH+GC1ikKdxPrhnRS6PfFVaiZeom22VFKN4X8ZthyN61kAaR05tfXTbCvatl9WIQg==",
+ "requires": {
+ "@babel/compat-data": "^7.8.0",
+ "@babel/helper-compilation-targets": "^7.8.3",
+ "@babel/helper-module-imports": "^7.8.3",
+ "@babel/helper-plugin-utils": "^7.8.3",
+ "@babel/plugin-proposal-async-generator-functions": "^7.8.3",
+ "@babel/plugin-proposal-dynamic-import": "^7.8.3",
+ "@babel/plugin-proposal-json-strings": "^7.8.3",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-proposal-object-rest-spread": "^7.8.3",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-proposal-optional-chaining": "^7.8.3",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.8.3",
+ "@babel/plugin-syntax-async-generators": "^7.8.0",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.0",
+ "@babel/plugin-syntax-json-strings": "^7.8.0",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.0",
+ "@babel/plugin-syntax-top-level-await": "^7.8.3",
+ "@babel/plugin-transform-arrow-functions": "^7.8.3",
+ "@babel/plugin-transform-async-to-generator": "^7.8.3",
+ "@babel/plugin-transform-block-scoped-functions": "^7.8.3",
+ "@babel/plugin-transform-block-scoping": "^7.8.3",
+ "@babel/plugin-transform-classes": "^7.8.3",
+ "@babel/plugin-transform-computed-properties": "^7.8.3",
+ "@babel/plugin-transform-destructuring": "^7.8.3",
+ "@babel/plugin-transform-dotall-regex": "^7.8.3",
+ "@babel/plugin-transform-duplicate-keys": "^7.8.3",
+ "@babel/plugin-transform-exponentiation-operator": "^7.8.3",
+ "@babel/plugin-transform-for-of": "^7.8.3",
+ "@babel/plugin-transform-function-name": "^7.8.3",
+ "@babel/plugin-transform-literals": "^7.8.3",
+ "@babel/plugin-transform-member-expression-literals": "^7.8.3",
+ "@babel/plugin-transform-modules-amd": "^7.8.3",
+ "@babel/plugin-transform-modules-commonjs": "^7.8.3",
+ "@babel/plugin-transform-modules-systemjs": "^7.8.3",
+ "@babel/plugin-transform-modules-umd": "^7.8.3",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3",
+ "@babel/plugin-transform-new-target": "^7.8.3",
+ "@babel/plugin-transform-object-super": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.8.3",
+ "@babel/plugin-transform-property-literals": "^7.8.3",
+ "@babel/plugin-transform-regenerator": "^7.8.3",
+ "@babel/plugin-transform-reserved-words": "^7.8.3",
+ "@babel/plugin-transform-shorthand-properties": "^7.8.3",
+ "@babel/plugin-transform-spread": "^7.8.3",
+ "@babel/plugin-transform-sticky-regex": "^7.8.3",
+ "@babel/plugin-transform-template-literals": "^7.8.3",
+ "@babel/plugin-transform-typeof-symbol": "^7.8.3",
+ "@babel/plugin-transform-unicode-regex": "^7.8.3",
+ "@babel/types": "^7.8.3",
+ "browserslist": "^4.8.2",
+ "core-js-compat": "^3.6.2",
+ "invariant": "^2.2.2",
+ "levenary": "^1.1.0",
+ "semver": "^5.5.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ }
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.9.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
+ "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.13.5",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
+ "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
+ }
+ }
+ },
+ "@babel/template": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz",
+ "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==",
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/parser": "^7.8.3",
+ "@babel/types": "^7.8.3"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz",
+ "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==",
+ "requires": {
+ "@babel/code-frame": "^7.8.3",
+ "@babel/generator": "^7.8.4",
+ "@babel/helper-function-name": "^7.8.3",
+ "@babel/helper-split-export-declaration": "^7.8.3",
+ "@babel/parser": "^7.8.4",
+ "@babel/types": "^7.8.3",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "@babel/types": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
+ "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==",
+ "requires": {
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ },
+ "dependencies": {
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
+ }
+ }
+ },
+ "@fortawesome/fontawesome-free": {
+ "version": "5.13.0",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz",
+ "integrity": "sha512-xKOeQEl5O47GPZYIMToj6uuA2syyFlq9EMSl2ui0uytjY9xbe8XS0pexNWmxrdcCyNGyDmLyYw5FtKsalBUeOg=="
+ },
+ "@istanbuljs/schema": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz",
+ "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw=="
+ },
+ "@ngtools/webpack": {
+ "version": "8.3.24",
+ "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.3.24.tgz",
+ "integrity": "sha512-OpR7t/99qNOpADayCuM67agBVdYkdbFyEEcOLaDFYh3LsefHOSSxtAGv8M77e7dguvtaljHTiVkMxgcXFsZM0Q==",
+ "requires": {
+ "@angular-devkit/core": "8.3.24",
+ "enhanced-resolve": "4.1.0",
+ "rxjs": "6.4.0",
+ "tree-kill": "1.2.2",
+ "webpack-sources": "1.4.3"
+ },
+ "dependencies": {
+ "@angular-devkit/core": {
+ "version": "8.3.24",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.24.tgz",
+ "integrity": "sha512-xpT5yg+ddGDnifryBv2sRSYtq5F3iZIS+lN/K2AhhEa50B7Z+QaCVlEzoV/IfrGd6sLArdnKYwjLHFZ0LElUuw==",
+ "requires": {
+ "ajv": "6.10.2",
+ "fast-json-stable-stringify": "2.0.0",
+ "magic-string": "0.25.3",
+ "rxjs": "6.4.0",
+ "source-map": "0.7.3"
+ }
+ },
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "magic-string": {
+ "version": "0.25.3",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz",
+ "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==",
+ "requires": {
+ "sourcemap-codec": "^1.4.4"
+ }
+ }
+ }
+ },
+ "@schematics/angular": {
+ "version": "8.0.6",
+ "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.0.6.tgz",
+ "integrity": "sha512-F0/MrbvrJQJIjt0GwEkmf9PZUX0xQlCjlDcH6U7yBni0/+R5Gd5g3G0f12fsSa2iAwpwrLkKpiQluj29eFituQ==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.0.6",
+ "@angular-devkit/schematics": "8.0.6"
+ }
+ },
+ "@schematics/update": {
+ "version": "0.800.6",
+ "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.800.6.tgz",
+ "integrity": "sha512-vrzGIJtMiwLWl96+aJXMYrPgPtktLRpY8ZiNnlLm3pMDmeg08uButRh/pQGt02HuO/apTNJ5g0bmG8K5wS4I5A==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.0.6",
+ "@angular-devkit/schematics": "8.0.6",
+ "@yarnpkg/lockfile": "1.1.0",
+ "ini": "1.3.5",
+ "pacote": "9.5.0",
+ "rxjs": "6.4.0",
+ "semver": "6.0.0",
+ "semver-intersect": "1.4.0"
+ }
+ },
+ "@types/events": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
+ "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g=="
+ },
+ "@types/glob": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==",
+ "requires": {
+ "@types/events": "*",
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/jasmine": {
+ "version": "3.3.16",
+ "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.3.16.tgz",
+ "integrity": "sha512-Nveep4zKGby8uIvG2AEUyYOwZS8uVeHK9TgbuWYSawUDDdIgfhCKz28QzamTo//Jk7Ztt9PO3f+vzlB6a4GV1Q==",
+ "dev": true
+ },
+ "@types/jasminewd2": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.8.tgz",
+ "integrity": "sha512-d9p31r7Nxk0ZH0U39PTH0hiDlJ+qNVGjlt1ucOoTUptxb2v+Y5VMnsxfwN+i3hK4yQnqBi3FMmoMFcd1JHDxdg==",
+ "dev": true,
+ "requires": {
+ "@types/jasmine": "*"
+ }
+ },
+ "@types/minimatch": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA=="
+ },
+ "@types/node": {
+ "version": "8.9.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.5.tgz",
+ "integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ=="
+ },
+ "@types/q": {
+ "version": "0.0.32",
+ "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
+ "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
+ "dev": true
+ },
+ "@types/selenium-webdriver": {
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.17.tgz",
+ "integrity": "sha512-tGomyEuzSC1H28y2zlW6XPCaDaXFaD6soTdb4GNdmte2qfHtrKqhy0ZFs4r/1hpazCfEZqeTSRLvSasmEx89uw==",
+ "dev": true
+ },
+ "@types/source-list-map": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
+ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA=="
+ },
+ "@types/webpack-sources": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.7.tgz",
+ "integrity": "sha512-XyaHrJILjK1VHVC4aVlKsdNN5KBTwufMb43cQs+flGxtPAf/1Qwl8+Q0tp5BwEGaI8D6XT1L+9bSWXckgkjTLw==",
+ "requires": {
+ "@types/node": "*",
+ "@types/source-list-map": "*",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "@webassemblyjs/ast": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
+ "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==",
+ "requires": {
+ "@webassemblyjs/helper-module-context": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/wast-parser": "1.8.5"
+ }
+ },
+ "@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz",
+ "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ=="
+ },
+ "@webassemblyjs/helper-api-error": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz",
+ "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA=="
+ },
+ "@webassemblyjs/helper-buffer": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz",
+ "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q=="
+ },
+ "@webassemblyjs/helper-code-frame": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz",
+ "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==",
+ "requires": {
+ "@webassemblyjs/wast-printer": "1.8.5"
+ }
+ },
+ "@webassemblyjs/helper-fsm": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz",
+ "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow=="
+ },
+ "@webassemblyjs/helper-module-context": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz",
+ "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==",
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "mamacro": "^0.0.3"
+ }
+ },
+ "@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz",
+ "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ=="
+ },
+ "@webassemblyjs/helper-wasm-section": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz",
+ "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==",
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-buffer": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/wasm-gen": "1.8.5"
+ }
+ },
+ "@webassemblyjs/ieee754": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz",
+ "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==",
+ "requires": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "@webassemblyjs/leb128": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz",
+ "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==",
+ "requires": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@webassemblyjs/utf8": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz",
+ "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw=="
+ },
+ "@webassemblyjs/wasm-edit": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz",
+ "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==",
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-buffer": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/helper-wasm-section": "1.8.5",
+ "@webassemblyjs/wasm-gen": "1.8.5",
+ "@webassemblyjs/wasm-opt": "1.8.5",
+ "@webassemblyjs/wasm-parser": "1.8.5",
+ "@webassemblyjs/wast-printer": "1.8.5"
+ }
+ },
+ "@webassemblyjs/wasm-gen": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz",
+ "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==",
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/ieee754": "1.8.5",
+ "@webassemblyjs/leb128": "1.8.5",
+ "@webassemblyjs/utf8": "1.8.5"
+ }
+ },
+ "@webassemblyjs/wasm-opt": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz",
+ "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==",
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-buffer": "1.8.5",
+ "@webassemblyjs/wasm-gen": "1.8.5",
+ "@webassemblyjs/wasm-parser": "1.8.5"
+ }
+ },
+ "@webassemblyjs/wasm-parser": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz",
+ "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==",
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-api-error": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/ieee754": "1.8.5",
+ "@webassemblyjs/leb128": "1.8.5",
+ "@webassemblyjs/utf8": "1.8.5"
+ }
+ },
+ "@webassemblyjs/wast-parser": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz",
+ "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==",
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/floating-point-hex-parser": "1.8.5",
+ "@webassemblyjs/helper-api-error": "1.8.5",
+ "@webassemblyjs/helper-code-frame": "1.8.5",
+ "@webassemblyjs/helper-fsm": "1.8.5",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@webassemblyjs/wast-printer": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz",
+ "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==",
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/wast-parser": "1.8.5",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
+ },
+ "@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
+ },
+ "@yarnpkg/lockfile": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
+ "dev": true
+ },
+ "JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ }
+ },
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "acorn": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
+ "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA=="
+ },
+ "adler-32": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz",
+ "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=",
+ "requires": {
+ "exit-on-epipe": "~1.0.1",
+ "printj": "~1.1.0"
+ }
+ },
+ "adm-zip": {
+ "version": "0.4.14",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz",
+ "integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g==",
+ "dev": true
+ },
+ "after": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+ "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
+ "dev": true
+ },
+ "agent-base": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
+ "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+ "dev": true,
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ },
+ "agentkeepalive": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz",
+ "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==",
+ "dev": true,
+ "requires": {
+ "humanize-ms": "^1.2.1"
+ }
+ },
+ "ajv": {
+ "version": "6.10.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
+ "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-errors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+ "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ=="
+ },
+ "ajv-keywords": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ=="
+ },
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
+ },
+ "ansi-colors": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
+ "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA=="
+ },
+ "ansi-escapes": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+ "dev": true
+ },
+ "ansi-html": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4="
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "app-root-path": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz",
+ "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==",
+ "dev": true
+ },
+ "append-transform": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
+ "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
+ "dev": true,
+ "requires": {
+ "default-require-extensions": "^2.0.0"
+ }
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+ },
+ "arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "aria-query": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
+ "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=",
+ "dev": true,
+ "requires": {
+ "ast-types-flow": "0.0.7",
+ "commander": "^2.11.0"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
+ },
+ "array-flatten": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ=="
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "requires": {
+ "array-uniq": "^1.0.1"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+ },
+ "arraybuffer.slice": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
+ "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ },
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "asn1.js": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+ "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+ "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+ "requires": {
+ "object-assign": "^4.1.1",
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
+ },
+ "ast-types-flow": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
+ "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=",
+ "dev": true
+ },
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "async-each": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="
+ },
+ "async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
+ },
+ "autoprefixer": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.1.tgz",
+ "integrity": "sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw==",
+ "requires": {
+ "browserslist": "^4.6.3",
+ "caniuse-lite": "^1.0.30000980",
+ "chalk": "^2.4.2",
+ "normalize-range": "^0.1.2",
+ "num2fraction": "^1.2.2",
+ "postcss": "^7.0.17",
+ "postcss-value-parser": "^4.0.0"
+ }
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+ },
+ "aws4": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
+ "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
+ },
+ "axobject-query": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
+ "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
+ "dev": true,
+ "requires": {
+ "ast-types-flow": "0.0.7"
+ }
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "requires": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "backo2": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+ "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "base64-arraybuffer": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
+ "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
+ "dev": true
+ },
+ "base64-js": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
+ },
+ "base64id": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
+ "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
+ "dev": true
+ },
+ "batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY="
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "better-assert": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
+ "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
+ "dev": true,
+ "requires": {
+ "callsite": "1.0.0"
+ }
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw=="
+ },
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "blob": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
+ "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
+ "dev": true
+ },
+ "blocking-proxy": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz",
+ "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+ }
+ }
+ },
+ "bonjour": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "requires": {
+ "array-flatten": "^2.1.0",
+ "deep-equal": "^1.0.1",
+ "dns-equal": "^1.0.0",
+ "dns-txt": "^2.0.2",
+ "multicast-dns": "^6.0.1",
+ "multicast-dns-service-types": "^1.1.0"
+ }
+ },
+ "bootstrap": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz",
+ "integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA=="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "requires": {
+ "bn.js": "^4.1.1",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.2",
+ "elliptic": "^6.0.0",
+ "inherits": "^2.0.1",
+ "parse-asn1": "^5.0.0"
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "browserslist": {
+ "version": "4.8.3",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.3.tgz",
+ "integrity": "sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001017",
+ "electron-to-chromium": "^1.3.322",
+ "node-releases": "^1.1.44"
+ }
+ },
+ "browserstack": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz",
+ "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==",
+ "dev": true,
+ "requires": {
+ "https-proxy-agent": "^2.2.1"
+ }
+ },
+ "buffer": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
+ "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "buffer-alloc": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+ "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+ "dev": true,
+ "requires": {
+ "buffer-alloc-unsafe": "^1.1.0",
+ "buffer-fill": "^1.0.0"
+ }
+ },
+ "buffer-alloc-unsafe": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
+ "dev": true
+ },
+ "buffer-fill": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+ "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+ "dev": true
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+ },
+ "buffer-indexof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g=="
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
+ },
+ "builtins": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
+ "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+ },
+ "cacache": {
+ "version": "11.3.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz",
+ "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+ "requires": {
+ "callsites": "^2.0.0"
+ }
+ },
+ "caller-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+ "requires": {
+ "caller-callsite": "^2.0.0"
+ }
+ },
+ "callsite": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+ "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
+ "dev": true
+ },
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001019",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001019.tgz",
+ "integrity": "sha512-6ljkLtF1KM5fQ+5ZN0wuyVvvebJxgJPTmScOMaFuQN2QuOzvRJnWSKfzQskQU5IOU4Gap3zasYPIinzwUjoj/g=="
+ },
+ "canonical-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz",
+ "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==",
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "cdk-table-exporter": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/cdk-table-exporter/-/cdk-table-exporter-9.0.0.tgz",
+ "integrity": "sha512-F//RrIX9ek5wwYFAG2VzgtL3l48tRPw7SLb0VpXobqYOxjcZBQlha+eFsDDhYfBkz/PHxSNNY3rPZen2O9ynVw==",
+ "requires": {
+ "file-saver": "^2.0.2",
+ "xlsx": "^0.14.1"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.17.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
+ },
+ "xlsx": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.14.5.tgz",
+ "integrity": "sha512-s/5f4/mjeWREmIWZ+HtDfh/rnz51ar+dZ4LWKZU3u9VBx2zLdSIWTdXgoa52/pnZ9Oe/Vu1W1qzcKzLVe+lq4w==",
+ "requires": {
+ "adler-32": "~1.2.0",
+ "cfb": "^1.1.2",
+ "codepage": "~1.14.0",
+ "commander": "~2.17.1",
+ "crc-32": "~1.2.0",
+ "exit-on-epipe": "~1.0.1",
+ "ssf": "~0.10.2"
+ }
+ }
+ }
+ },
+ "cfb": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.1.4.tgz",
+ "integrity": "sha512-rwFkl3aFO3f+ljR27YINwC0x8vPjyiEVbYbrTCKzspEf7Q++3THdfHVgJYNUbxNcupJECrLX+L40Mjm9hm/Bgw==",
+ "requires": {
+ "adler-32": "~1.2.0",
+ "commander": "^2.16.0",
+ "crc-32": "~1.2.0",
+ "printj": "~1.1.2"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+ },
+ "chrome-trace-event": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
+ "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "circular-dependency-plugin": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz",
+ "integrity": "sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw=="
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "clean-css": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
+ "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
+ "requires": {
+ "source-map": "~0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^2.0.0"
+ }
+ },
+ "cli-width": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
+ },
+ "clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "requires": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ }
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+ },
+ "codelyzer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.2.1.tgz",
+ "integrity": "sha512-awBZXFcJUyC5HMYXiHzjr3D24tww2l1D1OqtfA9vUhEtYr32a65A+Gblm/OvsO+HuKLYzn8EDMw1inSM3VbxWA==",
+ "dev": true,
+ "requires": {
+ "app-root-path": "^2.2.1",
+ "aria-query": "^3.0.0",
+ "axobject-query": "2.0.2",
+ "css-selector-tokenizer": "^0.7.1",
+ "cssauron": "^1.4.0",
+ "damerau-levenshtein": "^1.0.4",
+ "semver-dsl": "^1.0.1",
+ "source-map": "^0.5.7",
+ "sprintf-js": "^1.1.2"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "sprintf-js": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
+ "dev": true
+ }
+ }
+ },
+ "codepage": {
+ "version": "1.14.0",
+ "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz",
+ "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=",
+ "requires": {
+ "commander": "~2.14.1",
+ "exit-on-epipe": "~1.0.1"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz",
+ "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw=="
+ }
+ }
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
+ },
+ "compare-versions": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
+ "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
+ "dev": true
+ },
+ "component-bind": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
+ "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
+ },
+ "component-inherit": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
+ "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
+ "dev": true
+ },
+ "compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "requires": {
+ "mime-db": ">= 1.43.0 < 2"
+ }
+ },
+ "compression": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+ "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "requires": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.16",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "connect": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ }
+ },
+ "connect-history-api-fallback": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg=="
+ },
+ "console-browserify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
+ "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA=="
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+ },
+ "content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "convert-source-map": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
+ "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "copy-concurrently": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+ "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+ "requires": {
+ "aproba": "^1.1.1",
+ "fs-write-stream-atomic": "^1.0.8",
+ "iferr": "^0.1.5",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.0"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
+ },
+ "copy-webpack-plugin": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz",
+ "integrity": "sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg==",
+ "requires": {
+ "cacache": "^12.0.3",
+ "find-cache-dir": "^2.1.0",
+ "glob-parent": "^3.1.0",
+ "globby": "^7.1.1",
+ "is-glob": "^4.0.1",
+ "loader-utils": "^1.2.3",
+ "minimatch": "^3.0.4",
+ "normalize-path": "^3.0.0",
+ "p-limit": "^2.2.1",
+ "schema-utils": "^1.0.0",
+ "serialize-javascript": "^2.1.2",
+ "webpack-log": "^2.0.0"
+ },
+ "dependencies": {
+ "cacache": {
+ "version": "12.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+ "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "infer-owner": "^1.0.3",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "core-js": {
+ "version": "3.6.4",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz",
+ "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw=="
+ },
+ "core-js-compat": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz",
+ "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==",
+ "requires": {
+ "browserslist": "^4.8.5",
+ "semver": "7.0.0"
+ },
+ "dependencies": {
+ "browserslist": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz",
+ "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==",
+ "requires": {
+ "caniuse-lite": "^1.0.30001043",
+ "electron-to-chromium": "^1.3.413",
+ "node-releases": "^1.1.53",
+ "pkg-up": "^2.0.0"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001045",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001045.tgz",
+ "integrity": "sha512-Y8o2Iz1KPcD6FjySbk1sPpvJqchgxk/iow0DABpGyzA1UeQAuxh63Xh0Enj5/BrsYbXtCN32JmR4ZxQTCQ6E6A=="
+ },
+ "semver": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+ "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A=="
+ }
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "cosmiconfig": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "requires": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.1",
+ "parse-json": "^4.0.0"
+ }
+ },
+ "coverage-istanbul-loader": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/coverage-istanbul-loader/-/coverage-istanbul-loader-2.0.3.tgz",
+ "integrity": "sha512-LiGRvyIuzVYs3M1ZYK1tF0HekjH0DJ8zFdUwAZq378EJzqOgToyb1690dp3TAUlP6Y+82uu42LRjuROVeJ54CA==",
+ "requires": {
+ "convert-source-map": "^1.7.0",
+ "istanbul-lib-instrument": "^4.0.0",
+ "loader-utils": "^1.2.3",
+ "merge-source-map": "^1.1.0",
+ "schema-utils": "^2.6.1"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+ "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+ },
+ "schema-utils": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+ "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+ "requires": {
+ "ajv": "^6.12.0",
+ "ajv-keywords": "^3.4.1"
+ }
+ }
+ }
+ },
+ "crc-32": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz",
+ "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==",
+ "requires": {
+ "exit-on-epipe": "~1.0.1",
+ "printj": "~1.1.0"
+ }
+ },
+ "create-ecdh": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+ "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.0.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ }
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "css-parse": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz",
+ "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs="
+ },
+ "css-selector-tokenizer": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz",
+ "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^0.1.0",
+ "fastparse": "^1.1.1",
+ "regexpu-core": "^1.0.0"
+ }
+ },
+ "cssauron": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz",
+ "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=",
+ "dev": true,
+ "requires": {
+ "through": "X.X.X"
+ }
+ },
+ "cssesc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
+ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
+ "dev": true
+ },
+ "custom-event": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
+ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=",
+ "dev": true
+ },
+ "cyclist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
+ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk="
+ },
+ "damerau-levenshtein": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz",
+ "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==",
+ "dev": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "date-format": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
+ "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "debuglog": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz",
+ "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=",
+ "dev": true
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
+ },
+ "deep-equal": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
+ "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
+ "requires": {
+ "is-arguments": "^1.0.4",
+ "is-date-object": "^1.0.1",
+ "is-regex": "^1.0.4",
+ "object-is": "^1.0.1",
+ "object-keys": "^1.1.1",
+ "regexp.prototype.flags": "^1.2.0"
+ }
+ },
+ "default-gateway": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz",
+ "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==",
+ "requires": {
+ "execa": "^1.0.0",
+ "ip-regex": "^2.1.0"
+ }
+ },
+ "default-require-extensions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
+ "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
+ "dev": true,
+ "requires": {
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "del": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz",
+ "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==",
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "globby": "^6.1.0",
+ "is-path-cwd": "^2.0.0",
+ "is-path-in-cwd": "^2.0.0",
+ "p-map": "^2.0.0",
+ "pify": "^4.0.1",
+ "rimraf": "^2.6.3"
+ },
+ "dependencies": {
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "requires": {
+ "array-union": "^1.0.1",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ }
+ }
+ }
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "dependency-graph": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz",
+ "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==",
+ "dev": true
+ },
+ "des.js": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
+ "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "detect-node": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
+ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw=="
+ },
+ "dezalgo": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
+ "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
+ "dev": true,
+ "requires": {
+ "asap": "^2.0.0",
+ "wrappy": "1"
+ }
+ },
+ "di": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
+ "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=",
+ "dev": true
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "dir-glob": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+ "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+ "requires": {
+ "path-type": "^3.0.0"
+ }
+ },
+ "dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0="
+ },
+ "dns-packet": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
+ "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+ "requires": {
+ "ip": "^1.1.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "dns-txt": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
+ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "requires": {
+ "buffer-indexof": "^1.0.0"
+ }
+ },
+ "dom-serialize": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz",
+ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=",
+ "dev": true,
+ "requires": {
+ "custom-event": "~1.0.0",
+ "ent": "~2.2.0",
+ "extend": "^3.0.0",
+ "void-elements": "^2.0.0"
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="
+ },
+ "dotenv": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
+ "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
+ "dev": true
+ },
+ "duplexify": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+ "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "electron-to-chromium": {
+ "version": "1.3.414",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.414.tgz",
+ "integrity": "sha512-UfxhIvED++qLwWrAq9uYVcqF8FdeV9sU2S7qhiHYFODxzXRrd1GZRl/PjITHsTEejgibcWDraD8TQqoHb1aCBQ=="
+ },
+ "elliptic": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz",
+ "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==",
+ "requires": {
+ "bn.js": "^4.4.0",
+ "brorand": "^1.0.1",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.0"
+ }
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "~0.4.13"
+ }
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "engine.io": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
+ "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.4",
+ "base64id": "1.0.0",
+ "cookie": "0.3.1",
+ "debug": "~3.1.0",
+ "engine.io-parser": "~2.1.0",
+ "ws": "~3.3.1"
+ },
+ "dependencies": {
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "engine.io-client": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
+ "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
+ "dev": true,
+ "requires": {
+ "component-emitter": "1.2.1",
+ "component-inherit": "0.0.3",
+ "debug": "~3.1.0",
+ "engine.io-parser": "~2.1.1",
+ "has-cors": "1.1.0",
+ "indexof": "0.0.1",
+ "parseqs": "0.0.5",
+ "parseuri": "0.0.5",
+ "ws": "~3.3.1",
+ "xmlhttprequest-ssl": "~1.5.4",
+ "yeast": "0.1.2"
+ },
+ "dependencies": {
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "engine.io-parser": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
+ "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
+ "dev": true,
+ "requires": {
+ "after": "0.8.2",
+ "arraybuffer.slice": "~0.0.7",
+ "base64-arraybuffer": "0.1.5",
+ "blob": "0.0.5",
+ "has-binary2": "~1.0.2"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+ "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "ent": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz",
+ "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=",
+ "dev": true
+ },
+ "err-code": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz",
+ "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=",
+ "dev": true
+ },
+ "errno": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+ "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.17.5",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
+ "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.1.5",
+ "is-regex": "^1.0.5",
+ "object-inspect": "^1.7.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.0",
+ "string.prototype.trimleft": "^2.1.1",
+ "string.prototype.trimright": "^2.1.1"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es6-promise": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+ "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
+ "dev": true
+ },
+ "es6-promisify": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+ "dev": true,
+ "requires": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "eslint-scope": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+ "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
+ },
+ "esrecurse": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+ "requires": {
+ "estraverse": "^4.1.0"
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "eventemitter3": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz",
+ "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg=="
+ },
+ "events": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
+ "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg=="
+ },
+ "eventsource": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
+ "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
+ "requires": {
+ "original": "^1.0.0"
+ }
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true
+ },
+ "exit-on-epipe": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
+ "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+ },
+ "fastparse": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
+ "dev": true
+ },
+ "faye-websocket": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "figgy-pudding": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
+ "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w=="
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-loader": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.2.0.tgz",
+ "integrity": "sha512-+xZnaK5R8kBJrHK0/6HRlrKNamvVS5rjyuju+rnyxRGuwUJwpAMsVzUl5dz6rK8brkzjV6JpcFNjp6NqV0g1OQ==",
+ "requires": {
+ "loader-utils": "^1.2.3",
+ "schema-utils": "^2.0.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+ "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+ },
+ "schema-utils": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+ "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+ "requires": {
+ "ajv": "^6.12.0",
+ "ajv-keywords": "^3.4.1"
+ }
+ }
+ }
+ },
+ "file-saver": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz",
+ "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw=="
+ },
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "optional": true
+ },
+ "fileset": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
+ "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
+ "dev": true,
+ "requires": {
+ "glob": "^7.0.3",
+ "minimatch": "^3.0.3"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.0.0.tgz",
+ "integrity": "sha512-t7ulV1fmbxh5G9l/492O1p5+EBbr3uwpt6odhFTMc+nWyhmbloe+ja9BZ8pIBtqFWhOmCWVjx+pTW4zDkFoclw==",
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^3.0.0",
+ "pkg-dir": "^4.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "requires": {
+ "semver": "^6.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+ },
+ "pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "requires": {
+ "find-up": "^4.0.0"
+ }
+ }
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "flatted": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
+ "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
+ "dev": true
+ },
+ "flush-write-stream": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
+ "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.3.6"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.10.0.tgz",
+ "integrity": "sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ==",
+ "requires": {
+ "debug": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "font-awesome": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
+ "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ },
+ "frac": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
+ "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "fs-access": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz",
+ "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=",
+ "dev": true,
+ "requires": {
+ "null-check": "^1.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "fs-minipass": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
+ "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
+ "dev": true,
+ "requires": {
+ "minipass": "^2.6.0"
+ }
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+ "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1",
+ "node-pre-gyp": "*"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.3",
+ "bundled": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "optional": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "optional": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "3.2.6",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.7",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.6.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.3",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "bundled": true,
+ "optional": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "optional": true
+ },
+ "minipass": {
+ "version": "2.9.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.3.3",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.9.0"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "bundled": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.4.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.14.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4.4.2"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.4.7",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.8",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true,
+ "optional": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "bundled": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.13",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "genfun": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz",
+ "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==",
+ "dev": true
+ },
+ "gensync": {
+ "version": "1.0.0-beta.1",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
+ "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg=="
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
+ },
+ "globby": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+ "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+ "requires": {
+ "array-union": "^1.0.1",
+ "dir-glob": "^2.0.0",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
+ },
+ "hammerjs": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
+ "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
+ },
+ "handle-thing": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
+ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg=="
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+ },
+ "har-validator": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+ "requires": {
+ "ajv": "^6.5.5",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "has-binary2": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
+ "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
+ "dev": true,
+ "requires": {
+ "isarray": "2.0.1"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+ "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+ "dev": true
+ }
+ }
+ },
+ "has-cors": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
+ "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+ },
+ "has-symbols": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.6.tgz",
+ "integrity": "sha512-Kp6rShEsCHhF5dD3EWKdkgVA8ix90oSUJ0VY4g9goxxa0+f4lx63muTftn0mlJ/+8IESGWyKnP//V2D7S4ZbIQ==",
+ "dev": true
+ },
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "html-entities": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz",
+ "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA=="
+ },
+ "html-escaper": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz",
+ "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==",
+ "dev": true
+ },
+ "http-cache-semantics": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz",
+ "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==",
+ "dev": true
+ },
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc="
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "http-parser-js": {
+ "version": "0.4.10",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
+ "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q="
+ },
+ "http-proxy": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz",
+ "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==",
+ "requires": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "http-proxy-agent": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
+ "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
+ "dev": true,
+ "requires": {
+ "agent-base": "4",
+ "debug": "3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
+ "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==",
+ "requires": {
+ "http-proxy": "^1.17.0",
+ "is-glob": "^4.0.0",
+ "lodash": "^4.17.11",
+ "micromatch": "^3.1.10"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
+ },
+ "https-proxy-agent": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
+ "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
+ "dev": true,
+ "requires": {
+ "agent-base": "^4.3.0",
+ "debug": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
+ "dev": true,
+ "requires": {
+ "ms": "^2.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
+ },
+ "ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug=="
+ },
+ "ignore-walk": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
+ "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
+ "dev": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "image-size": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
+ "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
+ "optional": true
+ },
+ "immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
+ },
+ "import-cwd": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
+ "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
+ "requires": {
+ "import-from": "^2.1.0"
+ }
+ },
+ "import-fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+ "requires": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "import-from": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
+ "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "import-local": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+ "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+ "requires": {
+ "pkg-dir": "^3.0.0",
+ "resolve-cwd": "^2.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+ "dev": true
+ },
+ "infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz",
+ "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^3.2.0",
+ "chalk": "^2.4.2",
+ "cli-cursor": "^2.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^2.0.0",
+ "lodash": "^4.17.11",
+ "mute-stream": "0.0.7",
+ "run-async": "^2.2.0",
+ "rxjs": "^6.4.0",
+ "string-width": "^2.1.0",
+ "strip-ansi": "^5.1.0",
+ "through": "^2.3.6"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "internal-ip": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz",
+ "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==",
+ "requires": {
+ "default-gateway": "^4.2.0",
+ "ipaddr.js": "^1.9.0"
+ }
+ },
+ "interpret": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
+ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
+ "dev": true
+ },
+ "invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
+ },
+ "ip-regex": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk="
+ },
+ "ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
+ },
+ "is-absolute-url": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
+ "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q=="
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-arguments": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
+ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "is-callable": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
+ "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q=="
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
+ "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
+ }
+ }
+ },
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-path-cwd": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
+ "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ=="
+ },
+ "is-path-in-cwd": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz",
+ "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==",
+ "requires": {
+ "is-path-inside": "^2.1.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz",
+ "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==",
+ "requires": {
+ "path-is-inside": "^1.0.2"
+ }
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
+ "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+ },
+ "is-symbol": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+ "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+ "requires": {
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0="
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "isbinaryfile": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz",
+ "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==",
+ "dev": true,
+ "requires": {
+ "buffer-alloc": "^1.2.0"
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "istanbul-api": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.6.tgz",
+ "integrity": "sha512-x0Eicp6KsShG1k1rMgBAi/1GgY7kFGEBwQpw3PXGEmu+rBcBNhqU8g2DgY9mlepAsLPzrzrbqSgCGANnki4POA==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.2",
+ "compare-versions": "^3.4.0",
+ "fileset": "^2.0.3",
+ "istanbul-lib-coverage": "^2.0.5",
+ "istanbul-lib-hook": "^2.0.7",
+ "istanbul-lib-instrument": "^3.3.0",
+ "istanbul-lib-report": "^2.0.8",
+ "istanbul-lib-source-maps": "^3.0.6",
+ "istanbul-reports": "^2.2.4",
+ "js-yaml": "^3.13.1",
+ "make-dir": "^2.1.0",
+ "minimatch": "^3.0.4",
+ "once": "^1.4.0"
+ },
+ "dependencies": {
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ },
+ "istanbul-lib-instrument": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+ "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+ "dev": true,
+ "requires": {
+ "@babel/generator": "^7.4.0",
+ "@babel/parser": "^7.4.3",
+ "@babel/template": "^7.4.0",
+ "@babel/traverse": "^7.4.3",
+ "@babel/types": "^7.4.0",
+ "istanbul-lib-coverage": "^2.0.5",
+ "semver": "^6.0.0"
+ }
+ }
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz",
+ "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg=="
+ },
+ "istanbul-lib-hook": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz",
+ "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==",
+ "dev": true,
+ "requires": {
+ "append-transform": "^1.0.0"
+ }
+ },
+ "istanbul-lib-instrument": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz",
+ "integrity": "sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==",
+ "requires": {
+ "@babel/core": "^7.7.5",
+ "@babel/parser": "^7.7.5",
+ "@babel/template": "^7.7.4",
+ "@babel/traverse": "^7.7.4",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.0.0",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ }
+ }
+ },
+ "istanbul-lib-report": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz",
+ "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==",
+ "dev": true,
+ "requires": {
+ "istanbul-lib-coverage": "^2.0.5",
+ "make-dir": "^2.1.0",
+ "supports-color": "^6.1.0"
+ },
+ "dependencies": {
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ }
+ }
+ },
+ "istanbul-lib-source-maps": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz",
+ "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^2.0.5",
+ "make-dir": "^2.1.0",
+ "rimraf": "^2.6.3",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "istanbul-reports": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz",
+ "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==",
+ "dev": true,
+ "requires": {
+ "html-escaper": "^2.0.0"
+ }
+ },
+ "jasmine": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz",
+ "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=",
+ "dev": true,
+ "requires": {
+ "exit": "^0.1.2",
+ "glob": "^7.0.6",
+ "jasmine-core": "~2.8.0"
+ },
+ "dependencies": {
+ "jasmine-core": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz",
+ "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=",
+ "dev": true
+ }
+ }
+ },
+ "jasmine-core": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.4.0.tgz",
+ "integrity": "sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==",
+ "dev": true
+ },
+ "jasmine-spec-reporter": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
+ "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==",
+ "dev": true,
+ "requires": {
+ "colors": "1.1.2"
+ }
+ },
+ "jasminewd2": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz",
+ "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=",
+ "dev": true
+ },
+ "jest-worker": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz",
+ "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==",
+ "requires": {
+ "merge-stream": "^2.0.0",
+ "supports-color": "^6.1.0"
+ }
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "json3": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz",
+ "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA=="
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "jszip": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.4.0.tgz",
+ "integrity": "sha512-gZAOYuPl4EhPTXT0GjhI3o+ZAz3su6EhLrKUoAivcKqyqC7laS5JEv4XWZND9BgcDcF83vI85yGbDmDR6UhrIg==",
+ "requires": {
+ "lie": "~3.3.0",
+ "pako": "~1.0.2",
+ "readable-stream": "~2.3.6",
+ "set-immediate-shim": "~1.0.1"
+ }
+ },
+ "karma": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz",
+ "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.3.0",
+ "body-parser": "^1.16.1",
+ "braces": "^2.3.2",
+ "chokidar": "^2.0.3",
+ "colors": "^1.1.0",
+ "connect": "^3.6.0",
+ "core-js": "^2.2.0",
+ "di": "^0.0.1",
+ "dom-serialize": "^2.2.0",
+ "flatted": "^2.0.0",
+ "glob": "^7.1.1",
+ "graceful-fs": "^4.1.2",
+ "http-proxy": "^1.13.0",
+ "isbinaryfile": "^3.0.0",
+ "lodash": "^4.17.11",
+ "log4js": "^4.0.0",
+ "mime": "^2.3.1",
+ "minimatch": "^3.0.2",
+ "optimist": "^0.6.1",
+ "qjobs": "^1.1.4",
+ "range-parser": "^1.2.0",
+ "rimraf": "^2.6.0",
+ "safe-buffer": "^5.0.1",
+ "socket.io": "2.1.1",
+ "source-map": "^0.6.1",
+ "tmp": "0.0.33",
+ "useragent": "2.3.0"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
+ "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==",
+ "dev": true
+ },
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "karma-chrome-launcher": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
+ "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==",
+ "dev": true,
+ "requires": {
+ "fs-access": "^1.0.0",
+ "which": "^1.2.1"
+ }
+ },
+ "karma-coverage-istanbul-reporter": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.6.tgz",
+ "integrity": "sha512-WFh77RI8bMIKdOvI/1/IBmgnM+Q7NOLhnwG91QJrM8lW+CIXCjTzhhUsT/svLvAkLmR10uWY4RyYbHMLkTglvg==",
+ "dev": true,
+ "requires": {
+ "istanbul-api": "^2.1.6",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "karma-jasmine": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz",
+ "integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==",
+ "dev": true,
+ "requires": {
+ "jasmine-core": "^3.3"
+ }
+ },
+ "karma-jasmine-html-reporter": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.5.2.tgz",
+ "integrity": "sha512-ILBPsXqQ3eomq+oaQsM311/jxsypw5/d0LnZXj26XkfThwq7jZ55A2CFSKJVA5VekbbOGvMyv7d3juZj0SeTxA==",
+ "dev": true
+ },
+ "karma-source-map-support": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz",
+ "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==",
+ "requires": {
+ "source-map-support": "^0.5.5"
+ }
+ },
+ "killable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
+ "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg=="
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "less": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/less/-/less-3.9.0.tgz",
+ "integrity": "sha512-31CmtPEZraNUtuUREYjSqRkeETFdyEHSEPAGq4erDlUXtda7pzNmctdljdIagSb589d/qXGWiiP31R5JVf+v0w==",
+ "requires": {
+ "clone": "^2.1.2",
+ "errno": "^0.1.1",
+ "graceful-fs": "^4.1.2",
+ "image-size": "~0.5.0",
+ "mime": "^1.4.1",
+ "mkdirp": "^0.5.0",
+ "promise": "^7.1.1",
+ "request": "^2.83.0",
+ "source-map": "~0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "optional": true
+ }
+ }
+ },
+ "less-loader": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-5.0.0.tgz",
+ "integrity": "sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg==",
+ "requires": {
+ "clone": "^2.1.1",
+ "loader-utils": "^1.1.0",
+ "pify": "^4.0.1"
+ }
+ },
+ "leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="
+ },
+ "levenary": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz",
+ "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==",
+ "requires": {
+ "leven": "^3.1.0"
+ }
+ },
+ "license-webpack-plugin": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.2.tgz",
+ "integrity": "sha512-7poZHRla+ae0eEButlwMrPpkXyhNVBf2EHePYWT0jyLnI6311/OXJkTI2sOIRungRpQgU2oDMpro5bSFPT5F0A==",
+ "requires": {
+ "@types/webpack-sources": "^0.1.5",
+ "webpack-sources": "^1.2.0"
+ }
+ },
+ "lie": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+ "requires": {
+ "immediate": "~3.0.5"
+ }
+ },
+ "loader-runner": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
+ "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw=="
+ },
+ "loader-utils": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
+ "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^2.0.0",
+ "json5": "^1.0.1"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
+ },
+ "log4js": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz",
+ "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==",
+ "dev": true,
+ "requires": {
+ "date-format": "^2.0.0",
+ "debug": "^4.1.1",
+ "flatted": "^2.0.0",
+ "rfdc": "^1.1.4",
+ "streamroller": "^1.0.6"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "loglevel": {
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
+ "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA=="
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "magic-string": {
+ "version": "0.25.2",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz",
+ "integrity": "sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg==",
+ "dev": true,
+ "requires": {
+ "sourcemap-codec": "^1.4.4"
+ }
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ }
+ }
+ },
+ "make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true
+ },
+ "make-fetch-happen": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-4.0.2.tgz",
+ "integrity": "sha512-YMJrAjHSb/BordlsDEcVcPyTbiJKkzqMf48N8dAJZT9Zjctrkb6Yg4TY9Sq2AwSIQJFn5qBBKVTYt3vP5FMIHA==",
+ "dev": true,
+ "requires": {
+ "agentkeepalive": "^3.4.1",
+ "cacache": "^11.3.3",
+ "http-cache-semantics": "^3.8.1",
+ "http-proxy-agent": "^2.1.0",
+ "https-proxy-agent": "^2.2.1",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "node-fetch-npm": "^2.0.2",
+ "promise-retry": "^1.1.1",
+ "socks-proxy-agent": "^4.0.0",
+ "ssri": "^6.0.0"
+ }
+ },
+ "mamacro": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz",
+ "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA=="
+ },
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "mat-table-exporter": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/mat-table-exporter/-/mat-table-exporter-9.0.0.tgz",
+ "integrity": "sha512-xqvitbmC2dhABjVov0GACG8Nr0NmK83MB6nant4kuMIAVGc3yMZI+Q4F/hC/FHtVELwZuD+H8NFR9V/dqCAWdw==",
+ "requires": {
+ "cdk-table-exporter": "^9.0.0"
+ }
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ }
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "merge-source-map": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
+ "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
+ "requires": {
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ }
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
+ },
+ "mime-db": {
+ "version": "1.43.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
+ "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
+ },
+ "mime-types": {
+ "version": "2.1.26",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
+ "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
+ "requires": {
+ "mime-db": "1.43.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
+ },
+ "mini-css-extract-plugin": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz",
+ "integrity": "sha512-MNpRGbNA52q6U92i0qbVpQNsgk7LExy41MdAlG84FeytfDOtRIf/mCHdEgG8rpTKOaNKiqUnZdlptF469hxqOw==",
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "normalize-url": "1.9.1",
+ "schema-utils": "^1.0.0",
+ "webpack-sources": "^1.1.0"
+ }
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ },
+ "minipass": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
+ "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
+ "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
+ "dev": true,
+ "requires": {
+ "minipass": "^2.9.0"
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+ "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "requires": {
+ "minimist": "0.0.8"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ }
+ }
+ },
+ "move-concurrently": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+ "requires": {
+ "aproba": "^1.1.1",
+ "copy-concurrently": "^1.0.0",
+ "fs-write-stream-atomic": "^1.0.8",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.3"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "multicast-dns": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
+ "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "requires": {
+ "dns-packet": "^1.3.1",
+ "thunky": "^1.0.2"
+ }
+ },
+ "multicast-dns-service-types": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
+ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+ },
+ "neo-async": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
+ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw=="
+ },
+ "ng4-loading-spinner": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/ng4-loading-spinner/-/ng4-loading-spinner-1.2.3.tgz",
+ "integrity": "sha512-AxokaWmIMSv4YeZcwzSCs0f1PBnn/lgOVpaXuR5PdnNqGkpDema6b2KwONLtdzmL5YqKOpQo8DoyTRhlzGoohQ=="
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
+ },
+ "node-fetch-npm": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz",
+ "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==",
+ "dev": true,
+ "requires": {
+ "encoding": "^0.1.11",
+ "json-parse-better-errors": "^1.0.0",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node-forge": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
+ "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ=="
+ },
+ "node-libs-browser": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
+ "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==",
+ "requires": {
+ "assert": "^1.1.1",
+ "browserify-zlib": "^0.2.0",
+ "buffer": "^4.3.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "^1.0.0",
+ "crypto-browserify": "^3.11.0",
+ "domain-browser": "^1.1.1",
+ "events": "^3.0.0",
+ "https-browserify": "^1.0.0",
+ "os-browserify": "^0.3.0",
+ "path-browserify": "0.0.1",
+ "process": "^0.11.10",
+ "punycode": "^1.2.4",
+ "querystring-es3": "^0.2.0",
+ "readable-stream": "^2.3.3",
+ "stream-browserify": "^2.0.1",
+ "stream-http": "^2.7.2",
+ "string_decoder": "^1.0.0",
+ "timers-browserify": "^2.0.4",
+ "tty-browserify": "0.0.0",
+ "url": "^0.11.0",
+ "util": "^0.11.0",
+ "vm-browserify": "^1.0.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ }
+ }
+ },
+ "node-releases": {
+ "version": "1.1.53",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz",
+ "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ=="
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+ },
+ "normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI="
+ },
+ "normalize-url": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz",
+ "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=",
+ "requires": {
+ "object-assign": "^4.0.1",
+ "prepend-http": "^1.0.0",
+ "query-string": "^4.1.0",
+ "sort-keys": "^1.0.0"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
+ "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
+ "dev": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
+ "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
+ "dev": true
+ },
+ "npm-package-arg": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz",
+ "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.6.0",
+ "osenv": "^0.1.5",
+ "semver": "^5.5.0",
+ "validate-npm-package-name": "^3.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "npm-packlist": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
+ "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
+ "dev": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1",
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-pick-manifest": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz",
+ "integrity": "sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1",
+ "npm-package-arg": "^6.0.0",
+ "semver": "^5.4.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "npm-registry-fetch": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-3.9.1.tgz",
+ "integrity": "sha512-VQCEZlydXw4AwLROAXWUR7QDfe2Y8Id/vpAgp6TI1/H78a4SiQ1kQrKZALm5/zxM5n4HIi+aYb+idUAV/RuY0Q==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.3.4",
+ "bluebird": "^3.5.1",
+ "figgy-pudding": "^3.4.1",
+ "lru-cache": "^5.1.1",
+ "make-fetch-happen": "^4.0.2",
+ "npm-package-arg": "^6.1.0"
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "null-check": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz",
+ "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=",
+ "dev": true
+ },
+ "num2fraction": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
+ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4="
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-component": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
+ "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
+ "dev": true
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
+ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
+ },
+ "object-is": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz",
+ "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ },
+ "dependencies": {
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "dev": true
+ }
+ }
+ },
+ "open": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-6.2.0.tgz",
+ "integrity": "sha512-Vxf6HJkwrqmvh9UAID3MnMYXntbTxKLOSfOnO7LJdzPf3NE3KQYFNV0/Lcz2VAndbRFil58XVCyh8tiX11fiYw==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "opn": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
+ "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==",
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "optimist": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+ "dev": true,
+ "requires": {
+ "minimist": "~0.0.1",
+ "wordwrap": "~0.0.2"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+ "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+ "dev": true
+ }
+ }
+ },
+ "original": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
+ "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
+ "requires": {
+ "url-parse": "^1.4.3"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+ "dev": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+ },
+ "p-is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
+ },
+ "p-limit": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+ "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-map": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
+ "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="
+ },
+ "p-retry": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz",
+ "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==",
+ "requires": {
+ "retry": "^0.12.0"
+ },
+ "dependencies": {
+ "retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
+ }
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+ },
+ "pacote": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.0.tgz",
+ "integrity": "sha512-aUplXozRbzhaJO48FaaeClmN+2Mwt741MC6M3bevIGZwdCaP7frXzbUOfOWa91FPHoLITzG0hYaKY363lxO3bg==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.3",
+ "cacache": "^11.3.2",
+ "figgy-pudding": "^3.5.1",
+ "get-stream": "^4.1.0",
+ "glob": "^7.1.3",
+ "lru-cache": "^5.1.1",
+ "make-fetch-happen": "^4.0.1",
+ "minimatch": "^3.0.4",
+ "minipass": "^2.3.5",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "normalize-package-data": "^2.4.0",
+ "npm-package-arg": "^6.1.0",
+ "npm-packlist": "^1.1.12",
+ "npm-pick-manifest": "^2.2.3",
+ "npm-registry-fetch": "^3.8.0",
+ "osenv": "^0.1.5",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^1.1.1",
+ "protoduck": "^5.0.1",
+ "rimraf": "^2.6.2",
+ "safe-buffer": "^5.1.2",
+ "semver": "^5.6.0",
+ "ssri": "^6.0.1",
+ "tar": "^4.4.8",
+ "unique-filename": "^1.1.1",
+ "which": "^1.3.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
+ },
+ "parallel-transform": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
+ "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
+ "requires": {
+ "cyclist": "^1.0.1",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.1.5"
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
+ "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
+ "requires": {
+ "asn1.js": "^4.0.0",
+ "browserify-aes": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "parse5": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
+ "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA=="
+ },
+ "parseqs": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
+ "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
+ "dev": true,
+ "requires": {
+ "better-assert": "~1.0.0"
+ }
+ },
+ "parseuri": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
+ "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
+ "dev": true,
+ "requires": {
+ "better-assert": "~1.0.0"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
+ },
+ "path-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ=="
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "requires": {
+ "pify": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+ }
+ }
+ },
+ "pbkdf2": {
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
+ "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "requires": {
+ "find-up": "^3.0.0"
+ }
+ },
+ "pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
+ "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
+ "requires": {
+ "find-up": "^2.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
+ }
+ }
+ },
+ "portfinder": {
+ "version": "1.0.25",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
+ "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==",
+ "requires": {
+ "async": "^2.6.2",
+ "debug": "^3.1.1",
+ "mkdirp": "^0.5.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
+ },
+ "postcss": {
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "postcss-import": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz",
+ "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==",
+ "requires": {
+ "postcss": "^7.0.1",
+ "postcss-value-parser": "^3.2.3",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "dependencies": {
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ=="
+ }
+ }
+ },
+ "postcss-load-config": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz",
+ "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==",
+ "requires": {
+ "cosmiconfig": "^5.0.0",
+ "import-cwd": "^2.0.0"
+ }
+ },
+ "postcss-loader": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz",
+ "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==",
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "postcss": "^7.0.0",
+ "postcss-load-config": "^2.0.0",
+ "schema-utils": "^1.0.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz",
+ "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg=="
+ },
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
+ },
+ "primeicons": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-2.0.0.tgz",
+ "integrity": "sha512-GJTCeMSQU8UU1GqbsaDrg/IH+b/vSinJQl52NVpdJ7sShYLZA8Eq6jLF48Ye3N/dQloGrE07i7XsZvxQ9pNbqg=="
+ },
+ "primeng": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/primeng/-/primeng-8.1.1.tgz",
+ "integrity": "sha512-8dP8A3qkmOvDTe97kCeFvoCk6oPNDdgMTdT4UBzhC4ua5wM7i7pjYXuKzAXm3oEFf+iSEB6WqzzfSqyZdbEA+w=="
+ },
+ "printj": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
+ "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
+ },
+ "private": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "optional": true,
+ "requires": {
+ "asap": "~2.0.3"
+ }
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
+ },
+ "promise-retry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz",
+ "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=",
+ "dev": true,
+ "requires": {
+ "err-code": "^1.0.0",
+ "retry": "^0.10.0"
+ }
+ },
+ "protoduck": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz",
+ "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==",
+ "dev": true,
+ "requires": {
+ "genfun": "^5.0.0"
+ }
+ },
+ "protractor": {
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.3.tgz",
+ "integrity": "sha512-7pMAolv8Ah1yJIqaorDTzACtn3gk7BamVKPTeO5lqIGOrfosjPgXFx/z1dqSI+m5EeZc2GMJHPr5DYlodujDNA==",
+ "dev": true,
+ "requires": {
+ "@types/q": "^0.0.32",
+ "@types/selenium-webdriver": "^3.0.0",
+ "blocking-proxy": "^1.0.0",
+ "browserstack": "^1.5.1",
+ "chalk": "^1.1.3",
+ "glob": "^7.0.3",
+ "jasmine": "2.8.0",
+ "jasminewd2": "^2.1.0",
+ "optimist": "~0.6.0",
+ "q": "1.4.1",
+ "saucelabs": "^1.5.0",
+ "selenium-webdriver": "3.6.0",
+ "source-map-support": "~0.4.0",
+ "webdriver-js-extender": "2.1.0",
+ "webdriver-manager": "^12.0.6"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "del": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+ "dev": true,
+ "requires": {
+ "globby": "^5.0.0",
+ "is-path-cwd": "^1.0.0",
+ "is-path-in-cwd": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "arrify": "^1.0.0",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.4.18",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
+ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
+ "dev": true,
+ "requires": {
+ "source-map": "^0.5.6"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "webdriver-manager": {
+ "version": "12.1.7",
+ "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.7.tgz",
+ "integrity": "sha512-XINj6b8CYuUYC93SG3xPkxlyUc3IJbD6Vvo75CVGuG9uzsefDzWQrhz0Lq8vbPxtb4d63CZdYophF8k8Or/YiA==",
+ "dev": true,
+ "requires": {
+ "adm-zip": "^0.4.9",
+ "chalk": "^1.1.1",
+ "del": "^2.2.0",
+ "glob": "^7.0.3",
+ "ini": "^1.3.4",
+ "minimist": "^1.2.0",
+ "q": "^1.4.1",
+ "request": "^2.87.0",
+ "rimraf": "^2.5.2",
+ "semver": "^5.3.0",
+ "xml2js": "^0.4.17"
+ }
+ }
+ }
+ },
+ "proxy-addr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
+ "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.1"
+ }
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "psl": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
+ "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ=="
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ },
+ "dependencies": {
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+ },
+ "q": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
+ "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
+ "dev": true
+ },
+ "qjobs": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz",
+ "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+ },
+ "query-string": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
+ "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
+ "requires": {
+ "object-assign": "^4.1.0",
+ "strict-uri-encode": "^1.0.0"
+ }
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+ },
+ "querystringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
+ "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA=="
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+ }
+ }
+ },
+ "raw-loader": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-3.1.0.tgz",
+ "integrity": "sha512-lzUVMuJ06HF4rYveaz9Tv0WRlUMxJ0Y1hgSkkgg+50iEdaI0TthyEDe08KIHb0XsF6rn8WYTqPCaGTZg3sX+qA==",
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "schema-utils": "^2.0.1"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+ "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+ },
+ "schema-utils": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+ "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+ "requires": {
+ "ajv": "^6.12.0",
+ "ajv-keywords": "^3.4.1"
+ }
+ }
+ }
+ },
+ "read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
+ "requires": {
+ "pify": "^2.3.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ }
+ }
+ },
+ "read-package-json": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.1.tgz",
+ "integrity": "sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.1",
+ "graceful-fs": "^4.1.2",
+ "json-parse-better-errors": "^1.0.1",
+ "normalize-package-data": "^2.0.0",
+ "npm-normalize-package-bin": "^1.0.0"
+ }
+ },
+ "read-package-tree": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.2.2.tgz",
+ "integrity": "sha512-rW3XWUUkhdKmN2JKB4FL563YAgtINifso5KShykufR03nJ5loGFlkUMe1g/yxmqX073SoYYTsgXu7XdDinKZuA==",
+ "dev": true,
+ "requires": {
+ "debuglog": "^1.0.1",
+ "dezalgo": "^1.0.0",
+ "once": "^1.3.0",
+ "read-package-json": "^2.0.0",
+ "readdir-scoped-modules": "^1.0.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdir-scoped-modules": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz",
+ "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==",
+ "dev": true,
+ "requires": {
+ "debuglog": "^1.0.1",
+ "dezalgo": "^1.0.0",
+ "graceful-fs": "^4.1.2",
+ "once": "^1.3.0"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+ "dev": true,
+ "requires": {
+ "resolve": "^1.1.6"
+ }
+ },
+ "reflect-metadata": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
+ "dev": true
+ },
+ "regenerate": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
+ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg=="
+ },
+ "regenerate-unicode-properties": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz",
+ "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==",
+ "requires": {
+ "regenerate": "^1.4.0"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+ "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
+ },
+ "regenerator-transform": {
+ "version": "0.14.4",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz",
+ "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==",
+ "requires": {
+ "@babel/runtime": "^7.8.4",
+ "private": "^0.1.8"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexp.prototype.flags": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
+ "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1"
+ }
+ },
+ "regexpu-core": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
+ "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.2.1",
+ "regjsgen": "^0.2.0",
+ "regjsparser": "^0.1.4"
+ }
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "requires": {
+ "jsesc": "~0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ }
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g=="
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
+ },
+ "request": {
+ "version": "2.88.2",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+ "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.3",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
+ },
+ "resolve": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
+ "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==",
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "dev": true,
+ "requires": {
+ "onetime": "^2.0.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
+ },
+ "retry": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
+ "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=",
+ "dev": true
+ },
+ "rfdc": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
+ "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "run-async": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz",
+ "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==",
+ "dev": true,
+ "requires": {
+ "is-promise": "^2.1.0"
+ }
+ },
+ "run-queue": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+ "requires": {
+ "aproba": "^1.1.1"
+ }
+ },
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "sass": {
+ "version": "1.22.9",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.22.9.tgz",
+ "integrity": "sha512-FzU1X2V8DlnqabrL4u7OBwD2vcOzNMongEJEx3xMEhWY/v26FFR3aG0hyeu2T965sfR0E9ufJwmG+Qjz78vFPQ==",
+ "requires": {
+ "chokidar": ">=2.0.0 <4.0.0"
+ }
+ },
+ "sass-loader": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.2.0.tgz",
+ "integrity": "sha512-h8yUWaWtsbuIiOCgR9fd9c2lRXZ2uG+h8Dzg/AGNj+Hg/3TO8+BBAW9mEP+mh8ei+qBKqSJ0F1FLlYjNBc61OA==",
+ "requires": {
+ "clone-deep": "^4.0.1",
+ "loader-utils": "^1.0.1",
+ "neo-async": "^2.5.0",
+ "pify": "^4.0.1",
+ "semver": "^5.5.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ }
+ }
+ },
+ "saucelabs": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz",
+ "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==",
+ "dev": true,
+ "requires": {
+ "https-proxy-agent": "^2.2.1"
+ }
+ },
+ "sax": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
+ "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE="
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
+ },
+ "selenium-webdriver": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz",
+ "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==",
+ "dev": true,
+ "requires": {
+ "jszip": "^3.1.3",
+ "rimraf": "^2.5.4",
+ "tmp": "0.0.30",
+ "xml2js": "^0.4.17"
+ },
+ "dependencies": {
+ "tmp": {
+ "version": "0.0.30",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz",
+ "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.1"
+ }
+ }
+ }
+ },
+ "selfsigned": {
+ "version": "1.10.7",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
+ "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
+ "requires": {
+ "node-forge": "0.9.0"
+ }
+ },
+ "semver": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz",
+ "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ=="
+ },
+ "semver-dsl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz",
+ "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=",
+ "dev": true,
+ "requires": {
+ "semver": "^5.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "semver-intersect": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz",
+ "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^5.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
+ "serialize-javascript": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
+ "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ=="
+ },
+ "serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+ "requires": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "dependencies": {
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "set-immediate-shim": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "requires": {
+ "kind-of": "^6.0.2"
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+ },
+ "shelljs": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz",
+ "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="
+ },
+ "smart-buffer": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz",
+ "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==",
+ "dev": true
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "socket.io": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz",
+ "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==",
+ "dev": true,
+ "requires": {
+ "debug": "~3.1.0",
+ "engine.io": "~3.2.0",
+ "has-binary2": "~1.0.2",
+ "socket.io-adapter": "~1.1.0",
+ "socket.io-client": "2.1.1",
+ "socket.io-parser": "~3.2.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "socket.io-adapter": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz",
+ "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==",
+ "dev": true
+ },
+ "socket.io-client": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz",
+ "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==",
+ "dev": true,
+ "requires": {
+ "backo2": "1.0.2",
+ "base64-arraybuffer": "0.1.5",
+ "component-bind": "1.0.0",
+ "component-emitter": "1.2.1",
+ "debug": "~3.1.0",
+ "engine.io-client": "~3.2.0",
+ "has-binary2": "~1.0.2",
+ "has-cors": "1.1.0",
+ "indexof": "0.0.1",
+ "object-component": "0.0.3",
+ "parseqs": "0.0.5",
+ "parseuri": "0.0.5",
+ "socket.io-parser": "~3.2.0",
+ "to-array": "0.1.4"
+ },
+ "dependencies": {
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "socket.io-parser": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz",
+ "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==",
+ "dev": true,
+ "requires": {
+ "component-emitter": "1.2.1",
+ "debug": "~3.1.0",
+ "isarray": "2.0.1"
+ },
+ "dependencies": {
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "isarray": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+ "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+ "dev": true
+ }
+ }
+ },
+ "sockjs": {
+ "version": "0.3.19",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
+ "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==",
+ "requires": {
+ "faye-websocket": "^0.10.0",
+ "uuid": "^3.0.1"
+ }
+ },
+ "sockjs-client": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz",
+ "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==",
+ "requires": {
+ "debug": "^3.2.5",
+ "eventsource": "^1.0.7",
+ "faye-websocket": "~0.11.1",
+ "inherits": "^2.0.3",
+ "json3": "^3.3.2",
+ "url-parse": "^1.4.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
+ "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "socks": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz",
+ "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==",
+ "dev": true,
+ "requires": {
+ "ip": "1.1.5",
+ "smart-buffer": "^4.1.0"
+ }
+ },
+ "socks-proxy-agent": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz",
+ "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==",
+ "dev": true,
+ "requires": {
+ "agent-base": "~4.2.1",
+ "socks": "~2.3.2"
+ },
+ "dependencies": {
+ "agent-base": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+ "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+ "dev": true,
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ }
+ }
+ },
+ "sort-keys": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
+ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
+ "requires": {
+ "is-plain-obj": "^1.0.0"
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+ "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw=="
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
+ },
+ "source-map-loader": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz",
+ "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==",
+ "requires": {
+ "async": "^2.5.0",
+ "loader-utils": "^1.1.0"
+ }
+ },
+ "source-map-resolve": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
+ "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+ "requires": {
+ "atob": "^2.1.2",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-support": {
+ "version": "0.5.12",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz",
+ "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
+ },
+ "sourcemap-codec": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
+ },
+ "spdx-correct": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+ "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+ "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "dev": true
+ },
+ "spdy": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
+ "requires": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "requires": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "speed-measure-webpack-plugin": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.1.tgz",
+ "integrity": "sha512-qVIkJvbtS9j/UeZumbdfz0vg+QfG/zxonAjzefZrqzkr7xOncLVXkeGbTpzd1gjCBM4PmVNkWlkeTVhgskAGSQ==",
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
+ "ssf": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.3.tgz",
+ "integrity": "sha512-pRuUdW0WwyB2doSqqjWyzwCD6PkfxpHAHdZp39K3dp/Hq7f+xfMwNAWIi16DyrRg4gg9c/RvLYkJTSawTPTm1w==",
+ "requires": {
+ "frac": "~1.1.2"
+ }
+ },
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+ "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+ },
+ "stream-browserify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+ "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-each": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
+ "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "stream-http": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+ "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.6",
+ "to-arraybuffer": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
+ "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
+ },
+ "streamroller": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz",
+ "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.2",
+ "date-format": "^2.0.0",
+ "debug": "^3.2.6",
+ "fs-extra": "^7.0.1",
+ "lodash": "^4.17.14"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "strict-uri-encode": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
+ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
+ "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "string.prototype.trimleft": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
+ "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5",
+ "string.prototype.trimstart": "^1.0.0"
+ }
+ },
+ "string.prototype.trimright": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
+ "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5",
+ "string.prototype.trimend": "^1.0.0"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
+ "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
+ },
+ "style-loader": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.0.0.tgz",
+ "integrity": "sha512-B0dOCFwv7/eY31a5PCieNwMgMhVGFe9w+rh7s/Bx8kfFkrth9zfTZquoYvdw8URgiqxObQKcpW51Ugz1HjfdZw==",
+ "requires": {
+ "loader-utils": "^1.2.3",
+ "schema-utils": "^2.0.1"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+ "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+ },
+ "schema-utils": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+ "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+ "requires": {
+ "ajv": "^6.12.0",
+ "ajv-keywords": "^3.4.1"
+ }
+ }
+ }
+ },
+ "stylus": {
+ "version": "0.54.5",
+ "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz",
+ "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=",
+ "requires": {
+ "css-parse": "1.7.x",
+ "debug": "*",
+ "glob": "7.0.x",
+ "mkdirp": "0.5.x",
+ "sax": "0.5.x",
+ "source-map": "0.1.x"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.2",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.1.43",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
+ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
+ "stylus-loader": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz",
+ "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==",
+ "requires": {
+ "loader-utils": "^1.0.2",
+ "lodash.clonedeep": "^4.5.0",
+ "when": "~3.6.x"
+ }
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "symbol-observable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
+ "dev": true
+ },
+ "tapable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA=="
+ },
+ "tar": {
+ "version": "4.4.13",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
+ "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
+ "dev": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "terser": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz",
+ "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==",
+ "requires": {
+ "commander": "^2.20.0",
+ "source-map": "~0.6.1",
+ "source-map-support": "~0.5.12"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "terser-webpack-plugin": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz",
+ "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==",
+ "requires": {
+ "cacache": "^12.0.2",
+ "find-cache-dir": "^2.1.0",
+ "is-wsl": "^1.1.0",
+ "schema-utils": "^1.0.0",
+ "serialize-javascript": "^2.1.2",
+ "source-map": "^0.6.1",
+ "terser": "^4.1.2",
+ "webpack-sources": "^1.4.0",
+ "worker-farm": "^1.7.0"
+ },
+ "dependencies": {
+ "cacache": {
+ "version": "12.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+ "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "infer-owner": "^1.0.3",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "thunky": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
+ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="
+ },
+ "timers-browserify": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz",
+ "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==",
+ "requires": {
+ "setimmediate": "^1.0.4"
+ }
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "to-array": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
+ "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
+ "dev": true
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+ },
+ "tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "requires": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ }
+ },
+ "tree-kill": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="
+ },
+ "ts-node": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz",
+ "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.0",
+ "buffer-from": "^1.1.0",
+ "diff": "^3.1.0",
+ "make-error": "^1.1.1",
+ "minimist": "^1.2.0",
+ "mkdirp": "^0.5.1",
+ "source-map-support": "^0.5.6",
+ "yn": "^2.0.0"
+ }
+ },
+ "tslib": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz",
+ "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg=="
+ },
+ "tslint": {
+ "version": "5.15.0",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.15.0.tgz",
+ "integrity": "sha512-6bIEujKR21/3nyeoX2uBnE8s+tMXCQXhqMmaIPJpHmXJoBJPTLcI7/VHRtUwMhnLVdwLqqY3zmd8Dxqa5CVdJA==",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "^6.22.0",
+ "builtin-modules": "^1.1.1",
+ "chalk": "^2.3.0",
+ "commander": "^2.12.1",
+ "diff": "^3.2.0",
+ "glob": "^7.1.1",
+ "js-yaml": "^3.13.0",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "resolve": "^1.3.2",
+ "semver": "^5.3.0",
+ "tslib": "^1.8.0",
+ "tsutils": "^2.29.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "tsutils": {
+ "version": "2.29.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+ "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+ },
+ "typescript": {
+ "version": "3.4.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz",
+ "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==",
+ "dev": true
+ },
+ "ultron": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
+ "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==",
+ "dev": true
+ },
+ "unicode-canonical-property-names-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
+ "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ=="
+ },
+ "unicode-match-property-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz",
+ "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==",
+ "requires": {
+ "unicode-canonical-property-names-ecmascript": "^1.0.4",
+ "unicode-property-aliases-ecmascript": "^1.0.4"
+ }
+ },
+ "unicode-match-property-value-ecmascript": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz",
+ "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ=="
+ },
+ "unicode-property-aliases-ecmascript": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz",
+ "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg=="
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "universal-analytics": {
+ "version": "0.4.20",
+ "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.20.tgz",
+ "integrity": "sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.0.0",
+ "request": "^2.88.0",
+ "uuid": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
+ }
+ }
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg=="
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ }
+ }
+ },
+ "url-parse": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
+ "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
+ "requires": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
+ },
+ "useragent": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
+ "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "4.1.x",
+ "tmp": "0.0.x"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+ },
+ "util": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
+ "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
+ "requires": {
+ "inherits": "2.0.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
+ "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
+ "dev": true,
+ "requires": {
+ "builtins": "^1.0.3"
+ }
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "vm-browserify": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
+ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
+ },
+ "void-elements": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
+ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
+ "dev": true
+ },
+ "watchpack": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz",
+ "integrity": "sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA==",
+ "requires": {
+ "chokidar": "^2.1.8",
+ "graceful-fs": "^4.1.2",
+ "neo-async": "^2.5.0"
+ }
+ },
+ "wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "requires": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "webdriver-js-extender": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz",
+ "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==",
+ "dev": true,
+ "requires": {
+ "@types/selenium-webdriver": "^3.0.0",
+ "selenium-webdriver": "^3.0.1"
+ }
+ },
+ "webpack": {
+ "version": "4.39.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.39.2.tgz",
+ "integrity": "sha512-AKgTfz3xPSsEibH00JfZ9sHXGUwIQ6eZ9tLN8+VLzachk1Cw2LVmy+4R7ZiwTa9cZZ15tzySjeMui/UnSCAZhA==",
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-module-context": "1.8.5",
+ "@webassemblyjs/wasm-edit": "1.8.5",
+ "@webassemblyjs/wasm-parser": "1.8.5",
+ "acorn": "^6.2.1",
+ "ajv": "^6.10.2",
+ "ajv-keywords": "^3.4.1",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^4.1.0",
+ "eslint-scope": "^4.0.3",
+ "json-parse-better-errors": "^1.0.2",
+ "loader-runner": "^2.4.0",
+ "loader-utils": "^1.2.3",
+ "memory-fs": "^0.4.1",
+ "micromatch": "^3.1.10",
+ "mkdirp": "^0.5.1",
+ "neo-async": "^2.6.1",
+ "node-libs-browser": "^2.2.1",
+ "schema-utils": "^1.0.0",
+ "tapable": "^1.1.3",
+ "terser-webpack-plugin": "^1.4.1",
+ "watchpack": "^1.6.0",
+ "webpack-sources": "^1.4.1"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+ "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
+ }
+ }
+ },
+ "webpack-core": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz",
+ "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=",
+ "requires": {
+ "source-list-map": "~0.1.7",
+ "source-map": "~0.4.1"
+ },
+ "dependencies": {
+ "source-list-map": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz",
+ "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY="
+ },
+ "source-map": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz",
+ "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==",
+ "requires": {
+ "memory-fs": "^0.4.1",
+ "mime": "^2.4.4",
+ "mkdirp": "^0.5.1",
+ "range-parser": "^1.2.1",
+ "webpack-log": "^2.0.0"
+ },
+ "dependencies": {
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
+ }
+ }
+ },
+ "webpack-dev-server": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.9.0.tgz",
+ "integrity": "sha512-E6uQ4kRrTX9URN9s/lIbqTAztwEPdvzVrcmHE8EQ9YnuT9J8Es5Wrd8n9BKg1a0oZ5EgEke/EQFgUsp18dSTBw==",
+ "requires": {
+ "ansi-html": "0.0.7",
+ "bonjour": "^3.5.0",
+ "chokidar": "^2.1.8",
+ "compression": "^1.7.4",
+ "connect-history-api-fallback": "^1.6.0",
+ "debug": "^4.1.1",
+ "del": "^4.1.1",
+ "express": "^4.17.1",
+ "html-entities": "^1.2.1",
+ "http-proxy-middleware": "0.19.1",
+ "import-local": "^2.0.0",
+ "internal-ip": "^4.3.0",
+ "ip": "^1.1.5",
+ "is-absolute-url": "^3.0.3",
+ "killable": "^1.0.1",
+ "loglevel": "^1.6.4",
+ "opn": "^5.5.0",
+ "p-retry": "^3.0.1",
+ "portfinder": "^1.0.25",
+ "schema-utils": "^1.0.0",
+ "selfsigned": "^1.10.7",
+ "semver": "^6.3.0",
+ "serve-index": "^1.9.1",
+ "sockjs": "0.3.19",
+ "sockjs-client": "1.4.0",
+ "spdy": "^4.0.1",
+ "strip-ansi": "^3.0.1",
+ "supports-color": "^6.1.0",
+ "url": "^0.11.0",
+ "webpack-dev-middleware": "^3.7.2",
+ "webpack-log": "^2.0.0",
+ "ws": "^6.2.1",
+ "yargs": "12.0.5"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ },
+ "ws": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
+ "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ }
+ }
+ },
+ "webpack-log": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
+ "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
+ "requires": {
+ "ansi-colors": "^3.0.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "webpack-merge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz",
+ "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.15"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
+ "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
+ "webpack-subresource-integrity": {
+ "version": "1.1.0-rc.6",
+ "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.1.0-rc.6.tgz",
+ "integrity": "sha512-Az7y8xTniNhaA0620AV1KPwWOqawurVVDzQSpPAeR5RwNbL91GoBSJAAo9cfd+GiFHwsS5bbHepBw1e6Hzxy4w==",
+ "requires": {
+ "webpack-core": "^0.6.8"
+ }
+ },
+ "websocket-driver": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
+ "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
+ "requires": {
+ "http-parser-js": ">=0.4.0 <0.4.11",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
+ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg=="
+ },
+ "when": {
+ "version": "3.6.4",
+ "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz",
+ "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404="
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+ },
+ "wmf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
+ "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
+ },
+ "wordwrap": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+ "dev": true
+ },
+ "worker-farm": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+ "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+ "requires": {
+ "errno": "~0.1.7"
+ }
+ },
+ "worker-plugin": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-3.2.0.tgz",
+ "integrity": "sha512-W5nRkw7+HlbsEt3qRP6MczwDDISjiRj2GYt9+bpe8A2La00TmJdwzG5bpdMXhRt1qcWmwAvl1TiKaHRa+XDS9Q==",
+ "requires": {
+ "loader-utils": "^1.1.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "ws": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
+ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
+ "dev": true,
+ "requires": {
+ "async-limiter": "~1.0.0",
+ "safe-buffer": "~5.1.0",
+ "ultron": "~1.1.0"
+ }
+ },
+ "xlsx": {
+ "version": "0.15.6",
+ "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.15.6.tgz",
+ "integrity": "sha512-7vD9eutyLs65iDjNFimVN+gk/oDkfkCgpQUjdE82QgzJCrBHC4bGPH7fzKVyy0UPp3gyFVQTQEFJaWaAvZCShQ==",
+ "requires": {
+ "adler-32": "~1.2.0",
+ "cfb": "^1.1.4",
+ "codepage": "~1.14.0",
+ "commander": "~2.17.1",
+ "crc-32": "~1.2.0",
+ "exit-on-epipe": "~1.0.1",
+ "ssf": "~0.10.3",
+ "wmf": "~1.0.1"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.17.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
+ }
+ }
+ },
+ "xml2js": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
+ "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
+ "dev": true,
+ "requires": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "dependencies": {
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ }
+ }
+ },
+ "xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "dev": true
+ },
+ "xmlhttprequest-ssl": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
+ "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
+ "dev": true
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ },
+ "yargs": {
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^11.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ },
+ "yeast": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
+ "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
+ "dev": true
+ },
+ "yn": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz",
+ "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=",
+ "dev": true
+ },
+ "zone.js": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.9.1.tgz",
+ "integrity": "sha512-GkPiJL8jifSrKReKaTZ5jkhrMEgXbXYC+IPo1iquBjayRa0q86w3Dipjn8b415jpitMExe9lV8iTsv8tk3DGag=="
+ }
+ }
+}
diff --git a/mod2/ui/package.json b/mod2/ui/package.json
new file mode 100644
index 0000000..315ac39
--- /dev/null
+++ b/mod2/ui/package.json
@@ -0,0 +1,64 @@
+{
+ "name": "dcae-mod-fe",
+ "version": "0.0.0",
+ "scripts": {
+ "ng": "ng",
+ "start": "ng serve --proxy-config proxy.conf.json",
+ "build": "ng build",
+ "test": "ng test",
+ "lint": "ng lint",
+ "e2e": "ng e2e"
+ },
+ "private": true,
+ "dependencies": {
+ "@angular-devkit/build-angular": "^0.803.24",
+ "@angular/animations": "~8.0.0",
+ "@angular/cdk": "~8.2.3",
+ "@angular/common": "~8.0.0",
+ "@angular/compiler": "~8.0.0",
+ "@angular/core": "~8.0.0",
+ "@angular/forms": "~8.0.0",
+ "@angular/material": "^8.2.3",
+ "@angular/platform-browser": "~8.0.0",
+ "@angular/platform-browser-dynamic": "~8.0.0",
+ "@angular/router": "~8.0.0",
+ "@auth0/angular-jwt": "^4.0.0",
+ "@fortawesome/fontawesome-free": "^5.13.0",
+ "bootstrap": "^4.4.1",
+ "font-awesome": "^4.7.0",
+ "hammerjs": "^2.0.8",
+ "jszip": "^3.4.0",
+ "mat-table-exporter": "^9.0.0",
+ "ng4-loading-spinner": "^1.2.3",
+ "primeicons": "^2.0.0",
+ "primeng": "^8.0.0-rc.1",
+ "rxjs": "~6.4.0",
+ "tslib": "^1.9.0",
+ "xlsx": "^0.15.6",
+ "zone.js": "~0.9.1"
+ },
+ "devDependencies": {
+ "@angular-builders/custom-webpack": "^8.4.1",
+ "@angular-builders/dev-server": "^7.3.1",
+ "@angular/cli": "~8.0.1",
+ "@angular/compiler-cli": "~8.0.0",
+ "@angular/language-service": "~8.0.0",
+ "@babel/compat-data": "7.8.0",
+ "@types/jasmine": "~3.3.8",
+ "@types/jasminewd2": "~2.0.3",
+ "@types/node": "^8.9.5",
+ "codelyzer": "^5.0.0",
+ "dotenv": "^8.2.0",
+ "jasmine-core": "~3.4.0",
+ "jasmine-spec-reporter": "~4.2.1",
+ "karma": "~4.1.0",
+ "karma-chrome-launcher": "~2.2.0",
+ "karma-coverage-istanbul-reporter": "~2.0.1",
+ "karma-jasmine": "~2.0.1",
+ "karma-jasmine-html-reporter": "^1.4.0",
+ "protractor": "~5.4.0",
+ "ts-node": "~7.0.0",
+ "tslint": "~5.15.0",
+ "typescript": "~3.4.3"
+ }
+}
diff --git a/mod2/ui/pipelineConfig.json b/mod2/ui/pipelineConfig.json
new file mode 100644
index 0000000..2a1b18b
--- /dev/null
+++ b/mod2/ui/pipelineConfig.json
@@ -0,0 +1,21 @@
+{
+ "release": "3.1.3",
+ "blueprintRepo": "codecloud.web.att.com/scm/st_dcaecntr/platform_onboarding.git",
+ "featureBranch": "feature/cdptest",
+ "featureBranchDir": "DCAE-EOM-K8S/dcae-onboarding-dcae-mod-fe",
+ "jiraTag": "REPLACE-999",
+ "serviceInfo": [
+ {
+ "isKubernetes": true,
+ "serviceName": "dcae-mod-fe",
+ "compSpecFilePath": "public/dpo/comp_spec_toolbox_fe.json",
+ "inputsFilePath": "public/dpo/inputs_ftl3g_k8s.json",
+ "directory": ".",
+ "docker": {
+ "installDir": "/opt/app/dcae-onboarding-dcae-mod-fe",
+ "registry": "dockercentral.it.att.com:5100/com.att.dcae.dcaemod",
+ "filePath": "./Dockerfile"
+ }
+ }
+ ]
+}
diff --git a/mod2/ui/pom.xml b/mod2/ui/pom.xml
new file mode 100644
index 0000000..50122de
--- /dev/null
+++ b/mod2/ui/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ org.onap.dcae
+ ~ ================================================================================
+ ~ Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ ~ ================================================================================
+ ~ 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.
+ ~ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.oparent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>2.0.0</version>
+ </parent>
+ <groupId>org.onap.dcaegen2.platform.mod</groupId>
+ <artifactId>ui</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.github.eirslett</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.6</version>
+ <configuration>
+ <workingDirectory>./</workingDirectory>
+ <nodeVersion>v12.16.1</nodeVersion>
+ <npmVersion>6.13.4</npmVersion>
+ </configuration>
+ <executions>
+ <execution>
+ <id>install node and npm</id>
+ <goals>
+ <goal>install-node-and-npm</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>npm install</id>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>npm run build</id>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project> \ No newline at end of file
diff --git a/mod2/ui/proxy.conf.json b/mod2/ui/proxy.conf.json
new file mode 100644
index 0000000..e730329
--- /dev/null
+++ b/mod2/ui/proxy.conf.json
@@ -0,0 +1,11 @@
+{
+ "/api": {
+ "target": "http://zlecdyh2bdcc1s2dokr05.ec53e7.dyh2b.tci.att.com:32705/",
+ "secure": false,
+ "logLevel": "debug",
+ "pathRewrite": {
+ "^/api": ""
+ },
+ "changeOrigin": true
+ }
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/app-routing.module.ts b/mod2/ui/src/app/app-routing.module.ts
new file mode 100644
index 0000000..0ffe503
--- /dev/null
+++ b/mod2/ui/src/app/app-routing.module.ts
@@ -0,0 +1,55 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule, NavigationStart, NavigationEnd, Route} from '@angular/router';
+import { HomeComponent } from './home/home.component';
+import { OnboardingToolsComponent } from './onboarding-tools/onboarding-tools.component';
+import { CompSpecsComponent } from './comp-specs/comp-specs.component';
+import { MsInstancesComponent } from './msInstances/msInstances.component';
+import { LoginComponent } from './login/login.component';
+import { RegisterComponent } from './register/register.component';
+import { ResetPasswordComponent } from './reset-password/reset-password.component';
+import { AuthGuard } from './guards/auth.guard';
+import { RoleGuard } from './guards/role.guard';
+import { UserManagementComponent } from './user-management/user-management.component';
+import { LoginGuard } from './guards/login.guard';
+import { MicroservicesComponent } from './microservices/microservices.component';
+import { BlueprintsComponent } from './blueprints/blueprints.component';
+import { CompSpecValidationComponent } from './comp-spec-validation/comp-spec-validation.component';
+
+const routes: Routes = [
+ { path: '', component: HomeComponent, canActivate:[LoginGuard]},
+ { path: 'home', component: HomeComponent, canActivate:[AuthGuard] },
+ { path: 'login', component: LoginComponent, canActivate:[LoginGuard]},
+ { path: 'register', component: RegisterComponent, canActivate:[AuthGuard, RoleGuard] },
+ { path: 'reset-password', component: ResetPasswordComponent, canActivate:[AuthGuard]},
+ { path: 'users', component: UserManagementComponent, canActivate:[AuthGuard, RoleGuard]},
+ { path: 'OnboardingTools', component: OnboardingToolsComponent, canActivate:[AuthGuard] },
+ { path: 'CompSpecs', component: CompSpecsComponent, canActivate:[AuthGuard]},
+ { path: 'ms-instances', component: MsInstancesComponent, canActivate:[AuthGuard] },
+ { path: 'base-microservices', component: MicroservicesComponent, canActivate: [AuthGuard] },
+ { path: 'blueprints', component: BlueprintsComponent, canActivate: [AuthGuard] },
+ { path: 'spec-validator', component: CompSpecValidationComponent, canActivate: [AuthGuard] }
+];
+
+@NgModule({
+ imports: [RouterModule.forRoot(routes)],
+ exports: [RouterModule]
+})
+export class AppRoutingModule { }
diff --git a/mod2/ui/src/app/app.component.css b/mod2/ui/src/app/app.component.css
new file mode 100644
index 0000000..0b9779a
--- /dev/null
+++ b/mod2/ui/src/app/app.component.css
@@ -0,0 +1,173 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+.sidenav-container {
+ height: 100%;
+}
+
+.sidenav {
+ width: 190px;
+ background: linear-gradient(to bottom, #1D2329 0%, #454B52 8%)
+}
+
+.sidenav .mat-toolbar {
+ background: inherit;
+ color:rgb(225, 241, 247);
+}
+
+.subMenuItem{
+ color: white;
+ font-size: 14px;
+ font-weight: 400;
+ height: 6vh !important;
+ min-height: 35px !important;
+}
+
+.mat-toolbar.mat-primary {
+ display: block;
+ position: sticky;
+ top: 0;
+ z-index: 1;
+ height: 33px;
+ position: fixed;
+ border-radius: 0%;
+ background: linear-gradient(to bottom, #1D2329 0%, #454B52 135%)
+}
+
+.nav {
+ font-size: 16px;
+ font-weight: 500;
+ background-color: #454B52;
+ color:white;
+ height: 7vh !important;
+ min-height: 40px !important;
+}
+
+*:focus {
+ outline: none !important;
+ border: 0 !important;
+}
+
+.is-active{
+ background-color: #EA712F !important;
+}
+
+label {
+ cursor: pointer;
+}
+
+.input{
+ padding-top: 20px;
+}
+
+.inputLabel {
+ font-weight: 600;
+ margin-left: 25px;
+ width: 160px;
+}
+
+.inputFieldSm {
+ width: 200px;
+ height: 35px;
+ padding-left: 8px;
+}
+.inputFieldMed {
+ width: 300px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldLg {
+ width: 400px;
+ height: 35px;
+ padding-left: 6px;
+}
+
+/* B R E A D C R U M B S . . . . . . . . */
+.breadcrumb {
+ list-style: none;
+ overflow: hidden;
+ font: 12px Helvetica, Arial, Sans-Serif;
+ background: transparent;
+ margin-left: 5px;
+ margin-top: -3px;
+ padding: 0;
+}
+.breadcrumb li {
+ float: left;
+}
+.breadcrumb li a {
+ color: #1D2329;
+ font-weight: 700;
+ text-decoration: none;
+ padding: 6px 0 6px 45px;
+ background: brown; /* fallback color */
+ background: hsla(21,82%,55%,1);
+ position: relative;
+ display: block;
+ float: left;
+}
+.breadcrumb li a:after {
+ content: " ";
+ display: block;
+ width: 0;
+ height: 0;
+ border-top: 50px solid transparent; /* Go big on the size, and let overflow hide */
+ border-bottom: 50px solid transparent;
+ border-left: 30px solid hsla(21,82%,55%,1);
+ position: absolute;
+ top: 50%;
+ margin-top: -50px;
+ left: 100%;
+ z-index: 2;
+}
+.breadcrumb li a:before {
+ content: " ";
+ display: block;
+ width: 0;
+ height: 0;
+ border-top: 50px solid transparent; /* Go big on the size, and let overflow hide */
+ border-bottom: 50px solid transparent;
+ border-left: 30px solid #b9bec4;
+ position: absolute;
+ top: 50%;
+ margin-top: -50px;
+ margin-left: 3px;
+ left: 100%;
+ z-index: 1;
+}
+.breadcrumb li:first-child a {
+ padding-left: 14px;
+}
+.breadcrumb li:nth-child(2) a { background: hsla(30,100%,50%,.95); }
+.breadcrumb li:nth-child(2) a:after { border-left-color: hsla(30,100%,50%,.95); }
+.breadcrumb li:nth-child(3) a { background: hsla(38,100%,50%,.90); }
+.breadcrumb li:nth-child(3) a:after { border-left-color: hsla(38,100%,50%,.90); }
+.breadcrumb li:nth-child(4) a { background: hsla(45,100%,50%,.85); }
+.breadcrumb li:nth-child(4) a:after { border-left-color: hsla(45,100%,50%,.85); }
+.breadcrumb li:nth-child(5) a { background: hsla(52,100%,50%,.80); }
+.breadcrumb li:nth-child(5) a:after { border-left-color: hsla(52,100%,50%,.80); }
+.breadcrumb li:last-child a {
+ background: transparent !important;
+ color: black;
+ pointer-events: none;
+ cursor: default;
+ margin-left: -10px;
+}
+.breadcrumb li:last-child a:after { border: 0; }
+.breadcrumb li a:hover { background: rgba(102, 102, 102, 0.993); color: #e9fffd; cursor: pointer}
+.breadcrumb li a:hover:after { border-left-color: hsla(0,0%,40%,1); color: #bbc9d8 !important; cursor: pointer}
diff --git a/mod2/ui/src/app/app.component.html b/mod2/ui/src/app/app.component.html
new file mode 100644
index 0000000..e214dc1
--- /dev/null
+++ b/mod2/ui/src/app/app.component.html
@@ -0,0 +1,136 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<ng4-loading-spinner></ng4-loading-spinner>
+<mat-sidenav-container style="background: linear-gradient(to top, #878C94 0%, #DCDFE3 10%, #F2F2F2 40%, #DCDFE3 80%, #878C94 110%);" class="sidenav-container" *ngIf="authService.authPass">
+ <mat-sidenav [class.mat-elevation-z2]="!isActive" [class.mat-elevation-z8]="isActive" #sideMenu class="sidenav"
+ fixedInViewport="true" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
+ [mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="(isHandset$ | async) === true">
+ <mat-toolbar></mat-toolbar>
+ <hr width=90%>
+ <mat-action-list style="margin-top: -10px;">
+ <button class="nav" mat-list-item (click)="setCrumbs('', 'reset')" [routerLink]="'/home'" [routerLinkActive]="'is-active'">Home</button>
+ <button class="nav" mat-list-item (click)="setCrumbs('User Management', 'reset')" *ngIf="authService.isAdmin" [routerLink]="'/users'" [routerLinkActive]="'is-active'">User Management</button>
+ <button class="nav" mat-list-item (click)="setCrumbs('Onboarding Tools', 'reset')" [routerLink]="'/OnboardingTools'" [skipLocationChange]="false" [routerLinkActive]="'is-active'">Onboarding Tools</button>
+ <button class="nav" mat-list-item (click)="msMenu()">
+ <i *ngIf="msMenuIconRight" class="pi pi-chevron-right"></i>
+ <i *ngIf="!msMenuIconRight" class="pi pi-chevron-down"></i>
+ &nbsp;&nbsp;Microservices</button>
+ <div *ngIf="showMsMenu" style="margin-left: 20px;">
+ <button class="subMenuItem" mat-list-item (click)="setCrumbs('Microservices', 'reset')" [routerLink]="'/base-microservices'" [routerLinkActive]="'is-active'">Microservices</button>
+ <button class="subMenuItem" mat-list-item (click)="setCrumbs('MS Instances', 'reset')" [routerLink]="'/ms-instances'" [routerLinkActive]="'is-active'">MS Instances</button>
+ <button class="subMenuItem" mat-list-item (click)="setCrumbs('Blueprints', 'reset')" [routerLink]="'/blueprints'" [routerLinkActive]="'is-active'">Blueprints</button>
+
+ <button class="nav" mat-list-item (click)="utilitiesMenu()">
+ <i *ngIf="utilitiesMenuIconRight" class="pi pi-chevron-right"></i>
+ <i *ngIf="!utilitiesMenuIconRight" class="pi pi-chevron-down"></i>
+ &nbsp;&nbsp;Utilites</button>
+
+ <div *ngIf="showUtilitiesMenu" style="margin-left: 20px;">
+ <button class="subMenuItem" mat-list-item (click)="setCrumbs('Spec Validator', 'reset')"
+ [routerLink]="'/spec-validator'" [routerLinkActive]="'is-active'">Spec Validator</button>
+ <button class="subMenuItem" mat-list-item (click)="redirectToAPIs()">MOD APIs</button>
+ </div>
+ </div>
+ <button class="nav" mat-list-item (click)='redirectTo("https://wiki.web.att.com/pages/viewpage.action?spaceKey=DPD&title=DCAE+MOD+User+Guide")'>User Guide</button>
+
+ </mat-action-list>
+ </mat-sidenav>
+ <mat-sidenav-content style="margin-top: 70px; max-height: 90%">
+ <!-- Top bar when Logged in -->
+ <mat-toolbar [class.mat-elevation-z2]="!isActive" [class.mat-elevation-z8]="isActive" color="primary"
+ fixedInViewport="true" style="background-color: #1D2329; color:#F2F2F2">
+ <button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="sideMenu.toggle()" style="color:#F2F2F2">
+ <i *ngIf="!sideMenu.opened" class="pi pi-angle-double-right" style="font-size: 25px; margin-left: -30px; margin-bottom: 8px;"></i>
+ <i *ngIf="sideMenu.opened" class="pi pi-angle-double-left" style="font-size: 25px; margin-left: -30px; margin-bottom: 8px;"></i>
+ </button>
+ <span style="font-size: 22px; font-weight: 500; margin-left: 35px">MOD</span>
+ <button type="button" *ngIf="authService.authPass" (click)="handleLogout()"
+ style="float:right; margin-right: 18%; height: 32px; border: none; color:#F2F2F2; background: linear-gradient(to bottom, #1D2329 0%, #454B52 135%);
+ font-size: 16px; font-weight: 400">
+ <i class="pi pi-sign-out" style="vertical-align:text-top"></i>
+ Logout
+ </button>
+ <button type="button" *ngIf="authService.authPass" (click)="handleProfile()"
+ style="float:right; margin-right: 4%; height: 32px; border: none; color:#F2F2F2; background: linear-gradient(to bottom, #1D2329 0%, #454B52 135%);
+ font-size: 16px; font-weight: 400">
+ <i class="pi pi-user-edit" style="vertical-align:text-top"></i>
+ {{authService.getUser().username}}
+ </button>
+ <!-- BREADCRUMBS . . . . . -->
+ <ul class="breadcrumb">
+ <li *ngFor="let crumb of breadcrumbs" [routerLink]="crumb.link" (click)="setCrumbs(crumb.page, 'crumbClicked')"><a>{{crumb.page}}</a></li>
+ </ul>
+ </mat-toolbar>
+ <main [@routeAnimations]="prepareRoute(outlet)" class="content">
+ <router-outlet #outlet="outlet"></router-outlet>
+ </main>
+ </mat-sidenav-content>
+</mat-sidenav-container>
+
+<!-- Top bar when Logging in -->
+<mat-toolbar *ngIf="!authService.authPass" [class.mat-elevation-z2]="!isActive" [class.mat-elevation-z8]="isActive" color="primary"
+ fixedInViewport="true" style="background-color: #1D2329">
+ <span style="font-size: 22px; font-weight: 500">MOD</span>
+ <app-login></app-login>
+</mat-toolbar>
+
+<!-- Login Expired dialog -->
+<p-dialog header="Login Expired" [(visible)]="authService.reLoginMsg" [modal]="true" [style]="{width:'25vw'}" [baseZIndex]="10000"
+ [draggable]="false" [resizable]="false">
+ <p>Your login has expired. Please log in again.</p>
+ <p-footer>
+ <button type="button" pButton icon="pi pi-check" (click)="onConfirm()" label="OK"></button>
+ </p-footer>
+</p-dialog>
+
+<!--reset User Password dialog-->
+<p-dialog [(visible)]="resetPasswordFlag" appendTo="body" [modal]="true" [transitionOptions]="'300ms'" [style]="{width: '630px'}" [baseZIndex]="10000"
+[closable]="true" (onHide)="closeResetDialog()">
+<p-header style="display: inline-flex;">
+ Reset User Password
+</p-header>
+<form [formGroup]="resetPasswordForm">
+ <!-- * * * New Password * * * -->
+ <div class="input">
+ <div class="ui-inputgroup" >
+ <label class="inputLabel">New Password</label>
+ <span class="ui-inputgroup-addon" (click)="hidePassword=!hidePassword">
+ <i [ngClass]="hidePassword? 'pi pi-eye-slash':'pi pi-eye'"></i></span>
+ <input class="inputFieldSm" [type]="hidePassword? 'password':'text'" pInputText formControlName="password" />
+ </div>
+ </div>
+ <i *ngIf="resetPasswordForm.get('password').errors && resetPasswordForm.get('password').errors.minlength" style="width: 140px;margin-left: 20px;font-size: small;color: red;">password should be more than 5 characters</i>
+ <!-- * * * Confirm New Password * * * -->
+ <div class="input">
+ <div class="ui-inputgroup" >
+ <label class="inputLabel">Confirm Password</label>
+ <span class="ui-inputgroup-addon" (click)="hideConfirmPassword=!hideConfirmPassword">
+ <i [ngClass]="hideConfirmPassword? 'pi pi-eye-slash':'pi pi-eye'"></i></span>
+ <input class="inputFieldSm" [type]="hideConfirmPassword? 'password':'text'" pInputText formControlName="confirm_password" />
+ </div>
+ </div>
+ <i *ngIf="resetPasswordForm.errors && resetPasswordForm.errors.errMsg" style="width: 140px;margin-left: 20px;font-size: small;color: red;">{{resetPasswordForm.errors.errMsg}}</i>
+ <!-- * * * Submit and Cancel buttons * * * -->
+ <div style="margin-top: 2em; margin-left: 1.3em; margin-bottom: 2em;">
+ <button pButton type="button" (click)="closeResetDialog()" label="Cancel"></button>&nbsp;
+ <button pButton type="submit" (click)="resetPasswordForm.valid && submitReset()" class="ui-button-success" label="Submit" style="width: 70px"></button>
+ </div>
+</form>
+
+</p-dialog> \ No newline at end of file
diff --git a/mod2/ui/src/app/app.component.spec.ts b/mod2/ui/src/app/app.component.spec.ts
new file mode 100644
index 0000000..d6eb43c
--- /dev/null
+++ b/mod2/ui/src/app/app.component.spec.ts
@@ -0,0 +1,90 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { TestBed, async } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { AppComponent } from './app.component';
+import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
+import { MatSidenavModule } from '@angular/material/sidenav';
+import { MatToolbarModule } from '@angular/material/toolbar';
+import { MatCardModule } from '@angular/material/card';
+import { MatTreeModule } from '@angular/material/tree';
+import { DialogModule } from 'primeng/dialog';
+import { MatListModule } from '@angular/material/list';
+import { LoginComponent } from './login/login.component';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { CardModule } from 'primeng/card';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { JwtHelperService, JwtModule, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+describe('AppComponent', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ RouterTestingModule,
+ Ng4LoadingSpinnerModule,
+ MatSidenavModule,
+ MatToolbarModule,
+ MatCardModule,
+ MatTreeModule,
+ DialogModule,
+ MatListModule,
+ FormsModule,
+ ReactiveFormsModule,
+ CardModule,
+ HttpClientTestingModule,
+ JwtModule,
+ ],
+ declarations: [
+ AppComponent,
+ LoginComponent
+ ], providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+
+ it('should create the app', () => {
+ const fixture = TestBed.createComponent(AppComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app).toBeTruthy();
+ });
+
+ it(`should have as title 'mod-fe'`, () => {
+ const fixture = TestBed.createComponent(AppComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app.title).toEqual('mod-fe');
+ });
+
+ it(`should have menu item variables as 'false'`, () => {
+ const fixture = TestBed.createComponent(AppComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app.showUtilitiesMenu).toEqual(false);
+ expect(app.utilitiesMenuIconRight).toEqual(true);
+ });
+
+ it(`should change utilites menu arrow`, () => {
+ const fixture = TestBed.createComponent(AppComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ app.utilitiesMenu()
+ expect(app.showUtilitiesMenu).toEqual(true);
+ expect(app.utilitiesMenuIconRight).toEqual(false);
+ });
+}); \ No newline at end of file
diff --git a/mod2/ui/src/app/app.component.ts b/mod2/ui/src/app/app.component.ts
new file mode 100644
index 0000000..87d29b4
--- /dev/null
+++ b/mod2/ui/src/app/app.component.ts
@@ -0,0 +1,218 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, HostBinding, OnInit } from '@angular/core';
+import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
+import { Observable } from 'rxjs';
+import { map, shareReplay } from 'rxjs/operators';
+import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree';
+import { FlatTreeControl } from '@angular/cdk/tree';
+import { Event, Router, RouterOutlet, NavigationStart, NavigationEnd, RouterEvent } from '@angular/router';
+import { AuthService } from './services/auth.service';
+import { BreadcrumbService } from './services/breadcrumb.service';
+import { environment } from '../environments/environment';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+import { UserService } from './services/user.service';
+import { User } from './models/User';
+import { Authority } from './models/Authority.enum';
+
+interface TreeNode {
+ name: string;
+ children?: TreeNode[];
+}
+
+const TREE_DATA: TreeNode[] = [
+ {
+ name: 'Microservices',
+ children: [
+ { name: 'Microservices' },
+ { name: 'MS Instances' },
+ { name: 'Blueprints' },
+ { name: 'MOD APIs' }
+ ]
+ }
+];
+
+interface ExampleFlatNode {
+ expandable: boolean;
+ name: string;
+ level: number;
+}
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+export class AppComponent implements OnInit{
+
+ @HostBinding('@.disabled')
+ public animationsDisabled = true;
+ activeNode: any;
+ resetPasswordFlag: boolean = false;
+ resetPasswordForm: FormGroup;
+ hidePassword: boolean = true;
+ hideConfirmPassword: boolean = true;
+ breadcrumbs: any[] = [];
+
+ prepareRoute(outlet: RouterOutlet) {
+ return outlet && outlet.activatedRouteData && outlet.activatedRouteData['animation'];
+ }
+
+ title = 'mod-fe';
+ right: boolean = true;
+ down: boolean = false;
+
+ menu_tree(){
+ this.right = !this.right;
+ this.down = !this.down;
+ }
+
+ isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
+ .pipe(
+ map(result => result.matches),
+ shareReplay()
+ );
+
+ redirectTo(link){
+ window.open(link, "_blank");
+ }
+
+ redirectToAPIs() {
+ window.open(`http://${environment.api_baseURL}:31001/swagger-ui.html#/`, "_blank");
+ }
+
+ constructor(private breakpointObserver: BreakpointObserver, private router: Router, public authService: AuthService,
+ private bread: BreadcrumbService, private fb: FormBuilder, private userService: UserService) {
+ this.dataSource.data = TREE_DATA;
+ }
+
+ ngOnInit() {
+ this.resetPasswordForm = this.fb.group(
+ {
+ password: ['', [Validators.minLength(6)]],
+ confirm_password: ''
+ },
+ {validators: [this.passwordValidator]}
+ );
+
+ // Subscribe to breadcrumb changes
+ this.bread.breadcrumbs$.subscribe( (crumbArray) => {this.breadcrumbs = crumbArray});
+ }
+
+ setCrumbs(component, action) {
+ this.bread.setBreadcrumbs(component, action)
+ }
+
+ passwordValidator(group: FormGroup) {
+ if(group.value.password === group.value.confirm_password){
+ return null;
+ } else {
+ return {errMsg: 'Passwords do not match!'};
+ }
+ }
+
+ private _transformer = (node: TreeNode, level: number) => {
+ return {
+ expandable: !!node.children && node.children.length > 0,
+ name: node.name,
+ level: level,
+ };
+ }
+
+ tree_handler(name, treenode) {
+ if (name == "MOD APIs") {
+ window.open(`http://${environment.api_baseURL}:31001/swagger-ui.html#/`, "_blank");
+ } else if (name == "MS Instances") {
+ this.router.navigate(["ms-instances"]);
+ this.activeNode = treenode;
+ } else if(name == "Microservices") {
+ this.router.navigate(["base-microservices"]);
+ this.activeNode = treenode;
+ } else if(name == "Blueprints") {
+ this.router.navigate(["blueprints"]);
+ this.activeNode = treenode;
+ }
+
+ }
+
+ treeControl = new FlatTreeControl<ExampleFlatNode>(
+ node => node.level, node => node.expandable);
+
+ treeFlattener = new MatTreeFlattener(
+ this._transformer, node => node.level, node => node.expandable, node => node.children);
+
+ dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
+
+ hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
+
+ showMsMenu = false;
+ msMenuIconRight = true;
+ msMenu() {
+ this.showMsMenu = !this.showMsMenu
+ this.msMenuIconRight = !this.msMenuIconRight
+ }
+
+ showUtilitiesMenu = false;
+ utilitiesMenuIconRight = true;
+ utilitiesMenu(){
+ this.showUtilitiesMenu = !this.showUtilitiesMenu
+ this.utilitiesMenuIconRight = !this.utilitiesMenuIconRight
+ }
+
+ onConfirm() {
+ this.authService.reLoginMsg = false;
+ }
+
+ handleLogout() {
+ this.showMsMenu = false
+ this.authService.logout()
+ }
+
+ handleProfile() {
+ console.log(this.authService.getUser().roles);
+ this.resetPasswordFlag = true;
+ }
+
+ closeResetDialog() {
+ this.resetPasswordForm.reset();
+ this.resetPasswordFlag = false;
+ }
+
+ submitReset() {
+ if(this.authService.getUser().roles.includes(Authority.ADMIN)){
+ this.userService.editUser(this.authService.getUser().username, this.resetPasswordForm.value as User).subscribe(res=>{
+ alert("Password reset successful. Please login in using the new credentials.");
+ this.authService.logout();
+ }, (err)=>{
+ alert(err.error.message);
+
+ });
+ } else {
+ this.userService.editProfile(this.authService.getUser().username, this.resetPasswordForm.value as User).subscribe(res=>{
+ alert("Password reset successful. Please login in using the new credentials.");
+ this.authService.logout();
+ }, (err)=>{
+ alert(err.error.message);
+ });
+ }
+ this.resetPasswordForm.reset();
+ this.resetPasswordFlag = false;
+ }
+
+}
diff --git a/mod2/ui/src/app/app.module.ts b/mod2/ui/src/app/app.module.ts
new file mode 100644
index 0000000..1e1da59
--- /dev/null
+++ b/mod2/ui/src/app/app.module.ts
@@ -0,0 +1,172 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { BrowserModule } from '@angular/platform-browser';
+import { NgModule } from '@angular/core';
+
+import { AppRoutingModule } from './app-routing.module';
+import { AppComponent } from './app.component';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { PathLocationStrategy, LocationStrategy} from '@angular/common';
+
+import { SharedModule } from './shared/shared-module';
+import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
+import { HomeComponent } from './home/home.component';
+import { LayoutModule } from '@angular/cdk/layout';
+import { MatToolbarModule } from '@angular/material/toolbar';
+import { MatButtonModule } from '@angular/material/button';
+import { MatSidenavModule } from '@angular/material/sidenav';
+import { MatIconModule } from '@angular/material/icon';
+import { MatListModule } from '@angular/material/list';
+import { MatTableModule } from '@angular/material/table';
+import { MatPaginatorModule } from '@angular/material/paginator';
+import { MatSortModule } from '@angular/material/sort';
+import { MatTreeModule } from '@angular/material/tree';
+import { MatCardModule } from '@angular/material/card';
+import { MaterialElevationDirective } from './material-elevation.directive';
+import { MatProgressSpinnerModule, MatTooltipModule, MatMenuModule } from '@angular/material';
+import { OnboardingToolsComponent, SafePipe } from './onboarding-tools/onboarding-tools.component';
+import { CompSpecsComponent } from './comp-specs/comp-specs.component';
+import { MatTableExporterModule } from 'mat-table-exporter';
+import { TableModule } from 'primeng/table';
+import { MsInstancesComponent } from './msInstances/msInstances.component';
+import { ButtonModule } from 'primeng/button';
+import { SidebarModule } from 'primeng/sidebar';
+import { MenuModule } from 'primeng/menu';
+import { ToolbarModule } from 'primeng/toolbar';
+import { PanelMenuModule } from 'primeng/panelmenu';
+import { CardModule } from 'primeng/card';
+import { LoginComponent } from './login/login.component';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RegisterComponent } from './register/register.component';
+import { ResetPasswordComponent } from './reset-password/reset-password.component';
+import { AuthGuard } from './guards/auth.guard';
+import { RoleGuard } from './guards/role.guard';
+import { JwtInterceptorService } from './services/jwt-interceptor.service';
+import { JwtModule } from '@auth0/angular-jwt';
+import { UserManagementComponent } from './user-management/user-management.component';
+import { DialogModule } from 'primeng/dialog';
+import { ToastModule } from 'primeng/toast';
+import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
+import { PasswordModule } from 'primeng/password';
+import { TooltipModule } from 'primeng/tooltip';
+import { AccordionModule } from 'primeng/accordion';
+import { SplitButtonModule } from 'primeng/splitbutton';
+import { DropdownModule } from 'primeng/dropdown';
+import { FileUploadModule } from 'primeng/fileupload';
+import { InputTextareaModule } from 'primeng/inputtextarea';
+import { MatExpansionModule } from '@angular/material/expansion';
+import { RadioButtonModule } from 'primeng/radiobutton';
+import { SelectButtonModule } from 'primeng/selectbutton';
+import { MessageService } from 'primeng/api';
+import { MsAddChangeComponent } from './ms-add-change/ms-add-change.component';
+import { MicroservicesComponent } from './microservices/microservices.component';
+import { PaginatorModule } from 'primeng/paginator';
+import { ScrollPanelModule } from 'primeng/scrollpanel';
+import { CalendarModule } from 'primeng/calendar';
+import { BlueprintsComponent } from './blueprints/blueprints.component';
+import { CompSpecAddComponent } from './comp-spec-add/comp-spec-add.component';
+import { MsInstanceAddComponent } from './ms-instance-add/ms-instance-add.component';
+import {MultiSelectModule} from 'primeng/multiselect';
+import {CheckboxModule} from 'primeng/checkbox';
+import { InputSwitchModule } from 'primeng/inputswitch';
+import { CompSpecValidationComponent } from './comp-spec-validation/comp-spec-validation.component';
+
+@NgModule({
+ declarations: [
+ AppComponent,
+ HomeComponent,
+ MaterialElevationDirective,
+ SafePipe,
+ OnboardingToolsComponent,
+ CompSpecsComponent,
+ MsInstancesComponent,
+ LoginComponent,
+ RegisterComponent,
+ ResetPasswordComponent,
+ UserManagementComponent,
+ MsAddChangeComponent,
+ MicroservicesComponent,
+ BlueprintsComponent,
+ CompSpecAddComponent,
+ MsInstanceAddComponent,
+ CompSpecValidationComponent
+ ],
+ imports: [
+ BrowserModule,
+ AppRoutingModule,
+ BrowserAnimationsModule,
+ SharedModule,
+ HttpClientModule,
+ LayoutModule,
+ MatToolbarModule,
+ MatButtonModule,
+ MatSidenavModule,
+ MatIconModule,
+ MatListModule,
+ MatTableModule,
+ MatPaginatorModule,
+ MatSortModule,
+ MatTreeModule,
+ MatCardModule,
+ MatProgressSpinnerModule,
+ MatTableExporterModule,
+ TableModule,
+ ButtonModule,
+ SidebarModule,
+ MenuModule,
+ ToolbarModule,
+ PanelMenuModule,
+ FormsModule,
+ ReactiveFormsModule,
+ CardModule,
+ JwtModule.forRoot({
+ config: {
+ tokenGetter: ()=>localStorage.getItem('jwt')
+ }
+ }),
+ DialogModule,
+ ToastModule,
+ Ng4LoadingSpinnerModule,
+ TooltipModule,
+ AccordionModule,
+ SplitButtonModule,
+ DropdownModule,
+ FileUploadModule,
+ InputTextareaModule,
+ MatExpansionModule,
+ PasswordModule,
+ RadioButtonModule,
+ SelectButtonModule,
+ MatTooltipModule,
+ PaginatorModule,
+ ScrollPanelModule,
+ MatMenuModule,
+ CalendarModule,
+ MultiSelectModule,
+ CheckboxModule,
+ InputSwitchModule
+ ],
+ providers: [AuthGuard, RoleGuard, {
+ provide: HTTP_INTERCEPTORS,
+ useClass: JwtInterceptorService,
+ multi: true
+ }, Location, { provide: LocationStrategy, useClass: PathLocationStrategy }, MessageService],
+ bootstrap: [AppComponent]
+})
+export class AppModule { }
diff --git a/mod2/ui/src/app/blueprints/blueprints.component.css b/mod2/ui/src/app/blueprints/blueprints.component.css
new file mode 100644
index 0000000..ccc03d9
--- /dev/null
+++ b/mod2/ui/src/app/blueprints/blueprints.component.css
@@ -0,0 +1,142 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+td{
+ word-break:break-all;
+ font-size: 12px;
+}
+
+th{
+ font-size: 12px;
+}
+
+.table_column_filter{
+ width: 100%;
+ height: 20px;
+ font-size: 10px;
+}
+
+.table_div{
+ margin: 0px 50px 10px 20px;
+ min-width: 900px;
+ width: 98%;
+ border: 1px solid darkslategray;
+}
+
+.fa-refresh{
+ cursor: pointer;
+}
+
+textarea
+{
+ font-size: 12px;
+}
+
+.row-expand-layout{
+ display: grid;
+ width: 100%;
+ grid-template-columns: 20% 30% auto 25%;
+ grid-gap: 10px;
+ grid-auto-rows: minmax(100px, auto);
+}
+
+.row-expand-card{
+ font-size: 12px;
+ border-radius: 5px;
+ border: 1px solid slategray;
+ padding: 10px 5px 5px 10px;
+ /* This height prevents vertical scroll bars in Notes and Failure Reason */
+ height: 92px;
+ overflow: hidden;
+}
+
+.table_export_buttons_alignment{
+ margin-left: 5px;
+ margin-top: -32px;
+ float: left;
+}
+
+.table_export_button{
+ border-radius: 5px;
+ height: 22px;
+ font-size: 14px;
+ border: none;
+ margin-top: 4px;
+ margin-right: 7px;
+ display: inline-flex;
+}
+
+.table_caption_header{
+ margin-left: -18%;
+ width: 82%;
+ max-height: 25px;
+ display: inline-flex;
+}
+
+.table_global_filter{
+ width: 250px;
+ height:25px;
+ margin-bottom: -5px;
+ font-size: 12px;
+ margin-left: 15px;
+}
+
+.table_title{
+ width: 40%;
+ margin-left: 10%;
+}
+
+.table_action_item{
+ outline: none;
+ font-size: 12px;
+}
+
+::ng-deep .mat-menu-content {
+padding-top: 0px !important;
+padding-bottom: 0px !important;
+}
+.mat-menu-item{
+line-height:30px;
+height:30px;
+}
+
+.greenStatus{
+ background-color: rgba(80, 233, 105, 0.616)
+}
+
+.redStatus{
+ background-color: rgba(255, 29, 29, 0.527)
+}
+
+.blueStatus{
+ background-color: rgba(0, 183, 255, 0.384)
+}
+
+.greyStatus{
+ background-color: rgba(150, 150, 150, 0.432)
+}
+
+.ui-toast-detail{
+ white-space: pre-wrap;
+ font-size: 12px;
+}
+
+.ui-state-highlight {
+ background-color: #878C94 !important;
+ color: black !important;
+}
diff --git a/mod2/ui/src/app/blueprints/blueprints.component.html b/mod2/ui/src/app/blueprints/blueprints.component.html
new file mode 100644
index 0000000..53fed09
--- /dev/null
+++ b/mod2/ui/src/app/blueprints/blueprints.component.html
@@ -0,0 +1,283 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<ng4-loading-spinner [timeout]="1000000"></ng4-loading-spinner>
+<div class="table_div" [style.visibility]="visible">
+ <!-- * * * * Table of Blueprints * * * * -->
+ <p-table #dt [columns]="cols" [(selection)]="selectedBPs" [value]="bpElements" sortMode="multiple" [paginator]="true"
+ [rows]="18" [rowsPerPageOptions]="[10,12,14,16,18,20,25,50]" (onFilter)="onTableFiltered(dt.filteredValue, $event)" dataKey="id" editMode="row">
+
+ <!-- * * * * Top caption row * * * * -->
+ <ng-template pTemplate="caption">
+
+ <div class="table_caption_header">
+ <!--Blueprints Table Header-->
+ <div>
+ <!-- * * * * Refresh * * * * -->
+ <i class="fa fa-refresh" (click)="getAllBPs()"></i>
+ <!-- * * * * Global filter * * * * -->
+ <input class="table_global_filter" type="text" pInputText size="50" placeholder="Global Filter"
+ (input)="dt.filterGlobal($event.target.value, 'contains')">
+ <i class="fa fa-search" style="margin:4px 0 0 8px"></i>
+ </div>
+
+ <h4 class="table_title"><b>Deployment Artifacts</b></h4>
+
+ </div>
+ </ng-template>
+
+ <!-- * * * * Header row with dynamic column names. Columns include microservice Name, Release, Tag, Type, Version and Status * * * * -->
+ <ng-template pTemplate="header" let-columns>
+ <tr style="text-align: center; vertical-align: bottom;">
+ <th style="width: 3em"></th>
+ <th class="ui-state-highlight" *ngFor="let col of columns" style="outline: none;" [pSortableColumn]="col.field" style="font-size: 12px; outline: none;"
+ [ngStyle]="{'width': col.width}">
+ {{col.header}}<br>
+ <p-sortIcon [field]="col.field"></p-sortIcon>
+ </th>
+ <th style="width: 7%; vertical-align: middle;">
+ Actions
+ </th>
+ </tr>
+
+ <!-- * * * * Second header row for individual column filters * * * * -->
+ <tr>
+ <th style="width: 3em"></th>
+ <!-- * * * * column filters * * * * -->
+ <th *ngFor="let col of columns" style="text-align: center;" [ngSwitch]="col.field">
+ <input *ngSwitchCase="'instanceName'" [(ngModel)]="filteredName" pInputText type="text" (input)="dt.filter($event.target.value, col.field, 'contains')" class="table_column_filter" placeholder="Filter">
+ <input *ngSwitchCase="'instanceRelease'" [(ngModel)]="filteredRelease" pInputText type="text" (input)="dt.filter($event.target.value, col.field, 'contains')" class="table_column_filter" placeholder="Filter">
+ <input *ngSwitchCase="'tag'" [(ngModel)]="filteredTag" pInputText type="text" (input)="dt.filter($event.target.value, col.field, 'contains')" class="table_column_filter" placeholder="Filter">
+ <input *ngSwitchCase="'type'" [(ngModel)]="filteredType" pInputText type="text" (input)="dt.filter($event.target.value, col.field, 'contains')" class="table_column_filter" placeholder="Filter">
+ <input *ngSwitchCase="'version'" [(ngModel)]="filteredVersion" pInputText type="text" (input)="dt.filter($event.target.value, col.field, 'contains')" class="table_column_filter" placeholder="Filter">
+ <input *ngSwitchCase="'status'" [(ngModel)]="filteredStatus" pInputText type="text" (input)="dt.filter($event.target.value, col.field, 'contains')" class="table_column_filter" placeholder="Filter">
+ </th>
+ <th>
+ <div style="text-align: center;">
+ <p-tableHeaderCheckbox style="padding-right: 5px;"></p-tableHeaderCheckbox>
+ <button pButton type="button" class="ui-button-secondary" (click)="enableButtonCheck()" [matMenuTriggerFor]="menu" #menuTrigger="matMenuTrigger"
+ style="background-color: transparent; border: none; width: 20px; height: 20px; vertical-align: middle;">
+ <i class="pi pi-ellipsis-h" style="color: grey;"></i>
+ </button>
+ <mat-menu #menu="matMenu" xPosition="before">
+ <!--<div (mouseleave)="menuTrigger.closeMenu()">-->
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-download"></i> Download</span>
+ </div>
+
+ <!-- * * * * Download Blueprints * * * * -->
+ <div matTooltip="No Blueprints Selected" [matTooltipDisabled]="canDownload" matTooltipPosition="left">
+ <button mat-menu-item class="table_action_item" (click)="downloadSelectedBps()" [disabled]="!canDownload">Download Selected Blueprints</button>
+ </div>
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-times"></i> Delete</span>
+ </div>
+
+ <!-- * * * * Delete Selected Blueprints * * * -->
+ <div [matTooltip]="deleteTooltip" [matTooltipDisabled]="canDelete" matTooltipPosition="left">
+ <button mat-menu-item (click)="warnDeleteBlueprint(null)" class="table_action_item" [disabled]="!canDelete">Delete Selected Blueprints</button>
+ </div>
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-pencil"></i> Update</span>
+ </div>
+
+ <!-- * * * * State Changes * * * * -->
+ <div matTooltip="No Blueprints Selected" [matTooltipDisabled]="canUpdate" matTooltipPosition="left">
+ <button *ngFor="let state of states" mat-menu-item class="table_action_item" (click)="updateSelectedStatusesCheck(state)" [disabled]="!canUpdate">{{state.label}}</button>
+ </div>
+
+ <!--</div>-->
+ </mat-menu>
+ </div>
+ </th>
+ </tr>
+ </ng-template>
+
+ <!-- * * * * dynamic rows generated from columns object and msElems object * * * * -->
+ <ng-template pTemplate="body" let-rowData let-expanded="expanded" let-bpElem>
+ <tr>
+ <!-- * * * * Column for row expand buttons * * * * -->
+ <td>
+ <a href="#" [pRowToggler]="rowData">
+ <i [ngClass]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></i>
+ </a>
+ </td>
+
+ <td *ngFor="let col of cols">
+ <div *ngIf="col.field==='status'" style="width: -moz-max-content; width: fit-content; padding: 0px 5px 0px 5px; border-radius: 3px; font-weight: 600;"
+ [ngClass]="{
+ 'greenStatus' : bpElem[col.field] === 'DEV_COMPLETE' || bpElem[col.field] === 'PST_CERTIFIED' || bpElem[col.field] === 'ETE_CERTIFIED' || bpElem[col.field] === 'IN_PROD',
+ 'redStatus' : bpElem[col.field] === 'PST_FAILED' || bpElem[col.field] === 'ETE_FAILED' || bpElem[col.field] === 'PROD_FAILED',
+ 'blueStatus' : bpElem[col.field] === 'IN_DEV' || bpElem[col.field] === 'IN_PST' || bpElem[col.field] === 'IN_ETE',
+ 'greyStatus' : bpElem[col.field] === 'NOT_NEEDED'}">
+ {{bpElem[col.field]}}
+ </div>
+ <div *ngIf="col.field!=='status'">{{bpElem[col.field]}}</div>
+ </td>
+
+ <!-- * * * * Actions Column * * * * -->
+ <td>
+ <div style="text-align: center;">
+ <p-tableCheckbox [value]="rowData" style="padding-right: 5px;"></p-tableCheckbox>
+ <!-- * * * * Actions Button * * * * -->
+ <button #actionButton pButton type="button" #menuTrigger="matMenuTrigger" class="ui-button-secondary" style="background-color: transparent; border: none; width: 20px; height: 20px; vertical-align: middle;" [matMenuTriggerFor]="menu">
+ <i class="pi pi-ellipsis-h" style="color: grey;"></i>
+ </button>
+ <!-- * * * * Actions Menu Items * * * * -->
+ <mat-menu #menu="matMenu">
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i style="font-size: 12px;" class="pi pi-search"></i> View</span>
+ </div>
+
+ <button mat-menu-item class="table_action_item" (click)="viewBpContent(rowData)">View BP Content</button>
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-times"></i> Delete</span>
+ </div>
+
+ <div matTooltip='Only blueprints that are in a status of "In Dev", "Not Needed" or "Dev Complete" can be deleted' [matTooltipDisabled]="rowData.status === 'IN_DEV' || rowData.status === 'NOT_NEEDED' || rowData.status === 'DEV_COMPLETE'" matTooltipPosition="left">
+ <button mat-menu-item class="table_action_item" (click)="warnDeleteBlueprint(rowData)" [disabled]="rowData.status !== 'IN_DEV' && rowData.status !== 'NOT_NEEDED' && rowData.status !== 'DEV_COMPLETE'">Delete Blueprint</button>
+ </div>
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-pencil"></i> Update</span>
+ </div>
+
+ <div>
+ <div *ngFor="let state of states">
+ <button *ngIf="rowData.status !== state.field" mat-menu-item class="table_action_item" (click)="updateState(state, rowData, false)">{{state.label}}</button>
+ </div>
+ </div>
+ </mat-menu>
+ </div>
+ </td>
+ </tr>
+ </ng-template>
+
+
+ <!-- * * * * Row expand content * * * * -->
+ <ng-template pTemplate="rowexpansion" let-rowData let-columns="columns">
+ <tr>
+ <td [attr.colspan]="columns.length + 2">
+ <div class="row-expand-layout" [@rowExpansionTrigger]="'active'">
+ <!-- * * * * Audit Fields * * * * -->
+ <div class="row-expand-card" style="background-color: rgba(95, 158, 160, 0.295);">
+ <b>Created By:</b> {{rowData.metadata.createdBy}}<br>
+ <b>Created On:</b> {{rowData.metadata.createdOn}}<br>
+ <b>Updated By:</b> {{rowData.metadata.updatedBy}}<br>
+ <b>Updated On:</b> {{rowData.metadata.updatedOn}}<br>
+ </div>
+ <!-- * * * * Notes * * * * -->
+ <div class="row-expand-card" style="background-color: rgba(100, 148, 237, 0.295); white-space: pre-line;">
+ <b>Notes:</b><br>
+ <p-scrollPanel [style]="{width: '100%', height: '75px'}">
+ <div style="font-size: 12px; word-break: normal;">{{rowData.metadata.notes}}</div>
+ </p-scrollPanel>
+ </div>
+ <!-- * * * * Labels * * * * -->
+ <div class="row-expand-card" style="background-color: rgba(76, 65, 225, 0.295)">
+ <b style="padding-bottom: 5px;">Labels:</b><br>
+ <div *ngFor="let label of rowData['metadata']['labels']"
+ style="display: inline-flex; margin-top: 5px;">
+ <div style="padding: 2px 7px 3px 0px;">
+ <span style="background-color: rgba(80, 80, 80, 0.185); padding: 3px; border-radius: 3px;">{{label}}</span>
+ </div>
+ </div>
+ </div>
+ <!-- * * * * Failure Reason * * * * -->
+ <div class="row-expand-card" style="background-color: rgba(225, 65, 65, 0.295)">
+ <b>Failure Reason:</b><br>
+ <p-scrollPanel [style]="{width: '100%', height: '75px'}">
+ <div style="font-size: 12px; word-break: normal;">{{rowData.metadata.failureReason}}</div>
+ </p-scrollPanel>
+ </div>
+
+ </div>
+ </td>
+ </tr>
+ </ng-template>
+ </p-table>
+
+ <!-- * * * * download buttons for exporting table to either csv or excel file * * * * -->
+ <div class="table_export_buttons_alignment">
+ <button pButton type="button" (click)="exportTable('csv')" matTooltip="Export Table to CSV" matTooltipPosition="above" class="table_export_button" style="width: 55px;">
+ <i class="pi pi-file" style="margin-top: 3px; margin-left: 4px;"></i>
+ <label style="font-weight: 800; margin-top: 1px;">CSV</label>
+ </button>
+ <button pButton type="button" (click)="exportTable('excel')" matTooltip="Export Table to XLSX" class="table_export_button" matTooltipPosition="above" style="width: 65px; background-color: green;">
+ <i class="pi pi-file-excel" style="margin-top: 3px; margin-left: 4px;"></i>
+ <label style="font-weight: 800; margin-top: 1px">Excel</label>
+ </button>
+ </div>
+</div>
+
+<p-toast key="statusUpdate" class="ui-toast-detail" [style]="{width: '500px'}">
+ <ng-template let-message pTemplate="message">
+ <p><b>{{message.summary}}</b></p>
+ <p style="font-size: 12px;">{{message.detail}}</p>
+ </ng-template>
+</p-toast>
+<p-toast key="multipleBpReleasesSelected"></p-toast>
+
+<p-toast key="bpDeleteResponse"></p-toast>
+
+
+<!-- * * * * Confirm multiple statuses/releases update toast * * * * -->
+<p-toast position="center" key="confirmToast" (onClose)="onReject()" [baseZIndex]="5000" [style]="{width: '300px'}">
+ <ng-template let-message pTemplate="message">
+ <div style="text-align: center">
+ <i class="pi pi-exclamation-triangle" style="font-size: 3em"></i>
+ <h3>{{message.summary}}</h3>
+ <p>{{message.detail}}</p>
+ </div>
+ <div style="width: 100%; text-align: center;">
+ <button type="button" pButton (click)="onConfirm()" label="Confirm" class="ui-button-success"></button>
+ <button type="button" pButton (click)="onReject()" label="Cancel" class="ui-button-secondary" style="margin-left: 20px;"></button>
+ </div>
+ </ng-template>
+</p-toast>
+
+<!-- * * * * Confirm delete blueprint * * * * -->
+<p-toast position="center" key="confirmDeleteToast" class="ui-toast-detail" (onClose)="onReject()" [baseZIndex]="5000" [style]="{width: '300px'}">
+ <ng-template let-message pTemplate="message">
+ <div style="text-align: center">
+ <i class="pi pi-exclamation-triangle" style="font-size: 3em"></i>
+ <h3>{{message.summary}}</h3>
+ Confirm to delete blueprint(s):<br><br>
+ <p style="text-align: left; margin-left: 10%;">{{message.detail}}</p><br>
+ </div>
+ <div style="width: 100%; text-align: center;">
+ <button type="button" pButton (click)="onConfirmDelete()" label="Confirm" class="ui-button-success"></button>
+ <button type="button" pButton (click)="onRejectDelete()" label="Cancel" class="ui-button-secondary"
+ style="margin-left: 20px;"></button>
+ </div>
+ </ng-template>
+</p-toast>
+
+<!-- * * * * View BP Content Pop Up * * * * -->
+<p-dialog [(visible)]="showBpContentDialog" header="Blueprint Content" appendTo="body" [maximizable]="true" [modal]="true" [style]="{width: '80vw'}" [baseZIndex]="10000"
+ [closable]="false">
+ <pre>{{BpContentToView}}</pre>
+ <p-footer>
+ <button pButton label="Close" (click)="showBpContentDialog=false" type="button"></button>
+ <button pButton label="Download" (click)="download()" type="button"></button>
+ </p-footer>
+</p-dialog> \ No newline at end of file
diff --git a/mod2/ui/src/app/blueprints/blueprints.component.spec.ts b/mod2/ui/src/app/blueprints/blueprints.component.spec.ts
new file mode 100644
index 0000000..caa5c38
--- /dev/null
+++ b/mod2/ui/src/app/blueprints/blueprints.component.spec.ts
@@ -0,0 +1,153 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatMenuModule, MatTooltipModule } from '@angular/material';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
+import { MessageService } from 'primeng/api';
+import { ButtonModule } from 'primeng/button';
+import { DialogModule } from 'primeng/dialog';
+import { DropdownModule } from 'primeng/dropdown';
+import { ScrollPanelModule } from 'primeng/scrollpanel';
+import { TableModule } from 'primeng/table';
+import { ToastModule } from 'primeng/toast';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+
+import { BlueprintsComponent } from './blueprints.component';
+
+describe('BlueprintsComponent', () => {
+ let component: BlueprintsComponent;
+ let fixture: ComponentFixture<BlueprintsComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [BlueprintsComponent],
+ imports: [
+ Ng4LoadingSpinnerModule,
+ TableModule,
+ MatMenuModule,
+ ScrollPanelModule,
+ ToastModule,
+ DialogModule,
+ DropdownModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ButtonModule,
+ HttpClientTestingModule,
+ ToastModule,
+ RouterTestingModule,
+ MatTooltipModule,
+ BrowserAnimationsModule
+ ],
+ providers: [
+ MessageService,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(BlueprintsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it(`should set states`, async(() => {
+ const fixture = TestBed.createComponent(BlueprintsComponent);
+ const app = fixture.debugElement.componentInstance;
+ let mockStates = [
+ 'state1',
+ 'state2'
+ ]
+ app.setMenuStates(mockStates)
+ fixture.detectChanges();
+ expect(app.states).toEqual([ ]);
+ }));
+
+ it(`should not enable action buttons`, async(() => {
+ const fixture = TestBed.createComponent(BlueprintsComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ app.selectedBPs = []
+ app.enableButtonCheck()
+ fixture.detectChanges();
+
+ expect(app.canDownload).toEqual(false);
+ expect(app.canUpdate).toEqual(false);
+ expect(app.canDelete).toEqual(false);
+ }));
+
+ it(`should enable download/update buttons but not delete`, async(() => {
+ const fixture = TestBed.createComponent(BlueprintsComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ app.selectedBPs = [{status: 'TEST'}]
+ app.enableButtonCheck()
+ fixture.detectChanges();
+
+ expect(app.canDownload).toEqual(true);
+ expect(app.canUpdate).toEqual(true);
+ expect(app.canDelete).toEqual(false);
+ }));
+
+ it(`should enable download/update buttons but not delete`, async(() => {
+ const fixture = TestBed.createComponent(BlueprintsComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ app.selectedBPs = [{ status: 'IN_DEV' }]
+ app.enableButtonCheck()
+ fixture.detectChanges();
+
+ expect(app.canDownload).toEqual(true);
+ expect(app.canUpdate).toEqual(true);
+ expect(app.canDelete).toEqual(true);
+ }));
+
+ it(`should enable download/update buttons but not delete`, async(() => {
+ const fixture = TestBed.createComponent(BlueprintsComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ let mockBpToView = {
+ tag: 'test-tag',
+ type: 'k8s',
+ instanceRelease: '2008',
+ version: '1',
+ content: 'test'
+ }
+
+ app.viewBpContent(mockBpToView)
+ fixture.detectChanges();
+
+ expect(app.BpFileNameForDownload).toEqual('test-tag_k8s_2008_1');
+ expect(app.BpContentToView).toEqual('test');
+ expect(app.showBpContentDialog).toEqual(true);
+ }));
+
+});
+
+
diff --git a/mod2/ui/src/app/blueprints/blueprints.component.ts b/mod2/ui/src/app/blueprints/blueprints.component.ts
new file mode 100644
index 0000000..b4a7e73
--- /dev/null
+++ b/mod2/ui/src/app/blueprints/blueprints.component.ts
@@ -0,0 +1,602 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, ViewChild, ElementRef, Input, EventEmitter, Output, ChangeDetectorRef } from '@angular/core';
+import { Table } from 'primeng/table';
+import { MessageService } from 'primeng/api';
+import { trigger, state, style, transition, animate } from '@angular/animations';
+import * as saveAs from 'file-saver';
+import * as JSZip from 'jszip';
+import { AuthService } from '../services/auth.service';
+import { DatePipe } from '@angular/common';
+import { DeploymentArtifactService } from '../services/deployment-artifact.service';
+import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
+import { Toast } from 'primeng/toast'
+import { ActivatedRoute } from '@angular/router';
+import { DownloadService } from '../services/download.service';
+
+@Component({
+ selector: 'app-blueprints',
+ templateUrl: './blueprints.component.html',
+ styleUrls: ['./blueprints.component.css'],
+ animations: [
+ trigger('rowExpansionTrigger', [
+ state('void', style({
+ transform: 'translateX(-10%)',
+ opacity: 0
+ })),
+ state('active', style({
+ transform: 'translateX(0)',
+ opacity: 1
+ })),
+ transition('* <=> *', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
+ ])
+ ],
+ providers: [DatePipe, MessageService]
+})
+export class BlueprintsComponent implements OnInit {
+ @ViewChild(Table, { static: false }) dt: Table;
+ @ViewChild(Toast, { static: false }) toast: Toast;
+
+ /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. **/
+ bpElements: BlueprintElement[] = [];
+ cols: any[] = [
+ { field: 'instanceName', header: 'Instance Name' },
+ { field: 'instanceRelease', header: 'Instance Release', width: '7%' },
+ { field: 'tag', header: 'Tag' },
+ { field: 'type', header: 'Type', width: '7%' },
+ { field: 'version', header: 'Version', width: '6%' },
+ { field: 'status', header: 'Status', width: '125px' }];
+ states: {field: string, label: string}[] = [];
+ columns: any[];
+ filteredRows: any;
+ downloadItems: { label: string; command: () => void; }[];
+ username: string;
+ showBpContentDialog: boolean = false;
+ selectedBPs: BlueprintElement[] = [];
+ // Hides the BP list until the rows are retrieved and filtered
+ visible = "hidden";
+ // These 2 fields are passed from MS Instance to filter the BP list
+ tag: string;
+ release: string;
+
+ filteredName: string;
+ filteredRelease: string;
+ filteredTag: string;
+ filteredType: string;
+ filteredVersion: string;
+ filteredStatus: string;
+
+ constructor(private change: ChangeDetectorRef, private messageService: MessageService, private authService: AuthService,
+ private datePipe: DatePipe, private bpApis: DeploymentArtifactService, private spinnerService: Ng4LoadingSpinnerService,
+ private route: ActivatedRoute, private downloadService: DownloadService) { }
+
+ ngOnInit() {
+
+ this.username = this.authService.getUser().username;
+
+ this.getStates();
+ this.getAllBPs();
+
+ this.change.markForCheck();
+
+ this.route.queryParams.subscribe((params) => {
+ this.filteredTag = params['tag'];
+ this.filteredRelease = params['release']});
+ }
+
+ //gets statuses for status updates
+ getStates(){
+ this.states = []
+ this.bpApis.getStatuses().subscribe((response) => {this.setMenuStates(response)})
+ }
+
+ //fills actions menu with states
+ setMenuStates(states){
+ for(let item of states){
+ this.states.push({
+ field: item,
+ label: 'To ' + item
+ })
+ }
+ }
+
+ canDelete: boolean = false;
+ canDownload: boolean = false;
+ canUpdate: boolean = false;
+ deleteTooltip: string;
+ enableButtonCheck(){
+ if(this.selectedBPs.length > 0){
+ this.canDownload = true;
+ this.canUpdate = true;
+
+ for(let item of this.selectedBPs){
+ if (item.status !== 'IN_DEV' && item.status !== 'NOT_NEEDED' && item.status !== 'DEV_COMPLETE'){
+ this.canDelete = false;
+ this.deleteTooltip = 'Only blueprints that are in a status of "In Dev", "Not Needed" or "Dev Complete" can be deleted'
+ break
+ } else {
+ this.canDelete = true;
+ }
+ }
+
+ } else {
+ this.canDownload = false;
+ this.canUpdate = false;
+ this.canDelete = false;
+ this.deleteTooltip = 'No Blueprints Selected'
+ }
+ }
+
+ updateStateTo: string = ''; //selected state to update blueprint to
+ //checks if there are different releases/statuses selected
+ updateSelectedStatusesCheck(state){
+ this.updateStateTo = state.field
+ let multipleStates: boolean = false
+ let multipleReleases: boolean = false
+ let firstStatus = this.selectedBPs[0]['status']
+ let firstRelease = this.selectedBPs[0]['instanceRelease']
+
+ for(let bp of this.selectedBPs){
+ if(bp.instanceRelease !== firstRelease){
+ multipleReleases = true
+ }
+ if (bp.status !== firstStatus) {
+ multipleStates = true
+ }
+ }
+
+ if(multipleReleases && multipleStates){
+ this.messageService.add({ key: 'confirmToast', sticky: true, severity: 'warn', summary: 'Are you sure?', detail: 'You are about to update blueprints for different releases and statuses. Confirm to proceed.' });
+ } else if (multipleReleases && !multipleStates) {
+ this.messageService.add({ key: 'confirmToast', sticky: true, severity: 'warn', summary: 'Are you sure?', detail: 'You are about to update blueprints for different releases. Confirm to proceed.' });
+ } else if (!multipleReleases && multipleStates) {
+ this.messageService.add({ key: 'confirmToast', sticky: true, severity: 'warn', summary: 'Are you sure?', detail: 'You are about to update blueprints for different statuses. Confirm to proceed.' });
+ } else if (!multipleReleases && !multipleStates){
+ this.updateSelectedStatuses()
+ }
+ }
+ onConfirm() {
+ this.messageService.clear('confirmToast')
+ this.updateSelectedStatuses()
+ }
+ onReject() {
+ this.messageService.clear('confirmToast')
+ }
+
+ /* * * * Update status for multiple blueprints * * * */
+ successfulStatusUpdates: number = 0 //keeps track of how many status updates were successful
+ selectionLength: number = 0 //length of array of blueprints with different statuses than update choice
+ statusUpdateCount: number = 0 //keeps track of how many api calls have been made throughout a loop
+ statusUpdateErrors: string[] = [] //keeps list of errors
+ updateSelectedStatuses(){
+ this.successfulStatusUpdates = 0
+ this.statusUpdateErrors = []
+ this.statusUpdateCount = 0
+
+ let bpsToUpdate = this.selectedBPs.filter(bp => bp.status !== this.updateStateTo) //array of blueprints with different statuses than update choice
+ this.selectionLength = bpsToUpdate.length;
+
+ if (this.selectionLength === 0) { this.selectedBPs = [] } else {
+ this.spinnerService.show();
+ this.updateState(this.updateStateTo, bpsToUpdate, true)
+ }
+ }
+
+ /* * * * Update Statuses * * * */
+ //state is the state to update to
+ //data is the bp data from selection
+ //multiple is whether updates were called for single blueprint or multiple selected blueprints
+ updateState(state, data, multiple){
+ //single status update
+ if(!multiple){
+ this.bpApis.patchBlueprintStatus(state.field, data['id']).subscribe(
+ (response: string) => {
+ data.status = state.field
+ this.messageService.add({ key: 'statusUpdate', severity: 'success', summary: 'Status Updated' });
+ }, errResponse => {
+ this.statusUpdatesResponseHandler(errResponse, false)
+ }
+ )
+ }
+
+ //multiple status updates
+ if(multiple){
+ (async () => {
+ for (let bp of data) {
+ this.bpApis.patchBlueprintStatus(this.updateStateTo, bp.id).subscribe(
+ (response: string) => {
+ bp.status = this.updateStateTo
+ this.statusUpdatesResponseHandler(null, true)
+ }, errResponse => {
+ this.statusUpdatesResponseHandler(errResponse, true)
+ }
+ )
+ await timeout(1500);
+ }
+ })();
+
+ function timeout(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+ }
+ }
+ }
+
+ /* * * * Handles errors and messages for status updates * * * */
+ statusUpdatesResponseHandler(response, multiple){
+ if(!multiple){
+ if(response !== null){
+ if (response.error.message.includes('Only 1 blueprint can be in the DEV_COMPLETE state.')) {
+ let message = response.error.message.replace('Only 1 blueprint can be in the DEV_COMPLETE state. ', '\n\nOnly 1 blueprint can be in the DEV_COMPLETE state.\n')
+ this.messageService.add({ key: 'statusUpdate', severity: 'error', summary: 'Status Not Updated', detail: message, sticky: true });
+ } else {
+ this.messageService.add({ key: 'statusUpdate', severity: 'error', summary: 'Error Message', detail: response.error.message, sticky: true });
+ }
+ }
+ }
+
+ if(multiple){
+ this.statusUpdateCount++
+ if (response === null) {
+ this.successfulStatusUpdates++
+ } else {
+ if (response.error.message.includes('Only 1 blueprint can be in the DEV_COMPLETE state.')) {
+ let error = response.error.message.split('Only 1 blueprint can be in the DEV_COMPLETE state.')[0]
+ this.statusUpdateErrors.push(error)
+ } else {
+ this.messageService.add({ key: 'statusUpdate', severity: 'error', summary: 'Error Message', detail: response.error.message, sticky: true });
+ }
+ }
+
+ if (this.statusUpdateCount === this.selectionLength) {
+ if (this.successfulStatusUpdates > 0) {
+ this.messageService.add({ key: 'statusUpdate', severity: 'success', summary: `(${this.successfulStatusUpdates} of ${this.selectionLength}) Statuses Updated`, life: 5000 });
+ }
+ if (this.statusUpdateErrors.length > 0) {
+ let message: string = ''
+ for (let elem of this.statusUpdateErrors) {
+ message += '- ' + elem + '\n'
+ }
+ message += '\nOnly 1 blueprint can be in the DEV_COMPLETE state.\nChange the current DEV_COMPLETE blueprint to NOT_NEEDED or IN_DEV before changing another to DEV_COMPLETE.'
+ this.messageService.add({ key: 'statusUpdate', severity: 'error', summary: 'Statuses Not Updated', detail: message, sticky: true });
+ }
+ this.spinnerService.hide()
+ this.selectedBPs = []
+ }
+ }
+ }
+
+ bpToDelete: any;
+ deleteSingle: boolean = false;
+ rowIndexToDelete;
+ rowIndexToDeleteFiltered;
+ warnDeleteBlueprint(data){
+ if(data !== null){
+ this.deleteSingle = true;
+ this.rowIndexToDeleteFiltered = this.filteredRows.map(function (x) { return x.id; }).indexOf(data['id']);
+ this.rowIndexToDelete = this.bpElements.map(function (x) { return x.id; }).indexOf(data['id']);
+ this.bpToDelete = data;
+ this.messageService.add({ key: 'confirmDeleteToast', sticky: true, severity: 'warn', summary: 'Are you sure?', detail: `- ${data.instanceName} (v${data.version}) for ${data.instanceRelease}` });
+ } else {
+ this.deleteSingle = false;
+ this.selectionLength = this.selectedBPs.length;
+ let warnMessage: string = ''
+ for(let item of this.selectedBPs){
+ warnMessage += `- ${item.instanceName} (v${item.version}) for ${item.instanceRelease}\n`
+ }
+ this.messageService.add({ key: 'confirmDeleteToast', sticky: true, severity: 'warn', summary: 'Are you sure?', detail: warnMessage });
+ }
+ }
+
+ resetFilter = false;
+ onConfirmDelete() {
+ this.messageService.clear('confirmDeleteToast')
+
+ if (this.filteredName !== '' || this.filteredRelease !== '' || this.filteredTag !== '' || this.filteredType !== '' || this.filteredVersion !== '' || this.filteredStatus !== ''){
+ this.resetFilter = true;
+ } else {this.resetFilter = false}
+
+ if(this.deleteSingle){
+ this.bpApis.deleteBlueprint(this.bpToDelete['id']).subscribe(response => {
+ this.checkBpWasSelected(this.bpToDelete['id'])
+ this.bpElements.splice(this.rowIndexToDelete, 1)
+ if (this.resetFilter) {
+ this.resetFilters()
+ }
+ this.messageService.add({ key: 'bpDeleteResponse', severity: 'success', summary: 'Success Message', detail: 'Deployment Artifact Deleted' });
+ }, error => {
+ this.messageService.add({ key: 'bpDeleteResponse', severity: 'error', summary: 'Error Message', detail: error.error.message });
+ })
+ } else {
+ for(let item of this.selectedBPs){
+ this.bpApis.deleteBlueprint(item.id).subscribe(response => {
+ this.deleteResponseHandler(true, item.id)
+ }, error => {
+ this.messageService.add({ key: 'bpDeleteResponse', severity: 'error', summary: 'Error Message', detail: error.error.message });
+ })
+ }
+ }
+ }
+ onRejectDelete() {
+ this.messageService.clear('confirmDeleteToast')
+ }
+
+ checkBpWasSelected(id){
+ if(this.selectedBPs.length > 0){
+ for(let item of this.selectedBPs){
+ if(item.id === id){
+ let indexToDelete = this.selectedBPs.map(function (x) { return x.id; }).indexOf(item['id']);
+ this.selectedBPs.splice(indexToDelete, 1)
+ }
+ }
+ }
+ }
+
+ bpsToDelete: string[] = [];
+ deleteBpCount = 0;
+ deleteResponseHandler(success, bpToDeleteId){
+ this.deleteBpCount++
+ if(success){
+ this.bpsToDelete.push(bpToDeleteId)
+ }
+ if(this.deleteBpCount === this.selectionLength){
+ for(let item of this.bpsToDelete){
+
+ let indexToDelete = this.bpElements.map(function (x) { return x.id; }).indexOf(item);
+ this.bpElements.splice(indexToDelete, 1)
+ }
+
+ if(this.resetFilter){
+ this.resetFilters()
+ }
+
+ this.selectedBPs = [];
+ this.bpsToDelete = [];
+ this.deleteBpCount = 0;
+ this.messageService.add({ key: 'bpDeleteResponse', severity: 'success', summary: 'Success Message', detail: 'Deployment Artifacts Deleted' });
+ }
+ }
+
+ resetFilters(){
+ let filters: {field: string, value: string}[] = [];
+ filters.push({field: 'instanceName', value: this.filteredName})
+ filters.push({ field: 'instanceRelease', value: this.filteredRelease })
+ filters.push({ field: 'tag', value: this.filteredTag })
+ filters.push({ field: 'type', value: this.filteredType })
+ filters.push({ field: 'version', value: this.filteredVersion })
+ filters.push({ field: 'status', value: this.filteredStatus })
+
+ for(let item of filters){
+ this.dt.filter(item.value, item.field, 'contains')
+ }
+ }
+
+ /* * * * Gets all blueprints * * * */
+ getAllBPs() {
+ this.spinnerService.show();
+ this.bpElements = [];
+ this.columns = this.cols.map(col => ({ title: col.header, dataKey: col.field }));
+
+ this.visible = "hidden";
+
+ this.bpApis.getAllBlueprints()
+ .subscribe((data: any[]) => {
+ this.fillTable(data)
+ })
+
+ }
+
+ /* * * * Checks when table is filtered and stores filtered data in new object to be downloaded when download button is clicked * * * */
+ onTableFiltered(values) {
+ if (values) {
+ this.filteredRows = values;
+ } else {
+ this.filteredRows = this.bpElements
+ }
+ }
+
+ /* * * * Download table as excel file * * * */
+ exportTable(exportTo) {
+ let downloadElements: any[] = []
+
+ for (let row of this.filteredRows) {
+ let labels;
+ let notes;
+ if (exportTo === "excel") {
+ if (row.metadata.labels !== undefined && row.metadata.labels !== null ) {
+ labels = row.metadata.labels.join(",")
+ }
+ } else {
+ labels = row.metadata.labels
+ }
+
+ if (row.metadata.notes !== null && row.metadata.notes !== undefined && row.metadata.notes !== '') {
+ notes = encodeURI(row.metadata.notes).replace(/%20/g, " ").replace(/%0A/g, "\\n")
+ }
+
+ downloadElements.push({
+ Instance_Name: row.instanceName,
+ Instance_Release: row.instanceRelease,
+ Tag: row.tag,
+ Type: row.type,
+ Version: row.version,
+ Status: row.status,
+ Created_By: row.metadata.createdBy,
+ Created_On: row.metadata.createdOn,
+ Updated_By: row.metadata.updatedBy,
+ Updated_On: row.metadata.updatedOn,
+ Failure_Reason: row.metadata.failureReason,
+ Notes: notes,
+ Labels: labels
+ })
+ }
+
+ let csvHeaders = []
+
+ if (exportTo === "csv") {
+ csvHeaders = [
+ "Instance_Name",
+ "Instance_Release",
+ "Tag",
+ "Type",
+ "Version",
+ "Status",
+ "Created_By",
+ "Created_On",
+ "Updated_By",
+ "Updated_On",
+ "Failure_Reason",
+ "Notes",
+ "Labels"];
+
+ }
+
+ this.downloadService.exportTableData(exportTo, downloadElements, csvHeaders)
+ }
+
+ /* * * * Fills object with blueprint data to be used to fill table * * * */
+ fillTable(data) {
+ let fileName: string;
+ let tag: string;
+ let type: string;
+
+ for (let elem of data) {
+ fileName = elem.fileName;
+ if(fileName.includes('docker')){
+ type = 'docker'
+ if(fileName.includes('-docker')){
+ tag = fileName.split('-docker')[0]
+ } else if (fileName.includes('_docker')){
+ tag = fileName.split('_docker')[0]
+ }
+ } else if (fileName.includes('k8s')){
+ type = 'k8s'
+ if (fileName.includes('-k8s')) {
+ tag = fileName.split('-k8s')[0]
+ } else if (fileName.includes('_k8s')) {
+ tag = fileName.split('_k8s')[0]
+ }
+ }
+
+ //create temporary bp element to push to array of blueprints
+ var tempBpElement: BlueprintElement = {
+ instanceId: elem.msInstanceInfo.id,
+ instanceName: elem.msInstanceInfo.name,
+ instanceRelease: elem.msInstanceInfo.release,
+ id: elem.id,
+ version: elem.version,
+ content: elem.content,
+ status: elem.status,
+ fileName: fileName,
+ tag: tag,
+ type: type,
+ metadata: {
+ failureReason: elem.metadata.failureReason,
+ notes: elem.metadata.notes,
+ labels: elem.metadata.labels,
+ createdBy: elem.metadata.createdBy,
+ createdOn: this.datePipe.transform(elem.metadata.createdOn, 'MM-dd-yyyy HH:mm'),
+ updatedBy: elem.metadata.updatedBy,
+ updatedOn: this.datePipe.transform(elem.metadata.updatedOn, 'MM-dd-yyyy HH:mm')
+ },
+ specification: {
+ id: elem.specificationInfo.id
+ }
+ }
+
+ this.bpElements.push(tempBpElement)
+ }
+ this.bpElements.reverse();
+ this.filteredRows = this.bpElements;
+
+ this.resetFilters();
+
+ this.visible = "visible";
+ this.spinnerService.hide();
+ }
+
+ /* * * * Define content to show in bp view dialog pop up * * * */
+ BpContentToView: string;
+ viewBpContent(data){
+ this.BpFileNameForDownload = `${data['tag']}_${data['type']}_${data['instanceRelease']}_${data['version']}`
+ this.BpContentToView = data['content']
+ this.showBpContentDialog = true
+ }
+
+ /* * * * Download single blueprint * * * */
+ BpFileNameForDownload: string;
+ download() {
+ let file = new Blob([this.BpContentToView], { type: 'text;charset=utf-8' });
+ let name: string = this.BpFileNameForDownload + '.yaml'
+ saveAs(file, name)
+ }
+
+/* * * * Download selected blueprints * * * */
+ downloadSelectedBps() {
+ let canDownloadBps: boolean = true;
+
+ //checks if blueprints for multiple releases are selected
+ let selectedBpRelease: string = this.selectedBPs[0]['instanceRelease'];
+ for (let bp in this.selectedBPs) {
+ if (this.selectedBPs[bp]['instanceRelease'] !== selectedBpRelease) {
+ canDownloadBps = false
+ break
+ }
+ }
+
+ //downloads blueprints to zip file if all selected blueprints are for one release
+ if (canDownloadBps) {
+ var zip = new JSZip();
+ for (var i in this.selectedBPs) {
+ zip.file(`${this.selectedBPs[i]['tag']}_${this.selectedBPs[i]['type']}_${this.selectedBPs[i]['instanceRelease']}_${this.selectedBPs[i]['version']}.yaml`, this.selectedBPs[i]['content'])
+ }
+ zip.generateAsync({ type: "blob" }).then(function (content) {
+ saveAs(content, 'Blueprints.zip');
+ });
+ } else {
+ this.messageService.add({ key: 'multipleBpReleasesSelected', severity: 'error', summary: 'Error Message', detail: "Cannot download blueprints for different releases" });
+ }
+
+ this.selectedBPs = []
+ }
+}
+
+export interface BlueprintElement{
+ instanceId: string
+ instanceName: string
+ instanceRelease: string
+ id: string
+ version: string
+ content: string
+ status: string
+ fileName: string
+ tag: string
+ type: string
+ metadata: {
+ failureReason: string
+ notes: string
+ labels: string[]
+ createdBy: string
+ createdOn: string
+ updatedBy: string
+ updatedOn: string
+ },
+ specification: {
+ id: string
+ }
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.css b/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.css
new file mode 100644
index 0000000..54806ab
--- /dev/null
+++ b/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.css
@@ -0,0 +1,43 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+.input {
+ padding-top: 10px;
+}
+
+.inputLabel {
+ font-weight: 600;
+ margin-left: 20px;
+ width: 135px;
+}
+
+.inputFieldSm {
+ width: 200px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldMed {
+ width: 300px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldLg {
+ width: 400px;
+ height: 35px;
+ padding-left: 6px;
+}
diff --git a/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.html b/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.html
new file mode 100644
index 0000000..f15f19b
--- /dev/null
+++ b/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.html
@@ -0,0 +1,64 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<p-dialog *ngIf="visible" header="Component Spec ADD" [(visible)]="visible" appendTo="body" [modal]="true" [transitionOptions]="'300ms'"
+ [closeOnEscape]="false" [closable]="false" [style]="{width: '650px'}" (onHide)="closeDialog()">
+
+ <!-- * * * * * Input fields * * * * * -->
+ <form [formGroup]="csAddForm" (ngSubmit)="saveCs()" class="bg-faded">
+ <!-- * * * Type * * * -->
+ <div class="input">
+ <label class="inputLabel">Type<span style="color:red">*</span></label>
+ <p-dropdown [options]="types" placeholder="Select Type" optionLabel="type" formControlName="type"></p-dropdown>
+ </div>
+ <!-- * * * Labels * * * -->
+ <div class="input">
+ <label class="inputLabel">Labels</label>
+ <input class="inputFieldLg" type="text" pInputText formControlName="labels" />
+ </div>
+ <span style="padding: 9px 0px 0px 158px; font-size: 13px;">(Separate labels with a space)</span>
+ <!-- * * * Notes * * * -->
+ <div class="input">
+ <label class="inputLabel" style="vertical-align: top">Notes</label>
+ <textarea class="inputFieldLg" [rows]="1" [cols]="30" pInputTextarea autoResize="autoResize" formControlName="notes"></textarea>
+ </div>
+ <!-- * * * Comp Spec File Select * * * -->
+ <div class="input">
+ <label class="inputLabel">Component Spec<span style="color:red">*</span></label>
+
+ <input type="file" style="width: 460px; color:blue; font-style: italic;" (input)="onCompSpecUpload($event)" name="myfile" id="myfile" accept=".json">
+ </div>
+
+ <!-- * * * Policy File Select * * * -->
+ <div class="input">
+ <label class="inputLabel">Policy</label>
+
+ <input type="file" style="width: 460px; color:blue; font-style: italic;" (input)="onPolicyUpload($event)"
+ name="myPolicyFile" id="myPolicyFile" accept=".json">
+ </div>
+
+ <!-- * * * ADD and Cancel buttons * * * -->
+ <div style="float: right; padding: 20px 45px">
+ <button pButton type="button" (click)="closeDialog()" label="Cancel"></button>&nbsp;
+ <button pButton type="submit" class="ui-button-success" label="Add" [disabled]="!csAddForm.valid || !compSpecSelected" style="width: 70px"></button>
+ </div>
+ </form>
+
+ <p-toast key="jsonError" [style]="{width: '430px'}"></p-toast>
+
+</p-dialog>
diff --git a/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.spec.ts b/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.spec.ts
new file mode 100644
index 0000000..e29a110
--- /dev/null
+++ b/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.spec.ts
@@ -0,0 +1,77 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { MessageService } from 'primeng/api';
+import { ButtonModule } from 'primeng/button';
+import { DialogModule } from 'primeng/dialog';
+import { DropdownModule } from 'primeng/dropdown';
+import { ToastModule } from 'primeng/toast';
+
+
+import { CompSpecAddComponent } from './comp-spec-add.component';
+
+describe('CompSpecAddComponent', () => {
+ let component: CompSpecAddComponent;
+ let fixture: ComponentFixture<CompSpecAddComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [CompSpecAddComponent],
+ imports: [
+ DialogModule,
+ DropdownModule,
+ ToastModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ButtonModule,
+ HttpClientTestingModule,
+ RouterTestingModule
+ ],
+ providers: [
+ MessageService,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CompSpecAddComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it(`should invalidate spec JSON structure`, async(() => {
+ const fixture = TestBed.createComponent(CompSpecAddComponent);
+ const app = fixture.debugElement.componentInstance;
+ let mockErrorJson = "test: 'test}"
+ app.compSpecContent = mockErrorJson
+ expect(() => app.validateJsonStructure()).toThrowError('JSON Structure error, quit!')
+ }));
+
+});
diff --git a/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.ts b/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.ts
new file mode 100644
index 0000000..7564852
--- /dev/null
+++ b/mod2/ui/src/app/comp-spec-add/comp-spec-add.component.ts
@@ -0,0 +1,180 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { InputTextModule } from 'primeng/inputtext';
+import { DropdownModule } from 'primeng/dropdown';
+import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
+import { AuthService } from '../services/auth.service';
+import { MessageService } from 'primeng/api';
+
+interface Type {
+ type: string;
+}
+
+@Component({
+ selector: 'app-comp-spec-add',
+ templateUrl: './comp-spec-add.component.html',
+ styleUrls: ['./comp-spec-add.component.css']
+})
+
+export class CompSpecAddComponent implements OnInit {
+
+ compSpecSelected: any;
+ compSpecContent: any;
+
+ policySelected: any;
+ policyContent: any;
+
+ csAddForm: FormGroup;
+ // The loggged in user
+ username: string;
+
+ // Input form fields
+ type: string;
+ labels: string;
+ notes: string;
+ specFile: any;
+ policyJson: any;
+
+ // Dropdowns
+ types: Type[];
+
+ // Build JSON as a string
+ csAddString: any;
+ // Return JSON to parent component
+ csAddJson: any;
+
+ constructor(private fb: FormBuilder, private authService: AuthService, private messageService: MessageService) {
+ }
+
+ @Input() visible: boolean;
+ @Output() handler: EventEmitter<any> = new EventEmitter();
+
+ ngOnInit() {
+ // The logged in user
+ this.username = this.authService.getUser().username;
+
+ this.csAddForm = new FormGroup({
+ type: new FormControl(),
+ labels: new FormControl(),
+ notes: new FormControl(),
+ specFile: new FormControl(),
+ policyJson: new FormControl()
+ });
+
+ // FORM fields and validations
+ this.csAddForm = this.fb.group({
+ type: ['', [Validators.required]],
+ labels: ['', []],
+ notes: ['', []],
+ specFile: ['', []],
+ policyJson: ['', []]
+ });
+
+ // TYPE Dropdown
+ this.types = [
+ { type: 'DOCKER' },
+ { type: 'K8S' }
+ ];
+ }
+
+ saveCs() {
+ this.createOutputJson();
+ this.csAddJson = JSON.stringify(this.csAddString);
+ this.handler.emit(this.csAddJson);
+ this.closeDialog();
+ }
+
+ // Create the JSON to be sent to the parent component
+ // The "labels" functions below take into account leading/trailing spaces, multiple spaces between labels, and conversion into an array
+ createOutputJson() {
+ this.validateJsonStructure();
+
+ let policy;
+ if(this.policyContent !== undefined){
+ policy = JSON.parse(this.policyContent)
+ } else {
+ policy = null
+ }
+
+ this.csAddString = {
+ specContent: JSON.parse(this.compSpecContent),
+ policyJson: policy,
+ type: this.csAddForm.value['type'].type,
+ metadata: {
+ labels: this.csAddForm.value['labels'].trim().replace(/\s{2,}/g, ' ').split(" "),
+ notes: this.csAddForm.value['notes']
+ },
+ user: this.username
+ };
+ }
+
+ // Validate, catch, display JSON structure error, and quit!
+ validateJsonStructure() {
+ try {
+ JSON.parse(this.compSpecContent);
+ } catch (error) {
+ this.messageService.add({ key: 'jsonError', severity: 'error', summary: 'Invalid Component Spec JSON', detail: error, sticky: true });
+ throw new Error('JSON Structure error, quit!');
+ }
+
+ if(this.policyContent !== undefined){
+ try {
+ JSON.parse(this.policyContent);
+ } catch (error) {
+ this.messageService.add({ key: 'jsonError', severity: 'error', summary: 'Invalid Policy JSON', detail: error, sticky: true });
+ throw new Error('JSON Structure error, quit!');
+ }
+ }
+ }
+
+ // Read the selected Component Spec JSON file
+ onCompSpecUpload(event) {
+ this.compSpecSelected = event.target.files[0];
+ this.readCsFileContent(this.compSpecSelected);
+ }
+ //Read the selected Component Spec JSON file
+ onPolicyUpload(event) {
+ this.policySelected = event.target.files[0];
+ this.readPolicyFileContent(this.policySelected);
+ }
+
+ readCsFileContent(file) {
+ if (file) {
+ let fileReader = new FileReader();
+ fileReader.onload = (e) => { this.compSpecContent = fileReader.result; };
+ fileReader.readAsText(file);
+ }
+ }
+
+ readPolicyFileContent(file) {
+ if (file) {
+ let fileReader = new FileReader();
+ fileReader.onload = (e) => { this.policyContent = fileReader.result; };
+ fileReader.readAsText(file);
+ }
+ }
+
+ // The handler emits 'null' back to parent to close dialog and make it available again when clicked
+ closeDialog() {
+ this.visible = false;
+ this.handler.emit(null);
+ }
+
+}
diff --git a/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.css b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.css
new file mode 100644
index 0000000..d76e0fa
--- /dev/null
+++ b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.css
@@ -0,0 +1,73 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+.validator-input-card{
+ width: 40%;
+ min-width: 430px;
+ min-height: 100%;
+ border: 2px solid slategray;
+ border-radius: 5px;
+ background-color: white;
+ padding: 1%;
+}
+.validator-output-card{
+ width: 58%;
+ border: 2px solid slategray;
+ margin-left: 2%;
+ min-height: 100%;
+ border-radius: 5px;
+ background-color: white;
+ padding: 1%;
+}
+
+.input-section-card{
+ font-size: 14px;
+ border: solid slategray;
+ border-style: double;
+ margin-top: 7px
+}
+
+.validateSpec{
+ margin-top: 10px;
+}
+.downloadSchema{
+ margin-top: 80px;
+}
+
+.type-selection{
+ position: absolute;
+ background-color: rgba(128, 128, 128, 0.15);
+ width: 190px;
+ height: 40px;
+ display: inline-flex;
+ align-items: center;
+ margin-left: 150px;
+}
+
+.greenOutput{
+ background-color: rgba(0, 255, 0, 0.205);
+ height: 40px;
+ padding: 3px;
+ border: 2px solid rgba(0, 66, 0, 0.747);
+}
+.redOutput{
+ background-color: rgba(255, 0, 0, 0.267);
+ height: 87%;
+ padding: 10px;
+ border: 2px solid rgba(65, 0, 0, 0.712);
+}
diff --git a/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.html b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.html
new file mode 100644
index 0000000..9867364
--- /dev/null
+++ b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.html
@@ -0,0 +1,108 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<div style="margin-left: 2%; margin-right: 2%;">
+ <p style="font-size: 26px;">Component Specification Validation</p>
+ <div style="display: inline-flex; width: 100%; height: 100%; min-height: 450px;">
+ <div class="validator-input-card">
+ <div>
+ <mat-card class="input-section-card">
+ <span><b>Action</b></span><span style="color:red">*</span><br>
+ <div style="display: inline-flex;">
+ <div style="padding-right: 10%; width: 200px;">
+ <p-radioButton name="spec-validator-actions" value="validateSpec" [(ngModel)]="spec_validator_action" (click)="validateRadioButton()"></p-radioButton>&nbsp;&nbsp;Validate Spec File
+ </div>
+ <div>
+ <p-radioButton name="spec-validator-actions" value="downloadSchema" [(ngModel)]="spec_validator_action" (click)="downloadRadioButton()"></p-radioButton>&nbsp;&nbsp;Download Schema
+ </div>
+ </div>
+ </mat-card>
+
+ <mat-card class="input-section-card">
+ <span><b>Release</b></span><span style="color:red">*</span><br>
+ <div>
+ <div style="display: inline-flex; align-items: center;">
+ <p-radioButton name="spec-validator-release" value="2007" [(ngModel)]="release"></p-radioButton>&nbsp;&nbsp;2007+
+ </div>
+ </div>
+ </mat-card>
+
+ <mat-card class="input-section-card">
+ <span><b>Type</b></span><span style="color:red">*</span><br>
+ <div>
+ <div style="display: inline-flex; align-items: center;">
+ <p-radioButton name="spec-validator-type" value="k8s" [(ngModel)]="type"></p-radioButton>&nbsp;&nbsp;K8s
+ </div>
+ <br>
+ <div style="display: inline-flex; align-items: center;">
+ <p-radioButton name="spec-validator-type" value="docker" [(ngModel)]="type"></p-radioButton>&nbsp;&nbsp;Docker
+ </div>
+ </div>
+ </mat-card>
+
+ <mat-card *ngIf="spec_validator_action === 'validateSpec'" class="input-section-card">
+ <!-- * * * Comp Spec File Select * * * -->
+ <div>
+ <b>Component Spec File</b><span style="color:red">*</span><br>
+
+ <div style="display: inline-flex;">
+ <input #myFile type="file" style="color:blue; font-style: italic; width: fit-content"
+ (input)="onCompSpecUpload($event)" name="myfile" accept=".json">
+
+ <button pButton type="button" (click)="resetFile()"
+ style="background-color: transparent; border: none; height: 20px;"><i class="pi pi-times"
+ style="color: black;"></i></button>
+ </div>
+ </div>
+ </mat-card>
+
+ <div>
+ <div *ngIf="shouldValidate" style="background-color: rgba(128, 128, 128, 0.315); height: 2px; width: 100%; margin-top: 2%;"></div>
+ <div *ngIf="shouldDownload" style="background-color: rgba(128, 128, 128, 0.315); height: 2px; width: 100%; margin-top: 22%;"></div>
+
+ <div style="float: right; margin-top: 8px">
+ <div *ngIf="shouldValidate" matTooltip="Fill In Required Fields" [matTooltipDisabled]="!(release === '' || type === '' || compSpecContent === null)" matTooltipPosition="above">
+ <button [disabled]="release === '' || type === '' || compSpecContent === null" pButton label="Validate Spec" type="button" (click)="validateSpec()"></button>
+ </div>
+ <div *ngIf="shouldDownload" matTooltip="Fill In Required Fields" [matTooltipDisabled]="!(release === '' || type === '')" matTooltipPosition="above">
+ <button [disabled]="release === '' || type === ''" pButton label="Download Schema" type="button" (click)="downloadSchema()"></button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div *ngIf="shouldValidate" class="validator-output-card">
+ <span><b>Output:</b></span><br><br>
+ <div *ngIf="specValidated" style="width: 100%; padding: 1%; border-radius: 3px; overflow: hidden;" [ngClass]="{'greenOutput' : validCompSpec === true, 'redOutput' : validCompSpec === false}">
+ <div>
+ <span style="font-weight: 500;">{{specValidationOutputHeader}}</span>
+ <div *ngIf="specValidationOutputMessage !== ''" style="margin-top: 10px; width: 100%; height: 2px; background-color: rgba(128, 128, 128, 0.315); "></div>
+
+ <div *ngIf="specValidationOutputMessage !== ''" style="margin-top: 10px">
+ <p-scrollPanel [style]="{width: '100%', height: '50vh'}">
+ <pre style="white-space: pre-wrap;"><b>Summary:</b><br>{{specValidationOutputSummary}}</pre>
+ <pre style="white-space: pre-wrap;"><b>Message(s):</b><br>{{specValidationOutputMessage}}</pre>
+ </p-scrollPanel>
+ </div>
+
+ </div>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.spec.ts b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.spec.ts
new file mode 100644
index 0000000..a9efe28
--- /dev/null
+++ b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.spec.ts
@@ -0,0 +1,132 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { RadioButtonModule } from 'primeng/radiobutton';
+
+import { CompSpecValidationComponent } from './comp-spec-validation.component';
+import { FormsModule } from '@angular/forms';
+import { MatCardModule, MatTooltipModule } from '@angular/material';
+import { ScrollPanelModule } from 'primeng/scrollpanel';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { MessageService } from 'primeng/api';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
+
+describe('CompSpecValidationComponent', () => {
+ let component: CompSpecValidationComponent;
+ let fixture: ComponentFixture<CompSpecValidationComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ CompSpecValidationComponent ],
+ imports: [
+ RadioButtonModule,
+ FormsModule,
+ MatCardModule,
+ MatTooltipModule,
+ ScrollPanelModule,
+ HttpClientTestingModule,
+ Ng4LoadingSpinnerModule
+ ],
+ providers: [
+ MessageService,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CompSpecValidationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it(`should have as shouldValidate 'false'`, () => {
+ const fixture = TestBed.createComponent(CompSpecValidationComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app.shouldValidate).toEqual(false);
+ });
+
+ it(`should change shouldValidate to 'true'`, async(() => {
+ const fixture = TestBed.createComponent(CompSpecValidationComponent);
+ const app = fixture.debugElement.componentInstance;
+ app.validateRadioButton()
+ fixture.detectChanges();
+ expect(app.shouldValidate).toEqual(true);
+ }));
+
+ it(`should have as shouldDownload 'false'`, () => {
+ const fixture = TestBed.createComponent(CompSpecValidationComponent);
+ const app = fixture.debugElement.componentInstance;
+ expect(app.shouldDownload).toEqual(false);
+ });
+
+ it(`should change shouldDownload to 'true'`, async(() => {
+ const fixture = TestBed.createComponent(CompSpecValidationComponent);
+ const app = fixture.debugElement.componentInstance;
+ app.downloadRadioButton()
+ fixture.detectChanges();
+ expect(app.shouldDownload).toEqual(true);
+ }));
+
+ it(`should set validation error message`, async(() => {
+ const fixture = TestBed.createComponent(CompSpecValidationComponent);
+ const app = fixture.debugElement.componentInstance;
+ let mockSuccess = {
+ status: 200
+ }
+ app.setSpecValidationMessage(mockSuccess)
+ fixture.detectChanges();
+ expect(app.validCompSpec).toEqual(true)
+ }));
+
+ it(`should set validation error message`, async(() => {
+ const fixture = TestBed.createComponent(CompSpecValidationComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ let mockError = {
+ status: 400,
+ error: {
+ summary: 'Test',
+ errors: [
+ 'error1',
+ 'error2'
+ ]
+ }
+ }
+ app.setSpecValidationMessage(mockError)
+ fixture.detectChanges();
+ expect(app.validCompSpec).toEqual(false)
+ }));
+
+ it(`should invalidate JSON structure`, async(() => {
+ const fixture = TestBed.createComponent(CompSpecValidationComponent);
+ const app = fixture.debugElement.componentInstance;
+ let mockErrorJson = "test: 'test}"
+ app.compSpecContent = mockErrorJson
+ expect(() => app.validateJsonStructure()).toThrowError('JSON Structure error, quit!')
+ }));
+
+});
diff --git a/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.ts b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.ts
new file mode 100644
index 0000000..2ce8fef
--- /dev/null
+++ b/mod2/ui/src/app/comp-spec-validation/comp-spec-validation.component.ts
@@ -0,0 +1,145 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
+import { SpecValidationService } from '../services/spec-validation.service';
+import { DownloadService } from '../services/download.service';
+import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
+
+@Component({
+ selector: 'app-comp-spec-validation',
+ templateUrl: './comp-spec-validation.component.html',
+ styleUrls: ['./comp-spec-validation.component.css']
+})
+export class CompSpecValidationComponent implements OnInit {
+
+ @ViewChild('myFile', {static: false})
+ myInputVariable: ElementRef;
+
+ spec_validator_action;
+ release = '';
+ type = '';
+ shouldValidate = false;
+ shouldDownload = false;
+ validCompSpec = false;
+ specValidated = false;
+ specValidationOutputSummary: any;
+
+ constructor(private specValidator: SpecValidationService, private downloadService: DownloadService, private spinnerService: Ng4LoadingSpinnerService ) { }
+
+ ngOnInit() {
+
+ }
+
+ compSpecSelected: any;
+ onCompSpecUpload(event){
+ this.compSpecSelected = event.target.files[0];
+ this.readCsFileContent(this.compSpecSelected);
+ }
+
+ compSpecContent: any = null;
+ readCsFileContent(file) {
+ if (file) {
+ let fileReader = new FileReader();
+ fileReader.onload = (e) => { this.compSpecContent = fileReader.result; };
+ fileReader.readAsText(file);
+ }
+ }
+
+ validateRadioButton(){
+ this.shouldValidate = true;
+ this.shouldDownload = false;
+ }
+
+ downloadRadioButton(){
+ this.shouldValidate = false;
+ this.shouldDownload = true;
+ this.compSpecContent = null;
+ this.specValidated = false
+ }
+
+ resetFile(){
+ this.myInputVariable.nativeElement.value = "";
+ this.compSpecContent = null
+ this.compSpecSelected = null
+ this.specValidated = false
+ }
+
+ specValidationOutputHeader = ''
+ specValidationOutputMessage = '';
+ validateSpec(){
+ this.specValidationOutputHeader = ""
+ this.specValidationOutputMessage = ""
+ this.specValidationOutputSummary = ""
+
+ this.spinnerService.show()
+ this.validateJsonStructure()
+ this.specValidator.sendSpecFile(this.compSpecContent, this.type, this.release).subscribe(
+ res => {}, err => {
+ this.setSpecValidationMessage(err)
+ }
+ )
+ }
+
+ setSpecValidationMessage(res){
+ if(res.status === 200){
+ this.specValidationOutputHeader = "Success: Valid Component Spec"
+ this.specValidationOutputMessage = ""
+ this.validCompSpec = true
+ } else {
+ this.specValidationOutputHeader = `${res.status} Error: Invalid Component Spec`
+ this.specValidationOutputSummary = res.error.summary
+
+ for(let item of res.error.errors){
+ this.specValidationOutputMessage += `- ${item}\n\n`
+ }
+
+ this.validCompSpec = false
+ }
+
+ this.specValidated = true;
+ this.spinnerService.hide()
+ }
+
+ validateJsonStructure() {
+ try {
+ JSON.parse(this.compSpecContent);
+ } catch (error) {
+ this.specValidationOutputHeader = "Error: Invalid Component Spec"
+ this.specValidationOutputSummary = "JSON Structure Error"
+ this.specValidationOutputMessage = error
+ this.validCompSpec = false
+ this.specValidated = true
+ this.spinnerService.hide()
+ throw new Error('JSON Structure error, quit!');
+ }
+ }
+
+ downloadSchema(){
+ this.spinnerService.show()
+ this.specValidator.getSchema(this.type).subscribe(
+ res => {
+ this.downloadService.downloadJSON(res, `${this.release}+_${this.type}_Schema`)
+ this.spinnerService.hide()
+ }, err => {
+ console.log(err)
+ this.spinnerService.hide()
+ }
+ )
+ }
+}
diff --git a/mod2/ui/src/app/comp-specs/comp-specs.component.css b/mod2/ui/src/app/comp-specs/comp-specs.component.css
new file mode 100644
index 0000000..5f86e73
--- /dev/null
+++ b/mod2/ui/src/app/comp-specs/comp-specs.component.css
@@ -0,0 +1,121 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+td{
+ word-break:break-all
+}
+
+textarea
+{
+ font-size: 12px;
+}
+
+.table_actions_button{
+ background-color: transparent;
+ border: none;
+ width: 20px;
+ height: 20px;
+ vertical-align: middle;
+}
+
+.row-expand-layout{
+ display: grid;
+ grid-template-columns: 30% 40% auto;
+ grid-gap: 10px;
+ grid-auto-rows: minmax(100px, auto);
+}
+
+.row-expand-card{
+ font-size: 12px;
+ grid-row: 1;
+ border-radius: 5px;
+ border: 1px solid slategray;
+ padding: 10px;
+ /* This height prevents vertical scroll bar in Notes */
+ height: 92px;
+ overflow: hidden;
+}
+
+label {
+ cursor: pointer;
+}
+
+.fa-refresh{
+ cursor: pointer;
+}
+
+.input{
+ padding-top: 10px;
+}
+
+.inputLabel {
+ font-weight: 600;
+ margin-left: 20px;
+ width: 140px;
+}
+
+.inputFieldSm {
+ width: 200px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldMed {
+ width: 300px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldLg {
+ width: 400px;
+ height: 35px;
+ padding-left: 6px;
+}
+
+.table_action_item{
+ outline: none;
+ font-size: 12px;
+}
+
+::ng-deep .mat-menu-content {
+padding-top: 0px !important;
+padding-bottom: 0px !important;
+}
+.mat-menu-item{
+line-height:30px;
+height:30px;
+}
+
+.greenStatus{
+ background-color: rgba(80, 233, 105, 0.87)
+}
+
+.redStatus{
+ background-color: rgba(255, 29, 29, 0.733)
+}
+
+.blueStatus{
+ background-color: rgba(0, 183, 255, 0.432)
+}
+
+.greyStatus{
+ background-color: rgba(150, 150, 150, 0.432)
+}
+
+.ui-state-highlight {
+ background-color: #878C94 !important;
+ color: black !important;
+}
diff --git a/mod2/ui/src/app/comp-specs/comp-specs.component.html b/mod2/ui/src/app/comp-specs/comp-specs.component.html
new file mode 100644
index 0000000..3061cdf
--- /dev/null
+++ b/mod2/ui/src/app/comp-specs/comp-specs.component.html
@@ -0,0 +1,189 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<div style="margin: 0px 50px 10px 20px; border: 1px solid darkslategray; min-width: 980px">
+ <p-table #dt *ngIf="loadTable" [columns]="cols" [value]="csElements" sortMode="multiple" [paginator]="true"
+ [rows]="18" [rowsPerPageOptions]="[10,12,14,16,18,20,25,50]" (onFilter)="onTableFiltered(dt.filteredValue)" dataKey="id">
+ <ng-template pTemplate="caption">
+
+ <div style="margin-left: -18%; width: 82%; max-height: 25px; display: inline-flex;">
+ <!--CS Table Header-->
+ <div style="float: left;">
+ <!--Refresh-->
+ <i class="fa fa-refresh" (click)="getAllCs()"></i>
+ <!--Global Filter-->
+ <input type="text" pInputText size="50" placeholder="Global Filter"
+ (input)="dt.filterGlobal($event.target.value, 'contains')"
+ style="width: 250px; height:25px; font-size: 12px; margin-left: 15px">
+ <i class="fa fa-search" style="margin:4px 0px 0 8px"></i>
+ </div>
+
+ <h4 style="margin-left: 15%"><b>Component Specs</b></h4>
+
+ </div>
+ </ng-template>
+
+ <ng-template pTemplate="header" let-columns>
+ <tr>
+ <th style="width: 3em"></th>
+ <th class="ui-state-highlight" *ngFor="let col of columns" [pSortableColumn]="col.field"
+ style="font-size: 12px; outline: none; vertical-align: bottom; text-align: center;" [ngStyle]="{'width': col.width}">
+ {{col.header}}<br>
+ <p-sortIcon [field]="col.field"></p-sortIcon>
+ </th>
+ <th style="font-size: 13px; width: 8%; vertical-align: top; text-align: center;">
+ Actions
+ </th>
+ </tr>
+
+ <!--Second header row for individual column filters-->
+ <tr style="text-align: center;">
+ <th style="width: 3em"></th>
+ <th *ngFor="let col of columns" [ngSwitch]="col.field">
+ <input pInputText type="text" (input)="dt.filter($event.target.value, col.field, 'contains')"
+ style="width: 100%; height: 20px; font-size: 10px;" placeholder="Filter">
+ </th>
+ <th>
+
+ </th>
+ </tr>
+ </ng-template>
+
+ <ng-template pTemplate="body" let-rowData let-csElem>
+ <tr style="font-size: 12px;">
+ <!--Column for row expand buttons-->
+ <td>
+ <a href="#" [pRowToggler]="rowData">
+ <i [ngClass]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></i>
+ </a>
+ </td>
+
+ <td *ngFor="let col of cols">
+ <div *ngIf="col.field==='status'"
+ style="width: fit-content; width: -moz-max-content; padding: 0px 5px 0px 5px; border-radius: 3px; font-weight: 600;"
+ [ngClass]="{'greenStatus' : csElem[col.field] === 'ACTIVE', 'greyStatus' : csElem[col.field] === 'INACTIVE'}">
+ {{csElem[col.field]}}
+ </div>
+ <div *ngIf="col.field!=='status'">{{csElem[col.field]}}</div>
+ </td>
+
+ <!--Actions Column-->
+ <td>
+ <div style="text-align: center;">
+ <button pButton type="button"
+ style="background-color: transparent; border: none; width: 20px; height: 20px; vertical-align: middle;"
+ class="ui-button-secondary" [matMenuTriggerFor]="menu">
+ <i class="pi pi-ellipsis-h" style="color: grey;"></i>
+ </button>
+ <mat-menu #menu="matMenu" xPosition="before">
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-search" style="font-size: 10px;"></i> View</span>
+ </div>
+
+ <button mat-menu-item class="table_action_item" (click)="showViewCsDialog(rowData)">Component Spec</button>
+ <div matTooltip="Policy not included" [matTooltipDisabled]="rowData.policyJson" matTooltipPosition="left">
+ <button mat-menu-item [disabled]="!rowData.policyJson" class="table_action_item" (click)="showViewPolicyDialog(rowData)">Policy</button>
+ </div>
+ <!--
+ <div *ngIf="rowData.status !== 'ACTIVE'">
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-pencil"
+ style="font-size: 10px;"></i> Update</span>
+ </div>
+
+ <button mat-menu-item class="table_action_item" (click)="toActive(rowData)">To Active</button>
+ </div>-->
+ </mat-menu>
+ </div>
+ </td>
+ </tr>
+ </ng-template>
+
+ <!--Row expand content-->
+ <ng-template pTemplate="rowexpansion" let-rowData let-columns="columns">
+ <tr>
+ <td [attr.colspan]="columns.length + 2">
+ <div class="row-expand-layout" [@rowExpansionTrigger]="'active'">
+ <!-- Audit Fields -->
+ <div class="row-expand-card" style="background-color: rgba(95, 158, 160, 0.295)">
+ <b>Created By:</b> {{rowData.metadata.createdBy}}<br>
+ <b>Created On:</b> {{rowData.metadata.createdOn}}<br>
+ <b>Updated By:</b> {{rowData.metadata.updatedBy}}<br>
+ <b>Updated On:</b> {{rowData.metadata.updatedOn}}
+ </div>
+ <!-- Notes -->
+ <div class="row-expand-card" style="background-color: rgba(100, 148, 237, 0.219)">
+ <b>Notes:</b><br>
+ <p-scrollPanel [style]="{width: '100%', height: '62px'}">
+ <div style="font-size: 12px; word-break: normal;">{{rowData.metadata.notes}}</div>
+ </p-scrollPanel>
+ </div>
+ <!-- Labels -->
+ <div class="row-expand-card" style="background-color: rgba(76, 65, 225, 0.199)">
+ <b style="padding-bottom: 5px;">Labels:</b><br>
+ <div *ngFor="let label of rowData['metadata']['labels']"
+ style="display: inline-flex; margin-top: 5px;">
+ <div style="padding: 2px 7px 3px 0px;">
+ <span
+ style="background-color: rgba(80, 80, 80, 0.185); padding: 3px; border-radius: 3px;">{{label}}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </td>
+ </tr>
+ </ng-template>
+ </p-table>
+
+ <!--download buttons for exporting table to either csv or excel file-->
+ <div *ngIf="loadTable" style="margin-left: 10px; margin-top: -32px; float: left;">
+ <button pButton type="button" (click)="exportTable('csv')" matTooltip="Export Table to CSV"
+ matTooltipPosition="above"
+ style="border-radius: 5px; width: 65px; height: 22px; font-size: 14px; border: none; margin-top: 4px; display: inline-flex;">
+ <i class="pi pi-file" style="margin-top: 2px; margin-left: 8px;"></i>
+ <label style="font-weight: 800; vertical-align: middle;">CSV</label>
+ </button>
+ <button pButton type="button" (click)="exportTable('excel')" matTooltip="Export Table to XLSX"
+ matTooltipPosition="above"
+ style="border-radius: 5px; width: 65px; height: 22px; margin-left: 7px; font-size: 14px; background-color: green; border: none; display: inline-flex;">
+ <i class="pi pi-file-excel" style="margin-top: 2px; margin-left: 4px;"></i>
+ <label style="font-weight: 800; vertical-align: middle;">Excel</label>
+ </button>
+ </div>
+</div>
+
+<!-- * * * * View Spec Content Pop Up * * * * -->
+<p-dialog [(visible)]="showViewCs" header="Spec Content" appendTo="body" [maximizable]="true"
+ [modal]="true" [style]="{width: '80vw'}" [baseZIndex]="10000" [closable]="false">
+ <pre>{{specContentToView | json}}</pre>
+ <p-footer>
+ <button pButton label="Close" (click)="showViewCs=false" type="button"></button>
+ <button pButton label="Download" (click)="download(specContentToView, 'Component_Spec')" type="button"></button>
+ </p-footer>
+</p-dialog>
+
+<!-- * * * * View Policy JSON Pop Up * * * * -->
+<p-dialog [(visible)]="showViewPolicy" header="Policy Json" appendTo="body" [maximizable]="true" [modal]="true"
+ [style]="{width: '80vw'}" [baseZIndex]="10000" [closable]="false">
+ <pre>{{policyJsonToView | json}}</pre>
+ <p-footer>
+ <button pButton label="Close" (click)="showViewPolicy=false" type="button"></button>
+ <button pButton label="Download" (click)="download(policyJsonToView, 'Policy_Json')" type="button"></button>
+ </p-footer>
+</p-dialog>
diff --git a/mod2/ui/src/app/comp-specs/comp-specs.component.spec.ts b/mod2/ui/src/app/comp-specs/comp-specs.component.spec.ts
new file mode 100644
index 0000000..64405e3
--- /dev/null
+++ b/mod2/ui/src/app/comp-specs/comp-specs.component.spec.ts
@@ -0,0 +1,133 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientModule } from '@angular/common/http';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatMenuModule, MatTooltipModule } from '@angular/material';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
+import { MessageService } from 'primeng/api';
+import { ButtonModule } from 'primeng/button';
+import { DialogModule } from 'primeng/dialog';
+import { DropdownModule } from 'primeng/dropdown';
+import { ScrollPanelModule } from 'primeng/scrollpanel';
+import { TableModule } from 'primeng/table';
+import { ToastModule } from 'primeng/toast';
+
+import { CompSpecsComponent } from './comp-specs.component';
+
+describe('CompSpecsComponent', () => {
+ let component: CompSpecsComponent;
+ let fixture: ComponentFixture<CompSpecsComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ CompSpecsComponent
+ ],
+ imports: [
+ Ng4LoadingSpinnerModule,
+ TableModule,
+ MatMenuModule,
+ ScrollPanelModule,
+ ToastModule,
+ DialogModule,
+ DropdownModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ButtonModule,
+ HttpClientModule,
+ ToastModule,
+ RouterTestingModule,
+ MatTooltipModule
+ ],
+ providers: [
+ MessageService,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CompSpecsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it(`should fill csElements Object`, () => {
+ const fixture = TestBed.createComponent(CompSpecsComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ let mockCsElement = [{
+ id: 'testId1234',
+ name: 'test-MS',
+ type: 'k8s',
+ specContent: '',
+ policyJson: 'test',
+ status: 'New',
+ msInstanceInfo: {
+ release: '2008',
+ name: 'test Ms',
+ },
+ metadata: {
+ createdBy: 'test',
+ createdOn: '01-01-2020 12:00',
+ updatedBy: 'test',
+ updatedOn: '01-01-2020 12:00',
+ notes: 'test',
+ labels: ['test'],
+ }
+ }]
+
+ app.fillTable(mockCsElement)
+
+ expect(app.loadTable).toEqual(true);
+ expect(app.csElements.length).toEqual(1);
+ });
+
+ it(`should set spec content to view`, () => {
+ const fixture = TestBed.createComponent(CompSpecsComponent);
+ const app = fixture.debugElement.componentInstance;
+ let mockData = {
+ specContent: 'test'
+ }
+ app.showViewCsDialog(mockData)
+ expect(app.showViewCs).toEqual(true);
+ expect(app.specContentToView).toEqual('test');
+ });
+
+ it(`should set policy json content to view`, () => {
+ const fixture = TestBed.createComponent(CompSpecsComponent);
+ const app = fixture.debugElement.componentInstance;
+ let mockData = {
+ policyJson: 'test'
+ }
+ app.showViewPolicyDialog(mockData)
+ expect(app.showViewPolicy).toEqual(true);
+ expect(app.policyJsonToView).toEqual('test');
+ });
+});
+
diff --git a/mod2/ui/src/app/comp-specs/comp-specs.component.ts b/mod2/ui/src/app/comp-specs/comp-specs.component.ts
new file mode 100644
index 0000000..4327c0b
--- /dev/null
+++ b/mod2/ui/src/app/comp-specs/comp-specs.component.ts
@@ -0,0 +1,211 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
+import { compSpecsService } from '../services/comp-specs-service.service';
+import { Table } from 'primeng/table';
+import { MessageService } from 'primeng/api';
+import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
+import { DatePipe } from '@angular/common';
+import { trigger, state, transition, style, animate } from '@angular/animations';
+import { ActivatedRoute } from '@angular/router';
+import { DownloadService } from '../services/download.service';
+
+@Component({
+ selector: 'app-comp-specs',
+ templateUrl: './comp-specs.component.html',
+ styleUrls: ['./comp-specs.component.css'],
+ animations: [
+ trigger('rowExpansionTrigger', [
+ state('void', style({
+ transform: 'translateX(-10%)',
+ opacity: 0
+ })),
+ state('active', style({
+ transform: 'translateX(0)',
+ opacity: 1
+ })),
+ transition('* <=> *', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
+ ])
+ ],
+ providers: [DatePipe]
+})
+export class CompSpecsComponent implements OnInit {
+ @ViewChild(Table, { static: false }) dt: Table;
+
+ csElements: any[] = [];
+
+ cols: any[] = [
+ { field: 'instanceName', header: 'Instance Name' },
+ { field: 'release', header: 'Release', width: '15%' },
+ { field: 'type', header: 'Type', width: '15%' },
+ { field: 'policy', header: 'Policy', width: '15%' },
+ { field: 'status', header: 'Status', width: '15%' }
+ ];
+
+ columns: any[];
+ loadTable: boolean;
+ filteredRows: any;
+ summaryRows: any;
+ downloadItems: { label: string; command: () => void; }[];
+
+ msInstanceId: string;
+ msInstanceName: any;
+ msInstanceRelease: any;
+
+ constructor(private csApis: compSpecsService, private messageService: MessageService,
+ private spinnerService: Ng4LoadingSpinnerService, private datePipe: DatePipe,
+ private route: ActivatedRoute, private downloadService: DownloadService) { }
+
+ //create table of comp specs
+ ngOnInit() {
+ this.loadTable = false;
+
+ this.route.queryParams.subscribe((params) => {
+ this.msInstanceId = params['instanceId'];
+ });
+
+ this.getAllCs()
+ }
+
+ getAllCs() {
+
+ this.csElements = [];
+
+ this.csApis.getAllCompSpecs(this.msInstanceId)
+ .subscribe((data: any[]) => {
+ this.fillTable(data)
+ })
+
+ this.columns = this.cols.map(col => ({ title: col.header, dataKey: col.field }));
+ }
+
+ //filter table
+ onTableFiltered(values) {
+ if (values) { this.filteredRows = values; }
+ else { this.filteredRows = this.summaryRows; }
+ }
+
+ /* * * * Export ms instance table to excel or csv * * * */
+ exportTable(exportTo) {
+ let downloadElements: any[] = []
+
+ //labels array not handled well by excel download so converted them to a single string
+ for (let row of this.filteredRows) {
+ let labels;
+ let notes;
+ if (exportTo === "excel") {
+ if (row.metadata.labels !== undefined) {
+ labels = row.metadata.labels.join(",")
+ }
+ } else {
+ labels = row.metadata.labels
+ }
+
+ if (row.metadata.notes !== null && row.metadata.notes !== undefined && row.metadata.notes !== '') {
+ notes = encodeURI(row.metadata.notes).replace(/%20/g, " ").replace(/%0A/g, "\\n")
+ }
+
+ downloadElements.push({
+ Instance_Name: row.instanceName,
+ Release: row.release,
+ Type: row.type,
+ Status: row.status,
+ Created_By: row.metadata.createdBy,
+ Created_On: row.metadata.createdOn,
+ Updated_By: row.metadata.updatedBy,
+ Updated_On: row.metadata.updatedOn,
+ Notes: notes,
+ Labels: labels
+ })
+ }
+
+ let arrHeader = []
+
+ if (exportTo === "csv") {
+ arrHeader = [
+ "Instance_Name",
+ "Release",
+ "Type",
+ "Status",
+ "Created_By",
+ "Created_On",
+ "Updated_By",
+ "Updated_On",
+ "Notes",
+ "Labels"
+ ];
+ }
+
+ this.downloadService.exportTableData(exportTo, downloadElements, arrHeader)
+ }
+
+ //fill object with microservice data, to be used to fill table.
+ //checks if fields are empty and if they are, store 'N/A' as the values
+ fillTable(data) {
+ for (let elem of data) {
+ let policy = '';
+ if(elem.policyJson){policy = "Included"}
+
+ let tempCsElement: any = {
+ id: elem.id,
+ instanceName: elem.msInstanceInfo.name,
+ release: elem.msInstanceInfo.release,
+ type: elem.type,
+ policy: policy,
+ status: elem.status,
+ specContent: elem.specContent,
+ policyJson: elem.policyJson,
+ metadata: {
+ createdBy: elem.metadata.createdBy,
+ createdOn: this.datePipe.transform(elem.metadata.createdOn, 'MM-dd-yyyy HH:mm'),
+ updatedBy: elem.metadata.updatedBy,
+ updatedOn: this.datePipe.transform(elem.metadata.updatedOn, 'MM-dd-yyyy HH:mm'),
+ notes: elem.metadata.notes,
+ labels: elem.metadata.labels
+ }
+ }
+ this.csElements.unshift(tempCsElement)
+ }
+ this.msInstanceName = this.csElements[0]['instanceName']
+ this.msInstanceRelease = this.csElements[0]['release']
+ this.filteredRows = this.csElements
+ this.loadTable = true;
+ this.spinnerService.hide();
+ }
+
+ showViewCs: boolean = false;
+ specContentToView: string;
+ showViewCsDialog(data) {
+ this.showViewCs = true;
+ this.specContentToView = data.specContent;
+ }
+
+ showViewPolicy: boolean = false;
+ policyJsonToView: string;
+ showViewPolicyDialog(data) {
+ this.showViewPolicy = true;
+ this.policyJsonToView = data.policyJson;
+ }
+
+ /* * * * Download single spec file or policy * * * */
+ download(content, contentType) {
+ let fileName = `${this.msInstanceName}_${this.msInstanceRelease}_${contentType}`
+ this.downloadService.downloadJSON(content, fileName)
+ }
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/guards/auth.guard.spec.ts b/mod2/ui/src/app/guards/auth.guard.spec.ts
new file mode 100644
index 0000000..c82f8d6
--- /dev/null
+++ b/mod2/ui/src/app/guards/auth.guard.spec.ts
@@ -0,0 +1,44 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed, async, inject } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { AuthGuard } from './auth.guard';
+
+describe('AuthGuard', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [
+ AuthGuard,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ],
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule
+ ]
+ });
+ });
+
+ it('should ...', inject([AuthGuard], (guard: AuthGuard) => {
+ expect(guard).toBeTruthy();
+ }));
+});
diff --git a/mod2/ui/src/app/guards/auth.guard.ts b/mod2/ui/src/app/guards/auth.guard.ts
new file mode 100644
index 0000000..cce544b
--- /dev/null
+++ b/mod2/ui/src/app/guards/auth.guard.ts
@@ -0,0 +1,62 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
+import { Observable, of } from 'rxjs';
+import { AuthService } from '../services/auth.service';
+import { catchError, map } from 'rxjs/operators';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthGuard implements CanActivate {
+
+ constructor(
+ private authService: AuthService,
+ private router: Router
+ ) {}
+
+ canActivate(
+ next: ActivatedRouteSnapshot,
+ state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
+
+ return this.authService.checkLogin().pipe(map((e:boolean)=>{
+ if(e){
+ this.authService.setUser();
+ if(this.authService.getUser().roles.includes("ROLE_ADMIN")){
+ this.authService.isAdmin = true;
+ }else{
+ this.authService.isAdmin = false;
+ }
+ this.authService.authPass=true;
+ return true;
+ }
+ }), catchError(err=>{
+ this.authService.reLoginMsg = true;
+ // window.alert("Your login has expired. Please log in again.");
+ this.authService.authPass=false;
+ this.router.navigate(['/login']);
+ return of(false);
+ }))
+ }
+
+
+
+
+}
diff --git a/mod2/ui/src/app/guards/login.guard.spec.ts b/mod2/ui/src/app/guards/login.guard.spec.ts
new file mode 100644
index 0000000..d58450c
--- /dev/null
+++ b/mod2/ui/src/app/guards/login.guard.spec.ts
@@ -0,0 +1,41 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed, async, inject } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { LoginGuard } from './login.guard';
+
+describe('LoginGuard', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [
+ LoginGuard,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ],
+ imports: [HttpClientTestingModule, RouterTestingModule]
+ });
+ });
+
+ it('should ...', inject([LoginGuard], (guard: LoginGuard) => {
+ expect(guard).toBeTruthy();
+ }));
+});
diff --git a/mod2/ui/src/app/guards/login.guard.ts b/mod2/ui/src/app/guards/login.guard.ts
new file mode 100644
index 0000000..851ef61
--- /dev/null
+++ b/mod2/ui/src/app/guards/login.guard.ts
@@ -0,0 +1,52 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
+import { Observable, of } from 'rxjs';
+import { AuthService } from '../services/auth.service';
+import { catchError, map } from 'rxjs/operators';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class LoginGuard implements CanActivate {
+ constructor(
+ private authService: AuthService,
+ private router: Router
+ ) {}
+
+ canActivate(
+ next: ActivatedRouteSnapshot,
+ state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
+
+ return this.authService.checkLogin().pipe(map((e:boolean)=>{
+ if(e){
+ console.log("Hi this is loginguard");
+ this.authService.authPass=true;
+ this.router.navigate(['/home']);
+ return true;
+ }
+ }), catchError(err=>{
+ console.log("Login guard out");
+ this.authService.authPass=false;
+ this.router.navigate(['/login']);
+ return of(false);
+ }))
+}
+}
diff --git a/mod2/ui/src/app/guards/role.guard.spec.ts b/mod2/ui/src/app/guards/role.guard.spec.ts
new file mode 100644
index 0000000..c57dfe6
--- /dev/null
+++ b/mod2/ui/src/app/guards/role.guard.spec.ts
@@ -0,0 +1,44 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed, async, inject } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { RoleGuard } from './role.guard';
+
+describe('RoleGuard', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [
+ RoleGuard,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ],
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule
+ ]
+ });
+ });
+
+ it('should ...', inject([RoleGuard], (guard: RoleGuard) => {
+ expect(guard).toBeTruthy();
+ }));
+});
diff --git a/mod2/ui/src/app/guards/role.guard.ts b/mod2/ui/src/app/guards/role.guard.ts
new file mode 100644
index 0000000..7e5b7ae
--- /dev/null
+++ b/mod2/ui/src/app/guards/role.guard.ts
@@ -0,0 +1,61 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
+import { Observable, of } from 'rxjs';
+import { AuthService } from '../services/auth.service';
+import { catchError, map } from 'rxjs/operators';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class RoleGuard implements CanActivate {
+
+
+ constructor(
+ private authService: AuthService,
+ private router: Router
+ ) {}
+
+ canActivate(
+ next: ActivatedRouteSnapshot,
+ state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
+
+ return this.authService.checkLogin().pipe(map((e:boolean)=>{
+ if(e){
+ console.log("role guard in");
+ this.authService.setUser();
+ if(this.authService.getUser().roles.includes("ROLE_ADMIN")){
+ this.authService.isAdmin = true;
+ }else{
+ this.authService.isAdmin = false;
+ this.router.navigate(['/home']);
+ }
+ return this.authService.getUser().roles.includes("ROLE_ADMIN");
+ }
+ }), catchError(err=>{
+ this.authService.reLoginMsg = true;
+ // window.alert("Your login has expired. Please log in again.");
+ this.authService.authPass=false;
+ this.router.navigate(['/login']);
+ return of(false);
+ }))
+
+}
+}
diff --git a/mod2/ui/src/app/home/home.component.css b/mod2/ui/src/app/home/home.component.css
new file mode 100644
index 0000000..f345db2
--- /dev/null
+++ b/mod2/ui/src/app/home/home.component.css
@@ -0,0 +1,50 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+
+.card{
+ display: inline-block;
+ margin-top: 56px;
+ margin-left: 75px;
+ color: rgb(34, 32, 32);
+ font-family: Arial, Helvetica, sans-serif;
+ font-weight: 800;
+ text-align: center;
+ padding-top: 42px;
+ font-size: 20px;
+ border-width: 2px;
+ border-color: gray;
+ border-radius: 8px;
+ height: 112px;
+ width: 261px;
+ cursor: pointer
+}
+
+#subMenu{
+ height: 75px;
+ width: 229px;
+ padding-top: 24px;
+ margin-left: 61px;
+ font-size: 18px;
+ border-radius: 5px
+}
+
+
+.mat-form-field + .mat-form-field {
+ margin-left: 8px;
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/home/home.component.html b/mod2/ui/src/app/home/home.component.html
new file mode 100644
index 0000000..31fe720
--- /dev/null
+++ b/mod2/ui/src/app/home/home.component.html
@@ -0,0 +1,93 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<div style="margin: -50px 0px 0px -30px">
+ <mat-card
+ (click)="toggleMsMenu()"
+ appMaterialElevation
+ [defaultElevation]="defaultElevation"
+ raisedElevation="16"
+ class="card"
+ style="background-color: #60a4a5">
+ Microservices...
+ </mat-card>
+ <mat-card
+ (click)="navSelect('Onboarding Tools')"
+ appMaterialElevation
+ [defaultElevation]="defaultElevation"
+ raisedElevation="16"
+ class="card"
+ style="background-color: rgba(154, 135, 167, 0.904);"
+ [routerLink]="'/OnboardingTools'">
+ Onboarding Tools
+ </mat-card>
+ <mat-card *ngIf="authService.isAdmin"
+ (click)="navSelect('User Management')"
+ appMaterialElevation
+ [defaultElevation]="defaultElevation"
+ raisedElevation="16"
+ class="card"
+ style="background-color: rgba(160, 120, 83, 0.904);"
+ [routerLink]="'/users'">
+ User Management
+ </mat-card>
+</div>
+<br>
+<div *ngIf="displayMsMenu" style="margin-top: -60px">
+ <mat-card id="subMenu" (click)="navSelect('Microservices')"
+ appMaterialElevation
+ [defaultElevation]="defaultElevation"
+ raisedElevation="16"
+ class="card"
+ style="background-color: #70a7a9; position: absolute;">
+ Microservices
+ </mat-card>
+</div>
+<br>
+<div *ngIf="displayMsMenu" style="margin-top: 70px">
+ <mat-card id="subMenu" (click)="navSelect('MS Instances')"
+ appMaterialElevation
+ [defaultElevation]="defaultElevation"
+ raisedElevation="16"
+ class="card"
+ style="background-color: #8fbbbc; position: absolute;">
+ MS Instances
+ </mat-card>
+</div>
+<br>
+<div *ngIf="displayMsMenu" style="margin-top: 70px">
+ <mat-card id="subMenu" (click)="navSelect('Blueprints')"
+ appMaterialElevation
+ [defaultElevation]="defaultElevation"
+ raisedElevation="16"
+ class="card"
+ style="background-color: #afcecf; position: absolute;">
+ Blueprints
+ </mat-card>
+</div>
+<br>
+<div *ngIf="displayMsMenu" style="margin-top: 70px">
+ <mat-card id="subMenu" (click)="navSelect('MOD APIs')"
+ appMaterialElevation
+ [defaultElevation]="defaultElevation"
+ raisedElevation="16"
+ class="card"
+ style="background-color: #cfe2e2; position: absolute;">
+ MOD APIs
+ </mat-card>
+</div> \ No newline at end of file
diff --git a/mod2/ui/src/app/home/home.component.ts b/mod2/ui/src/app/home/home.component.ts
new file mode 100644
index 0000000..36f9ee1
--- /dev/null
+++ b/mod2/ui/src/app/home/home.component.ts
@@ -0,0 +1,64 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, HostBinding } from '@angular/core';
+import { AppComponent } from '../app.component';
+import { AuthService } from '../services/auth.service';
+import { BreadcrumbService } from '../services/breadcrumb.service';
+
+@Component({
+ selector: 'app-home',
+ templateUrl: './home.component.html',
+ styleUrls: ['./home.component.css']
+})
+export class HomeComponent implements OnInit {
+
+ defaultElevation = 2;
+ raisedElevation = 8;
+ panelOpenState = false;
+
+ name = 'Angular';
+
+ displayMsMenu = false;
+
+ constructor(private appComp: AppComponent, public authService: AuthService, private bread: BreadcrumbService) { }
+
+ ngOnInit() {
+ }
+
+ disableAnimation = true;
+ ngAfterViewInit(): void {
+ // timeout required to avoid the dreaded 'ExpressionChangedAfterItHasBeenCheckedError'
+ setTimeout(() => this.disableAnimation = false);
+ }
+
+ toggleMsMenu() {
+ if (this.displayMsMenu == false) {
+ this.displayMsMenu = true
+ } else {
+ this.displayMsMenu = false
+ }
+ }
+
+ navSelect(menuItem: any) {
+ this.appComp.tree_handler(menuItem, null);
+ // Set the breadcrumbs for the selected menu item (card)
+ this.bread.setBreadcrumbs(menuItem, "reset");
+ }
+
+}
diff --git a/mod2/ui/src/app/login/login.component.css b/mod2/ui/src/app/login/login.component.css
new file mode 100644
index 0000000..55e48a1
--- /dev/null
+++ b/mod2/ui/src/app/login/login.component.css
@@ -0,0 +1,25 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+.field-icon {
+ float:right;
+ left: -15px;
+ margin-top: 1px;
+ position: relative;
+ z-index: 2;
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/login/login.component.html b/mod2/ui/src/app/login/login.component.html
new file mode 100644
index 0000000..b98baff
--- /dev/null
+++ b/mod2/ui/src/app/login/login.component.html
@@ -0,0 +1,58 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<p-card header="Log in to MOD" [style]="{margin:'100px 300px 300px 300px'}">
+<hr class="line-break">
+<form [formGroup]="form" (ngSubmit)="submit()" class="p-5 bg-faded" style="margin-left: 220px;margin-bottom: 100px;">
+ <div class="ui-g ui-fluid" >
+ <div class="ui-g-12 ui-md-4">
+ <div class="ui-inputgroup" >
+ <span class="ui-inputgroup-addon"><i class="pi pi-user" style="line-height: 1.25;"></i></span>
+ <input type="text" placeholder="ATT UID" formControlName="username">
+ </div>
+ </div>
+ </div>
+ <!-- <div class="ui-g ui-fluid" >
+ <div class="ui-g-12 ui-md-4">
+ <div class="ui-inputgroup" >
+ <span class="ui-inputgroup-addon"><i class="pi pi-user" style="line-height: 1.25;"></i></span>
+ <input type="text" placeholder="ATT UID" formControlName="uid">
+ </div>
+ </div>
+ </div> -->
+ <div class="ui-g ui-fluid">
+ <div class="ui-g-12 ui-md-4">
+ <div class="ui-inputgroup" >
+ <span class="ui-inputgroup-addon" (click)="hide=!hide">
+ <i [ngClass]="hide? 'pi pi-eye-slash':'pi pi-eye'"></i></span>
+ <input [type]="hide? 'password':'text'" placeholder="password" formControlName="password" >
+ <!-- <a routerLink="/reset-password">Forget password?</a> -->
+ </div>
+ </div>
+ </div>
+
+ <p-footer class="text-left ui-g-12">
+ <!-- <button pButton type="button" class="ui-button-info" label="Cancel" (click)="cancel()" style="margin-right: .25em"></button> -->
+ <button pButton type="submit" class="ui-button-success" label="Login" [disabled]="!form.valid"></button>
+ </p-footer>
+ <div class="text-left ui-g-12">
+ <p>Not a registered user? Contact the DCAE-MOD team at <i>dcae-mod-team@att.com</i></p>
+ <a href="mailto:dcae-mod-team@att.com?subject=account application&body=Please help open a dcae account with username:">Cick here to contact now</a>
+ </div>
+ </form>
+</p-card>
diff --git a/mod2/ui/src/app/login/login.component.spec.ts b/mod2/ui/src/app/login/login.component.spec.ts
new file mode 100644
index 0000000..5656be4
--- /dev/null
+++ b/mod2/ui/src/app/login/login.component.spec.ts
@@ -0,0 +1,59 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { CardModule } from 'primeng/card';
+
+import { LoginComponent } from './login.component';
+
+describe('LoginComponent', () => {
+ let component: LoginComponent;
+ let fixture: ComponentFixture<LoginComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [LoginComponent],
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ CardModule,
+ HttpClientTestingModule,
+ RouterTestingModule
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(LoginComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/login/login.component.ts b/mod2/ui/src/app/login/login.component.ts
new file mode 100644
index 0000000..16cafee
--- /dev/null
+++ b/mod2/ui/src/app/login/login.component.ts
@@ -0,0 +1,65 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+import { AuthService } from '../services/auth.service';
+import { User } from '../models/User';
+import { Router } from '@angular/router';
+
+@Component({
+ selector: 'app-login',
+ templateUrl: './login.component.html',
+ styleUrls: ['./login.component.css']
+})
+
+export class LoginComponent implements OnInit {
+
+ form: FormGroup;
+ hide: boolean=true;
+
+ constructor(private fb: FormBuilder, private authService: AuthService, private router: Router) { }
+
+ ngOnInit() {
+ this.form = this.fb.group({
+ username: ['', [Validators.required]],
+ // uid: ['', [Validators.required]],
+ password: ['', [Validators.required]]
+ });
+ }
+
+ submit() {
+ this.authService.login(this.form.value as User).subscribe(
+ res => {
+ // if (this.authService.getUser().roles && this.authService.getUser().roles.includes("ROLE_USER")) {
+ // this.authService.isAdmin = false;
+ // }
+ if(this.authService.getUser().roles &&this.authService.getUser().roles.includes("ROLE_ADMIN")) {
+ this.authService.isAdmin = true;
+ } else {
+ this.authService.isAdmin = false;
+ }
+ this.router.navigate(['/home']);
+ },
+ (err) => {
+ alert('User or Password is not correct, please re-enter');
+ this.form.reset();
+ }
+ );
+ }
+}
diff --git a/mod2/ui/src/app/material-elevation.directive.ts b/mod2/ui/src/app/material-elevation.directive.ts
new file mode 100644
index 0000000..8843d1e
--- /dev/null
+++ b/mod2/ui/src/app/material-elevation.directive.ts
@@ -0,0 +1,64 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Directive, ElementRef, HostListener, Input, Renderer2, OnChanges, SimpleChanges } from '@angular/core';
+
+@Directive({
+ selector: '[appMaterialElevation]'
+})
+export class MaterialElevationDirective implements OnChanges {
+
+ @Input()
+ defaultElevation = 2;
+
+ @Input()
+ raisedElevation = 8;
+
+ constructor(
+ private element: ElementRef,
+ private renderer: Renderer2
+ ) {
+ this.setElevation(this.defaultElevation);
+ }
+
+ ngOnChanges(_changes: SimpleChanges) {
+ this.setElevation(this.defaultElevation);
+ }
+
+ @HostListener('mouseenter')
+ onMouseEnter() {
+ this.setElevation(this.raisedElevation);
+ }
+
+ @HostListener('mouseleave')
+ onMouseLeave() {
+ this.setElevation(this.defaultElevation);
+ }
+
+ setElevation(amount: number) {
+ // remove all elevation classes
+ const classesToRemove = Array.from((<HTMLElement>this.element.nativeElement).classList).filter(c => c.startsWith('mat-elevation-z'));
+ classesToRemove.forEach((c) => {
+ this.renderer.removeClass(this.element.nativeElement, c);
+ });
+
+ // add the given elevation class
+ const newClass = `mat-elevation-z${amount}`;
+ this.renderer.addClass(this.element.nativeElement, newClass);
+ }
+}
diff --git a/mod2/ui/src/app/microservices/microservices.component.css b/mod2/ui/src/app/microservices/microservices.component.css
new file mode 100644
index 0000000..5f86e73
--- /dev/null
+++ b/mod2/ui/src/app/microservices/microservices.component.css
@@ -0,0 +1,121 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+td{
+ word-break:break-all
+}
+
+textarea
+{
+ font-size: 12px;
+}
+
+.table_actions_button{
+ background-color: transparent;
+ border: none;
+ width: 20px;
+ height: 20px;
+ vertical-align: middle;
+}
+
+.row-expand-layout{
+ display: grid;
+ grid-template-columns: 30% 40% auto;
+ grid-gap: 10px;
+ grid-auto-rows: minmax(100px, auto);
+}
+
+.row-expand-card{
+ font-size: 12px;
+ grid-row: 1;
+ border-radius: 5px;
+ border: 1px solid slategray;
+ padding: 10px;
+ /* This height prevents vertical scroll bar in Notes */
+ height: 92px;
+ overflow: hidden;
+}
+
+label {
+ cursor: pointer;
+}
+
+.fa-refresh{
+ cursor: pointer;
+}
+
+.input{
+ padding-top: 10px;
+}
+
+.inputLabel {
+ font-weight: 600;
+ margin-left: 20px;
+ width: 140px;
+}
+
+.inputFieldSm {
+ width: 200px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldMed {
+ width: 300px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldLg {
+ width: 400px;
+ height: 35px;
+ padding-left: 6px;
+}
+
+.table_action_item{
+ outline: none;
+ font-size: 12px;
+}
+
+::ng-deep .mat-menu-content {
+padding-top: 0px !important;
+padding-bottom: 0px !important;
+}
+.mat-menu-item{
+line-height:30px;
+height:30px;
+}
+
+.greenStatus{
+ background-color: rgba(80, 233, 105, 0.87)
+}
+
+.redStatus{
+ background-color: rgba(255, 29, 29, 0.733)
+}
+
+.blueStatus{
+ background-color: rgba(0, 183, 255, 0.432)
+}
+
+.greyStatus{
+ background-color: rgba(150, 150, 150, 0.432)
+}
+
+.ui-state-highlight {
+ background-color: #878C94 !important;
+ color: black !important;
+}
diff --git a/mod2/ui/src/app/microservices/microservices.component.html b/mod2/ui/src/app/microservices/microservices.component.html
new file mode 100644
index 0000000..95ec45c
--- /dev/null
+++ b/mod2/ui/src/app/microservices/microservices.component.html
@@ -0,0 +1,185 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<ng4-loading-spinner [timeout]="1000000"></ng4-loading-spinner>
+<div style="margin: 0px 0px 10px 20px; width: 97%; min-width: 900px; border: 1px solid darkslategray">
+ <!--Table of base microservices-->
+ <p-table #dt *ngIf="loadTable" [columns]="cols" [value]="msElements" sortMode="multiple" [paginator]="true"
+ [rows]="18" [rowsPerPageOptions]="[10,12,14,16,18,20,25,50]" (onFilter)="onTableFiltered(dt.filteredValue)" dataKey="id">
+
+ <!--Top caption row-->
+ <ng-template pTemplate="caption">
+
+ <div style="margin-left: -5%; width: 90%; max-height: 25px; display: inline-flex;">
+ <!--Microservices Table Header-->
+ <div style="float: left;">
+ <!--Refresh-->
+ <i class="fa fa-refresh" (click)="getAllMs()"></i>
+ <!--Global Filter-->
+ <input type="text" pInputText size="50" placeholder="Global Filter"
+ (input)="dt.filterGlobal($event.target.value, 'contains')"
+ style="width: 250px; height:25px; font-size: 12px; margin-left: 15px">
+ <i class="fa fa-search" style="margin:4px 0px 0 8px"></i>
+ </div>
+
+ <h4 style="margin-left: 15%"><b>Microservices</b></h4>
+
+ </div>
+
+ <div style="float: right;">
+ <button pButton type="button" (click)="showAddChangeDialog()" matTooltip="Add Microservice" matTooltipPosition="above"
+ style="border-radius: 5px; width: 65px; height: 27px; font-size: 14px; border: none; display: inline-flex;">
+ <i class="pi pi-plus" style="margin-top: 5px; margin-left: 10px;"></i>
+ <label style="font-weight: 800; margin-top: 3px">MS</label>
+ </button>
+ </div>
+
+ </ng-template>
+
+ <!--Header row with dynamic column names. Columns include microservice Name, Type, Location and Namespace-->
+ <ng-template pTemplate="header" let-columns>
+ <tr style="text-align: center">
+ <th style="width: 3em"></th>
+ <th class="ui-state-highlight" *ngFor="let col of columns" [pSortableColumn]="col.field" style="font-size: 12px; outline: none; vertical-align: bottom;" [ngStyle]="{'width': col.width}">
+ {{col.header}}<br>
+ <p-sortIcon [field]="col.field"></p-sortIcon>
+ </th>
+ <th style="font-size: 13px; width: 6.5%; vertical-align: top;">
+ Actions
+ </th>
+ </tr>
+
+ <!--Second header row for individual column filters-->
+ <tr style="text-align: center;">
+ <th style="width: 3em"></th>
+ <th *ngFor="let col of columns" [ngSwitch]="col.field">
+ <input pInputText type="text"
+ (input)="dt.filter($event.target.value, col.field, 'contains')" style="width: 100%; height: 20px; font-size: 10px;"
+ placeholder="Filter">
+ </th>
+ <th></th>
+ </tr>
+ </ng-template>
+
+ <!--dynamic rows generated from columns object and msElems object-->
+ <ng-template pTemplate="body" let-rowData let-expanded="expanded" let-msElem>
+ <tr style="font-size: 12px;">
+ <!--Column for row expand buttons-->
+ <td>
+ <a href="#" [pRowToggler]="rowData">
+ <i [ngClass]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></i>
+ </a>
+ </td>
+
+ <td *ngFor="let col of cols">
+ <div *ngIf="col.field==='status'"
+ style="width: fit-content; width: -moz-max-content; padding: 0px 5px 0px 5px; border-radius: 3px; font-weight: 600;"
+ [ngClass]="{'greenStatus' : msElem[col.field] === 'ACTIVE',
+ 'greyStatus' : msElem[col.field] === 'INACTIVE'}">
+ {{msElem[col.field]}}
+ </div>
+ <div *ngIf="col.field!=='status'">{{msElem[col.field]}}</div>
+ </td>
+
+ <!--Actions Column-->
+ <td>
+ <div style="text-align: center;">
+ <button pButton type="button" style="background-color: transparent; border: none; width: 20px; height: 20px; vertical-align: middle;" class="ui-button-secondary" [matMenuTriggerFor]="menu">
+ <i class="pi pi-ellipsis-h" style="color: grey;"></i>
+ </button>
+ <mat-menu #menu="matMenu" xPosition="before">
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-plus"
+ style="font-size: 10px;"></i> Add</span>
+ </div>
+
+ <button mat-menu-item class="table_action_item" (click)="showAddChangeMsInstanceDialog(rowData)">Add MS
+ Instance...</button>
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-pencil"></i> Update</span>
+ </div>
+
+ <button mat-menu-item class="table_action_item" (click)="showAddChangeDialog(rowData)">Update Microservice...</button>
+ </mat-menu>
+ </div>
+ </td>
+ </tr>
+ </ng-template>
+
+ <!--Row expand content-->
+ <ng-template pTemplate="rowexpansion" let-rowData let-columns="columns">
+ <tr>
+ <td [attr.colspan]="columns.length + 2">
+ <div class="row-expand-layout" [@rowExpansionTrigger]="'active'">
+ <!-- Audit Fields -->
+ <div class="row-expand-card" style="background-color: rgba(95, 158, 160, 0.295)">
+ <b>Created By:</b> {{rowData.metadata.createdBy}}<br>
+ <b>Created On:</b> {{rowData.metadata.createdOn}}<br>
+ <b>Updated By:</b> {{rowData.metadata.updatedBy}}<br>
+ <b>Updated On:</b> {{rowData.metadata.updatedOn}}
+ </div>
+ <!-- Notes -->
+ <div class="row-expand-card" style="background-color: rgba(100, 148, 237, 0.219)">
+ <b>Notes:</b><br>
+ <p-scrollPanel [style]="{width: '100%', height: '62px'}">
+ <div style="font-size: 12px; word-break: normal;">{{rowData.metadata.notes}}</div>
+ </p-scrollPanel>
+ </div>
+ <!-- Labels -->
+ <div class="row-expand-card" style="background-color: rgba(76, 65, 225, 0.199)">
+ <b style="padding-bottom: 5px;">Labels:</b><br>
+ <div *ngFor="let label of rowData['metadata']['labels']" style="display: inline-flex; margin-top: 5px;">
+ <div style="padding: 2px 7px 3px 0px;">
+ <span style="background-color: rgba(80, 80, 80, 0.185); padding: 3px; border-radius: 3px;">{{label}}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </td>
+ </tr>
+ </ng-template>
+ </p-table>
+
+ <!--download buttons for exporting table to either csv or excel file-->
+ <div *ngIf="loadTable" style="margin-left: 10px; margin-top: -32px; float: left;">
+ <button pButton type="button" (click)="exportTable('csv')"
+ matTooltip="Export Table to CSV" matTooltipPosition="above"
+ style="border-radius: 5px; width: 65px; height: 22px; font-size: 14px; border: none; margin-top: 4px; display: inline-flex;">
+ <i class="pi pi-file" style="margin-top: 2px; margin-left: 8px;"></i>
+ <label style="font-weight: 800; vertical-align: middle;">CSV</label>
+ </button>
+ <button pButton type="button" (click)="exportTable('excel')"
+ matTooltip="Export Table to XLSX" matTooltipPosition="above"
+ style="border-radius: 5px; width: 65px; height: 22px; margin-left: 7px; font-size: 14px; background-color: green; border: none; display: inline-flex;">
+ <i class="pi pi-file-excel" style="margin-top: 2px; margin-left: 4px;"></i>
+ <label style="font-weight: 800; vertical-align: middle;">Excel</label>
+ </button>
+ </div>
+
+ <!-- Dialog to Add or Change a MS -->
+ <app-ms-add-change *ngIf="showMsAddChangeDialog" [visible]="showMsAddChangeDialog" [currentRow]="currentRow" (handler)="addOrChangeMs($event)"></app-ms-add-change>
+
+ <!-- Dialog to Add (or Change) a MS Instance -->
+ <app-ms-instance-add *ngIf="showAddChangeMsInstance" [visible]="showAddChangeMsInstance" [msName]="addInstanceTo" [currentRow]="currentRow" (handler)="addMsInstance($event)"></app-ms-instance-add>
+
+ <!-- Shared success message -->
+ <p-toast key="addChangeSuccess"></p-toast>
+
+</div> \ No newline at end of file
diff --git a/mod2/ui/src/app/microservices/microservices.component.spec.ts b/mod2/ui/src/app/microservices/microservices.component.spec.ts
new file mode 100644
index 0000000..2d2e5f1
--- /dev/null
+++ b/mod2/ui/src/app/microservices/microservices.component.spec.ts
@@ -0,0 +1,134 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatMenuModule } from '@angular/material';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
+import { MessageService } from 'primeng/api';
+import { ButtonModule } from 'primeng/button';
+import { CalendarModule } from 'primeng/calendar';
+import { DialogModule } from 'primeng/dialog';
+import { DropdownModule } from 'primeng/dropdown';
+import { ScrollPanelModule } from 'primeng/scrollpanel';
+import { TableModule } from 'primeng/table';
+import { ToastModule } from 'primeng/toast';
+import { MsAddChangeComponent } from '../ms-add-change/ms-add-change.component';
+import { MsInstanceAddComponent } from '../ms-instance-add/ms-instance-add.component';
+
+import { MicroservicesComponent } from './microservices.component';
+
+describe('MicroservicesComponent', () => {
+ let component: MicroservicesComponent;
+ let fixture: ComponentFixture<MicroservicesComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ MicroservicesComponent,
+ MsAddChangeComponent,
+ MsInstanceAddComponent,
+ ],
+ imports: [
+ Ng4LoadingSpinnerModule,
+ TableModule,
+ MatMenuModule,
+ ScrollPanelModule,
+ ToastModule,
+ DialogModule,
+ DropdownModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ButtonModule,
+ CalendarModule,
+ HttpClientTestingModule,
+ ToastModule,
+ RouterTestingModule
+ ],
+ providers: [
+ MessageService,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MicroservicesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it(`should fill msInstances Object`, () => {
+ const fixture = TestBed.createComponent(MicroservicesComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ let mockMicroservice = [{
+ id: 'testId1234',
+ name: 'test-MS',
+ tag: 'test-MS-tag',
+ serviceName: 'testServiceName',
+ type: 'testType',
+ location: 'TestLocation',
+ namespace: 'testNameSpace',
+ status: 'testStatus',
+ metadata: {
+ createdBy: 'test',
+ createdOn: '01-01-2020 12:00',
+ updatedBy: 'test',
+ updatedOn: '01-01-2020 12:00',
+ notes: 'test',
+ labels: ['test'],
+ },
+ msInstances: 'test'
+ }]
+
+ app.fillTable(mockMicroservice)
+
+ expect(app.loadTable).toEqual(true);
+ expect(app.msElements.length).toEqual(1);
+ });
+
+ it(`should set addOrChange to "Add"`, () => {
+ const fixture = TestBed.createComponent(MicroservicesComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ let mockRowData = null
+ app.showAddChangeDialog(mockRowData)
+
+ expect(app.addOrChange).toEqual('Add');
+ });
+
+ it(`should set addOrChange to "Change"`, () => {
+ const fixture = TestBed.createComponent(MicroservicesComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ let mockRowData = {field: 'test'}
+ app.showAddChangeDialog(mockRowData)
+
+ expect(app.addOrChange).toEqual('Change');
+ });
+});
diff --git a/mod2/ui/src/app/microservices/microservices.component.ts b/mod2/ui/src/app/microservices/microservices.component.ts
new file mode 100644
index 0000000..640e750
--- /dev/null
+++ b/mod2/ui/src/app/microservices/microservices.component.ts
@@ -0,0 +1,311 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, ViewChild, ElementRef, Input, EventEmitter, Output } from '@angular/core';
+import { MatTableDataSource } from '@angular/material/table';
+import { Table } from 'primeng/table';
+import { MessageService } from 'primeng/api';
+import { trigger, state, style, transition, animate } from '@angular/animations';
+import { BaseMicroserviceService } from '../services/base-microservice.service';
+import { MsAddService } from '../services/ms-add.service';
+import { MicroserviceInstanceService } from '../services/microservice-instance.service';
+import { AuthService } from '../services/auth.service';
+import { DatePipe } from '@angular/common';
+import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
+import { DownloadService } from '../services/download.service';
+
+@Component({
+ selector: 'app-microservices',
+ templateUrl: './microservices.component.html',
+ styleUrls: ['./microservices.component.css'],
+ animations: [
+ trigger('rowExpansionTrigger', [
+ state('void', style({
+ transform: 'translateX(-10%)',
+ opacity: 0
+ })),
+ state('active', style({
+ transform: 'translateX(0)',
+ opacity: 1
+ })),
+ transition('* <=> *', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
+ ])
+ ],
+ providers: [DatePipe]
+})
+export class MicroservicesComponent implements OnInit {
+ @ViewChild(Table, { static: false }) dt: Table;
+
+ /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
+ msElements: any[] = [];
+ dataSource = new MatTableDataSource<any>(this.msElements);
+ cols: any[] = [
+ { field: 'name', header: 'MS Name' },
+ { field: 'tag', header: 'MS Tag' },
+ { field: 'serviceName', header: 'Service Short Name'},
+ { field: 'type', header: 'Type', width: '11%' },
+ { field: 'namespace', header: 'Namespace', width: '15%' },
+ { field: 'status', header: 'Status', width: '90px' }
+ ];
+ columns: any[];
+ loadTable: boolean;
+ filteredRows: any;
+ downloadItems: { label: string; command: () => void; }[];
+ showAddChangeMsInstance: boolean;
+ addInstanceTo: string = "";
+ msInstanceStates: { label: string, value: string }[] = [
+ { label: 'New', value: 'new' },
+ { label: 'In Dev', value: 'in-dev' },
+ { label: 'Dev Complete', value: 'dev-complete' },
+ { label: 'In Test', value: 'in-test' },
+ { label: 'Certified', value: 'certified' },
+ { label: 'Prod Deployed', value: 'prod-deployed' }
+ ]
+
+ // Json to add MS to DB, returned from child
+ msAddChangeJson: any;
+
+ showMsAddChangeDialog: boolean = false;
+ currentRow: any;
+ currentMsRow: string = "";
+ addOrChange: string;
+ username: string;
+ errorMessage: any;
+ successMessage: string;
+
+ constructor(private spinnerService: Ng4LoadingSpinnerService, private baseMsService: BaseMicroserviceService,
+ private msInstanceApi: MicroserviceInstanceService, private messageService: MessageService,
+ private addChangeMsApi: MsAddService, private authService: AuthService, private datePipe: DatePipe,
+ private downloadService: DownloadService) { }
+
+ ngOnInit() {
+ this.username = this.authService.getUser().username;
+ this.getAllMs();
+ }
+
+ getAllMs() {
+ this.spinnerService.show();
+ this.msElements = [];
+ this.loadTable = false;
+
+ this.baseMsService.getAllBaseMs()
+ .subscribe((data: any[]) => {
+ this.fillTable(data)
+ })
+
+ this.columns = this.cols.map(col => ({ title: col.header, dataKey: col.field }));
+ }
+
+ /*checks when table is filtered and stores filtered data in new
+ object to be downloaded when download button is clicked*/
+ onTableFiltered(values) {
+ if (values !== null) {
+ this.filteredRows = values;
+ } else {
+ this.filteredRows = this.msElements;
+ }
+ }
+
+ //download table as excel file
+ exportTable(exportTo: string) {
+ let downloadElements: any[] = []
+
+ //labels array not handled well by excel download so converted them to a single string
+ for (let row of this.filteredRows) {
+ let labels;
+ let notes;
+ if (exportTo === "excel") {
+ if (row.metadata.labels !== undefined) {
+ labels = row.metadata.labels.join(",")
+ }
+ } else {
+ labels = row.metadata.labels
+ }
+
+ if (row.metadata.notes !== null && row.metadata.notes !== undefined && row.metadata.notes !== '') {
+ notes = encodeURI(row.metadata.notes).replace(/%20/g, " ").replace(/%0A/g, "\\n")
+ }
+
+ downloadElements.push({
+ MS_Name: row.name,
+ MS_Tag: row.tag,
+ Service_Short_Name: row.serviceName,
+ Type: row.type,
+ Location: row.location,
+ Namespace: row.namespace,
+ Status: row.status,
+ Created_By: row.metadata.createdBy,
+ Created_On: row.metadata.createdOn,
+ Updated_By: row.metadata.updatedBy,
+ Updated_On: row.metadata.updatedOn,
+ Notes: notes,
+ Labels: labels
+ })
+ }
+
+ let csvHeaders = []
+
+ if (exportTo === "csv") {
+ csvHeaders = [
+ "MS_Name",
+ "MS_Tag",
+ "Service_Short_Name",
+ "Type",
+ "Location",
+ "Namespace",
+ "Status",
+ "Created_By",
+ "Created_On",
+ "Updated_By",
+ "Updated_On",
+ "Notes",
+ "Labels"
+ ];
+ }
+
+ this.downloadService.exportTableData(exportTo, downloadElements, csvHeaders)
+ }
+
+ // * * * * * Show the Dialog to Add a MS (<app-ms-add-change> tag in the html) * * * * *
+ showAddChangeDialog(rowData) {
+ this.showMsAddChangeDialog = true;
+ this.currentRow = rowData;
+ if (this.currentRow) {
+ this.addOrChange = "Change";
+ } else {
+ this.addOrChange = "Add";
+ }
+ }
+
+ // * * * * * Add or Change a MS * * * * *
+ // The response includes the entire MS record that was Added or Changed, (along with ID and audit fields).
+ // When Added, the response is added directly to the table. When Changed, the current record is updated field-by-field.
+ addOrChangeMs(jsonFromChildDialog) {
+ if (jsonFromChildDialog) {
+ this.msAddChangeJson = jsonFromChildDialog;
+ if (this.addOrChange == "Change") {
+ this.currentMsRow = this.currentRow['id']
+ }
+ this.addChangeMsApi.addChangeMsToCatalog(this.addOrChange, this.currentMsRow, this.msAddChangeJson).subscribe(
+ (response: any) => {
+ if (this.addOrChange == "Add") {
+ this.msElements.unshift(response);
+ this.successMessage = "Microservice Added";
+ } else {
+ this.updateCurrentRow(jsonFromChildDialog);
+ this.successMessage = "Microservice Updated";
+ }
+ this.showMsAddChangeDialog = false;
+ this.messageService.add({ key: 'addChangeSuccess', severity: 'success', summary: 'Success', detail: this.successMessage, life: 5000 });
+ },
+ errResponse => {
+ // for testing only - this.updateCurrentRow(jsonFromChildDialog);
+ this.messageService.add({ key: 'msAddChangeError', severity: 'error', summary: 'Error', detail: errResponse.error.message, sticky: true });
+ }
+ )
+ }
+ else {
+ this.showMsAddChangeDialog = false;
+ };
+ }
+
+ updateCurrentRow(jsonFromChildDialog) {
+ const newRow = JSON.parse(jsonFromChildDialog);
+ this.currentRow['name'] = newRow['name'];
+ this.currentRow['serviceName'] = newRow['serviceName'];
+ this.currentRow['type'] = newRow['type'];
+ this.currentRow['location'] = newRow['location'];
+ this.currentRow['namespace'] = newRow['namespace'];
+ this.currentRow['metadata']['labels'] = newRow['metadata']['labels'];
+ this.currentRow['metadata']['notes'] = newRow['metadata']['notes'];
+ }
+
+ /* * * * Show pop up for Adding a new MS Instance * * * */
+ showAddChangeMsInstanceDialog(data) {
+ this.addInstanceTo = data['name']
+ this.showAddChangeMsInstance = true
+ }
+
+ /* * * * Call API to Add a new MS Instance * * * */
+ addMsInstance(body) {
+ if (body === null) {
+ this.showAddChangeMsInstance = false;
+ } else {
+ this.msInstanceApi.addChangeMsInstance("ADD", this.addInstanceTo, body).subscribe(
+ (data) => {
+ this.messageService.add({ key: 'addChangeSuccess', severity: 'success', summary: 'Success', detail: "MS Instance Added", life: 5000 });
+ this.showAddChangeMsInstance = false;
+ },
+ (errResponse) => {
+ console.log(errResponse)
+ this.messageService.add({ key: 'instanceAddChangeError', severity: 'error', summary: 'Error', detail: errResponse.error.message, sticky: true });
+ }
+ )
+ }
+ }
+
+ //fill object with microservice data, to be used to fill table.
+ //checks if fields are empty and if they are, store 'N/A' as the values
+ fillTable(data) {
+ for (let elem of data) {
+ var tempMsElement: any = {
+ id: elem.id,
+ name: elem.name,
+ tag: elem.tag,
+ serviceName: elem.serviceName,
+ type: elem.type,
+ location: elem.location,
+ namespace: elem.namespace,
+ status: elem.status,
+ metadata: {
+ createdBy: elem.metadata.createdBy,
+ createdOn: this.datePipe.transform(elem.metadata.createdOn, 'MM-dd-yyyy HH:mm'),
+ updatedBy: elem.metadata.updatedBy,
+ updatedOn: this.datePipe.transform(elem.metadata.updatedOn, 'MM-dd-yyyy HH:mm'),
+ notes: elem.metadata.notes,
+ labels: elem.metadata.labels
+ },
+ msInstances: elem.msInstances
+ }
+ this.msElements.push(tempMsElement)
+ }
+ this.filteredRows = this.msElements
+ this.loadTable = true;
+ this.spinnerService.hide();
+ }
+}
+
+export interface AddMsInstance{
+ name: string,
+ release: string,
+ metadata: {
+ scrumLead: string,
+ scrumLeadId: string,
+ systemsEngineer: string,
+ systemsEngineerId: string,
+ developer: string;
+ developerId: string;
+ pstDueDate: string,
+ pstDueIteration: string,
+ eteDueDate: string,
+ eteDueIteration: string,
+ labels: string[],
+ notes: string
+ }
+ user: string
+}
diff --git a/mod2/ui/src/app/models/AuthResponse.ts b/mod2/ui/src/app/models/AuthResponse.ts
new file mode 100644
index 0000000..f44104d
--- /dev/null
+++ b/mod2/ui/src/app/models/AuthResponse.ts
@@ -0,0 +1,28 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Authority } from './Authority.enum';
+
+export class AuthResponse {
+ token?: string;
+ type?: null;
+ id?: string;
+ username?:string;
+ roles?: Authority[];
+ message?:string;
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/models/Authority.enum.ts b/mod2/ui/src/app/models/Authority.enum.ts
new file mode 100644
index 0000000..cbac582
--- /dev/null
+++ b/mod2/ui/src/app/models/Authority.enum.ts
@@ -0,0 +1,22 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+export enum Authority {
+ ADMIN = 'ROLE_ADMIN',
+ USER = 'ROLE_USER'
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/models/User.ts b/mod2/ui/src/app/models/User.ts
new file mode 100644
index 0000000..3c662d9
--- /dev/null
+++ b/mod2/ui/src/app/models/User.ts
@@ -0,0 +1,25 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+export class User{
+ username: string;
+ fullName?: string;
+ password?: string;
+ active?: boolean;
+ roles?: any[];
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/ms-add-change/ms-add-change.component.css b/mod2/ui/src/app/ms-add-change/ms-add-change.component.css
new file mode 100644
index 0000000..f256b2f
--- /dev/null
+++ b/mod2/ui/src/app/ms-add-change/ms-add-change.component.css
@@ -0,0 +1,57 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+.input {
+ padding-top: 10px;
+}
+
+.inputLabel {
+ font-weight: 600;
+ margin-left: 20px;
+ width: 150px;
+}
+
+.inputFieldSm {
+ width: 200px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldMed {
+ width: 300px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldLg {
+ width: 400px;
+ height: 35px;
+ padding-left: 6px;
+}
+
+.validationMsg {
+ padding-left: 175px;
+ color: red;
+ font-size: 11px;
+ font-weight: 550;
+}
+
+.validationMsgWarning {
+ padding-left: 175px;
+ color: rgb(255, 81, 0);
+ font-size: 11px;
+ font-weight: 550;
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/ms-add-change/ms-add-change.component.html b/mod2/ui/src/app/ms-add-change/ms-add-change.component.html
new file mode 100644
index 0000000..2fd19d7
--- /dev/null
+++ b/mod2/ui/src/app/ms-add-change/ms-add-change.component.html
@@ -0,0 +1,109 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<p-dialog *ngIf="visible" [header]="guiHeader" [(visible)]="visible" appendTo="body" [modal]="true" [transitionOptions]="'300ms'"
+ [closeOnEscape]="false" [closable]="false" [style]="{width: '645px'}" (onHide)="closeDialog()">
+
+ <!-- "Add / Change MS" Error Message -->
+ <p-toast key="msAddChangeError" [style]="{width: '500px'}"></p-toast>
+
+ <!-- * * * * * Input fields * * * * * -->
+ <form [formGroup]="msAddForm" (ngSubmit)="saveMs()" class="bg-faded">
+ <!-- * * * MS Name * * * -->
+ <div class="input">
+ <label class="inputLabel">MS Name<span style="color:red">*</span></label>
+ <input class="inputFieldMed" type="text" pInputText formControlName="name">
+ </div>
+ <!-- * * * MS Tag * * * -->
+ <div class="input">
+ <label class="inputLabel">MS Tag<span style="color:red">*</span></label>
+ <input *ngIf="!currentRow" class="inputFieldMed" type="text" pInputText formControlName="tag">
+ <!-- If Updating (vs ADDing) the data, the "Tag" is Read-Only -->
+ <input *ngIf="currentRow" class="inputFieldMed" type="text" pInputText formControlName="tag" style="border:none" readonly>
+ <!-- * * * (Validation Rules Display) * * * -->
+ <div class="validationMsg" *ngIf="msAddForm.controls['tag'].invalid &&
+ !msAddForm.value['tag']=='' &&
+ msAddForm.controls['tag'].value.length < 51">
+ Format: lowercase alphanumeric with embedded dashes (5-50 characters)
+ </div>
+ <!-- * * * (Validation Rule - length > 50) * * * -->
+ <div class="validationMsg" *ngIf="msAddForm.controls['tag'].value.length > 50">
+ MS Tag cannot exceed 50 chars
+ </div>
+ </div>
+ <!-- * * * Service Short Name * * * -->
+ <div class="input">
+ <label class="inputLabel">Service Short Name</label>
+ <input class="inputFieldMed" type="text" pInputText formControlName="serviceName">
+ <!-- * * * (Validation Rules Display) * * * -->
+ <div class="validationMsg" *ngIf="msAddForm.controls['serviceName'].invalid &&
+ !msAddForm.value['serviceName']=='' &&
+ msAddForm.controls['serviceName'].value.length < 26">
+ Format: lowercase alpha with embedded dashes
+ </div>
+ <!-- * * * (Warning! Global vs Central/Edge Service Name length) * * * -->
+ <div class="validationMsgWarning" *ngIf="msAddForm.controls['serviceName'].valid &&
+ msAddForm.controls['serviceName'].value.length > 12 &&
+ msAddForm.controls['serviceName'].value.length < 26">
+ Warning! Only Global Site short names can exceed 12 chars (max 25)
+ </div>
+ <!-- * * * (Validation Rule - length > 25) * * * -->
+ <div class="validationMsg" *ngIf="msAddForm.controls['serviceName'].value.length > 25">
+ Global Site short names cannot exceed 25 chars
+ </div>
+ </div>
+ <!-- * * * Type * * * -->
+ <div class="input">
+ <label class="inputLabel">Type<span style="color:red">*</span></label>
+ <p-dropdown [options]="types" placeholder="Select Type" optionLabel="type" formControlName="type"></p-dropdown>
+ </div>
+ <!-- * * * Location
+ <div class="input">
+ <label class="inputLabel">Location<span style="color:red">*</span></label>
+ <p-dropdown [options]="locations" placeholder="Select Location" optionLabel="location" formControlName="location"></p-dropdown>
+ </div>
+ * * * -->
+ <!-- * * * Namespace * * * -->
+ <div class="input">
+ <label class="inputLabel">Namespace</label>
+ <input class="inputFieldMed" type="text" pInputText formControlName="namespace">
+ <!-- * * * (Validation Rules Display) * * * -->
+ <div class="validationMsg" *ngIf="msAddForm.controls['namespace'].invalid && !msAddForm.value['namespace']==''">
+ Format: lowercase alphanumeric with embedded dashes
+ </div>
+ </div>
+ <!-- * * * Labels * * * -->
+ <div class="input">
+ <label class="inputLabel">Labels</label>
+ <input class="inputFieldLg" type="text" pInputText formControlName="labels">
+ </div>
+ <span style="padding: 9px 0px 0px 172px; font-size: 13px;">(Separate labels with a space)</span>
+ <!-- * * * Notes * * * -->
+ <div class="input">
+ <label class="inputLabel" style="vertical-align: top">Notes</label>
+ <textarea class="inputFieldLg" [rows]="1" [cols]="30" pInputTextarea autoResize="autoResize" formControlName="notes"></textarea>
+ </div>
+ <!-- * * * ADD and CANCEL buttons * * * -->
+ <div style="float: right; padding: 20px 45px">
+ <button pButton type="button" (click)="closeDialog()" style="margin-right: 10px" label="Cancel"></button>
+ <button pButton type="submit" class="ui-button-success" style="width: 77px; text-align:center" [label]="addOrUpdate"
+ [disabled]="!msAddForm.valid || !msAddForm.value['name'].trim()"></button>
+ </div>
+ </form>
+
+</p-dialog>
diff --git a/mod2/ui/src/app/ms-add-change/ms-add-change.component.spec.ts b/mod2/ui/src/app/ms-add-change/ms-add-change.component.spec.ts
new file mode 100644
index 0000000..4ba7ae9
--- /dev/null
+++ b/mod2/ui/src/app/ms-add-change/ms-add-change.component.spec.ts
@@ -0,0 +1,67 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { MessageService } from 'primeng/api';
+import { ButtonModule } from 'primeng/button';
+import { DialogModule } from 'primeng/dialog';
+import { DropdownModule } from 'primeng/dropdown';
+import { ToastModule } from 'primeng/toast';
+
+import { MsAddChangeComponent } from './ms-add-change.component';
+
+describe('MsAddChangeComponent', () => {
+ let component: MsAddChangeComponent;
+ let fixture: ComponentFixture<MsAddChangeComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [MsAddChangeComponent],
+ imports: [
+ DialogModule,
+ DropdownModule,
+ ToastModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ButtonModule,
+ HttpClientTestingModule,
+ RouterTestingModule
+ ],
+ providers: [
+ MessageService,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MsAddChangeComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/ms-add-change/ms-add-change.component.ts b/mod2/ui/src/app/ms-add-change/ms-add-change.component.ts
new file mode 100644
index 0000000..6991104
--- /dev/null
+++ b/mod2/ui/src/app/ms-add-change/ms-add-change.component.ts
@@ -0,0 +1,180 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { InputTextModule } from 'primeng/inputtext';
+import { DropdownModule } from 'primeng/dropdown';
+import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
+import { AuthService } from '../services/auth.service';
+
+interface Type {
+ type: string;
+}
+interface Location {
+ location: string;
+}
+
+@Component({
+ selector: 'app-ms-add-change',
+ templateUrl: './ms-add-change.component.html',
+ styleUrls: ['./ms-add-change.component.css']
+})
+
+export class MsAddChangeComponent implements OnInit {
+
+ guiHeader: string = "Microservice ADD"
+ // Used for the Add/Update button label
+ addOrUpdate: string = "Add";
+
+ msAddForm: FormGroup;
+ // The loggged in user
+ username: string;
+
+ // Input form fields
+ name: string;
+ tag: string;
+ serviceName: string = "";
+ type: string;
+ location: string;
+ namespace: string;
+ labels: string;
+ notes: string;
+
+ // Dropdowns
+ types: Type[];
+ locations: Location[];
+
+ // Return JSON to parent component
+ msAddChangeString: any;
+ msAddChangeJson: any;
+
+ constructor(private fb: FormBuilder, private authService: AuthService) {
+ }
+
+ @Input() visible: boolean;
+ @Input() currentRow: any;
+ @Output() handler: EventEmitter<any> = new EventEmitter();
+
+ ngOnInit() {
+ // The logged in user
+ this.username = this.authService.getUser().username;
+
+ this.msAddForm = new FormGroup({
+ name: new FormControl(),
+ tag: new FormControl(),
+ serviceName: new FormControl(),
+ type: new FormControl(),
+ //location: new FormControl(),
+ namespace: new FormControl(),
+ labels: new FormControl(),
+ notes: new FormControl()
+ });
+
+ // FORM fields and validations
+ this.msAddForm = this.fb.group({
+ name: ['', [Validators.required]],
+ tag: ['', [Validators.required, Validators.pattern('^([a-z0-9](-[a-z0-9])*)+$'), Validators.minLength(5), Validators.maxLength(50)]],
+ serviceName: ['', [Validators.pattern('^([a-z](-[a-z])*)+$'), Validators.maxLength(25)]],
+ type: ['', [Validators.required]],
+ //location: ['', [Validators.required]],
+ namespace: ['', [Validators.pattern('^([a-z0-9](-[a-z0-9])*)+$')]],
+ labels: ['', []],
+ notes: ['', []]
+ },
+ {updateOn: "blur"}
+ );
+
+ // TYPE Dropdown
+ this.types = [
+ { type: 'FM_COLLECTOR' },
+ { type: 'PM_COLLECTOR' },
+ { type: 'ANALYTIC' },
+ { type: 'TICK' },
+ { type: 'OTHER' }
+ ];
+ // LOCATION Dropdown
+ this.locations = [
+ { location: 'EDGE' },
+ { location: 'CENTRAL' },
+ { location: 'UNSPECIFIED' }
+ ];
+
+ // "Update" was selected, so populate the current row data in the GUI
+ if (this.currentRow) {
+ this.guiHeader = "Microservice Update";
+ this.addOrUpdate = "Update";
+ this.populateFields();
+ }
+
+ }
+
+ populateFields() {
+ let labelsStr: string;
+ if (this.currentRow['metadata']['labels']) {
+ labelsStr = this.currentRow['metadata']['labels'].join(' ')
+ }
+
+ // Prevent validation (length check) from failing in the html
+ if (this.currentRow['serviceName']) {
+ this.serviceName = this.currentRow['serviceName']
+ }
+
+ this.msAddForm.patchValue({
+ name: this.currentRow['name'],
+ tag: this.currentRow['tag'],
+ serviceName: this.serviceName,
+ type: {type: this.currentRow['type']},
+ //location: {location: this.currentRow['location']},
+ namespace: this.currentRow['namespace'],
+ labels: labelsStr,
+ notes: this.currentRow['metadata']['notes']
+ })
+ }
+
+ // The handler emits 'null' back to parent to close dialog and make it available again when clicked
+ closeDialog() {
+ this.visible = false;
+ this.handler.emit(null);
+ }
+
+ // Create the JSON to be sent to the parent component
+ // The "labels" functions below take into account leading/trailing spaces, multiple spaces between labels, and conversion into an array
+ createOutputJson() {
+ this.msAddChangeString = {
+ name: this.msAddForm.value['name'].trim(),
+ tag: this.msAddForm.value['tag'],
+ serviceName: this.msAddForm.value['serviceName'],
+ type: this.msAddForm.value['type'].type,
+ location: 'UNSPECIFIED',
+ //location: this.msAddForm.value['location'].location,
+ namespace: this.msAddForm.value['namespace'].trim(),
+ metadata: {
+ labels: this.msAddForm.value['labels'].trim().replace(/\s{2,}/g, ' ').split(" "),
+ notes: this.msAddForm.value['notes']
+ },
+ user: this.username
+ };
+ }
+
+ saveMs() {
+ this.createOutputJson();
+ this.msAddChangeJson = JSON.stringify(this.msAddChangeString);
+ this.handler.emit(this.msAddChangeJson);
+ }
+
+}
diff --git a/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.css b/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.css
new file mode 100644
index 0000000..8ecfc18
--- /dev/null
+++ b/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.css
@@ -0,0 +1,48 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+.input{
+ padding-top: 8px;
+}
+
+.inputLabel {
+ font-weight: 600;
+ margin-left: 20px;
+ width: 165px;
+}
+
+.inputFieldXSm {
+ width: 75px;
+ height: 30px;
+ padding-left: 6px;
+}
+.inputFieldSm {
+ width: 200px;
+ height: 30px;
+ padding-left: 6px;
+}
+.inputFieldMed {
+ width: 300px;
+ height: 30px;
+ padding-left: 6px;
+}
+.inputFieldLg {
+ width: 400px;
+ height: 30px;
+ padding-left: 6px;
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.html b/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.html
new file mode 100644
index 0000000..804de33
--- /dev/null
+++ b/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.html
@@ -0,0 +1,93 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<p-dialog [(visible)]="visible" [header]="guiHeader" appendTo="body" [modal]="true" [transitionOptions]="'300ms'" [style]="{width: '720px'}" [baseZIndex]="10000"
+ [closable]="false" (onHide)="closeDialog()">
+
+ <!-- "Add / Change MS Instance" Error Message -->
+ <p-toast key="instanceAddChangeError"></p-toast>
+
+ <form [formGroup]="msInstanceAddForm">
+ <!-- * * * Name * * * -->
+ <div class="input">
+ <label class="inputLabel">MS Name</label>
+ <b>{{msName}}</b>
+ </div>
+ <!-- * * * Release * * * -->
+ <div class="input">
+ <label class="inputLabel">Release<span style="color:red">*</span></label>
+ <p-dropdown [options]="msInstanceReleases" placeholder="Select Release" formControlName="release"></p-dropdown>
+ </div>
+ <!-- * * * Scrum Lead / UID * * * -->
+ <div class="input">
+ <label class="inputLabel">Scrum Lead/UID</label>
+ <input class="inputFieldLg" type="text" pInputText formControlName="scrumLead" /> / <input class="inputFieldXSm" type="text" pInputText formControlName="scrumLeadId" />
+ </div>
+ <!-- * * * Systems Engineer / UID * * * -->
+ <div class="input">
+ <label class="inputLabel">Systems Engineer/UID</label>
+ <input class="inputFieldLg" type="text" pInputText formControlName="systemsEngineer" /> / <input class="inputFieldXSm" type="text" pInputText formControlName="systemsEngineerId" />
+ </div>
+ <!-- * * * Developer / UID * * * -->
+ <div class="input">
+ <label class="inputLabel">Developer<span style="color:red">*</span>/UID<span style="color:red">*</span></label>
+ <input class="inputFieldLg" type="text" pInputText formControlName="developer" /> / <input class="inputFieldXSm" type="text" pInputText formControlName="developerId" />
+ </div>
+ <!-- * * * PST Due Date * * * -->
+ <div class="input">
+ <label class="inputLabel">PST Due Date</label>
+ <p-calendar appendTo="body" [baseZIndex]="10001" dateFormat="yy-mm-dd" formControlName="pstDueDate" [showIcon]="true"></p-calendar>
+ </div>
+ <!-- * * * PST Due Iteration * * * -->
+ <div class="input">
+ <label class="inputLabel">PST Due Iteration</label>
+ <input class="inputFieldSm" type="text" pInputText formControlName="pstDueIteration" />
+ </div>
+ <!-- * * * ETE Due Date * * * -->
+ <div class="input">
+ <label class="inputLabel">ETE Due Date</label>
+ <p-calendar appendTo="body" [baseZIndex]="10001" dateFormat="yy-mm-dd" formControlName="eteDueDate" [showIcon]="true"></p-calendar>
+ </div>
+ <!-- * * * ETE Due Iteration * * * -->
+ <div class="input">
+ <label class="inputLabel">ETE Due Iteration</label>
+ <input class="inputFieldSm" type="text" pInputText formControlName="eteDueIteration" />
+ </div>
+ <!-- * * * Labels * * * -->
+ <div class="input">
+ <label class="inputLabel">Labels</label>
+ <input class="inputFieldLg" type="text" pInputText formControlName="labels" />
+ </div>
+ <span style="padding: 0px 0px 0px 188px; font-size: 13px;">(Separate labels with a space)</span>
+ <!-- * * * Notes * * * -->
+ <div class="input">
+ <label class="inputLabel" style="vertical-align: top">Notes</label>
+ <textarea class="inputFieldLg" [rows]="1" [cols]="30" pInputTextarea autoResize="autoResize" formControlName="notes"></textarea>
+ </div>
+
+ <!-- * * * ADD and Cancel buttons * * * -->
+ <div style="float: right; padding: 10px 25px 5px;">
+ <button pButton type="button" (click)="closeDialog()" label="Cancel"></button>&nbsp;
+ <button pButton type="submit" (click)="submitMsInstance()" class="ui-button-success" [label]="addOrUpdate" style="width: 77px"
+ [disabled]="!msInstanceAddForm.valid ||
+ !msInstanceAddForm.value['developer'].trim() ||
+ !msInstanceAddForm.value['developerId'].trim()"></button>
+ </div>
+ </form>
+
+</p-dialog> \ No newline at end of file
diff --git a/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.spec.ts b/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.spec.ts
new file mode 100644
index 0000000..2318a2c
--- /dev/null
+++ b/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.spec.ts
@@ -0,0 +1,71 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { DatePipe } from '@angular/common';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { MessageService } from 'primeng/api';
+import { ButtonModule } from 'primeng/button';
+import { CalendarModule } from 'primeng/calendar';
+import { DialogModule } from 'primeng/dialog';
+import { DropdownModule } from 'primeng/dropdown';
+import { ToastModule } from 'primeng/toast';
+
+import { MsInstanceAddComponent } from './ms-instance-add.component';
+
+describe('MsInstanceAddComponent', () => {
+ let component: MsInstanceAddComponent;
+ let fixture: ComponentFixture<MsInstanceAddComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [MsInstanceAddComponent],
+ imports: [
+ DialogModule,
+ DropdownModule,
+ ToastModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ButtonModule,
+ HttpClientTestingModule,
+ RouterTestingModule,
+ CalendarModule,
+ ],
+ providers: [
+ MessageService,
+ DatePipe,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MsInstanceAddComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.ts b/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.ts
new file mode 100644
index 0000000..228ddc1
--- /dev/null
+++ b/mod2/ui/src/app/ms-instance-add/ms-instance-add.component.ts
@@ -0,0 +1,189 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { MicroserviceInstanceService } from '../services/microservice-instance.service';
+import { MessageService } from 'primeng/api';
+import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
+import { AuthService } from '../services/auth.service';
+import { DatePipe } from '@angular/common';
+
+@Component({
+ selector: 'app-ms-instance-add',
+ templateUrl: './ms-instance-add.component.html',
+ styleUrls: ['./ms-instance-add.component.css']
+})
+export class MsInstanceAddComponent implements OnInit {
+
+ guiHeader: string = "Microservice Instance ADD";
+ // Used for the Add/Update button label
+ addOrUpdate: string = "Add";
+
+ msInstanceAddForm: FormGroup;
+ msInstanceToAdd: AddMsInstance;
+ addInstanceTo: string = "";
+ username: string;
+ msInstanceReleases: { label: string, value: string }[] = [
+ { label: '2004', value: '2004' },
+ { label: '2006', value: '2006' },
+ { label: '2008', value: '2008' },
+ { label: '2009', value: '2009' },
+ { label: '2010', value: '2010' },
+ { label: '2011', value: '2011' },
+ { label: '2012', value: '2012' }
+ ]
+
+ @Input() visible: boolean;
+ @Input() msName: string;
+ @Input() msInstanceChange: string; // Use to differentiate Add from Change, since currentRow can be problematic
+ @Input() currentRow: any;
+ @Output() handler: EventEmitter<any> = new EventEmitter();
+
+ constructor(private addChangeMsInstanceApi: MicroserviceInstanceService, private messageService: MessageService, private fb: FormBuilder, private authService: AuthService, private datePipe: DatePipe) { }
+
+ ngOnInit() {
+ this.username = this.authService.getUser().username;
+
+ this.msInstanceAddForm = new FormGroup({
+ name: new FormControl(),
+ release: new FormControl(),
+ scrumLead: new FormControl(),
+ scrumLeadId: new FormControl(),
+ systemsEngineer: new FormControl(),
+ systemsEngineerId: new FormControl(),
+ developer: new FormControl(),
+ developerId: new FormControl(),
+ status: new FormControl(),
+ pstDueDate: new FormControl(),
+ pstDueIteration: new FormControl(),
+ eteDueDate: new FormControl(),
+ eteDueIteration: new FormControl(),
+ labels: new FormControl(),
+ notes: new FormControl()
+ });
+
+ this.msInstanceAddForm = this.fb.group({
+ name: ['', []],
+ release: ['', [Validators.required]],
+ scrumLead: ['', []],
+ scrumLeadId: ['', []],
+ systemsEngineer: ['', []],
+ systemsEngineerId: ['', []],
+ developer: ['', [Validators.required]],
+ developerId: ['', [Validators.required]],
+ status: ['', []],
+ pstDueDate: ['', []],
+ pstDueIteration: ['', []],
+ eteDueDate: ['', []],
+ eteDueIteration: ['', []],
+ labels: ['', []],
+ notes: ['', []]
+ });
+
+ if (this.msInstanceChange) {
+ this.guiHeader = "Microservice Instance Update";
+ this.addOrUpdate = "Update";
+ this.populateFields();
+ }
+ }
+
+ populateFields() {
+ this.msName = this.currentRow['name'];
+
+ let labelsStr: string;
+ if (this.currentRow['metadata']['labels']) {
+ labelsStr = this.currentRow['metadata']['labels'].join(' ')
+ }
+
+ this.msInstanceAddForm.patchValue({
+ release: this.currentRow['release'],
+ scrumLead: this.currentRow['metadata']['scrumLead'],
+ scrumLeadId: this.currentRow['metadata']['scrumLeadId'],
+ systemsEngineer: this.currentRow['metadata']['systemsEngineer'],
+ systemsEngineerId: this.currentRow['metadata']['systemsEngineerId'],
+ developer: this.currentRow['metadata']['developer'],
+ developerId: this.currentRow['metadata']['developerId'],
+ pstDueDate: this.currentRow['pstDueDate'],
+ pstDueIteration: this.currentRow['pstDueIteration'],
+ eteDueDate: this.currentRow['eteDueDate'],
+ eteDueIteration: this.currentRow['eteDueIteration'],
+ labels: labelsStr,
+ notes: this.currentRow['metadata']['notes']
+ })
+}
+
+ /* * * * On click of cancel * * * */
+ closeDialog() {
+ this.visible = false;
+ this.handler.emit(null)
+ }
+
+ /* * * * On click of add * * * */
+ submitMsInstance() {
+ // Prevent error on "split" if record existed before "labels" were implemented
+ let labels: string[] = []
+ if (!this.msInstanceAddForm.value['labels']){
+ labels = []
+ } else {
+ labels = this.msInstanceAddForm.value['labels'].trim().replace(/\s{2,}/g, ' ').split(" ")
+ }
+
+ //build request body
+ this.msInstanceToAdd = {
+ name: this.msName,
+ release: this.msInstanceAddForm.value['release'],
+ metadata: {
+ scrumLead: this.msInstanceAddForm.value['scrumLead'],
+ scrumLeadId: this.msInstanceAddForm.value['scrumLeadId'],
+ systemsEngineer: this.msInstanceAddForm.value['systemsEngineer'],
+ systemsEngineerId: this.msInstanceAddForm.value['systemsEngineerId'],
+ developer: this.msInstanceAddForm.value['developer'],
+ developerId: this.msInstanceAddForm.value['developerId'],
+ pstDueDate: this.msInstanceAddForm.value['pstDueDate'],
+ pstDueIteration: this.msInstanceAddForm.value['pstDueIteration'],
+ eteDueDate: this.msInstanceAddForm.value['eteDueDate'],
+ eteDueIteration: this.msInstanceAddForm.value['eteDueIteration'],
+ labels: labels,
+ notes: this.msInstanceAddForm.value['notes']
+ },
+ user: this.username
+ }
+
+ this.handler.emit(this.msInstanceToAdd) //return request body back to parent
+ }
+}
+
+export interface AddMsInstance {
+ name: string,
+ release: string,
+ metadata: {
+ scrumLead: string,
+ scrumLeadId: string,
+ systemsEngineer: string,
+ systemsEngineerId: string,
+ developer: string,
+ developerId: string,
+ pstDueDate: any,
+ pstDueIteration: string,
+ eteDueDate: any,
+ eteDueIteration: string,
+ labels: string[],
+ notes: string
+ }
+ user: string
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/msInstances/msInstances.component.css b/mod2/ui/src/app/msInstances/msInstances.component.css
new file mode 100644
index 0000000..62c5ac8
--- /dev/null
+++ b/mod2/ui/src/app/msInstances/msInstances.component.css
@@ -0,0 +1,148 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+td{
+ word-break:break-all;
+ font-size: 12px;
+}
+
+th{
+ text-align: center;
+ font-size: 12px;
+}
+
+.table_column_filter{
+ width: 100%;
+ height: 20px;
+ font-size: 10px;
+}
+
+.table_div{
+ margin: 0px 50px 10px 20px;
+ min-width: 980px;
+ width: 98%;
+ border: 1px solid darkslategray;
+}
+
+.fa-refresh{
+ cursor: pointer;
+}
+
+textarea
+{
+ font-size: 12px;
+}
+
+.row-expand-layout{
+ display: grid;
+ grid-template-columns: 17% 30% 30% auto;
+ grid-gap: 10px;
+ grid-auto-rows: minmax(100px, auto);
+}
+
+.row-expand-card{
+ font-size: 12px;
+ border-radius: 5px;
+ border: 1px solid slategray;
+ padding: 10px;
+ /* This height prevents vertical scroll bar in Notes */
+ height: 92px;
+ overflow: hidden;
+ min-width: 195px;
+}
+
+.table_export_buttons_alignment{
+ margin-left: 5px;
+ margin-top: -32px;
+ float: left;
+}
+
+.table_export_button{
+ border-radius: 5px;
+ height: 22px;
+ font-size: 14px;
+ border: none;
+ margin-top: 4px;
+ margin-right: 7px;
+ display: inline-flex;
+}
+
+.table_caption_header{
+ margin-left: -18%;
+ width: 82%;
+ max-height: 25px;
+ display: inline-flex;
+}
+
+.table_global_filter{
+ width: 250px;
+ height: 25px;
+ margin-left: 15px;
+ font-size: 12px;
+}
+
+.table_title{
+ margin-left: 15%;
+}
+
+.table_actions_button{
+ background-color: transparent;
+ border: none;
+ width: 20px;
+ height: 20px;
+ vertical-align: middle;
+}
+
+.table_action_item{
+ outline: none;
+ font-size: 12px;
+}
+
+::ng-deep .mat-menu-content {
+ padding-top: 0px !important;
+ padding-bottom: 0px !important;
+}
+.mat-menu-item{
+ line-height:30px;
+ height:30px;
+}
+
+.greenStatus{
+ background-color: rgba(80, 233, 105, 0.87)
+}
+
+.redStatus{
+ background-color: rgba(255, 29, 29, 0.733)
+}
+
+.blueStatus{
+ background-color: rgba(0, 183, 255, 0.432)
+}
+
+.greyStatus{
+ background-color: rgba(150, 150, 150, 0.432)
+}
+
+.toast-newline {
+ white-space: pre-line;
+}
+
+.ui-state-highlight {
+ background-color: #878C94 !important;
+ color: black !important;
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/msInstances/msInstances.component.html b/mod2/ui/src/app/msInstances/msInstances.component.html
new file mode 100644
index 0000000..1545de3
--- /dev/null
+++ b/mod2/ui/src/app/msInstances/msInstances.component.html
@@ -0,0 +1,221 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<ng4-loading-spinner [timeout]="1000000"></ng4-loading-spinner>
+<div class="table_div">
+ <p-table #dt *ngIf="loadTable" [columns]="cols" [value]="msInstances" sortMode="multiple" [paginator]="true"
+ [rows]="18" [rowsPerPageOptions]="[10,12,14,16,18,20,25,50]" selectionMode="multiple"
+ [(selection)]="selectedMsInstances" (onFilter)="onTableFiltered(dt.filteredValue)" dataKey="id">
+ <ng-template pTemplate="caption">
+
+ <div class="table_caption_header">
+ <!--Microservices Table Header-->
+ <div style="float: left;">
+ <!--Refresh-->
+ <i class="fa fa-refresh" (click)="getAllInstances()"></i>
+ <!--Global Filter-->
+ <input type="text" pInputText size="50" placeholder="Global Filter"
+ (input)="dt.filterGlobal($event.target.value, 'contains')"
+ class="table_global_filter">
+ <i class="fa fa-search" style="margin:4px 0 0 8px"></i>
+ </div>
+
+ <div class="table_title">
+ <h4><b>Microservice Instances</b></h4>
+ </div>
+ </div>
+
+ </ng-template>
+
+ <!--column headers-->
+ <ng-template pTemplate="header" let-columns>
+ <tr>
+ <th style="width: 3em"></th>
+ <th class="ui-state-highlight" *ngFor="let col of columns" style="outline: none; vertical-align: bottom; text-align: center;" [pSortableColumn]="col.field" [ngStyle]="{'width': col.width}">
+ {{col.header}}<br>
+ <p-sortIcon [field]="col.field" style="font-size: 8px;"></p-sortIcon>
+ </th>
+ <!--actions column-->
+ <th style="width: 7%;">
+ Actions
+ </th>
+ </tr>
+ <!--Second header row for individual column filters-->
+ <tr>
+ <th style="width: 3em"></th>
+ <th *ngFor="let col of columns" [ngSwitch]="col.field">
+ <input pInputText type="text" (input)="dt.filter($event.target.value, col.field, 'contains')" class="table_column_filter" placeholder="Filter">
+ </th>
+ <th>
+ <div style="text-align: center;">
+ <p-tableHeaderCheckbox style="padding-right: 5px;"></p-tableHeaderCheckbox>
+ <button pButton type="button" class="ui-button-secondary" (click)="checkCanGenerateBp()" [matMenuTriggerFor]="menu"
+ style="background-color: transparent; border: none; width: 20px; height: 20px; vertical-align: middle;">
+ <i class="pi pi-ellipsis-h" style="color: grey;"></i>
+ </button>
+ <mat-menu #menu="matMenu" xPosition="before">
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-plus"
+ style="font-size: 10px;"></i> Add</span>
+ </div>
+
+ <div matTooltip="{{generateSelectedBPsTooltip}}" [matTooltipDisabled]="canGenerateSelectedBPs" matTooltipPosition="left">
+ <button mat-menu-item (click)="generateSelectedBlueprints()" class="table_action_item" [disabled]="!canGenerateSelectedBPs" style="margin-top: 5px;">Generate Selected Blueprints</button>
+ </div>
+ </mat-menu>
+ </div>
+ </th>
+ </tr>
+ </ng-template>
+
+ <!--row data-->
+ <ng-template pTemplate="body" let-rowData let-expanded="expanded" let-msElem>
+ <tr>
+ <!--Column for row expand buttons-->
+ <td>
+ <a href="#" [pRowToggler]="rowData">
+ <i [ngClass]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></i>
+ </a>
+ </td>
+
+ <td *ngFor="let col of cols">
+ <div *ngIf="col.field==='status'"
+ style="width: fit-content; width: -moz-max-content; padding: 0px 5px 0px 5px; border-radius: 3px; font-weight: 600;" [ngClass]="{
+ 'greenStatus' : msElem[col.field] === 'DEV_COMPLETE' || msElem[col.field] === 'CERTIFIED' || msElem[col.field] === 'PROD_DEPLOYED',
+ 'blueStatus' : msElem[col.field] === 'NEW' || msElem[col.field] === 'IN_DEV' || msElem[col.field] === 'IN_TEST'}">
+ {{msElem[col.field]}}
+ </div>
+ <div *ngIf="col.field!=='status'">{{msElem[col.field]}}</div>
+ </td>
+
+ <td>
+ <div style="text-align: center">
+ <p-tableCheckbox [value]="rowData" style="padding-right: 5px;"></p-tableCheckbox>
+ <button pButton type="button" class="ui-button-secondary" [matMenuTriggerFor]="menu"
+ style="background-color: transparent; border: none; width: 20px; height: 20px; vertical-align: middle;">
+ <i class="pi pi-ellipsis-h" style="color: grey;"></i>
+ </button>
+ <mat-menu #menu="matMenu" xPosition="before">
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-plus" style="font-size: 10px;"></i> Add</span>
+ </div>
+ <!-- * * * * Add component spec * * * * -->
+ <button mat-menu-item class="table_action_item" (click)="showAddCSDialog(rowData)">Component Spec...</button>
+ <!-- * * * * Generate Blueprint * * * * -->
+ <div matTooltip="No Active Component Spec" [matTooltipDisabled]="rowData.activeSpec!==null" matTooltipPosition="left">
+ <button mat-menu-item class="table_action_item" (click)="generateBlueprints(rowData)" [disabled]="rowData.activeSpec===null">Generate Blueprint</button>
+ </div>
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-search" style="font-size: 10px;"></i> View</span>
+ </div>
+ <!-- * * * * Go to spec files table * * * * -->
+ <div matTooltip="No Component Specs" [matTooltipDisabled]="rowData.activeSpec!==null" matTooltipPosition="left">
+ <button mat-menu-item class="table_action_item" (click)="viewCompSpecs(rowData)" [disabled]="rowData.activeSpec===null">Component Specs</button>
+ </div>
+ <!-- * * * * Go to blueprints table * * * * -->
+ <button mat-menu-item class="table_action_item" (click)="viewBlueprints(rowData)" [disabled]="rowData.activeSpec===null">Blueprints</button>
+
+ <div style="background-color: rgba(128, 128, 128, 0.25);">
+ <span style="font-size: 12px; margin-left: 10px; font-weight: 500;"><i class="pi pi-pencil"></i> Update</span>
+ </div>
+ <!-- * * * * Update ms instance record * * * * -->
+ <button mat-menu-item class="table_action_item" (click)="showAddChangeDialog(rowData)">Update MS Instance...</button>
+ </mat-menu>
+ </div>
+ </td>
+ </tr>
+ </ng-template>
+
+ <!--Row expand content-->
+ <ng-template pTemplate="rowexpansion" let-rowData let-columns="columns">
+ <tr>
+ <td [attr.colspan]="columns.length + 2">
+ <div class="row-expand-layout" [@rowExpansionTrigger]="'active'">
+ <!-- Audit Fields -->
+ <div class="row-expand-card" style="background-color: rgba(95, 158, 160, 0.295);">
+ <b>Created By:</b> {{rowData.metadata.createdBy}}<br>
+ <b>Created On:</b> {{rowData.metadata.createdOn}}<br>
+ <b>Updated By:</b> {{rowData.metadata.updatedBy}}<br>
+ <b>Updated On:</b> {{rowData.metadata.updatedOn}}
+ </div>
+ <!-- People -->
+ <div class="row-expand-card" style="background-color: rgba(160, 159, 95, 0.295)">
+ <b>Scrum Lead: </b>{{rowData.metadata.scrumLead}}
+ <span *ngIf="rowData.metadata.scrumLeadId"> ({{rowData.metadata.scrumLeadId}})</span><br/>
+ <b>Systems Engineer: </b>{{rowData.metadata.systemsEngineer}}
+ <span *ngIf="rowData.metadata.systemsEngineerId"> ({{rowData.metadata.systemsEngineerId}})</span><br/>
+ <b>Developer: </b>{{rowData.metadata.developer}}
+ <span *ngIf="rowData.metadata.developerId"> ({{rowData.metadata.developerId}})</span>
+ </div>
+ <!-- Notes -->
+ <div class="row-expand-card" style="background-color: rgba(100, 148, 237, 0.295); white-space: pre-line;">
+ <b>Notes:</b><br>
+ <p-scrollPanel [style]="{width: '100%', height: '62px'}">
+ <div style="font-size: 12px; word-break: normal;">{{rowData.metadata.notes}}</div>
+ </p-scrollPanel>
+ </div>
+ <!-- Labels -->
+ <div class="row-expand-card" style="background-color: rgba(76, 65, 225, 0.295)">
+ <b style="padding-bottom: 5px;">Labels:</b><br>
+ <div *ngFor="let label of rowData['metadata']['labels']"
+ style="display: inline-flex; margin-top: 5px;">
+ <div style="padding: 2px 7px 3px 0px;">
+ <span style="background-color: rgba(80, 80, 80, 0.185); padding: 5px; border-radius: 3px;">{{label}}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </td>
+ </tr>
+ </ng-template>
+
+ </p-table>
+
+ <!--download buttons for exporting table to either csv or excel file-->
+ <div *ngIf="loadTable" class="table_export_buttons_alignment">
+ <button pButton type="button" class="table_export_button" (click)="exportTable('csv')" matTooltip="Export Table to CSV" matTooltipPosition="above" style="width: 55px;">
+ <i class="pi pi-file" style="margin-top: 3px; margin-left: 4px;"></i>
+ <label style="font-weight: 800; margin-top: 1px;">CSV</label>
+ </button>
+ <button pButton type="button" class="table_export_button" (click)="exportTable('excel')" matTooltip="Export Table to XLSX" matTooltipPosition="above" style="width: 65px; background-color: green;">
+ <i class="pi pi-file-excel" style="margin-top: 3px; margin-left: 4px;"></i>
+ <label style="font-weight: 800; margin-top: 1px">Excel</label>
+ </button>
+ </div>
+
+ <!-- Dialog to Change an MS Instance -->
+ <app-ms-instance-add *ngIf="showAddChangeMsInstance" [visible]="showAddChangeMsInstance" [msName]="msName" [msInstanceChange]="msInstanceChange" [currentRow]="currentRow" (handler)="addChangeMsInstance($event)"></app-ms-instance-add>
+
+ <!-- Dialog to Add a Component Spec -->
+ <app-comp-spec-add *ngIf="showCsAddDialog" [visible]="showCsAddDialog" (handler)="addNewCs($event)"></app-comp-spec-add>
+
+ <!--Pop-up for "Success" changing MS Instance-->
+ <p-toast key="changeSuccess"></p-toast>
+ <!--Pop-up for "Success" adding Component Spec-->
+ <p-toast key="compSpecAdded" [style]="{width: '400px'}"></p-toast>
+ <!--Pop-up for "Error" adding Component Spec-->
+ <p-toast class="toast-newline" key="errorOnCsAdd" [style]="{width: '700px'}"></p-toast>
+
+ <p-toast class="toast-newline" key="csViewError" [style]="{width: '700px'}"></p-toast>
+
+ <p-toast key="bpGenMessage" [style]="{width: '450px'}"></p-toast>
+
+</div> \ No newline at end of file
diff --git a/mod2/ui/src/app/msInstances/msInstances.component.spec.ts b/mod2/ui/src/app/msInstances/msInstances.component.spec.ts
new file mode 100644
index 0000000..5a26b58
--- /dev/null
+++ b/mod2/ui/src/app/msInstances/msInstances.component.spec.ts
@@ -0,0 +1,127 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatMenuModule, MatTooltipModule } from '@angular/material';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
+import { MessageService } from 'primeng/api';
+import { ButtonModule } from 'primeng/button';
+import { CalendarModule } from 'primeng/calendar';
+import { DialogModule } from 'primeng/dialog';
+import { DropdownModule } from 'primeng/dropdown';
+import { ScrollPanelModule } from 'primeng/scrollpanel';
+import { TableModule } from 'primeng/table';
+import { ToastModule } from 'primeng/toast';
+import { CompSpecAddComponent } from '../comp-spec-add/comp-spec-add.component';
+import { MsInstanceAddComponent } from '../ms-instance-add/ms-instance-add.component';
+
+import { MsInstancesComponent } from './msInstances.component';
+
+describe('MsInstancesComponent', () => {
+ let component: MsInstancesComponent;
+ let fixture: ComponentFixture<MsInstancesComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ MsInstancesComponent,
+ CompSpecAddComponent,
+ MsInstanceAddComponent
+ ],
+ imports: [
+ Ng4LoadingSpinnerModule,
+ TableModule,
+ MatMenuModule,
+ ScrollPanelModule,
+ ToastModule,
+ DialogModule,
+ DropdownModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ButtonModule,
+ CalendarModule,
+ HttpClientTestingModule,
+ ToastModule,
+ RouterTestingModule,
+ MatTooltipModule
+ ],
+ providers: [
+ MessageService,
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MsInstancesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it(`should fill msInstances Object`, () => {
+ const fixture = TestBed.createComponent(MsInstancesComponent);
+ const app = fixture.debugElement.componentInstance;
+
+ let mockMsInstance = [{
+ id: 'testId1234',
+ name: 'test-MS',
+ release: '2008',
+ version: '1.0.0',
+ status: 'New',
+ msInfo: {
+ id: 'testBaseMsId1234',
+ name: 'test Base Ms',
+ tag: 'test-MS-tag',
+ },
+ metadata: {
+ scrumLead: 'test',
+ scrumLeadId: 'testId',
+ systemsEngineer: 'test',
+ systemsEngineerId: 'testId',
+ developer: 'test',
+ developerId: 'testId',
+ pstDueDate: '01-01-2020 12:00',
+ pstDueIteration: '1.1',
+ eteDueDate: '01-01-2020 12:00',
+ eteDueIteration: '1.1',
+ createdBy: 'test',
+ createdOn: '01-01-2020 12:00',
+ updatedBy: 'test',
+ updatedOn: '01-01-2020 12:00',
+ notes: 'test',
+ labels: ['test'],
+ },
+ activeSpec: 'test'
+ }]
+
+ app.fillTable(mockMsInstance)
+
+ expect(app.loadTable).toEqual(true);
+ expect(app.msInstances.length).toEqual(1);
+ });
+});
diff --git a/mod2/ui/src/app/msInstances/msInstances.component.ts b/mod2/ui/src/app/msInstances/msInstances.component.ts
new file mode 100644
index 0000000..e011cb9
--- /dev/null
+++ b/mod2/ui/src/app/msInstances/msInstances.component.ts
@@ -0,0 +1,511 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
+import { MatTableDataSource } from '@angular/material/table';
+import { Table } from 'primeng/table';
+import { MessageService } from 'primeng/api';
+import { trigger, state, style, transition, animate } from '@angular/animations';
+import { MicroserviceInstanceService } from '../services/microservice-instance.service';
+import { DatePipe } from '@angular/common';
+import { DeploymentArtifactService } from '../services/deployment-artifact.service';
+import { CompSpecAddService } from '../services/comp-spec-add.service';
+import { BreadcrumbService } from '../services/breadcrumb.service';
+import { Router } from '@angular/router';
+import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
+import { DownloadService } from '../services/download.service';
+
+@Component({
+ selector: 'app-msInstances',
+ templateUrl: './msInstances.component.html',
+ styleUrls: ['./msInstances.component.css'],
+ animations: [
+ trigger('rowExpansionTrigger', [
+ state('void', style({
+ transform: 'translateX(-10%)',
+ opacity: 0
+ })),
+ state('active', style({
+ transform: 'translateX(0)',
+ opacity: 1
+ })),
+ transition('* <=> *', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
+ ])
+ ],
+ providers: [DatePipe]
+})
+export class MsInstancesComponent implements OnInit {
+ @ViewChild(Table, { static: false }) dt: Table;
+ @ViewChild('myInput', { static: false }) myInputVariable: ElementRef;
+
+
+ /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
+ msInstances: msInstance[] = [];
+ expandedItems: Array<any> = new Array<any>();
+ dataSource = new MatTableDataSource<msInstance>(this.msInstances);
+ cols: any[] = [
+ { field: 'baseMsName', header: 'MS Name' },
+ { field: 'tag', header: 'MS Tag' },
+ { field: 'release', header: 'Release', width: '7%' },
+ { field: 'pstDueDate', header: 'PST Date', width: '9%' },
+ { field: 'pstDueIteration', header: 'PST Iteration', width: '6.5%' },
+ { field: 'eteDueDate', header: 'ETE Date', width: '9%' },
+ { field: 'eteDueIteration', header: 'ETE Iteration', width: '6.5%' },
+ { field: 'status', header: 'Status', width: '125px' }
+ ];
+ selectedMsInstances: msInstance[] = [];
+ columns: any[];
+ loadTable: boolean;
+ filteredRows: any;
+ downloadItems: { label: string; command: () => void; }[];
+ showAddChangeMsInstance: boolean;
+ currentRow: any;
+ msInstanceChange: string = "change";
+ generatedBPs: any[] = [];
+ canGenerateSelectedBPs: boolean = false;
+ generateSelectedBPsTooltip: string = '';
+
+ // Json to add CS (Component Spec) to DB, returned from child
+ csAddJson: any;
+
+ showCsAddDialog: boolean = false;
+
+ showViewCs: boolean =false;
+ msInstanceId: string = '';
+ errorList: string[];
+
+ constructor(private spinnerService: Ng4LoadingSpinnerService, private msInstanceApi: MicroserviceInstanceService,
+ private bpApis: DeploymentArtifactService, private addCsApi: CompSpecAddService, private messageService: MessageService,
+ private datePipe: DatePipe, private router: Router, private downloadService: DownloadService, private bread: BreadcrumbService) { }
+
+ ngOnInit() {
+
+ this.getAllInstances();
+
+ }
+
+ getAllInstances() {
+ this.spinnerService.show();
+ this.msInstances = [];
+ this.loadTable = false;
+
+ this.msInstanceApi.getAllMsInstances()
+ .subscribe((data: any[]) => {
+ this.fillTable(data)
+ })
+
+ this.columns = this.cols.map(col => ({ title: col.header, dataKey: col.field }));
+ }
+
+
+ // * * * * * Show the Dialog to Change an MS Instance (<app-ms-instance-add> tag in the html) * * * * *
+ showAddChangeDialog(rowData) {
+ this.msInstanceId = rowData['id']
+ this.showAddChangeMsInstance = true;
+ this.currentRow = rowData;
+ }
+
+ /* * * * Call API to Change an MS Instance * * * */
+ addChangeMsInstance(jsonFromChildDialog) {
+ if (jsonFromChildDialog === null) {
+ this.showAddChangeMsInstance = false;
+ } else {
+ this.msInstanceApi.addChangeMsInstance("CHANGE", this.msInstanceId, jsonFromChildDialog).subscribe(
+ (data) => {
+ this.updateCurrentRow(data);
+ this.messageService.add({ key: 'changeSuccess', severity: 'success', summary: 'Success', detail: "MS Instance Updated", life: 5000 });
+ this.showAddChangeMsInstance = false;
+ },
+ (errResponse) => {
+ if (errResponse.error.message) {
+ this.messageService.add({ key: 'instanceAddChangeError', severity: 'error', summary: 'Error', detail: errResponse.error.message, sticky: true });
+ } else {
+ this.messageService.add({ key: 'instanceAddChangeError', severity: 'error', summary: 'Error', detail: errResponse.error.status, sticky: true });
+ }
+ }
+ )
+ }
+ }
+
+ updateCurrentRow(responseData) {
+ const newRow = responseData;
+ this.currentRow['release'] = newRow['release'];
+ this.currentRow['metadata']['scrumLead'] = newRow['metadata']['scrumLead'];
+ this.currentRow['metadata']['scrumLeadId'] = newRow['metadata']['scrumLeadId'];
+ this.currentRow['metadata']['systemsEngineer'] = newRow['metadata']['systemsEngineer'];
+ this.currentRow['metadata']['systemsEngineerId'] = newRow['metadata']['systemsEngineerId'];
+ this.currentRow['metadata']['developer'] = newRow['metadata']['developer'];
+ this.currentRow['metadata']['developerId'] = newRow['metadata']['developerId'];
+ this.currentRow['pstDueDate'] = this.datePipe.transform(newRow['metadata']['pstDueDate'], 'yyyy-MM-dd');
+ this.currentRow['pstDueIteration'] = newRow['metadata']['pstDueIteration'];
+ this.currentRow['eteDueDate'] = this.datePipe.transform(newRow['metadata']['eteDueDate'], 'yyyy-MM-dd');
+ this.currentRow['eteDueIteration'] = newRow['metadata']['eteDueIteration'];
+ this.currentRow['metadata']['labels'] = newRow['metadata']['labels'];
+ this.currentRow['metadata']['notes'] = newRow['metadata']['notes'];
+ this.currentRow['metadata']['updatedBy'] = newRow['metadata']['updatedBy'];
+ this.currentRow['metadata']['updatedOn'] = this.datePipe.transform(newRow['metadata']['updatedOn'], 'MM-dd-yyyy HH:mm');
+ }
+
+ // * * * * * Show the Dialog to Add a CS (in the html) * * * * *
+ // * * * * * Store the MS Instance ID for the URL and the "current row" to update when a CS is saved * * * * *
+ showAddCSDialog(rowData) {
+ this.showCsAddDialog = true;
+ this.msInstanceId = rowData['id'];
+ this.currentRow = rowData;
+ }
+
+ // * * * * * Add a CS * * * * *
+ addNewCs(jsonFromChildDialog) {
+ let compSpecAddMessage = '';
+ if (jsonFromChildDialog) {
+ this.csAddJson = jsonFromChildDialog;
+ if((JSON.parse(this.csAddJson)).policyJson === null){
+ compSpecAddMessage = 'Component Spec Added';
+ } else {
+ console.log("here")
+ compSpecAddMessage = 'Component Spec and Policy added '
+ }
+
+ this.addCsApi.addCsToCatalog(this.msInstanceId, this.csAddJson).subscribe(
+ (response: any) => {
+ this.messageService.add({ key: 'compSpecAdded', severity: 'success', summary: 'Success', detail: compSpecAddMessage, life: 5000 });
+ this.showCsAddDialog = false;
+ this.currentRow['activeSpec'] = true;
+ },
+ errResponse => {
+ if (errResponse.error.errors) {
+ this.messageService.add({ key: 'errorOnCsAdd', severity: 'error', summary: errResponse.error.message, detail: errResponse.error.errors.join('\n'), sticky: true});
+ } else {
+ let summary = errResponse.error.status + " - " + errResponse.error.error;
+ this.messageService.add({ key: 'errorOnCsAdd', severity: 'error', summary: summary, detail: errResponse.error.message, sticky: true});
+ }
+ });
+ } else {
+ this.showCsAddDialog = false
+ };
+ }
+
+/* * * * View Component Specs
+msName: string;
+msRelease: string;
+ showViewCsDialog(data){
+ this.msInstanceId = data['id']
+ this.msName = data['name']
+ this.msRelease = data['release']
+ this.showViewCs = true;
+ }
+ csView(data){
+ if(data===null){
+ this.showViewCs = false
+ } else {
+ this.showViewCs = false
+ this.messageService.add({ key: 'csViewError', severity: 'error', summary: 'Error Message', detail: data.error.message, sticky: true });
+ }
+ }
+ * * * */
+
+ /* * * * Generate single blueprint * * * */
+ generateBlueprints(data){
+ this.bpApis.postBlueprint(data['id']).subscribe((response) => {
+ this.messageService.add({ key: 'bpGenMessage', severity: 'success', summary: 'Success Message', detail: 'Blueprint Generated', life: 5000 });
+ }, (errResponse) => {
+ this.messageService.add({ key: 'bpGenMessage', severity: 'error', summary: 'Error Message', detail: errResponse.error.message, life: 15000 });
+ })
+ }
+
+ /* * * * Check if generate selected blueprints button should be disabled and set tooltip message * * * */
+ checkCanGenerateBp() {
+ if (this.selectedMsInstances.length > 0) {
+
+ let noActiveSpecs: string[] = [];
+ let checkReleases: boolean = true;
+ let firstRelease = this.selectedMsInstances[0]['release'];
+ for (let elem of this.selectedMsInstances) {
+ if (elem.release !== firstRelease){
+ checkReleases = false
+ this.canGenerateSelectedBPs = false
+ this.generateSelectedBPsTooltip = 'Cannot Generate Blueprints For Different Releases'
+ break
+ }
+ if (elem.activeSpec === null) {
+ noActiveSpecs.push(elem.name)
+ this.generateSelectedBPsTooltip += elem.name
+ }
+ }
+
+ if (noActiveSpecs.length < 1 && checkReleases) {
+ this.canGenerateSelectedBPs = true
+ } else if (noActiveSpecs.length > 0 && checkReleases){
+ this.canGenerateSelectedBPs = false
+ this.generateSelectedBPsTooltip = 'No Active Specs For : '
+ let i: number = 1;
+ for (let elem of noActiveSpecs) {
+ if (i === noActiveSpecs.length) {
+ this.generateSelectedBPsTooltip += '{' + elem + '}'
+ } else {
+ this.generateSelectedBPsTooltip += '{' + elem + '}, '
+ }
+ i++
+ }
+ }
+ } else {
+ this.canGenerateSelectedBPs = false
+ this.generateSelectedBPsTooltip = "No Instances Selected"
+ }
+ }
+
+ /* * * * Generate multiple blueprint * * * */
+ successfulBpGens: number;
+ generateSelectedBlueprints(){
+ this.successfulBpGens = 0;
+ this.count = 0;
+ this.selectionLength = this.selectedMsInstances.length;
+
+ this.spinnerService.show();
+
+ (async () => {
+ for (let instance of this.selectedMsInstances) {
+ this.bpApis.postBlueprint(instance.id).subscribe((response) => {
+ this.bpGenSuccess()
+ }, (errResponse) => {
+ this.bpGenError(errResponse.error.message)
+ })
+ await timeout(1500);
+ }
+ })();
+
+ function timeout(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+ }
+
+ this.selectedMsInstances = []
+ }
+
+ /* * * * For BP Gen Successes * * * */
+ selectionLength: number;
+ count: number;
+ bpGenSuccess(){
+ this.successfulBpGens++;
+ this.count++;
+ if (this.count === this.selectionLength){
+ if(this.successfulBpGens > 0){
+ this.messageService.add({ key: 'bpGenMessage', severity: 'success', summary: 'Success Message', detail: 'Blueprints Generated', life: 5000 });
+ this.spinnerService.hide()
+ }
+ }
+ }
+
+ /* * * * For BP Gen Errors * * * */
+ bpGenError(err){
+ this.count++;
+ if (this.count === this.selectionLength) {
+ if (this.successfulBpGens > 0) {
+ this.messageService.add({ key: 'bpGenMessage', severity: 'success', summary: 'Success Message', detail: 'Blueprints Generated', life: 5000 });
+ this.spinnerService.hide()
+ }
+ }
+ this.messageService.add({ key: 'bpGenMessage', severity: 'error', summary: 'Error Message', detail: err, life: 15000 });
+ }
+
+ /* * * * View the Blueprints for the selected MS Instance * * * */
+ viewBlueprints(rowData) {
+ this.router.navigate(["blueprints"], {queryParams:{tag: rowData['tag'], release:rowData['release'] }});
+ this.bread.setBreadcrumbs("Blueprints", "add");
+ }
+
+ /* * * * View the Component Spec for the selected MS Instance * * * */
+ viewCompSpecs(rowData) {
+ this.router.navigate(["CompSpecs"], { queryParams: { instanceId: rowData['id'] }});
+ this.bread.setBreadcrumbs("Component Specs", "add");
+ }
+
+ /* * * * Stores filtered data in new array * * * */
+ onTableFiltered(values) {
+ if (values) { this.filteredRows = values; }
+ else { this.filteredRows = this.msInstances; }
+ }
+
+ /* * * * Export ms instance table to excel or csv * * * */
+ exportTable(exportTo) {
+ let downloadElements: any[] = []
+
+ //labels array not handled well by excel download so converted them to a single string
+ for(let row of this.filteredRows){
+ let labels;
+ let notes;
+ if(exportTo === "excel"){
+ if(row.metadata.labels !== undefined){
+ labels = row.metadata.labels.join(",")
+ }
+ } else {
+ labels = row.metadata.labels
+ }
+
+ if (row.metadata.notes !== null && row.metadata.notes !== undefined && row.metadata.notes !== '') {
+ notes = encodeURI(row.metadata.notes).replace(/%20/g, " ").replace(/%0A/g, "\\n")
+ }
+
+ downloadElements.push({
+ MS_Name: row.name,
+ MS_Tag: row.tag,
+ Release: row.release,
+ PST_Due_Date: row.pstDueDate,
+ PST_Due_Iteration: row.pstDueIteration,
+ ETE_Due_Date: row.eteDueDate,
+ ETE_Due_Iteration: row.eteDueIteration,
+ Status: row.status,
+ Created_By: row.metadata.createdBy,
+ Created_On: row.metadata.createdOn,
+ Updated_By: row.metadata.updatedBy,
+ Updated_On: row.metadata.updatedOn,
+ Scrum_Lead: row.metadata.scrumLead,
+ Scrum_Lead_Id: row.metadata.scrumLeadId,
+ Systems_Engineer: row.metadata.systemsEngineer,
+ Systems_Engineer_Id: row.metadata.systemsEngineerId,
+ Developer: row.metadata.developer,
+ Developer_Id: row.metadata.developerId,
+ Notes: notes,
+ Labels: labels
+ })
+ }
+
+ let csvHeaders = [];
+
+ if (exportTo === "csv") {
+ csvHeaders = [
+ "MS_Name",
+ "MS_Tag",
+ "Release",
+ "PST_Due_Date",
+ "PST_Due_Iteration",
+ "ETE_Due_Date",
+ "ETE_Due_Iteration",
+ "Status",
+ "Created_By",
+ "Created_On",
+ "Updated_By",
+ "Updated_On",
+ "Scrum_Lead",
+ "Scrum_Lead_Id",
+ "Systems_Engineer",
+ "Systems_Engineer_Id",
+ "Developer",
+ "Developer_Id",
+ "Notes",
+ "Labels"
+ ];
+ }
+
+ this.downloadService.exportTableData(exportTo, downloadElements, csvHeaders)
+ }
+
+ /* * * * Fill ms instance table * * * */
+ fillTable(data) {
+
+ for (let elem of data) {
+
+ /* * * Now storing as dates (not strings) on DB, so need to convert old data (mm-dd-yyyy and m-d-yyyy) * * */
+ let pstDueDate: any;
+ if (elem.metadata.pstDueDate && (elem.metadata.pstDueDate.length <= 11 &&
+ elem.metadata.pstDueDate.length > 7)) {
+ pstDueDate = new Date(elem.metadata.pstDueDate.replace(/-/g, '/')) // dash is invalid date format, FF fails
+ pstDueDate = this.datePipe.transform(pstDueDate, 'yyyy-MM-dd')
+ } else if (elem.metadata.pstDueDate) {
+ pstDueDate = this.datePipe.transform(elem.metadata.pstDueDate, 'yyyy-MM-dd')
+ } else {
+ pstDueDate = elem.metadata.pstDueDate
+ }
+
+ let eteDueDate: any;
+ if (elem.metadata.eteDueDate && (elem.metadata.eteDueDate.length <= 11 &&
+ elem.metadata.eteDueDate.length > 7)) {
+ eteDueDate = new Date(elem.metadata.eteDueDate.replace(/-/g, '/')) // dash is invalid date format, FF fails
+ eteDueDate = this.datePipe.transform(eteDueDate, 'yyyy-MM-dd')
+ } else if (elem.metadata.eteDueDate) {
+ eteDueDate = this.datePipe.transform(elem.metadata.eteDueDate, 'yyyy-MM-dd')
+ } else {
+ eteDueDate = elem.metadata.eteDueDate
+ }
+
+ var tempElem: msInstance = {
+ id: elem.id,
+ name: elem.name,
+ tag: elem.msInfo.tag,
+ release: elem.release,
+ version: elem.version,
+ status: elem.status,
+ baseMsId: elem.msInfo.id,
+ baseMsName: elem.msInfo.name,
+ metadata: {
+ scrumLead: elem.metadata.scrumLead,
+ scrumLeadId: elem.metadata.scrumLeadId,
+ systemsEngineer: elem.metadata.systemsEngineer,
+ systemsEngineerId: elem.metadata.systemsEngineerId,
+ developer: elem.metadata.developer,
+ developerId: elem.metadata.developerId,
+ createdBy: elem.metadata.createdBy,
+ createdOn: this.datePipe.transform(elem.metadata.createdOn, 'MM-dd-yyyy HH:mm'),
+ updatedBy: elem.metadata.updatedBy,
+ updatedOn: this.datePipe.transform(elem.metadata.updatedOn, 'MM-dd-yyyy HH:mm'),
+ notes: elem.metadata.notes,
+ labels: elem.metadata.labels,
+ },
+ pstDueDate: pstDueDate,
+ pstDueIteration: elem.metadata.pstDueIteration,
+ eteDueDate: eteDueDate,
+ eteDueIteration: elem.metadata.eteDueIteration,
+ activeSpec: elem.activeSpec
+ }
+ this.msInstances.push(tempElem)
+ }
+
+ this.filteredRows = this.msInstances
+ this.loadTable = true;
+ this.spinnerService.hide()
+ }
+}
+
+export interface msInstance{
+ id: string,
+ name: string,
+ tag: string,
+ release: string,
+ version: string,
+ status: string,
+ baseMsId: string,
+ baseMsName: string ,
+ metadata: {
+ scrumLead: string,
+ scrumLeadId: string,
+ systemsEngineer: string,
+ systemsEngineerId: string,
+ developer: string,
+ developerId: string,
+ createdBy: string,
+ createdOn: string,
+ updatedBy: string,
+ updatedOn: string,
+ notes: string,
+ labels: string[],
+ }
+ pstDueDate: string,
+ pstDueIteration: string,
+ eteDueDate: string,
+ eteDueIteration: string,
+ activeSpec: any
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.css b/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.css
new file mode 100644
index 0000000..1130851
--- /dev/null
+++ b/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.css
@@ -0,0 +1,27 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+iframe{
+ padding-top: 0px;
+ border: none;
+}
+
+#content{
+ position:absolute;
+ left: 0; right: 0; bottom: 0; top: 0px;
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.html b/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.html
new file mode 100644
index 0000000..417ee39
--- /dev/null
+++ b/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.html
@@ -0,0 +1,23 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<ng4-loading-spinner id=loadingSpinner [timeout]="60000"></ng4-loading-spinner>
+<div id="content">
+ <iframe width="100%" height="98.5%" [src]="video | safe" onload="document.getElementById('loadingSpinner').style.display='none';"></iframe>
+</div>
+
diff --git a/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.spec.ts b/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.spec.ts
new file mode 100644
index 0000000..d88c06d
--- /dev/null
+++ b/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.spec.ts
@@ -0,0 +1,48 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
+import { SafePipe } from '../onboarding-tools/onboarding-tools.component';
+
+import { OnboardingToolsComponent } from './onboarding-tools.component';
+
+describe('OnboardingToolsComponent', () => {
+ let component: OnboardingToolsComponent;
+ let fixture: ComponentFixture<OnboardingToolsComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [OnboardingToolsComponent, SafePipe],
+ imports: [
+ Ng4LoadingSpinnerModule,
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OnboardingToolsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.ts b/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.ts
new file mode 100644
index 0000000..d400120
--- /dev/null
+++ b/mod2/ui/src/app/onboarding-tools/onboarding-tools.component.ts
@@ -0,0 +1,52 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, ViewEncapsulation, ViewChild, ElementRef, PipeTransform, Pipe, OnInit } from '@angular/core';
+import { DomSanitizer } from "@angular/platform-browser";
+import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
+import { environment } from '../../environments/environment';
+
+@Pipe({ name: 'safe' })
+export class SafePipe implements PipeTransform {
+ constructor(private sanitizer: DomSanitizer) { }
+ transform(url) {
+ return this.sanitizer.bypassSecurityTrustResourceUrl(url);
+ }
+}
+
+@Component({
+ selector: 'app-onboarding-tools',
+ templateUrl: './onboarding-tools.component.html',
+ styleUrls: ['./onboarding-tools.component.css']
+})
+
+export class OnboardingToolsComponent implements OnInit {
+
+ title = 'Onboarding Tools';
+
+ //video: string = `http://${environment.api_baseURL}:30991/onboarding-toolbox/blueprint-generator`
+ video: string = 'http://dcae-onboarding-toolbox-fe.ecomp.idns.cip.att.com:30991/onboarding-toolbox/blueprint-generator'
+
+ constructor(private spinnerService: Ng4LoadingSpinnerService) {
+ this.spinnerService.show();
+ }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/mod2/ui/src/app/register/register.component.css b/mod2/ui/src/app/register/register.component.css
new file mode 100644
index 0000000..730a52d
--- /dev/null
+++ b/mod2/ui/src/app/register/register.component.css
@@ -0,0 +1,18 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
diff --git a/mod2/ui/src/app/register/register.component.html b/mod2/ui/src/app/register/register.component.html
new file mode 100644
index 0000000..74f9347
--- /dev/null
+++ b/mod2/ui/src/app/register/register.component.html
@@ -0,0 +1,62 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<p-card header="Register a New User" [style]="{margin:'100px 200px 100px 200px'}" class="ui-card">
+ <hr class="line-break">
+ <form [formGroup]="form" class="p-5 bg-faded" style="margin-left: 250px;margin-bottom: 100px;">
+ <div class="ui-g ui-fluid">
+ <div class="ui-g-12 ui-md-6">
+ <div class="ui-inputgroup" >
+ <span class="ui-inputgroup-addon"><i class="pi pi-user" style="line-height: 1.25;"></i></span>
+ <input type="text" pInputText placeholder="ATT UID" formControlName="username" class="ui-inputtext">
+ </div>
+ </div>
+ </div>
+ <i *ngIf="form.get('username').errors && form.get('username').errors.minlength" style="width: 140px;margin-left: 20px;font-size: small;color: red;">username should be at least 5 characters</i>
+ <i *ngIf="form.get('username').errors && form.get('username').errors.maxlength" style="width: 140px;margin-left: 20px;font-size: small;color: red;">username should be at most 10 characters</i>
+ <div class="ui-g ui-fluid" >
+ <div class="ui-g-12 ui-md-6">
+ <div class="ui-inputgroup" >
+ <span class="ui-inputgroup-addon"><i class="pi pi-user" style="line-height: 1.25;"></i></span>
+ <input type="text" pInputText placeholder="Full Name" formControlName="fullName" class="ui-inputtext">
+ </div>
+ </div>
+ </div>
+ <div class="ui-g ui-fluid" >
+ <div class="ui-g-12 ui-md-6">
+ <div class="ui-inputgroup">
+ <button pButton type="button" icon="pi pi-refresh" class="ui-button-warn" (click)="generateNewPassword()" ></button>
+ <input type="text" pInputText formControlName="password" placeholder="Generate password" class="ui-inputtext">
+ </div>
+ </div>
+ </div>
+ <i *ngIf="form.get('password').errors && form.get('password').errors.minlength" style="width: 140px;margin-left: 20px;font-size: small;color: red;">password should be at least 6 characters</i>
+ <div class="ui-g ui-fluid" >
+ <div class="ui-g-12 ui-md-6">
+ <div class="ui-inputgroup" >
+ <span class="ui-inputgroup-addon"><i class="pi pi-users" style="line-height: 1.25; height: 1em;"></i></span>
+ <p-multiSelect [options]="rolesFromBackend" formControlName="roles" [showToggleAll]="true" [virtualScroll]="true" [filter]="false" [style]="{height:'3em'}" class="ui-multiselect"></p-multiSelect>
+ </div>
+ </div>
+ </div>
+ <p-footer class="text-left ui-g-12">
+ <button pButton type="button" class="ui-button-info" label="Cancel" (click)="cancel()" style="margin-right: .25em"></button>
+ <button pButton type="submit" class="ui-button-success" label="Register" [disabled]="!form.valid" (click)="submit()"></button>
+ </p-footer>
+ </form>
+</p-card>
diff --git a/mod2/ui/src/app/register/register.component.spec.ts b/mod2/ui/src/app/register/register.component.spec.ts
new file mode 100644
index 0000000..d05fcd1
--- /dev/null
+++ b/mod2/ui/src/app/register/register.component.spec.ts
@@ -0,0 +1,61 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { CardModule } from 'primeng/card';
+import { MultiSelectModule } from 'primeng/multiselect';
+
+import { RegisterComponent } from './register.component';
+
+describe('RegisterComponent', () => {
+ let component: RegisterComponent;
+ let fixture: ComponentFixture<RegisterComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [RegisterComponent],
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ MultiSelectModule,
+ CardModule,
+ HttpClientTestingModule,
+ RouterTestingModule
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RegisterComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/register/register.component.ts b/mod2/ui/src/app/register/register.component.ts
new file mode 100644
index 0000000..28b0677
--- /dev/null
+++ b/mod2/ui/src/app/register/register.component.ts
@@ -0,0 +1,99 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+import { AuthService } from '../services/auth.service';
+import { Router } from '@angular/router';
+import { User } from '../models/User';
+import { AuthResponse } from '../models/AuthResponse';
+import {SelectItem} from 'primeng/api';
+import { UserService } from '../services/user.service';
+
+@Component({
+ selector: 'app-register',
+ templateUrl: './register.component.html',
+ styleUrls: ['./register.component.css']
+})
+export class RegisterComponent implements OnInit {
+
+ user: User = {
+ username:'',
+ fullName:'',
+ password:'',
+ roles: []
+ };
+ form: FormGroup;
+ roleOptions: SelectItem[];
+ rolesFromBackend = [];
+
+ constructor(private fb: FormBuilder, private authService: AuthService, private router: Router, private userService: UserService) { }
+
+ ngOnInit() {
+ this.form = this.fb.group({
+ username: ['', [Validators.required, Validators.minLength(5), Validators.maxLength(10)]],
+ fullName: ['', [Validators.required]],
+ password: ['', [Validators.required, Validators.minLength(6)]],
+ roles:['', [Validators.required]]
+ });
+ // this.roleOptions = [{label:'Admin', value:{name:'ROLE_ADMIN'}}, {label:'User', value:{name:'ROLE_USER'}}, {label:'ScrumLead', value:{name:'ROLE_SCRUMLEAD'}}, {label:'Developer', value:{name:'ROLE_DEVELOPER'}}, {label:'PST', value:{name:'ROLE_PST'}}, {label:'ETE', value:{name:'ROLE_ETE'}}, {label:'Ops', value:{name:'ROLE_OPS'}}];
+ this.userService.getRoles().subscribe(res=>{
+ Object.values(res).forEach(ele=>{
+ this.rolesFromBackend.push({label:ele.substring(5), value:ele});
+ });
+ });
+ }
+
+ generateNewPassword() {
+ this.form.value.password = '';
+ const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&';
+ var array = new Uint32Array(32);
+ window.crypto.getRandomValues(array);
+ for(let i=0;i<32;i++) {
+ const index = Math.floor(array[i] % chars.length);
+ this.form.value.password += chars.charAt(index);
+ }
+ this.form.patchValue({password: this.form.value.password});
+ }
+
+ cancel() {
+ const result = window.confirm("Are you sure to quit registering current user and go back to user management?");
+ if(result === true){
+ this.router.navigate(['/users']);
+ }
+ }
+
+ submit() {
+ this.user.fullName = this. form.value.fullName;
+ this.user.username = this.form.value.username;
+ this.user.password = this.form.value.password;
+ this.user.roles = this.form.value.roles;
+ console.log(this.user.roles);
+ this.authService.register(this.user)
+ .subscribe( (res: AuthResponse) => {
+ alert(res.message);
+ this.router.navigate(['/users']);
+ }, (err) => {
+ console.log(err);
+ alert(err.error.message);
+ this.form.reset();
+ }
+ );
+ }
+
+}
diff --git a/mod2/ui/src/app/reset-password/reset-password.component.css b/mod2/ui/src/app/reset-password/reset-password.component.css
new file mode 100644
index 0000000..730a52d
--- /dev/null
+++ b/mod2/ui/src/app/reset-password/reset-password.component.css
@@ -0,0 +1,18 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
diff --git a/mod2/ui/src/app/reset-password/reset-password.component.html b/mod2/ui/src/app/reset-password/reset-password.component.html
new file mode 100644
index 0000000..748216a
--- /dev/null
+++ b/mod2/ui/src/app/reset-password/reset-password.component.html
@@ -0,0 +1,64 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<p-card header="Password Reset" [style]="{margin:'100px 300px 500px 300px'}">
+ <hr class="line-break">
+ <form [formGroup]="form" (ngSubmit)="submit()" class="p-5 bg-faded" style="margin-left: 200px;margin-bottom: 100px;">
+ <div class="ui-g ui-fluid" >
+ <div class="ui-g-12 ui-md-4">
+ <div class="ui-inputgroup" >
+ <span class="ui-inputgroup-addon"><i class="pi pi-user" style="line-height: 1.25;"></i></span>
+ <input type="text" pInputText placeholder="User id" formControlName="id" >
+ </div>
+ </div>
+ </div>
+ <div *ngIf="!authService.isAdmin; else admin">
+ <div class="ui-g ui-fluid">
+ <div class="ui-g-12 ui-md-4">
+ <div class="ui-inputgroup" >
+ <span class="ui-inputgroup-addon"><i class="pi pi-key" style="line-height: 1.25;"></i></span>
+ <input type="text" pInputText placeholder="New Password" formControlName="newPassword">
+ </div>
+ </div>
+ </div>
+ <div class="ui-g ui-fluid">
+ <div class="ui-g-12 ui-md-4">
+ <div class="ui-inputgroup" >
+ <span class="ui-inputgroup-addon"><i class="pi pi-key" style="line-height: 1.25;"></i></span>
+ <input type="text" pInputText placeholder="Confirm Password" formControlName="confirm_newPassword">
+ </div>
+ </div>
+ </div>
+ </div>
+ <ng-template class="ui-g ui-fluid" #admin>
+ <div class="ui-g-12 ui-md-4">
+ <div class="ui-inputgroup">
+ <input type="text" pInputText formControlName="password" placeholder="generate password">
+ <button pButton type="button" icon="pi pi-refresh" class="ui-button-warn" (click)="generateNewPassword()" ></button>
+ </div>
+ </div>
+ </ng-template>
+ <p-footer class="text-left ui-g-12">
+ <button pButton type="button" class="ui-button-info" label="Cancel" (click)="cancel()" style="margin-right: .25em"></button>
+ <button pButton type="submit" class="ui-button-success" label="Login" [disabled]="!form.valid"></button>
+ </p-footer>
+ <div class="text-left ui-g-12">
+ <a routerLink="/register">Not a registered user? Click here to register now!</a>
+ </div>
+ </form>
+ </p-card>
diff --git a/mod2/ui/src/app/reset-password/reset-password.component.spec.ts b/mod2/ui/src/app/reset-password/reset-password.component.spec.ts
new file mode 100644
index 0000000..a26d90b
--- /dev/null
+++ b/mod2/ui/src/app/reset-password/reset-password.component.spec.ts
@@ -0,0 +1,58 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { CardModule } from 'primeng/card';
+
+import { ResetPasswordComponent } from './reset-password.component';
+
+describe('ResetPasswordComponent', () => {
+ let component: ResetPasswordComponent;
+ let fixture: ComponentFixture<ResetPasswordComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ResetPasswordComponent],
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ CardModule,
+ HttpClientTestingModule,
+ RouterTestingModule
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ResetPasswordComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/reset-password/reset-password.component.ts b/mod2/ui/src/app/reset-password/reset-password.component.ts
new file mode 100644
index 0000000..b704b40
--- /dev/null
+++ b/mod2/ui/src/app/reset-password/reset-password.component.ts
@@ -0,0 +1,78 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit } from '@angular/core';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+import { AuthService } from '../services/auth.service';
+import { Router } from '@angular/router';
+import { User } from '../models/User';
+
+@Component({
+ selector: 'app-reset-password',
+ templateUrl: './reset-password.component.html',
+ styleUrls: ['./reset-password.component.css']
+})
+export class ResetPasswordComponent implements OnInit {
+
+ form: FormGroup;
+
+ constructor(private fb: FormBuilder, public authService: AuthService, private router: Router) { }
+
+ ngOnInit() {
+ this.form = this.fb.group({
+ id: ['', [Validators.required]],
+ password: '',
+ newPassword: '',
+ confirm_newPassword: ''
+ });
+ }
+
+ cancel() {
+ this.form.reset();
+ }
+
+ generateNewPassword() {
+ this.form.value.password = '';
+ let p = '';
+ const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&';
+ for(let i=1;i<12;i++) {
+ const index = Math.floor(Math.random() * chars.length + 1);
+ this.form.value.password += chars.charAt(index);
+ }
+ this.form.patchValue({password: this.form.value.password});
+ }
+
+ submit() {
+ const id = this.form.value.id;
+ if(!this.authService.isAdmin){
+ if(this.form.value.newPassword === this.form.value.confirm_newPassword){
+ const password = this.form.value.newPassword;
+ console.log(id);
+ console.log(password); // toJane: need to call user API
+ } else {
+ alert('Your passwords do not match, please re-confirm!');
+ this.form.patchValue({newPassword: '', confirm_newPassword: ''});
+ }
+ } else {
+ const password = this.form.value.password;
+ console.log(id);
+ console.log(password);// toJane: need to call user API
+ }
+}
+
+}
diff --git a/mod2/ui/src/app/services/auth.service.spec.ts b/mod2/ui/src/app/services/auth.service.spec.ts
new file mode 100644
index 0000000..eecc055
--- /dev/null
+++ b/mod2/ui/src/app/services/auth.service.spec.ts
@@ -0,0 +1,43 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { AuthService } from './auth.service';
+
+describe('AuthService', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ],
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule
+ ]
+ });
+ });
+ it('should be created', () => {
+ const service: AuthService = TestBed.get(AuthService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/auth.service.ts b/mod2/ui/src/app/services/auth.service.ts
new file mode 100644
index 0000000..49bb5f1
--- /dev/null
+++ b/mod2/ui/src/app/services/auth.service.ts
@@ -0,0 +1,95 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient, HttpHandler, HttpHeaders } from '@angular/common/http';
+import { Observable } from 'rxjs';
+import { tap } from 'rxjs/internal/operators';
+import { User } from '../models/User';
+import { JwtHelperService } from '@auth0/angular-jwt';
+import { AuthResponse } from '../models/AuthResponse';
+import { Router } from '@angular/router';
+import { environment } from '../../environments/environment';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthService{
+
+ private user: User = {
+ username: '',
+ roles:[]
+ };
+ authPass=false;
+ isAdmin=false;
+ reLoginMsg = false;
+
+ constructor(
+ private http:HttpClient,
+ private jwtHelper: JwtHelperService,
+ private router: Router
+ ) {
+
+ }
+
+ register(user: User): Observable<AuthResponse> {
+ return this.http.post<AuthResponse>(`http://${environment.api_baseURL}:31003/api/auth/signup`, user);
+ // return this.http.post<AuthResponse>(`http://localhost:8082/api/auth/signup`, user);
+
+ }
+
+ login(user: User): Observable<AuthResponse> {
+ return this.http.post<AuthResponse>(`http://${environment.api_baseURL}:31003/api/auth/signin`, user)
+ .pipe(
+ tap((res: AuthResponse) => {
+ localStorage.setItem('token', res.token);
+ this.setUser();
+ this.authPass = true;
+ })
+ );
+ }
+
+ setUser() {
+ this.user.username = this.jwtHelper.decodeToken(localStorage.getItem('token')).sub;
+ this.user.roles = this.jwtHelper.decodeToken(localStorage.getItem('token')).roles;
+ this.user.fullName = this.jwtHelper.decodeToken(localStorage.getItem('token')).fullName;
+
+ }
+
+ checkLogin(): Observable<boolean>{
+ return this.http.post<boolean>(`http://${environment.api_baseURL}:31003/api/auth/validate-token`, null);
+ }
+
+ getJwt() {
+ if(localStorage.getItem('token')){
+ return localStorage.getItem('token');
+ }
+ return "";
+ }
+
+ logout() {
+ localStorage.removeItem('token');
+ this.authPass = false;
+ this.router.navigate(['/login']);
+ }
+
+ getUser(): User {
+ return this.user;
+ }
+
+}
diff --git a/mod2/ui/src/app/services/base-microservice.service.spec.ts b/mod2/ui/src/app/services/base-microservice.service.spec.ts
new file mode 100644
index 0000000..1cef5bd
--- /dev/null
+++ b/mod2/ui/src/app/services/base-microservice.service.spec.ts
@@ -0,0 +1,42 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, TestBed } from '@angular/core/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { BaseMicroserviceService } from './base-microservice.service';
+
+describe('BaseMicroserviceService', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ HttpClientTestingModule,
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+
+ it('should be created', () => {
+ const service: BaseMicroserviceService = TestBed.get(BaseMicroserviceService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/base-microservice.service.ts b/mod2/ui/src/app/services/base-microservice.service.ts
new file mode 100644
index 0000000..a5c64b1
--- /dev/null
+++ b/mod2/ui/src/app/services/base-microservice.service.ts
@@ -0,0 +1,35 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { environment } from '../../environments/environment';
+import { HttpClient } from '@angular/common/http';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class BaseMicroserviceService {
+
+ private url: string = `http://${environment.api_baseURL}:31001/api/`;
+
+ constructor(private http: HttpClient) { }
+
+ getAllBaseMs() {
+ return this.http.get(this.url + "base-microservice");
+ }
+}
diff --git a/mod2/ui/src/app/services/breadcrumb.service.ts b/mod2/ui/src/app/services/breadcrumb.service.ts
new file mode 100644
index 0000000..aa647aa
--- /dev/null
+++ b/mod2/ui/src/app/services/breadcrumb.service.ts
@@ -0,0 +1,73 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { Observable, of, Subject, BehaviorSubject } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+
+export class BreadcrumbService {
+
+ breadcrumbs: any[] = [];
+
+ breadcrumbs$: Subject<any[]> = new BehaviorSubject([]);
+
+ constructor() {
+ this.setBreadcrumbs('', "reset");
+ }
+
+ setBreadcrumbs(component: string, action: string) {
+ if (action == "reset") {
+ this.breadcrumbs = [];
+ this.breadcrumbs.push({ page: 'Home', link: '/home' });
+ }
+
+ // If the breadcrumb item is clicked, remove evwrything to the right of the clicked item
+ if (action == "crumbClicked") {
+ const pos = this.breadcrumbs.map(function(crumb) { return crumb.page }).indexOf(component);
+ for (1; this.breadcrumbs.length -1 -pos; 1) {
+ this.breadcrumbs.pop()
+ }
+ } else { // Add the component that was selected
+ if (component == 'Microservices') {
+ this.breadcrumbs.push({ page: 'Microservices', link: '/base-microservices' });
+ } else if (component == 'MS Instances') {
+ this.breadcrumbs.push({ page: 'MS Instances', link: '/ms-instances' });
+ } else if (component == 'Blueprints') {
+ this.breadcrumbs.push({ page: 'Blueprints', link: '/blueprints' });
+ } else if (component == 'Component Specs') {
+ this.breadcrumbs.push({ page: 'Component Specs', link: '/CompSpecs' });
+ } else if (component == 'User Management') {
+ this.breadcrumbs.push({ page: 'User Management', link: '/users' });
+ } else if (component == 'Onboarding Tools') {
+ this.breadcrumbs.push({ page: 'Onboarding Tools', link: '/OnboardingTools' });
+ } else if (component == 'Spec Validator') {
+ this.breadcrumbs.push({ page: 'Spec Validator', link: '/spec-validator' });
+ }
+ }
+ this.notifySubscriber()
+ }
+
+
+ notifySubscriber() {
+ this.breadcrumbs$.next(this.breadcrumbs);
+ }
+}
+
diff --git a/mod2/ui/src/app/services/comp-spec-add.service.spec.ts b/mod2/ui/src/app/services/comp-spec-add.service.spec.ts
new file mode 100644
index 0000000..f7f5913
--- /dev/null
+++ b/mod2/ui/src/app/services/comp-spec-add.service.spec.ts
@@ -0,0 +1,42 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, TestBed } from '@angular/core/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { CompSpecAddService } from './comp-spec-add.service';
+
+describe('CompSpecAddService', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ HttpClientTestingModule,
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+
+ it('should be created', () => {
+ const service: CompSpecAddService = TestBed.get(CompSpecAddService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/comp-spec-add.service.ts b/mod2/ui/src/app/services/comp-spec-add.service.ts
new file mode 100644
index 0000000..d269ac4
--- /dev/null
+++ b/mod2/ui/src/app/services/comp-spec-add.service.ts
@@ -0,0 +1,45 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { environment } from '../../environments/environment';
+import { Observable } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+
+export class CompSpecAddService {
+
+ private URL: string = `http://${environment.api_baseURL}:31001/api/specification/`;
+
+ constructor(private http: HttpClient) { }
+
+ addCsToCatalog(msInstanceId: string, addCsJson: any): Observable<any> {
+ let url = this.URL + msInstanceId;
+ let body = addCsJson;
+ let headers = new HttpHeaders({
+ 'Content-Type': 'application/json'
+ });
+
+ let options = {headers:headers}
+ return this.http.post<any>(url, body, options);
+ }
+
+}
diff --git a/mod2/ui/src/app/services/comp-specs-service.service.spec.ts b/mod2/ui/src/app/services/comp-specs-service.service.spec.ts
new file mode 100644
index 0000000..58cf0a2
--- /dev/null
+++ b/mod2/ui/src/app/services/comp-specs-service.service.spec.ts
@@ -0,0 +1,43 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { compSpecsService } from './comp-specs-service.service';
+
+describe('CompSpecsServiceService', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+ it('should be created', () => {
+ const service: compSpecsService = TestBed.get(compSpecsService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/comp-specs-service.service.ts b/mod2/ui/src/app/services/comp-specs-service.service.ts
new file mode 100644
index 0000000..6fcd92c
--- /dev/null
+++ b/mod2/ui/src/app/services/comp-specs-service.service.ts
@@ -0,0 +1,43 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { environment } from '../../environments/environment';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class compSpecsService {
+
+ private baseUrl: string = `http://${environment.api_baseURL}:31001/api/specification/`;
+ constructor(private http: HttpClient) {
+ }
+
+ getAllCompSpecs(instanceId) {
+ let url = this.baseUrl + instanceId
+
+ return this.http.get(url);
+ }
+
+ post(msId, body){
+ let url: string = this.baseUrl + msId
+
+ return this.http.post<any>(url, body)
+ }
+}
diff --git a/mod2/ui/src/app/services/deployment-artifact.service.spec.ts b/mod2/ui/src/app/services/deployment-artifact.service.spec.ts
new file mode 100644
index 0000000..f392732
--- /dev/null
+++ b/mod2/ui/src/app/services/deployment-artifact.service.spec.ts
@@ -0,0 +1,43 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { DeploymentArtifactService } from './deployment-artifact.service';
+
+describe('DeploymentArtifactService', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+ it('should be created', () => {
+ const service: DeploymentArtifactService = TestBed.get(DeploymentArtifactService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/deployment-artifact.service.ts b/mod2/ui/src/app/services/deployment-artifact.service.ts
new file mode 100644
index 0000000..e344bff
--- /dev/null
+++ b/mod2/ui/src/app/services/deployment-artifact.service.ts
@@ -0,0 +1,71 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { environment } from '../../environments/environment';
+import { AuthService } from './auth.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class DeploymentArtifactService {
+
+ private URL: string = `http://${environment.api_baseURL}:31001/api/deployment-artifact/`;
+ private username = this.authService.getUser().username;
+ private url_User = "?user=" + this.username;
+
+ constructor(private http: HttpClient, private authService: AuthService) { }
+
+ getAllBlueprints() {
+ return this.http.get(this.URL);
+ }
+
+ getStatuses() {
+ let url = this.URL + 'statuses'
+
+ return this.http.get(url)
+ }
+
+ patchBlueprintStatus(update, bpId){
+ let url = this.URL + bpId + "?user=" + this.username
+ let status: string = update
+ let body = {
+ status: status
+ }
+
+ return this.http.patch(url, body)
+ }
+
+ postBlueprint(instanceID: string){
+ let url = ''
+
+ url = this.URL + instanceID + "?user=" + this.username
+ console.log(url)
+
+ return this.http.post<any>(url, '')
+ }
+
+ deleteBlueprint(instanceID: string){
+ console.log(instanceID)
+ let url = this.URL + instanceID + this.url_User
+
+ return this.http.delete(url)
+ }
+
+}
diff --git a/mod2/ui/src/app/services/download.service.spec.ts b/mod2/ui/src/app/services/download.service.spec.ts
new file mode 100644
index 0000000..1df7bfd
--- /dev/null
+++ b/mod2/ui/src/app/services/download.service.spec.ts
@@ -0,0 +1,41 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, TestBed } from '@angular/core/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { DownloadService } from './download.service';
+
+describe('DownloadService', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ HttpClientTestingModule,
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+ it('should be created', () => {
+ const service: DownloadService = TestBed.get(DownloadService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/download.service.ts b/mod2/ui/src/app/services/download.service.ts
new file mode 100644
index 0000000..619eff7
--- /dev/null
+++ b/mod2/ui/src/app/services/download.service.ts
@@ -0,0 +1,85 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import * as saveAs from 'file-saver';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class DownloadService {
+
+ constructor() { }
+
+ /* * * * Download json file * * * */
+ downloadJSON(content, fileName){
+ let file = new Blob([JSON.stringify(content)], { type: 'text;charset=utf-8' });
+ let name: string = `${fileName}.json`
+ saveAs(file, name)
+ }
+
+ /* * * * Export ms instance table to excel or csv * * * */
+ exportTableData(exportTo, downloadElements, arrHeader) {
+ if (exportTo === "excel") {
+ import("xlsx").then(xlsx => {
+ const worksheet = xlsx.utils.json_to_sheet(downloadElements);
+ const workbook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
+ const excelBuffer: any = xlsx.write(workbook, { bookType: 'xlsx', type: 'array' });
+ this.saveAsExcelFile(excelBuffer, "Table_Data");
+ });
+ } else if (exportTo === "csv") {
+ let csvData = this.convertToCSV(downloadElements, arrHeader)
+ var blob = new Blob([csvData], { type: 'text/csv' })
+ saveAs(blob, "Table_Data.csv");
+ }
+ }
+ saveAsExcelFile(buffer: any, fileName: string): void {
+ import("file-saver").then(FileSaver => {
+ let EXCEL_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';
+ let EXCEL_EXTENSION = '.xlsx';
+ const data: Blob = new Blob([buffer], {
+ type: EXCEL_TYPE
+ });
+ FileSaver.saveAs(data, fileName + '_export_' + new Date().getTime() + EXCEL_EXTENSION);
+ });
+ }
+ convertToCSV(objArray, headerList) {
+ let array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
+ let str = '';
+ let row = '';
+ for (let index in headerList) {
+ row += headerList[index] + ',';
+ }
+ row = row.slice(0, -1);
+ str += row + '\r\n';
+ for (let i = 0; i < array.length; i++) {
+ let line = '';
+ for (let index in headerList) {
+ let head = headerList[index];
+ if (array[i][head] === null || array[i][head] === undefined) {
+ line += ','
+ } else {
+ if (head === "Labels" && array[i][head].length > 1) { line += '[' + array[i][head].join('] [') + '],'; }
+ else { line += array[i][head] + ','; }
+ }
+ }
+ str += line + '\r\n';
+ }
+ return str;
+ }
+}
diff --git a/mod2/ui/src/app/services/global-filters.service.spec.ts b/mod2/ui/src/app/services/global-filters.service.spec.ts
new file mode 100644
index 0000000..cadfd3f
--- /dev/null
+++ b/mod2/ui/src/app/services/global-filters.service.spec.ts
@@ -0,0 +1,30 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { TestBed } from '@angular/core/testing';
+
+import { GlobalFiltersService } from './global-filters.service';
+
+describe('GlobalFiltersService', () => {
+ beforeEach(() => TestBed.configureTestingModule({}));
+
+ it('should be created', () => {
+ const service: GlobalFiltersService = TestBed.get(GlobalFiltersService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/global-filters.service.ts b/mod2/ui/src/app/services/global-filters.service.ts
new file mode 100644
index 0000000..0937f92
--- /dev/null
+++ b/mod2/ui/src/app/services/global-filters.service.ts
@@ -0,0 +1,55 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class GlobalFiltersService {
+
+ //global filter values
+ instanceName: string;
+ instanceTag: string;
+ release: string;
+ status: string;
+
+ shouldFilter: boolean = false;
+
+ constructor() { }
+
+ setFilters(filters){
+ this.instanceName = filters.instanceName
+ this.instanceTag = filters.instanceTag
+ this.release = filters.release
+ this.status = filters.status
+ }
+
+ getFilters(){
+ let globalFilters = {instanceName: this.instanceName, instanceTag: this.instanceTag, release: this.release, status: this.status}
+ return globalFilters
+ }
+
+ checkShouldFilter(){
+ return this.shouldFilter
+ }
+
+ setShouldFilter(){
+ this.shouldFilter = !this.shouldFilter
+ }
+}
diff --git a/mod2/ui/src/app/services/jwt-interceptor.service.spec.ts b/mod2/ui/src/app/services/jwt-interceptor.service.spec.ts
new file mode 100644
index 0000000..6fea9ba
--- /dev/null
+++ b/mod2/ui/src/app/services/jwt-interceptor.service.spec.ts
@@ -0,0 +1,30 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { TestBed } from '@angular/core/testing';
+
+import { JwtInterceptorService } from './jwt-interceptor.service';
+
+describe('JwtInterceptorService', () => {
+ beforeEach(() => TestBed.configureTestingModule({}));
+
+ it('should be created', () => {
+ const service: JwtInterceptorService = TestBed.get(JwtInterceptorService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/jwt-interceptor.service.ts b/mod2/ui/src/app/services/jwt-interceptor.service.ts
new file mode 100644
index 0000000..2647583
--- /dev/null
+++ b/mod2/ui/src/app/services/jwt-interceptor.service.ts
@@ -0,0 +1,40 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable, Injector } from '@angular/core';
+import { HttpInterceptor } from '@angular/common/http';
+import { AuthService } from './auth.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class JwtInterceptorService implements HttpInterceptor{
+
+ constructor(private injector: Injector) { }
+
+ intercept(req: import("@angular/common/http").HttpRequest<any>, next: import("@angular/common/http").HttpHandler): import("rxjs").Observable<import("@angular/common/http").HttpEvent<any>> {
+ let authService = this.injector.get(AuthService);
+ let jwtReq = req.clone({
+ setHeaders: {
+ Authorization: `Bearer ${authService.getJwt()}`
+ }
+ })
+ return next.handle(jwtReq);
+ }
+
+}
diff --git a/mod2/ui/src/app/services/microservice-instance.service.spec.ts b/mod2/ui/src/app/services/microservice-instance.service.spec.ts
new file mode 100644
index 0000000..b3c4074
--- /dev/null
+++ b/mod2/ui/src/app/services/microservice-instance.service.spec.ts
@@ -0,0 +1,41 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, TestBed } from '@angular/core/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { MicroserviceInstanceService } from './microservice-instance.service';
+
+describe('MicroserviceInstanceService', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ HttpClientTestingModule,
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+ it('should be created', () => {
+ const service: MicroserviceInstanceService = TestBed.get(MicroserviceInstanceService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/microservice-instance.service.ts b/mod2/ui/src/app/services/microservice-instance.service.ts
new file mode 100644
index 0000000..96cce77
--- /dev/null
+++ b/mod2/ui/src/app/services/microservice-instance.service.ts
@@ -0,0 +1,46 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { environment } from '../../environments/environment';
+import { HttpClient } from '@angular/common/http';
+import { AddMsInstance } from '../microservices/microservices.component';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class MicroserviceInstanceService {
+
+ private url: string = `http://${environment.api_baseURL}:31001/api/microservice-instance/`;
+
+ constructor(private http: HttpClient) { }
+
+ getAllMsInstances() {
+ return this.http.get(this.url);
+ }
+
+ addChangeMsInstance(addOrChange: string, msNameOrId: string, body: AddMsInstance){
+ let URL = this.url + msNameOrId
+
+ if (addOrChange == "ADD") {
+ return this.http.post<any>(URL, body);
+ } else {
+ return this.http.patch<any>(URL, body);
+ }
+ }
+}
diff --git a/mod2/ui/src/app/services/ms-add.service.spec.ts b/mod2/ui/src/app/services/ms-add.service.spec.ts
new file mode 100644
index 0000000..dc53a56
--- /dev/null
+++ b/mod2/ui/src/app/services/ms-add.service.spec.ts
@@ -0,0 +1,42 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, TestBed } from '@angular/core/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { MsAddService } from './ms-add.service';
+
+describe('MsAddService', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ HttpClientTestingModule,
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+
+ it('should be created', () => {
+ const service: MsAddService = TestBed.get(MsAddService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/ms-add.service.ts b/mod2/ui/src/app/services/ms-add.service.ts
new file mode 100644
index 0000000..367799d
--- /dev/null
+++ b/mod2/ui/src/app/services/ms-add.service.ts
@@ -0,0 +1,52 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { environment } from '../../environments/environment';
+import { Observable } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+
+
+
+export class MsAddService {
+
+ private URL: string = `http://${environment.api_baseURL}:31001/api/base-microservice`;
+
+ constructor(private http: HttpClient) { }
+
+ addChangeMsToCatalog(addOrChange, msID, addChangeMsJson): Observable<any> {
+ let url = this.URL;
+ let headers = new HttpHeaders({'Content-Type': 'application/json'});
+ let options = {headers:headers};
+ let body;
+
+ body = addChangeMsJson;
+
+ if (addOrChange == "Add") {
+ return this.http.post<any>(url, body, options);
+ } else {
+ url = url + "/" + msID;
+ return this.http.patch<any>(url, body, options);
+ }
+ }
+
+}
diff --git a/mod2/ui/src/app/services/spec-validation.service.spec.ts b/mod2/ui/src/app/services/spec-validation.service.spec.ts
new file mode 100644
index 0000000..e83f832
--- /dev/null
+++ b/mod2/ui/src/app/services/spec-validation.service.spec.ts
@@ -0,0 +1,41 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, TestBed } from '@angular/core/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { SpecValidationService } from './spec-validation.service';
+
+describe('SpecValidationService', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ HttpClientTestingModule,
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+ it('should be created', () => {
+ const service: SpecValidationService = TestBed.get(SpecValidationService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/spec-validation.service.ts b/mod2/ui/src/app/services/spec-validation.service.ts
new file mode 100644
index 0000000..2785efe
--- /dev/null
+++ b/mod2/ui/src/app/services/spec-validation.service.ts
@@ -0,0 +1,53 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { environment } from '../../environments/environment';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class SpecValidationService {
+
+ private URL: string = 'http://zlecdyh2adcc1s2dokr04.1463c9.dyh2a.tci.att.com:31002/';
+
+ constructor(private http: HttpClient) { }
+
+ sendSpecFile(specContent, type, release){
+
+ let url = ''
+
+ if(release === "2007"){
+ url = `${this.URL}v6/api/comp_spec_validator/`
+ }
+
+ let body = {
+ compspec_content: specContent,
+ type: type
+ }
+
+ return this.http.post(url, body)
+ }
+
+ getSchema(type){
+ let url = `${this.URL}v6/api/schema/${type}`
+
+ return this.http.get(url)
+ }
+}
diff --git a/mod2/ui/src/app/services/user.service.spec.ts b/mod2/ui/src/app/services/user.service.spec.ts
new file mode 100644
index 0000000..979e9fa
--- /dev/null
+++ b/mod2/ui/src/app/services/user.service.spec.ts
@@ -0,0 +1,44 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, TestBed } from '@angular/core/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+
+import { UserService } from './user.service';
+
+describe('UserService', () => {
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ HttpClientTestingModule
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => TestBed.configureTestingModule({}));
+
+ it('should be created', () => {
+ const service: UserService = TestBed.get(UserService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/services/user.service.ts b/mod2/ui/src/app/services/user.service.ts
new file mode 100644
index 0000000..ec1d503
--- /dev/null
+++ b/mod2/ui/src/app/services/user.service.ts
@@ -0,0 +1,53 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable } from 'rxjs';
+import { User } from '../models/User';
+import { AuthResponse } from '../models/AuthResponse';
+import { environment } from '../../environments/environment';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class UserService {
+
+ constructor(private http: HttpClient) {}
+
+ getUsers(): Observable<User[]> {
+ return this.http.get<User[]>(`http://${environment.api_baseURL}:31003/api/users/getAll`);
+ }
+
+ editUser(username: string, user: User): Observable<any>{
+ return this.http.patch<any>(`http://${environment.api_baseURL}:31003/api/users/admin/${username}`, user);
+ }
+
+ editProfile(username: string, user: User): Observable<any>{
+ return this.http.patch<any>(`http://${environment.api_baseURL}:31003/api/users/user/${username}`, user);
+ }
+
+ deleteUser(username: string): Observable<{message:string}> {
+ return this.http.delete<{message: string}>(`http://${environment.api_baseURL}:31003/api/users/${username}`);
+ }
+
+ getRoles() {
+ return this.http.get(`http://${environment.api_baseURL}:31003/api/roles`);
+ }
+
+}
diff --git a/mod2/ui/src/app/shared/shared-module.ts b/mod2/ui/src/app/shared/shared-module.ts
new file mode 100644
index 0000000..7ab21b6
--- /dev/null
+++ b/mod2/ui/src/app/shared/shared-module.ts
@@ -0,0 +1,61 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { NgModule } from '@angular/core';
+import {MatSelectModule} from '@angular/material/select';
+import { FormsModule } from '@angular/forms';
+import {MatTableModule} from '@angular/material/table';
+import { MatFormFieldModule, MatInputModule } from '@angular/material';
+import { MatPaginatorModule } from '@angular/material';
+//import { MatSort } from '@angular/material';
+import { MatToolbarModule, MatIconModule, MatSidenavModule, MatListModule, MatButtonModule } from '@angular/material';
+
+@NgModule({
+ declarations: [
+ ],
+ imports: [
+ MatSelectModule,
+ FormsModule,
+ MatToolbarModule,
+ MatIconModule,
+ MatSidenavModule,
+ MatListModule,
+ MatButtonModule,
+ MatTableModule,
+ MatPaginatorModule,
+ MatFormFieldModule,
+ MatInputModule
+ //MatSort
+
+ ],
+ exports: [
+ MatSelectModule,
+ FormsModule,
+ MatToolbarModule,
+ MatIconModule,
+ MatSidenavModule,
+ MatListModule,
+ MatButtonModule,
+ MatTableModule,
+ MatPaginatorModule,
+ MatFormFieldModule,
+ MatInputModule
+ // MatSort
+ ]
+ })
+ export class SharedModule { } \ No newline at end of file
diff --git a/mod2/ui/src/app/user-management/user-management.component.css b/mod2/ui/src/app/user-management/user-management.component.css
new file mode 100644
index 0000000..495d0f8
--- /dev/null
+++ b/mod2/ui/src/app/user-management/user-management.component.css
@@ -0,0 +1,54 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+.pi-trash:hover {
+ color:red;
+}
+.pi-pencil:hover {
+ color:blue;
+}
+
+label {
+ cursor: pointer;
+}
+
+.input{
+ padding-top: 10px;
+}
+
+.inputLabel {
+ font-weight: 600;
+ margin-left: 20px;
+ width: 140px;
+}
+
+.inputFieldSm {
+ width: 200px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldMed {
+ width: 300px;
+ height: 35px;
+ padding-left: 6px;
+}
+.inputFieldLg {
+ width: 400px;
+ height: 35px;
+ padding-left: 6px;
+} \ No newline at end of file
diff --git a/mod2/ui/src/app/user-management/user-management.component.html b/mod2/ui/src/app/user-management/user-management.component.html
new file mode 100644
index 0000000..6885fe1
--- /dev/null
+++ b/mod2/ui/src/app/user-management/user-management.component.html
@@ -0,0 +1,89 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<div style="margin: 0px 20px 10px 20px">
+ <p-table #dt [value]="users" [rowHover]="true">
+ <ng-template pTemplate="caption">
+ <h5><strong>System User List and Management</strong><i style="font-size: smaller;"> ( for admin only )</i></h5>
+ <br/>
+ <a routerLink="/register">Want to register a new user? Click here!</a>
+ </ng-template>
+ <ng-template pTemplate="header">
+ <tr>
+ <th style="width: 15%">Username (ATT UID)</th>
+ <th>Full Name</th>
+ <th>Roles</th>
+ <!-- <th>Active Status</th> -->
+ <th style="width: 15%">Actions</th>
+ </tr>
+ </ng-template>
+ <ng-template pTemplate="body" let-user>
+ <tr>
+ <td>{{user.username}}</td>
+ <td>{{user.fullName}}</td>
+ <td>{{user.roles}}</td>
+ <!-- <td>true</td> -->
+ <td>
+ <i class="pi pi-trash" (click)="handleDelete(user.username)" pTooltip="delete user" tooltipPosition="right"></i>
+ <i class="pi pi-pencil" (click)="handleEdit(user)" pTooltip="edit user" tooltipPosition="right" style="margin-left: .5em;"></i>
+ </td>
+ </tr>
+ </ng-template>
+ </p-table>
+
+ <!--edit user information dialog-->
+ <p-dialog [(visible)]="editUserFlag" appendTo="body" [modal]="true" [transitionOptions]="'300ms'" [style]="{width: '635px'}" [baseZIndex]="10000"
+ [closable]="true" (onHide)="closeEditDialog()">
+ <p-header style="display: inline-flex;">
+ Edit User Information
+ </p-header>
+
+ <form [formGroup]="editUserForm">
+ <!-- * * * Username * * * -->
+ <div class="input">
+ <label class="inputLabel">ATT UID</label>&nbsp;
+ <b>{{editUser.username}}</b>
+ </div>
+ <!-- * * * User Full Name * * * -->
+ <div class="input">
+ <label class="inputLabel">Full Name</label>&nbsp;
+ <input class="inputFieldSm" type="text" pInputText formControlName="fullName"/>
+ </div>
+ <!-- * * * Roles * * * -->
+ <div class="input">
+ <label class="inputLabel">Roles</label>&nbsp;
+ <p-multiSelect [options]="rolesFromBackend" formControlName="roles" [showToggleAll]="true" [virtualScroll]="true" [filter]="false" [style]="{height:'3.6em', width:'200px'}"></p-multiSelect>
+ <!-- <b>{{editUser.roles}}</b> -->
+ </div>
+ <!-- * * * Re-Generate Password * * * -->
+ <div class="input">
+ <div class="ui-inputgroup">
+ <label class="inputLabel">New Password</label>&nbsp;
+ <button pButton type="button" icon="pi pi-refresh" class="ui-button-warn" (click)="generateNewPassword()" ></button>
+ <input type="text" pInputText formControlName="password" placeholder="Generate password" class="ui-inputtext" pTooltip="Password should be greater than 5 characters" tooltipPosition="right">
+ </div>
+ </div>
+ <i *ngIf="editUserForm.get('password').errors && editUserForm.get('password').errors.minlength" style="width: 140px;margin-left: 20px;font-size: small;color: red;">password should be at least 6 characters</i>
+ <!-- * * * Submit and Cancel buttons * * * -->
+ <div style="margin-top: 2em; margin-left: 1.3em; margin-bottom: 2em;">
+ <button pButton type="button" (click)="closeEditDialog()" label="Cancel"></button>&nbsp;
+ <button pButton type="submit" (click)="submitEdit(editUser)" class="ui-button-success" label="Submit" style="width: 70px"></button>
+ </div>
+ </form>
+</p-dialog>
+</div> \ No newline at end of file
diff --git a/mod2/ui/src/app/user-management/user-management.component.spec.ts b/mod2/ui/src/app/user-management/user-management.component.spec.ts
new file mode 100644
index 0000000..2cb6a6e
--- /dev/null
+++ b/mod2/ui/src/app/user-management/user-management.component.spec.ts
@@ -0,0 +1,63 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+import { JwtHelperService, JWT_OPTIONS } from '@auth0/angular-jwt';
+import { DialogModule } from 'primeng/dialog';
+import { MultiSelectModule } from 'primeng/multiselect';
+import { TableModule } from 'primeng/table';
+
+import { UserManagementComponent } from './user-management.component';
+
+describe('UserManagementComponent', () => {
+ let component: UserManagementComponent;
+ let fixture: ComponentFixture<UserManagementComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [UserManagementComponent],
+ imports: [
+ TableModule,
+ DialogModule,
+ MultiSelectModule,
+ FormsModule,
+ ReactiveFormsModule,
+ HttpClientTestingModule,
+ RouterTestingModule
+ ],
+ providers: [
+ { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
+ JwtHelperService
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(UserManagementComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/mod2/ui/src/app/user-management/user-management.component.ts b/mod2/ui/src/app/user-management/user-management.component.ts
new file mode 100644
index 0000000..b7ee6e7
--- /dev/null
+++ b/mod2/ui/src/app/user-management/user-management.component.ts
@@ -0,0 +1,149 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import { Component, OnInit, ViewChild, ChangeDetectionStrategy } from '@angular/core';
+import { User } from '../models/User';
+import { UserService } from '../services/user.service';
+import { Router } from '@angular/router';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+import { SelectItem } from 'primeng/api';
+import { AuthService } from '../services/auth.service';
+
+@Component({
+ selector: 'app-user-management',
+ templateUrl: './user-management.component.html',
+ styleUrls: ['./user-management.component.css']
+})
+export class UserManagementComponent implements OnInit {
+
+ users: User[] = [];
+ editUser: User = {
+ username:'',
+ fullName:'',
+ roles: []
+ };
+ editUserFlag: boolean = false;
+ editUserForm: FormGroup;
+ rolesFromBackend = [];
+ selectedRoles : Array<String>= [];
+
+ constructor(private userService: UserService, private router: Router, private fb: FormBuilder, private authService: AuthService) { }
+
+ ngOnInit() {
+ this.userService.getUsers().subscribe((res: User[]) => {
+ this.users = res;
+ this.users.map(user=>{
+ let tempRoles = [];
+ user.roles.map(role=>{
+ tempRoles.push(role.name.substring(5));
+ });
+ user.roles = tempRoles;
+ });
+
+ });
+ this.editUserForm = this.fb.group({
+ username: '',
+ fullName: '',
+ password: [null, [ Validators.minLength(6)]],
+ roles: [this.selectedRoles, [Validators.required]]
+ });
+ this.userService.getRoles().subscribe(res=>{
+ Object.values(res).forEach(ele=>{
+ this.rolesFromBackend.push({label:ele.substring(5), value:ele});
+ });
+ });
+ }
+
+ handleDelete(username) {
+ const result = window.confirm('Are you sure to delete this user?');
+ if(result === true) {
+ this.userService.deleteUser(username).subscribe(res=>{
+ alert(res.message);
+ this.userService.getUsers().subscribe( r => {
+ this.users = r;
+ this.users.map(user=>{
+ let tempRoles = [];
+ user.roles.map(role=>{
+ tempRoles.push(role.name.substring(5));
+ });
+ user.roles = tempRoles;
+ });
+ });
+ });
+ }
+ }
+
+ handleEdit(user) {
+ this.selectedRoles = [];
+ this.editUserFlag = true;
+ this.editUser = user;
+ this.editUserForm.get('username').setValue(user.username);
+ this.editUserForm.get('fullName').setValue(user.fullName);
+ user.roles.map(ele => {
+ let temp = "ROLE_" + ele;
+ this.selectedRoles.push(temp);
+ })
+
+ this.editUserForm.get('roles').setValue(this.selectedRoles);
+
+ }
+
+ closeEditDialog() {
+ this.editUserForm.reset();
+ this.editUserFlag = false;
+ }
+
+ generateNewPassword() {
+ this.editUserForm.value.password = '';
+ const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&';
+ var array = new Uint32Array(32);
+ window.crypto.getRandomValues(array);
+ for(let i=0;i<32;i++) {
+ const index = Math.floor(array[i] % chars.length);
+ this.editUserForm.value.password += chars.charAt(index);
+ }
+ this.editUserForm.patchValue({password: this.editUserForm.value.password});
+ }
+
+ submitEdit(user) {
+ this.editUserFlag = false;
+ console.log(this.editUserForm.value.fullName);
+ let tempUser = this.editUserForm.value as User;
+ console.log(tempUser);
+ this.userService.editUser(user.username, this.editUserForm.value as User).subscribe(res=>{
+ alert("User information updated successfully.");
+ this.userService.getUsers().subscribe( r => {
+ this.users = r;
+ this.users.map(user=>{
+ let tempRoles = [];
+ user.roles.map(role=>{
+ tempRoles.push(role.name.substring(5));
+ });
+ user.roles = tempRoles;
+ });
+ }, (err)=>{
+ // alert(err.error.message);
+ alert("Sorry but your credentials are out of date. Please log in again to resolve this.");
+ this.authService.logout();
+ });
+ }, (err)=>{
+ alert(err.error.message);
+ });
+ }
+
+}
diff --git a/mod2/ui/src/assets/.gitkeep b/mod2/ui/src/assets/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mod2/ui/src/assets/.gitkeep
diff --git a/mod2/ui/src/assets/env.js b/mod2/ui/src/assets/env.js
new file mode 100644
index 0000000..144ee8b
--- /dev/null
+++ b/mod2/ui/src/assets/env.js
@@ -0,0 +1,17 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */ \ No newline at end of file
diff --git a/mod2/ui/src/environments/environment.prod.ts b/mod2/ui/src/environments/environment.prod.ts
new file mode 100644
index 0000000..7edd870
--- /dev/null
+++ b/mod2/ui/src/environments/environment.prod.ts
@@ -0,0 +1,22 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+export const environment = {
+ production: true,
+ //api_baseURL: process.env.DCAE_HOSTNAME
+};
diff --git a/mod2/ui/src/environments/environment.ts b/mod2/ui/src/environments/environment.ts
new file mode 100644
index 0000000..1907c5e
--- /dev/null
+++ b/mod2/ui/src/environments/environment.ts
@@ -0,0 +1,35 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+// This file can be replaced during build by using the `fileReplacements` array.
+// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
+// The list of file replacements can be found in `angular.json`.
+
+export const environment = {
+ production: false,
+ api_baseURL: `${process.env.DCAE_HOSTNAME}`
+};
+
+/*
+ * For easier debugging in development mode, you can import the following file
+ * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
+ *
+ * This import should be commented out in production mode because it will have a negative impact
+ * on performance if an error is thrown.
+ */
+// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
diff --git a/mod2/ui/src/favicon.ico b/mod2/ui/src/favicon.ico
new file mode 100644
index 0000000..8081c7c
--- /dev/null
+++ b/mod2/ui/src/favicon.ico
Binary files differ
diff --git a/mod2/ui/src/index.html b/mod2/ui/src/index.html
new file mode 100644
index 0000000..f2836a8
--- /dev/null
+++ b/mod2/ui/src/index.html
@@ -0,0 +1,36 @@
+<!--
+ # ============LICENSE_START=======================================================
+ # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ # ================================================================================
+ # 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.
+ # ============LICENSE_END=========================================================
+ -->
+
+<!doctype html>
+<html lang="en">
+<head>
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
+ <meta charset="utf-8">
+ <title>ModFe</title>
+ <base href="/">
+
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="icon" type="image/x-icon" href="favicon.ico">
+ <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap" rel="stylesheet">
+ <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel=“stylesheet”>
+</head>
+<body>
+ <app-root></app-root>
+</body>
+</html>
diff --git a/mod2/ui/src/main.ts b/mod2/ui/src/main.ts
new file mode 100644
index 0000000..54bf0d7
--- /dev/null
+++ b/mod2/ui/src/main.ts
@@ -0,0 +1,31 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+import 'hammerjs';
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+ .catch(err => console.error(err));
diff --git a/mod2/ui/src/polyfills.ts b/mod2/ui/src/polyfills.ts
new file mode 100644
index 0000000..20fe70e
--- /dev/null
+++ b/mod2/ui/src/polyfills.ts
@@ -0,0 +1,81 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ * file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/guide/browser-support
+ */
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+// import 'classlist.js'; // Run `npm install --save classlist.js`.
+
+/**
+ * Web Animations `@angular/platform-browser/animations`
+ * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
+ * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
+ */
+// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+
+/**
+ * By default, zone.js will patch all possible macroTask and DomEvents
+ * user can disable parts of macroTask/DomEvents patch by setting following flags
+ * because those flags need to be set before `zone.js` being loaded, and webpack
+ * will put import in the top of bundle, so user need to create a separate file
+ * in this directory (for example: zone-flags.ts), and put the following flags
+ * into that file, and then add the following code before importing zone.js.
+ * import './zone-flags.ts';
+ *
+ * The flags allowed in zone-flags.ts are listed here.
+ *
+ * The following flags will work for all browsers.
+ *
+ * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+ *
+ * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
+ * with the following flag, it will bypass `zone.js` patch for IE/Edge
+ *
+ * (window as any).__Zone_enable_cross_context_check = true;
+ *
+ */
+
+/***************************************************************************************************
+ * Zone JS is required by default for Angular itself.
+ */
+import 'zone.js/dist/zone'; // Included with Angular CLI.
+
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
diff --git a/mod2/ui/src/styles.css b/mod2/ui/src/styles.css
new file mode 100644
index 0000000..6a392de
--- /dev/null
+++ b/mod2/ui/src/styles.css
@@ -0,0 +1,33 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+@import "~@angular/material/prebuilt-themes/indigo-pink.css";
+@import "~bootstrap/dist/css/bootstrap.css";
+
+html,
+body {
+ height: 100%;
+ overflow: hidden;
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ margin: 0;
+ font-family: Roboto, "Helvetica Neue", sans-serif;
+} \ No newline at end of file
diff --git a/mod2/ui/src/test.ts b/mod2/ui/src/test.ts
new file mode 100644
index 0000000..ccff8e7
--- /dev/null
+++ b/mod2/ui/src/test.ts
@@ -0,0 +1,38 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/dist/zone-testing';
+import { getTestBed } from '@angular/core/testing';
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+declare const require: any;
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
diff --git a/mod2/ui/tsconfig.app.json b/mod2/ui/tsconfig.app.json
new file mode 100644
index 0000000..c85ee27
--- /dev/null
+++ b/mod2/ui/tsconfig.app.json
@@ -0,0 +1,14 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./out-tsc/app",
+ "types": ["node"]
+ },
+ "include": [
+ "src/**/*.ts"
+ ],
+ "exclude": [
+ "src/test.ts",
+ "src/**/*.spec.ts"
+ ]
+}
diff --git a/mod2/ui/tsconfig.json b/mod2/ui/tsconfig.json
new file mode 100644
index 0000000..e65fbae
--- /dev/null
+++ b/mod2/ui/tsconfig.json
@@ -0,0 +1,33 @@
+{
+ "compileOnSave": false,
+ "include": [
+ "typings.d.ts"
+ ],
+ "exclude": [
+ "node_modules/@types/nodes/index.d.ts"
+ ],
+ "compilerOptions": {
+ "baseUrl": "./",
+ "outDir": "./dist/out-tsc",
+ "sourceMap": true,
+ "declaration": false,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "importHelpers": true,
+ "target": "es2015",
+ "types": [
+ "node",
+ "lodash",
+ "typings.d.ts"
+ ],
+ "typeRoots": [
+ "node_modules/@types"
+ ],
+ "lib": [
+ "es2018",
+ "dom"
+ ]
+ }
+}
diff --git a/mod2/ui/tsconfig.spec.json b/mod2/ui/tsconfig.spec.json
new file mode 100644
index 0000000..6400fde
--- /dev/null
+++ b/mod2/ui/tsconfig.spec.json
@@ -0,0 +1,18 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./out-tsc/spec",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "files": [
+ "src/test.ts",
+ "src/polyfills.ts"
+ ],
+ "include": [
+ "src/**/*.spec.ts",
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/mod2/ui/tslint.json b/mod2/ui/tslint.json
new file mode 100644
index 0000000..188bd78
--- /dev/null
+++ b/mod2/ui/tslint.json
@@ -0,0 +1,92 @@
+{
+ "extends": "tslint:recommended",
+ "rules": {
+ "array-type": false,
+ "arrow-parens": false,
+ "deprecation": {
+ "severity": "warn"
+ },
+ "component-class-suffix": true,
+ "contextual-lifecycle": true,
+ "directive-class-suffix": true,
+ "directive-selector": [
+ true,
+ "attribute",
+ "app",
+ "camelCase"
+ ],
+ "component-selector": [
+ true,
+ "element",
+ "app",
+ "kebab-case"
+ ],
+ "import-blacklist": [
+ true,
+ "rxjs/Rx"
+ ],
+ "interface-name": false,
+ "max-classes-per-file": false,
+ "max-line-length": [
+ true,
+ 140
+ ],
+ "member-access": false,
+ "member-ordering": [
+ true,
+ {
+ "order": [
+ "static-field",
+ "instance-field",
+ "static-method",
+ "instance-method"
+ ]
+ }
+ ],
+ "no-consecutive-blank-lines": false,
+ "no-console": [
+ true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-empty": false,
+ "no-inferrable-types": [
+ true,
+ "ignore-params"
+ ],
+ "no-non-null-assertion": true,
+ "no-redundant-jsdoc": true,
+ "no-switch-case-fall-through": true,
+ "no-use-before-declare": true,
+ "no-var-requires": false,
+ "object-literal-key-quotes": [
+ true,
+ "as-needed"
+ ],
+ "object-literal-sort-keys": false,
+ "ordered-imports": false,
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "trailing-comma": false,
+ "no-conflicting-lifecycle": true,
+ "no-host-metadata-property": true,
+ "no-input-rename": true,
+ "no-inputs-metadata-property": true,
+ "no-output-native": true,
+ "no-output-on-prefix": true,
+ "no-output-rename": true,
+ "no-outputs-metadata-property": true,
+ "template-banana-in-box": true,
+ "template-no-negated-async": true,
+ "use-lifecycle-interface": true,
+ "use-pipe-transform-interface": true
+ },
+ "rulesDirectory": [
+ "codelyzer"
+ ]
+} \ No newline at end of file
diff --git a/mod2/ui/typings.d.ts b/mod2/ui/typings.d.ts
new file mode 100644
index 0000000..125f045
--- /dev/null
+++ b/mod2/ui/typings.d.ts
@@ -0,0 +1,32 @@
+/*
+ * # ============LICENSE_START=======================================================
+ * # Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * # ================================================================================
+ * # 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.
+ * # ============LICENSE_END=========================================================
+ */
+
+declare var process: Process;
+
+interface GlobalEnvironment {
+ process: Process
+}
+
+interface Process {
+ env: Env
+}
+
+interface Env{
+ DCAE_HOSTNAME: string
+}
+
diff --git a/releases/1.1.0-distributorapi-container.yaml b/releases/1.1.0-distributorapi-container.yaml
new file mode 100644
index 0000000..f80e5d1
--- /dev/null
+++ b/releases/1.1.0-distributorapi-container.yaml
@@ -0,0 +1,9 @@
+distribution_type: 'container'
+container_release_tag: '1.1.0'
+project: 'dcaegen2-platform'
+log_dir: 'dcaegen2-platform-mod-distributorapi-docker-merge-master/30'
+ref: 66ae1f86dd66a064c6095fce19bc7dd6dd072473
+containers:
+ - name: 'org.onap.dcaegen2.platform.mod.distributorapi'
+ version: '1.1.0-SNAPSHOT-20200908T140636Z'
+git_tag: '1.1.0-mod-distributorapi'
diff --git a/releases/1.5.0-blueprint-generator.yaml b/releases/1.5.0-blueprint-generator.yaml
new file mode 100644
index 0000000..928096d
--- /dev/null
+++ b/releases/1.5.0-blueprint-generator.yaml
@@ -0,0 +1,4 @@
+distribution_type: 'maven'
+version: '1.5.0'
+project: 'dcaegen2/platform'
+log_dir: 'dcaegen2-platform-mod-bpgenerator-maven-stage-master/225'
diff --git a/releases/2.12.3-onboardingapi-container.yaml b/releases/2.12.3-onboardingapi-container.yaml
new file mode 100644
index 0000000..1b0dfb9
--- /dev/null
+++ b/releases/2.12.3-onboardingapi-container.yaml
@@ -0,0 +1,9 @@
+distribution_type: 'container'
+container_release_tag: '2.12.3'
+project: 'dcaegen2-platform'
+log_dir: 'dcaegen2-platform-mod-onboardingapi-docker-merge-master/30'
+ref: b4287ad1fab97142df4d5260ec94d41bb782992a
+containers:
+ - name: 'org.onap.dcaegen2.platform.mod.onboardingapi'
+ version: '2.12.3-SNAPSHOT-20200908T020337Z'
+git_tag: '2.12.3-mod-onboardingapi'