diff --git a/.travis.yml b/.travis.yml index 0cdd1143f1c..f8dbcc9154f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -79,6 +79,17 @@ matrix: packages: - google-chrome-stable + # Run tests (in zeppelin-web-angular) + - os: linux + sudo: false + dist: xenial + jdk: "openjdk8" + env: CI="true" BUILD_FLAG="clean -DskipTests -DskipRat" TEST_FLAG="package -DskipRat" MODULES="-pl ${INTERPRETERS}" TEST_MODULES="-pl zeppelin-web-angular" + addons: + apt: + packages: + - google-chrome-stable + # Test core modules # Several tests were excluded from this configuration due to the following issues: # HeliumApplicationFactoryTest - https://issues.apache.org/jira/browse/ZEPPELIN-2470 diff --git a/LICENSE b/LICENSE index 121d2e186bc..33041b17ac8 100644 --- a/LICENSE +++ b/LICENSE @@ -236,16 +236,19 @@ The text of each license is also included at licenses/LICENSE-[project]-[version (The MIT License) jekyll-bootstrap 0.3.0 (https://github.com/plusjade/jekyll-bootstrap) - https://github.com/plusjade/jekyll-bootstrap (The MIT License) jekyll 1.3.0 (http://jekyllrb.com/) - https://github.com/jekyll/jekyll/blob/v1.3.0/LICENSE (The MIT License) ngInfiniteScroll 1.3.4 (https://github.com/sroze/ngInfiniteScroll) - https://github.com/sroze/ngInfiniteScroll/blob/master/LICENSE + (The MIT License) @antv/G2 3.5 (https://github.com/antvis/g2) - https://github.com/antvis/g2/blob/master/LICENSE + (The MIT License) Lodash (https://lodash.com) - https://github.com/lodash/lodash/blob/master/LICENSE + (The MIT License) Monaco Editor (https://github.com/microsoft/monaco-editor) - https://github.com/microsoft/monaco-editor/blob/master/LICENSE.md ======================================================================== MIT-style licenses ======================================================================== The following components are provided under the MIT-style license. See project link for details. The text of each license is also included at licenses/LICENSE-[project]-[version].txt. - + (MIT Style) jekyll-table-of-contents (https://github.com/ghiculescu/jekyll-table-of-contents) - https://github.com/ghiculescu/jekyll-table-of-contents/blob/master/LICENSE.txt (MIT Style) lunr.js (https://github.com/olivernn/lunr.js) - https://github.com/olivernn/lunr.js/blob/v0.7.1/LICENSE - + ======================================================================== Apache licenses ======================================================================== diff --git a/pom.xml b/pom.xml index 15e6c2cca88..c7bee7d50a6 100644 --- a/pom.xml +++ b/pom.xml @@ -90,6 +90,7 @@ zeppelin-jupyter zeppelin-plugins zeppelin-distribution + zeppelin-web-angular @@ -103,8 +104,8 @@ 1.12.5 - v8.9.3 - 5.5.1 + v12.3.1 + 6.9.0 1.6 @@ -1013,6 +1014,16 @@ **/e2e/**/**.spec.js package-lock.json + + **/*.json + **/browserslist + **/.prettierrc + **/.prettierignore + **/.editorconfig + **/src/**/*.svg + **/.gitkeep + + **/src/main/java/org/apache/zeppelin/jdbc/SqlCompleter.java diff --git a/zeppelin-web-angular/.editorconfig b/zeppelin-web-angular/.editorconfig new file mode 100644 index 00000000000..c220b3125b7 --- /dev/null +++ b/zeppelin-web-angular/.editorconfig @@ -0,0 +1,15 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset=utf-8 +end_of_line=lf +trim_trailing_whitespace=true +insert_final_newline=false +indent_style=space +indent_size=2 + + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/zeppelin-web-angular/.gitignore b/zeppelin-web-angular/.gitignore new file mode 100644 index 00000000000..22b094f61f7 --- /dev/null +++ b/zeppelin-web-angular/.gitignore @@ -0,0 +1,47 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp +/out-tsc + +# 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 + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# System Files +.DS_Store +Thumbs.db + +# +.env +yarn.lock \ No newline at end of file diff --git a/zeppelin-web-angular/.prettierignore b/zeppelin-web-angular/.prettierignore new file mode 100644 index 00000000000..b9f1979fbdf --- /dev/null +++ b/zeppelin-web-angular/.prettierignore @@ -0,0 +1,3 @@ +**/*.md +**/*.less +**/*.svg diff --git a/zeppelin-web-angular/.prettierrc b/zeppelin-web-angular/.prettierrc new file mode 100644 index 00000000000..4b9bb8a441b --- /dev/null +++ b/zeppelin-web-angular/.prettierrc @@ -0,0 +1,15 @@ +{ + "singleQuote": true, + "printWidth": 120, + "tabWidth": 2, + "useTabs": false, + "htmlWhitespaceSensitivity": "ignore", + "overrides": [ + { + "files": ".prettierrc", + "options": { + "parser": "json" + } + } + ] +} diff --git a/zeppelin-web-angular/README.md b/zeppelin-web-angular/README.md new file mode 100644 index 00000000000..dea1a0d7d71 --- /dev/null +++ b/zeppelin-web-angular/README.md @@ -0,0 +1,276 @@ + + +# Zeppelin WEB + +Zeppelin notebooks front-end built with Angular. + +- Jira issue [ZEPPELIN-4321](https://issues.apache.org/jira/browse/ZEPPELIN-4321) +- Design Document: [Zeppelin Notebook Rework Proposal](https://docs.google.com/document/d/1z_VscS81Xwx_3QaexKB2s0uEMEuWKsPXh9mWFRq0-hY) + +![screenshot](/screenshot.png?raw=true "Screenshot") + +## Setup + +### Prerequisites + +- [Node.js](https://nodejs.org) version 10.9.0 or later or use [creationix/nvm](https://github.com/creationix/nvm). +- NPM package manager (which is installed with Node.js by default). +- [Angular CLI](https://angular.io/cli) version 8.3.0 or later. + +### Install + +Run the `npm install` command to install dependencies in the project directory. + +### Start Zeppelin server + +[Run Zeppelin server](https://zeppelin.apache.org/contribution/contributions.html#run-zeppelin-server-in-development-mode) on `http://localhost:8080`. + +If you are using a custom port instead of the default(http://localhost:8080) or other network address, you can create `.env` file in the project directory and set `SERVER_PROXY`. + +*.env* + +``` +SERVER_PROXY=http://localhost:8080 +``` + +### Development server + +Run `npm start` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. + +### Build + +Run `npm build` to build the project. The build artifacts will be stored in the `dist/` directory. + +### Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Implementation Progress + +### Pages + +| Name | Route | Module | UI | +| --- | ----- | ---------- | -- | +| Home | `/` | HomeModule | Y | +| Login | `/login` | LoginModule | Y | +| Job Manager | `/jobmanager` | JobManagerModule | Y | +| Interpreter Setting | `/interpreter` | InterpreterModule | Y | +| Notebook | `/notebook/{id}` | NotebookModule | Y | +| Notebook Repos | `/notebookRepos` | | | +| Credential | `/credential` | | | +| Helium | `/helium` | | WIP | +| Configuration | `/configuration` | | | + +### Notebook Features + +| Feature | Description | Status | +| ------ | ---- | ---- | +| Files System | Create/ Rename/ Import etc. | Y | +| Toolbar Actions | The top toolbar actions | Y | + +### Paragraph Features + +| Feature | Description | Status | +| ------ | ---- | ---- | +| Grid layout and resizable | | Y | +| Code Editor | | Y | +| Actions | The Corresponding actions of the drop-down menu in the setting button | Y | +| Actions(hot-keys) | Support hot-keys for the actions | WIP | +| Publishable | [publish paragraphs](http://zeppelin.apache.org/docs/0.8.0/usage/other_features/publishing_paragraphs.html) | | +| Stream | | | + +### Result Display + +| Type | Status | +| ------ | ---- | +| Dynamic Form | Y | +| Text | Y | +| Html | Y | +| Table | Y | +| Network | | + +### Table Visualization + +| Type | State | +| ------ | ---- | +| Line Chart | Y | +| Bard Chart | Y | +| Pie Chart | Y | +| Area Chart | Y | +| Scatter Chart | Y | + +### Helium Visualization + +| Type | Description | Status | +| ------ | ---- | ---- | +| Prototype | To verify the implementable prototype | Y | +| Publish Dependencies | Just like [zeppelin-vis](https://github.com/apache/zeppelin/tree/master/zeppelin-web/src/app/visualization) | WIP | +| Example Projects | | Y | +| Development Documents | | WIP | + +## Contributing + +### Dev Mode + +Follow the [Setup](#Setup) steps to starting the frontend service. The app will automatically reload if you change any of the source files. + +### Technologies + +Zeppelin-WEB-Angular is using Angular as the main Framework, before developing we hope highly recommended to have a good knowledge of [Angular](https://angular.io/) and [RxJs](https://github.com/ReactiveX/rxjs). + +In addition: + +- We use [G2](https://github.com/antvis/g2) [(MIT)](https://github.com/antvis/g2/blob/master/LICENSE) visualization +- We use [Lodash](https://lodash.com/) [(MIT)](https://github.com/lodash/lodash/blob/master/LICENSE) to process complex data +- We use [Monaco Editor](https://github.com/microsoft/monaco-editor) [(MIT)](https://github.com/microsoft/monaco-editor/blob/master/LICENSE.md) to make code editor + +### Coding style + +- We follow mainly the [Angular Style Guide](https://angular.io/guide/styleguide) +- We use a 2 spaces indentation +- We use single quotes + +But don't worry, TSLint and prettier will make you remember it for the most part. +Git hooks will automatically check and fix it when commit. + +### Folder Structure + +We follow mainly the [Workspace and project file structure](https://angular.io/guide/styleguide) to organize the folder structure and files. + +#### Src Folder Structure + +`src` folder contains the source code for Zeppelin-WEB-Angular. + +``` +├── app +│ ├── core +│ │ └── message-listener # handle WebSocket message +│ ├── interfaces # interfaces +│ ├── pages +│ │ ├── login # login module +│ │ └── workspace +│ │ ├── home # welcome module +│ │ ├── interpreter # interpreter settings +│ │ ├── job-manager # job manager module +│ │ └── notebook # notebook module +│ │ ├── action-bar # notebook settings +│ │ ├── interpreter-binding # interpreter binding +│ │ ├── permissions # permissions +│ │ └── paragraph # paragraph module +│ │ ├── code-editor # code editor module +│ │ ├── control # paragraph controls +│ │ ├── dynamic-forms # dynamic forms +│ │ └── result # display result +│ ├── sdk # Zeppelin API Frontend SDK +│ ├── share # Share Components +│ ├── services # API Service +│ └── visualization +│ ├── area-chart # Area Chart Component +│ ├── bar-chart # Bar Chart Component +│ ├── line-chart # Line Chart Component +│ ├── pie-chart # Pie Chart Component +│ ├── scatter-chart # Scatter Chart Component +│ └── table # Data Table Component +├── assets # Assets +└── styles + └── theme # Theme Files + ├── dark + └── light +``` + +#### Import Path Rules + +We specify path mapping in the `tsconfig.json` file to get a clear import path. + +So please follow the rules following: + +- Add `public-api.ts` and `index.ts` to the folder where want to export the modules +- `public-api.ts` File only included you wish to export modules +- `index.ts` File only export `./public-api.ts` +- Use relative paths instead of mapped paths when the same level to prevent circular references + +### Good Practices + +The following guide for this project only. Most of the time you only need to follow Angular's guide. + +#### Change Detection Strategy + +Use [OnPush](https://angular.io/api/core/ChangeDetectionStrategy#OnPush) as the change detection strategy for components. + +#### WebSocket Listen and Send + +*Send Message*: Inject the `MessageService` and then use its instance methods. + +```ts + +import { MessageService } from '@zeppelin/services'; + +export class SomeComponent { + + constructor(public messageService: MessageService) { } + + fun() { + // Do something + this.messageService.listNoteJobs(); + } +} +``` + +*Listen to Message* + +Make sure the class extends from `MessageListenersManager` and inject the `MessageService` and ensures that it is public. + +After that, you can use the `@MessageListener` decorator to decorate the corresponding message method. + +```ts +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { MessageService } from '@zeppelin/services'; +import { OP, ListNoteJobs } from '@zeppelin/sdk'; + +export class SomeComponent extends MessageListenersManager { + + constructor(public messageService: MessageService) { } + + @MessageListener(OP.LIST_NOTE_JOBS) + fun(data: ListNoteJobs) { + // Do something + } +} +``` + +#### Theming + +Use we provide the function to wrap component styles to implement theming. You can find the theme variables in the `src/styles/theme/` folder. + +```less +@import "theme-mixin"; + +.themeMixin({ + // component styles +}); +``` + +#### Imports order + +Follow of the following imports order: + +```ts +import * from '@angular/*' // Angular modules +import * from 'rxjs/*' // Rxjs modules +// BLANK LINE +import * from '*' // Other third party modules +// BLANK LINE +import * from '@zeppelin/*' // This project modules +// BLANK LINE +import * from './*' // Same level modules +``` \ No newline at end of file diff --git a/zeppelin-web-angular/WEB-INF/web.xml b/zeppelin-web-angular/WEB-INF/web.xml new file mode 100644 index 00000000000..f40bf861738 --- /dev/null +++ b/zeppelin-web-angular/WEB-INF/web.xml @@ -0,0 +1,41 @@ + + + + + + zeppelin-web-angular + + default + org.glassfish.jersey.servlet.ServletContainer + + jersey.config.server.provider.packages + org.apache.zeppelin.rest + + + 1 + + + + configuration + deployment + + + + + true + true + + + diff --git a/zeppelin-web-angular/angular.json b/zeppelin-web-angular/angular.json new file mode 100644 index 00000000000..37904c102f7 --- /dev/null +++ b/zeppelin-web-angular/angular.json @@ -0,0 +1,330 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "zeppelin": { + "root": "", + "sourceRoot": "src", + "projectType": "application", + "prefix": "zeppelin", + "schematics": { + "@schematics/angular:component": { + "style": "less", + "skipTests": true, + "changeDetection": "OnPush" + }, + "ng-zorro-antd:component": { + "style": "less", + "skipTests": true, + "changeDetection": "OnPush", + "classnameWithModule": true + }, + "@schematics/angular:class": { + "skipTests": true + }, + "@schematics/angular:directive": { + "skipTests": true + }, + "@schematics/angular:guard": { + "skipTests": true + }, + "@schematics/angular:module": { + "skipTests": true + }, + "@schematics/angular:pipe": { + "skipTests": true + }, + "@schematics/angular:service": { + "skipTests": true + } + }, + "architect": { + "build": { + "builder": "ngx-build-plus:browser", + "options": { + "outputPath": "dist/zeppelin", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.app.json", + "assets": [ + "src/favicon.ico", + "src/assets", + { + "glob": "**/*", + "input": "./node_modules/mathjax", + "output": "/" + }, + { + "glob": "**/*", + "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", + "output": "/assets/" + }, + { + "glob": "**/*", + "input": "./WEB-INF", + "output": "/WEB-INF/" + } + ], + "styles": [ + "src/styles/theme/dark/antd-dark.less", + "src/styles/theme/light/antd-light.less", + "src/styles.less", + "./node_modules/highlight.js/styles/github.css", + "./node_modules/monaco-editor/min/vs/editor/editor.main.css" + ], + "stylePreprocessorOptions": { + "includePaths": [ + "src/styles/theme", + "src/styles/theme/dark", + "src/styles/theme/light" + ] + }, + "scripts": [ + "node_modules/mathjax/MathJax.js", + "node_modules/systemjs/dist/s.js", + "node_modules/systemjs/dist/extras/amd.js", + "node_modules/systemjs/dist/extras/named-register.js", + "node_modules/systemjs/dist/extras/use-default.js" + ] + }, + "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": false + } + } + }, + "serve": { + "builder": "ngx-build-plus:dev-server", + "options": { + "browserTarget": "zeppelin:build" + }, + "configurations": { + "production": { + "browserTarget": "zeppelin:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "zeppelin:build" + } + }, + "test": { + "builder": "ngx-build-plus:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.spec.json", + "karmaConfig": "src/karma.conf.js", + "styles": [ + "src/styles.less" + ], + "scripts": [], + "assets": [ + "src/favicon.ico", + "src/assets" + ] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "src/tsconfig.app.json", + "src/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "zeppelin-e2e": { + "root": "e2e/", + "projectType": "application", + "prefix": "", + "architect": { + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "zeppelin:serve" + }, + "configurations": { + "production": { + "devServerTarget": "zeppelin:serve:production" + } + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": "e2e/tsconfig.e2e.json", + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "zeppelin-helium": { + "projectType": "library", + "root": "projects/zeppelin-helium", + "sourceRoot": "projects/zeppelin-helium/src", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/zeppelin-helium/tsconfig.lib.json", + "project": "projects/zeppelin-helium/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/zeppelin-helium/src/test.ts", + "tsConfig": "projects/zeppelin-helium/tsconfig.spec.json", + "karmaConfig": "projects/zeppelin-helium/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/zeppelin-helium/tsconfig.lib.json", + "projects/zeppelin-helium/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "helium-vis-example": { + "projectType": "library", + "root": "projects/helium-vis-example", + "sourceRoot": "projects/helium-vis-example/src", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/helium-vis-example/tsconfig.lib.json", + "project": "projects/helium-vis-example/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/helium-vis-example/src/test.ts", + "tsConfig": "projects/helium-vis-example/tsconfig.spec.json", + "karmaConfig": "projects/helium-vis-example/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/helium-vis-example/tsconfig.lib.json", + "projects/helium-vis-example/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "zeppelin-visualization": { + "projectType": "library", + "root": "projects/zeppelin-visualization", + "sourceRoot": "projects/zeppelin-visualization/src", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/zeppelin-visualization/tsconfig.lib.json", + "project": "projects/zeppelin-visualization/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/zeppelin-visualization/src/test.ts", + "tsConfig": "projects/zeppelin-visualization/tsconfig.spec.json", + "karmaConfig": "projects/zeppelin-visualization/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/zeppelin-visualization/tsconfig.lib.json", + "projects/zeppelin-visualization/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "zeppelin-sdk": { + "projectType": "library", + "root": "projects/zeppelin-sdk", + "sourceRoot": "projects/zeppelin-sdk/src", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/zeppelin-sdk/tsconfig.lib.json", + "project": "projects/zeppelin-sdk/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/zeppelin-sdk/src/test.ts", + "tsConfig": "projects/zeppelin-sdk/tsconfig.spec.json", + "karmaConfig": "projects/zeppelin-sdk/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/zeppelin-sdk/tsconfig.lib.json", + "projects/zeppelin-sdk/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + } + }, + "defaultProject": "zeppelin" +} \ No newline at end of file diff --git a/zeppelin-web-angular/browserslist b/zeppelin-web-angular/browserslist new file mode 100644 index 00000000000..80848532e47 --- /dev/null +++ b/zeppelin-web-angular/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/zeppelin-web-angular/e2e/protractor.conf.js b/zeppelin-web-angular/e2e/protractor.conf.js new file mode 100644 index 00000000000..1be6b530682 --- /dev/null +++ b/zeppelin-web-angular/e2e/protractor.conf.js @@ -0,0 +1,44 @@ +/* + * 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. + */ + +// @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/zeppelin-web-angular/e2e/src/app.e2e-spec.ts b/zeppelin-web-angular/e2e/src/app.e2e-spec.ts new file mode 100644 index 00000000000..d788f85250e --- /dev/null +++ b/zeppelin-web-angular/e2e/src/app.e2e-spec.ts @@ -0,0 +1,23 @@ +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('zeppelin app is running!'); + }); + + 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/zeppelin-web-angular/e2e/src/app.po.ts b/zeppelin-web-angular/e2e/src/app.po.ts new file mode 100644 index 00000000000..b8498c26f24 --- /dev/null +++ b/zeppelin-web-angular/e2e/src/app.po.ts @@ -0,0 +1,11 @@ +import { browser, by, element } from 'protractor'; + +export class AppPage { + navigateTo() { + return browser.get(browser.baseUrl) as Promise; + } + + getTitleText() { + return element(by.css('app-root .content span')).getText() as Promise; + } +} diff --git a/zeppelin-web-angular/e2e/tsconfig.json b/zeppelin-web-angular/e2e/tsconfig.json new file mode 100644 index 00000000000..39b800f7896 --- /dev/null +++ b/zeppelin-web-angular/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/zeppelin-web-angular/karma.conf.js b/zeppelin-web-angular/karma.conf.js new file mode 100644 index 00000000000..67c6820c27b --- /dev/null +++ b/zeppelin-web-angular/karma.conf.js @@ -0,0 +1,44 @@ +/* + * 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. + */ + +// 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/zeppelin'), + 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/zeppelin-web-angular/package-lock.json b/zeppelin-web-angular/package-lock.json new file mode 100644 index 00000000000..46c0a074b8d --- /dev/null +++ b/zeppelin-web-angular/package-lock.json @@ -0,0 +1,15996 @@ +{ + "name": "zeppelin", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.803.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.14.tgz", + "integrity": "sha512-CPDDNTpM/9XWCFxCRL1/mYB54ivZcmWaVSjUgN2zcHWBc0gW3lrJrmmb+cJ1KSlOI7hoZaMTV1gWoX2QXd4JrA==", + "dev": true, + "requires": { + "@angular-devkit/core": "8.3.14", + "rxjs": "6.4.0" + }, + "dependencies": { + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular-devkit/build-angular": { + "version": "0.803.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.803.14.tgz", + "integrity": "sha512-AtrhLDcy5DHi5zWiahEmvbD6THkJkWv27TySTfpZlmMjpRJHNqK7uQiKR1iWSqo4VNpimFle3fwkfjQYHlEKqA==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.803.14", + "@angular-devkit/build-optimizer": "0.803.14", + "@angular-devkit/build-webpack": "0.803.14", + "@angular-devkit/core": "8.3.14", + "@babel/core": "7.5.5", + "@babel/preset-env": "7.5.5", + "@ngtools/webpack": "8.3.14", + "ajv": "6.10.2", + "autoprefixer": "9.6.1", + "browserslist": "4.6.6", + "cacache": "12.0.2", + "caniuse-lite": "1.0.30000989", + "circular-dependency-plugin": "5.2.0", + "clean-css": "4.2.1", + "copy-webpack-plugin": "5.0.4", + "core-js": "3.2.1", + "file-loader": "4.2.0", + "find-cache-dir": "3.0.0", + "glob": "7.1.4", + "istanbul-instrumenter-loader": "3.0.1", + "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.3.8", + "terser-webpack-plugin": "1.4.1", + "tree-kill": "1.2.1", + "webpack": "4.39.2", + "webpack-dev-middleware": "3.7.0", + "webpack-dev-server": "3.8.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": { + "core-js": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", + "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "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" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true + } + } + } + } + }, + "@angular-devkit/build-ng-packagr": { + "version": "0.803.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-ng-packagr/-/build-ng-packagr-0.803.14.tgz", + "integrity": "sha512-qIYLEOxL8kOmOVjisN0rSMGeN7D2TYc90k73LnXUtT8WL4a+bd6r8PNGrH9hrF8ABZ01oJ4PQi8kuE4Jm7+ptA==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.803.14", + "rxjs": "6.4.0" + }, + "dependencies": { + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular-devkit/build-optimizer": { + "version": "0.803.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.803.14.tgz", + "integrity": "sha512-f1RYhO0swLfoLvCj/fUrDWm4vzVSnffcCc4C4PHnqoOGBRQpmIzG7G54Pm8YK677slioToYZQ68s3/zVtsQNWg==", + "dev": true, + "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": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "@angular-devkit/build-webpack": { + "version": "0.803.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.803.14.tgz", + "integrity": "sha512-hvxAyJzDCaIISATHcu0+rAAj7ZcmX7VREX6J3FUMYDxhdjKqe45Q5J6Oy/Df2ZSV3YxwySZVcIhrBstm+0LC7Q==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.803.14", + "@angular-devkit/core": "8.3.14", + "rxjs": "6.4.0" + }, + "dependencies": { + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular-devkit/core": { + "version": "8.3.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.14.tgz", + "integrity": "sha512-+IYLbtCxwIpaieRj0wurEXBzZ/fDSdWbyrCfajzDerzsxqghNcafAXSazHXWwISqtbr/pAOuqUNR+mEk2XBz3Q==", + "dev": true, + "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" + }, + "dependencies": { + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "@angular-devkit/schematics": { + "version": "8.3.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.14.tgz", + "integrity": "sha512-5gPmTBN85a2gTxz/FsM5fO9Bxw4KG6uJNLMDAWfPG8vvSQEl7J64ujyqxPz39TernQTEKeuhRC4I5H1aaW9I/Q==", + "dev": true, + "requires": { + "@angular-devkit/core": "8.3.14", + "rxjs": "6.4.0" + }, + "dependencies": { + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular/animations": { + "version": "8.2.12", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.2.12.tgz", + "integrity": "sha512-QVtZUw5J9c0RcDaJntIoeWVk/q9dhjDFxh+yw/uPl9Z4upWASdsOpZU2lfjqyU0myfg8dnQyZa1+Ce7n/DaClQ==", + "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" + } + }, + "@angular/cli": { + "version": "8.3.14", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.3.14.tgz", + "integrity": "sha512-cOP2UvnnYocx1U1aiNkuLCcBxSktIXkadzrY7UlWJtQiCPGWm3Y87BfrQXub9Nsh79iyV8k8uKZKEax2ayESSg==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.803.14", + "@angular-devkit/core": "8.3.14", + "@angular-devkit/schematics": "8.3.14", + "@schematics/angular": "8.3.14", + "@schematics/update": "0.803.14", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.1", + "debug": "^4.1.1", + "ini": "1.3.5", + "inquirer": "6.5.1", + "npm-package-arg": "6.1.0", + "npm-pick-manifest": "3.0.2", + "open": "6.4.0", + "pacote": "9.5.5", + "read-package-tree": "5.3.1", + "rimraf": "3.0.0", + "semver": "6.3.0", + "symbol-observable": "1.2.0", + "universal-analytics": "^0.4.20", + "uuid": "^3.3.2" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "rimraf": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", + "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "@angular/common": { + "version": "8.2.12", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.2.12.tgz", + "integrity": "sha512-BNz1lo+PP+lwIX3sErRGBRnkMzT5yT8CJ5o/M29AanCdcx9dpoJG2WKgpIgw8UBcj9QlP0CkSmzPtUNtcNMthA==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler": { + "version": "8.2.12", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.2.12.tgz", + "integrity": "sha512-V5mDWioGmSZ4cJJ2THo8qHYKwj3sUI7dpJ0oab2Al0FQAN8JCimWO6AQKRtjmnr78ZkMy9Xe/KK6ebl40ewL5Q==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler-cli": { + "version": "8.2.12", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-8.2.12.tgz", + "integrity": "sha512-OrNnkJ7OrpbcOtB4TWFBF6D3dtEfUuOQgfc3HBjizZuL8EuX0pU5dv4VTvLTRkmyUT/7fmmWdkEXJL+UQtXqPg==", + "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", + "source-map": "^0.6.1", + "tslib": "^1.9.0", + "yargs": "13.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "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=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "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" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "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" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.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 + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": 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.3", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": 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" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": 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.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": 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 + }, + "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=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "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" + }, + "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" + } + } + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.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=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "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.2.12", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.2.12.tgz", + "integrity": "sha512-wEFwhHCuuXynXAMeA1G+0KIYY0jqXYs7I8p+GO+ufKoUmzWHFTvtMJ6nvKgy+LmZTByO2gf9oVAAlRodNb8ttQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/forms": { + "version": "8.2.12", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.2.12.tgz", + "integrity": "sha512-y1UObndCGbTYwLSzUWzCiX7th+mb4n712asApooGmfmIQmgTyHbKxYUJ9Ep1pgd0pqLBBnK249MQLH15NDpbyQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/language-service": { + "version": "8.2.12", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-8.2.12.tgz", + "integrity": "sha512-uXGVSC4ugkyBt7pYdI8qaKNV0TIxfjSWb3dWNuhD6b9riPtaa+xJFQrfMu7OX/tVX642aFxca4jkUHBLCyWptA==", + "dev": true + }, + "@angular/platform-browser": { + "version": "8.2.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.2.12.tgz", + "integrity": "sha512-VBvMjmFJapZ2pFlmxZiHtfPwbHp79RRi5mrdMhETjKMaLaC2tAR/99ijCpx2urDMqb/VDm7YHOtoLEpBFVDulg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "8.2.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.2.12.tgz", + "integrity": "sha512-O4krb+9tj028JOQHPgLk/87lyUlHt8dpNxzuYCT0G6kEmknjpyZBaxhvDPygGjGHXV3LDqlYVH+bh8ygJUhwmw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/router": { + "version": "8.2.12", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.2.12.tgz", + "integrity": "sha512-mq1FethFpYosSVzChstMpxZlL+oUFeaA+FrzZQL7zJP/mm61yFkkhoYGVG6pG0NWSzpJE4NY6YvGCvHgN4ZECw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@ant-design/colors": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz", + "integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==", + "requires": { + "tinycolor2": "^1.4.1" + } + }, + "@ant-design/icons-angular": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons-angular/-/icons-angular-8.1.1.tgz", + "integrity": "sha512-JMfavPHwahJcGWT13bTCt4IHzrsNgbJzzB+VWYtzjwWszMCVkkOOn+aJbslupHOl72KWDvklN/LjCQPBgu7xLQ==", + "requires": { + "@ant-design/colors": "^3.1.0", + "tslib": "^1.9.0" + } + }, + "@antv/adjust": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@antv/adjust/-/adjust-0.1.1.tgz", + "integrity": "sha512-9FaMOyBlM4AgoRL0b5o0VhEKAYkexBNUrxV8XmpHU/9NBPJONBOB/NZUlQDqxtLItrt91tCfbAuMQmF529UX2Q==", + "requires": { + "@antv/util": "~1.3.1" + } + }, + "@antv/attr": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@antv/attr/-/attr-0.1.2.tgz", + "integrity": "sha512-QXjP+T2I+pJQcwZx1oCA4tipG43vgeCeKcGGKahlcxb71OBAzjJZm1QbF4frKXcnOqRkxVXtCr70X9TRair3Ew==", + "requires": { + "@antv/util": "~1.3.1" + } + }, + "@antv/component": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.3.8.tgz", + "integrity": "sha512-1WN3FzeRyJ1jraS/2og5gnm2ragnwtRMVQMiLolztWaUgC++F/B1CcSrPYfV1WvYrfuwbpX/QQxo3HL9aS+YJA==", + "requires": { + "@antv/attr": "~0.1.2", + "@antv/g": "~3.3.5", + "@antv/util": "~1.3.1", + "wolfy87-eventemitter": "~5.1.0" + } + }, + "@antv/coord": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.1.0.tgz", + "integrity": "sha512-W1R8h3Jfb3AfMBVfCreFPMVetgEYuwHBIGn0+d3EgYXe2ckOF8XWjkpGF1fZhOMHREMr+Gt27NGiQh8yBdLUgg==", + "requires": { + "@antv/util": "~1.3.1" + } + }, + "@antv/data-set": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@antv/data-set/-/data-set-0.10.2.tgz", + "integrity": "sha512-FFWG5tiTiFiUrLDRwulraU5XfOdDjkYOlZna+AMT9FJw406D/gfS8eXM9YibscBH28M/+KLAVO8xEwuD1sc3bw==", + "requires": { + "@antv/hierarchy": "~0.4.0", + "@antv/util": "~1.3.1", + "d3-array": "~1.2.0", + "d3-composite-projections": "~1.2.0", + "d3-dsv": "~1.0.5", + "d3-geo": "~1.6.4", + "d3-geo-projection": "~2.1.2", + "d3-hexjson": "~1.0.1", + "d3-hierarchy": "~1.1.5", + "d3-sankey": "~0.7.1", + "d3-voronoi": "~1.1.2", + "dagre": "~0.8.2", + "point-at-length": "~1.0.2", + "regression": "~2.0.0", + "simple-statistics": "~6.1.0", + "topojson-client": "~3.0.0", + "wolfy87-eventemitter": "~5.1.0" + } + }, + "@antv/g": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@antv/g/-/g-3.3.6.tgz", + "integrity": "sha512-2GtyTz++s0BbN6s0ZL2/nrqGYCkd52pVoNH92YkrTdTOvpO6Z4DNoo6jGVgZdPX6Nzwli6yduC8MinVAhE8X6g==", + "requires": { + "@antv/gl-matrix": "~2.7.1", + "@antv/util": "~1.3.1", + "d3-ease": "~1.0.3", + "d3-interpolate": "~1.1.5", + "d3-timer": "~1.0.6", + "wolfy87-eventemitter": "~5.1.0" + } + }, + "@antv/g2": { + "version": "3.5.9", + "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-3.5.9.tgz", + "integrity": "sha512-AS0Exn9Khhx4Xp8JViv37/wjJbiC9zVY02hIdvUeTx4SaKC0nhE0euPfmthen1cQw7nVlGLYEGoav/qxpLAhiw==", + "requires": { + "@antv/adjust": "~0.1.0", + "@antv/attr": "~0.1.2", + "@antv/component": "~0.3.3", + "@antv/coord": "~0.1.0", + "@antv/g": "~3.3.6", + "@antv/scale": "~0.1.1", + "@antv/util": "~1.3.1", + "venn.js": "~0.2.20", + "wolfy87-eventemitter": "~5.1.0" + } + }, + "@antv/gl-matrix": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@antv/gl-matrix/-/gl-matrix-2.7.1.tgz", + "integrity": "sha512-oOWcVNlpELIKi9x+Mm1Vwbz8pXfkbJKykoCIOJ/dNK79hSIANbpXJ5d3Rra9/wZqK6MC961B7sybFhPlLraT3Q==" + }, + "@antv/hierarchy": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@antv/hierarchy/-/hierarchy-0.4.0.tgz", + "integrity": "sha512-ols+m+Z8QA4895SWMTOSjVImOX4tEbWQTwJ0NE+WATc0WLSKs6D9y2yaR+ZWt6P60BMGVIKS6lIfabO3CwGgnQ==", + "requires": { + "@antv/util": "~1.3.1" + } + }, + "@antv/scale": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.1.3.tgz", + "integrity": "sha512-oknlOg4OUqIh8LygrfQttx+OAnNJm2fQ81si4g8aby1WJJwj/TU1gCr+J3loIpKBtBK4VpP/OzTTqg1Ym67SOQ==", + "requires": { + "@antv/util": "~1.3.1", + "fecha": "~2.3.3" + } + }, + "@antv/util": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@antv/util/-/util-1.3.1.tgz", + "integrity": "sha512-cbUta0hIJrKEaW3eKoGarz3Ita+9qUPF2YzTj8A6wds/nNiy20G26ztIWHU+5ThLc13B1n5Ik52LbaCaeg9enA==", + "requires": { + "@antv/gl-matrix": "^2.7.1" + } + }, + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "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 + } + } + }, + "@babel/generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.4.tgz", + "integrity": "sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w==", + "dev": true, + "requires": { + "@babel/types": "^7.6.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "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 + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", + "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-call-delegate": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", + "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-define-map": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", + "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", + "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", + "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", + "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", + "dev": true, + "requires": { + "@babel/types": "^7.5.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", + "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", + "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", + "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "dev": true, + "requires": { + "lodash": "^4.17.13" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-replace-supers": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", + "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.5.5", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-wrap-function": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", + "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" + } + }, + "@babel/helpers": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.2.tgz", + "integrity": "sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA==", + "dev": true, + "requires": { + "@babel/template": "^7.6.0", + "@babel/traverse": "^7.6.2", + "@babel/types": "^7.6.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.4.tgz", + "integrity": "sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", + "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", + "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", + "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.2.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz", + "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz", + "integrity": "sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.6.0" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", + "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", + "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", + "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", + "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", + "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", + "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz", + "integrity": "sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "lodash": "^4.17.13" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", + "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-define-map": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-optimise-call-expression": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5", + "@babel/helper-split-export-declaration": "^7.4.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", + "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz", + "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz", + "integrity": "sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.6.0" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", + "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", + "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", + "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", + "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", + "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", + "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", + "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz", + "integrity": "sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz", + "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz", + "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.3.tgz", + "integrity": "sha512-jTkk7/uE6H2s5w6VlMHeWuH+Pcy2lmdwFoeWCVnvIrDUnB5gQqTVI8WfmEAhF2CDEarGrknZcmSFg1+bkfCoSw==", + "dev": true, + "requires": { + "regexpu-core": "^4.6.0" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", + "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", + "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-replace-supers": "^7.5.5" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", + "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "^7.4.4", + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", + "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", + "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", + "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", + "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz", + "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", + "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.0.0" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", + "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", + "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz", + "integrity": "sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.6.0" + } + }, + "@babel/preset-env": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", + "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-dynamic-import": "^7.5.0", + "@babel/plugin-proposal-json-strings": "^7.2.0", + "@babel/plugin-proposal-object-rest-spread": "^7.5.5", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-syntax-async-generators": "^7.2.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@babel/plugin-syntax-json-strings": "^7.2.0", + "@babel/plugin-syntax-object-rest-spread": "^7.2.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.2.0", + "@babel/plugin-transform-async-to-generator": "^7.5.0", + "@babel/plugin-transform-block-scoped-functions": "^7.2.0", + "@babel/plugin-transform-block-scoping": "^7.5.5", + "@babel/plugin-transform-classes": "^7.5.5", + "@babel/plugin-transform-computed-properties": "^7.2.0", + "@babel/plugin-transform-destructuring": "^7.5.0", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/plugin-transform-duplicate-keys": "^7.5.0", + "@babel/plugin-transform-exponentiation-operator": "^7.2.0", + "@babel/plugin-transform-for-of": "^7.4.4", + "@babel/plugin-transform-function-name": "^7.4.4", + "@babel/plugin-transform-literals": "^7.2.0", + "@babel/plugin-transform-member-expression-literals": "^7.2.0", + "@babel/plugin-transform-modules-amd": "^7.5.0", + "@babel/plugin-transform-modules-commonjs": "^7.5.0", + "@babel/plugin-transform-modules-systemjs": "^7.5.0", + "@babel/plugin-transform-modules-umd": "^7.2.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", + "@babel/plugin-transform-new-target": "^7.4.4", + "@babel/plugin-transform-object-super": "^7.5.5", + "@babel/plugin-transform-parameters": "^7.4.4", + "@babel/plugin-transform-property-literals": "^7.2.0", + "@babel/plugin-transform-regenerator": "^7.4.5", + "@babel/plugin-transform-reserved-words": "^7.2.0", + "@babel/plugin-transform-shorthand-properties": "^7.2.0", + "@babel/plugin-transform-spread": "^7.2.0", + "@babel/plugin-transform-sticky-regex": "^7.2.0", + "@babel/plugin-transform-template-literals": "^7.4.4", + "@babel/plugin-transform-typeof-symbol": "^7.2.0", + "@babel/plugin-transform-unicode-regex": "^7.4.4", + "@babel/types": "^7.5.5", + "browserslist": "^4.6.0", + "core-js-compat": "^3.1.1", + "invariant": "^2.2.2", + "js-levenshtein": "^1.1.3", + "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==", + "dev": true + } + } + }, + "@babel/runtime": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz", + "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "@babel/template": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" + } + }, + "@babel/traverse": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.3.tgz", + "integrity": "sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.6.3", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.6.3", + "@babel/types": "^7.6.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz", + "integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@ngtools/webpack": { + "version": "8.3.14", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.3.14.tgz", + "integrity": "sha512-eIU3W3T4YxiExkS/c09FkqQpnKeIuUFFnxyfdG40zospt28B6V5ZaEVw2z5+2CjxJlDUTUYZlhPiV9Rwadp3jg==", + "dev": true, + "requires": { + "@angular-devkit/core": "8.3.14", + "enhanced-resolve": "4.1.0", + "rxjs": "6.4.0", + "tree-kill": "1.2.1", + "webpack-sources": "1.4.3" + }, + "dependencies": { + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, + "@schematics/angular": { + "version": "8.3.14", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.14.tgz", + "integrity": "sha512-1XXBh9+lowvltRlcCjDJa4GEr5Xq+uNJcxULHBaNY7YfQSwZ5KuyhTBWjCdKmMaTOV3pEcIHwyuNh26mpn98Bw==", + "dev": true, + "requires": { + "@angular-devkit/core": "8.3.14", + "@angular-devkit/schematics": "8.3.14" + } + }, + "@schematics/update": { + "version": "0.803.14", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.803.14.tgz", + "integrity": "sha512-1erj7oaR2vKXo1DLE0s4BbbouBmgeAHEkPHQM7FPtyroZ18kytlT+qjTbsSnlRCwcFsjxmRkbRjXaXDz7ttsYQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "8.3.14", + "@angular-devkit/schematics": "8.3.14", + "@yarnpkg/lockfile": "1.1.0", + "ini": "1.3.5", + "pacote": "9.5.5", + "rxjs": "6.4.0", + "semver": "6.3.0", + "semver-intersect": "1.4.0" + }, + "dependencies": { + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@types/anymatch": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", + "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", + "dev": true + }, + "@types/date-fns": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/date-fns/-/date-fns-2.6.0.tgz", + "integrity": "sha1-sGLKRlYgApCb4MY6ZGftFzE2rME=", + "dev": true, + "requires": { + "date-fns": "*" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/highlight.js": { + "version": "9.12.3", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz", + "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", + "dev": true + }, + "@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/lodash": { + "version": "4.14.144", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.144.tgz", + "integrity": "sha512-ogI4g9W5qIQQUhXAclq6zhqgqNUr7UlFaqDHbch7WLSLeeM/7d3CRaw7GLajxvyFvhJqw4Rpcz5bhoaYtIx6Tg==", + "dev": true + }, + "@types/mathjax": { + "version": "0.0.35", + "resolved": "https://registry.npmjs.org/@types/mathjax/-/mathjax-0.0.35.tgz", + "integrity": "sha512-flo9bVJE2Lzv3X5NQXVhNhv7srqk//Ngr8MT+/jRErkWGYkk8EBm42J5W0XUH6p4nWF1iLGe+atSuIkR5wA2yw==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@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==", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "dev": true + }, + "@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/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/selenium-webdriver": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz", + "integrity": "sha512-lMC2G0ItF2xv4UCiwbJGbnJlIuUixHrioOhNGHSCsYCJ8l4t9hMCUimCytvFv7qy6AfSzRxhRHoGa+UqaqwyeA==", + "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==", + "dev": true + }, + "@types/tapable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.4.tgz", + "integrity": "sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ==", + "dev": true + }, + "@types/uglify-js": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.0.4.tgz", + "integrity": "sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ==", + "dev": true, + "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==", + "dev": true + } + } + }, + "@types/webpack": { + "version": "4.39.5", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.39.5.tgz", + "integrity": "sha512-9twG6D97ao13MBLvigwfBJe6rxtb04UY3TcYHBYkW5sXZjUrNhqIRxLYg74VzK/YAE8xlVhOyd+3Whr7E5RrBA==", + "dev": true, + "requires": { + "@types/anymatch": "*", + "@types/node": "*", + "@types/tapable": "*", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "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==", + "dev": true + } + } + }, + "@types/webpack-sources": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz", + "integrity": "sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w==", + "dev": true, + "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==", + "dev": true + } + } + }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "dev": true, + "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==", + "dev": true + }, + "@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==", + "dev": true + }, + "@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==", + "dev": true + }, + "@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==", + "dev": true, + "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==", + "dev": true + }, + "@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==", + "dev": true, + "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==", + "dev": true + }, + "@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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + }, + "@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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + }, + "@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==", + "dev": true + }, + "@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" + } + }, + "abs-svg-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", + "integrity": "sha1-32Acjo0roQ1KdtYl4japo5wnI78=" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "dev": true + }, + "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.13", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", + "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", + "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.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "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==", + "dev": true + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.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 + }, + "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 + }, + "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" + } + } + } + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz", + "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==", + "dev": true, + "requires": { + "type-fest": "^0.5.2" + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "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": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "ansi-to-html": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.12.tgz", + "integrity": "sha512-qBkIqLW979675mP76yB7yVkzeAWtATegdnDQ0RA3CZzknx0yUlNxMSML4xFdBfTs2GWYFQ1FELfbGbVSPzJ+LA==", + "requires": { + "entities": "^1.1.2" + } + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "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==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "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=", + "dev": true + }, + "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==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "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=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "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=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "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=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.1.tgz", + "integrity": "sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw==", + "dev": true, + "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" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.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=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "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": { + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "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 + } + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "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==", + "dev": true + }, + "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=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "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==", + "dev": true + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "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.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", + "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "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==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "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" + } + }, + "boxen": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", + "integrity": "sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^2.4.2", + "cli-boxes": "^2.2.0", + "string-width": "^3.0.0", + "term-size": "^1.2.0", + "type-fest": "^0.3.0", + "widest-line": "^2.0.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 + }, + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.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 + }, + "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" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "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": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", + "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000984", + "electron-to-chromium": "^1.3.191", + "node-releases": "^1.1.25" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "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==", + "dev": true + }, + "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==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "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=", + "dev": true + }, + "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=", + "dev": true + }, + "cacache": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.2.tgz", + "integrity": "sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==", + "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", + "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" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "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" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "http-cache-semantics": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", + "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==", + "dev": true + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true + } + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "caniuse-lite": { + "version": "1.0.30000989", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz", + "integrity": "sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==", + "dev": true + }, + "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=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "cfb": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.1.3.tgz", + "integrity": "sha512-joXBW0nMuwV9no7UTMiyVJnQL6XIU3ThXVjFUDHgl9MpILPOomyfaGqC290VELZ48bbQKZXnQ81UT5HouTxHsw==", + "requires": { + "adler-32": "~1.2.0", + "commander": "^2.16.0", + "crc-32": "~1.2.0", + "printj": "~1.1.2" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "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" + } + }, + "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": "3.2.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.2.2.tgz", + "integrity": "sha512-bw3pm7kZ2Wa6+jQWYP/c7bAZy3i4GwiIiMO2EeRjrE48l8vBqC/WvFhSF0xyM8fQiPEGvwMY/5bqDG7sSEOuhg==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "chownr": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + } + } + }, + "cli-boxes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.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=", + "dev": true, + "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=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.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": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "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=", + "dev": true + }, + "codelyzer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.2.0.tgz", + "integrity": "sha512-izfUfhEOOgAizszPlEDxo71DK/C4wprZw0vkY6UWcOSTQvN1JyfXf9DXwaV7WX+/JC+hH0ShXfdtGLA9Rca7LA==", + "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=", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "compare-versions": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.5.1.tgz", + "integrity": "sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg==", + "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==", + "dev": true + }, + "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.17", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", + "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", + "dev": true, + "requires": { + "mime-db": ">= 1.40.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "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" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "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==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "configstore": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", + "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "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" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "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==", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "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==", + "dev": true + }, + "contour_plot": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/contour_plot/-/contour_plot-0.0.1.tgz", + "integrity": "sha1-R1hw8DK44zhBKqX8UHiA8L9JXHc=" + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "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==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "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=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz", + "integrity": "sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg==", + "dev": true, + "requires": { + "cacache": "^11.3.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.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "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" + } + }, + "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==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + } + } + }, + "core-js": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", + "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + }, + "core-js-compat": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.3.3.tgz", + "integrity": "sha512-GNZkENsx5pMnS7Inwv7ZO/s3B68a9WU5kIjxqrD/tkNR8mtfXJRk8fAKRlbvWZSGPc59/TkiOBDYl5Cb65pTVA==", + "dev": true, + "requires": { + "browserslist": "^4.7.1", + "semver": "^6.3.0" + }, + "dependencies": { + "browserslist": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.2.tgz", + "integrity": "sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001004", + "electron-to-chromium": "^1.3.295", + "node-releases": "^1.1.38" + } + }, + "caniuse-lite": { + "version": "1.0.30001004", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001004.tgz", + "integrity": "sha512-3nfOR4O8Wa2RWoYfJkMtwRVOsK96TQ+eq57wd0iKaEWl8dwG4hKZ/g0MVBfCvysFvMLi9fQGR/DvozMdkEPl3g==", + "dev": true + } + } + }, + "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=", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + } + } + }, + "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==", + "dev": true, + "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" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "css-parse": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz", + "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=", + "dev": true + }, + "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" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "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" + } + } + } + }, + "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 + }, + "cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", + "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=", + "dev": true + }, + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + }, + "d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" + }, + "d3-color": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.0.tgz", + "integrity": "sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg==" + }, + "d3-composite-projections": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/d3-composite-projections/-/d3-composite-projections-1.2.3.tgz", + "integrity": "sha512-RxNBoRGf3epTnQBUKeEpaXpD8BA/Ud0xRuLwWxyI7dWfuuYgJZMKw6ZsZOwfDNC0ZbMWaU0eBFlL05A2jlcsWg==", + "requires": { + "d3-geo": "^1.11.6", + "d3-path": "^1.0.7" + }, + "dependencies": { + "d3-geo": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.11.6.tgz", + "integrity": "sha512-z0J8InXR9e9wcgNtmVnPTj0TU8nhYT6lD/ak9may2PdKqXIeHUr8UbFLoCtrPYNsjv6YaLvSDQVl578k6nm7GA==", + "requires": { + "d3-array": "1" + } + } + } + }, + "d3-dispatch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.5.tgz", + "integrity": "sha512-vwKx+lAqB1UuCeklr6Jh1bvC4SZgbSqbkGBLClItFBIYH4vqDJCA7qfoy14lXmJdnBOdxndAMxjCbImJYW7e6g==" + }, + "d3-dsv": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.10.tgz", + "integrity": "sha512-vqklfpxmtO2ZER3fq/B33R/BIz3A1PV0FaZRuFM8w6jLo7sUX1BZDh73fPlr0s327rzq4H6EN1q9U+eCBCSN8g==", + "requires": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + } + }, + "d3-ease": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.5.tgz", + "integrity": "sha512-Ct1O//ly5y5lFM9YTdu+ygq7LleSgSE4oj7vUt9tPLHUi8VCV7QoizGpdWRWAwCO9LdYzIrQDg97+hGVdsSGPQ==" + }, + "d3-geo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.6.4.tgz", + "integrity": "sha1-8g4eRhyxhF9ai+Vatvh2VCp+MZk=", + "requires": { + "d3-array": "1" + } + }, + "d3-geo-projection": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-2.1.2.tgz", + "integrity": "sha1-ffjh6dBG1jHGUJ9+UxNX1K3CSqM=", + "requires": { + "commander": "2", + "d3-array": "1", + "d3-geo": "^1.1.0" + } + }, + "d3-hexjson": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d3-hexjson/-/d3-hexjson-1.0.1.tgz", + "integrity": "sha512-TeH4T0PSbDazMm3gHgc4ulO0PfrZpz0Uk3y5tCGz+NgC7HnX7KBdem7uAN+j9x3ZshTh7raN3V/bFhaLB2C8DA==", + "requires": { + "d3-array": "1" + } + }, + "d3-hierarchy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz", + "integrity": "sha512-L+GHMSZNwTpiq4rt9GEsNcpLa4M96lXMR8M/nMG9p5hBE0jy6C+3hWtyZMenPQdwla249iJy7Nx0uKt3n+u9+w==" + }, + "d3-interpolate": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", + "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", + "requires": { + "d3-color": "1" + } + }, + "d3-path": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.8.tgz", + "integrity": "sha512-J6EfUNwcMQ+aM5YPOB8ZbgAZu6wc82f/0WFxrxwV6Ll8wBwLaHLKCqQ5Imub02JriCVVdPjgI+6P3a4EWJCxAg==" + }, + "d3-sankey": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.7.1.tgz", + "integrity": "sha1-0imDImj8aaf+yEgD6WwiVqYUxSE=", + "requires": { + "d3-array": "1", + "d3-collection": "1", + "d3-shape": "^1.2.0" + } + }, + "d3-selection": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.0.tgz", + "integrity": "sha512-EYVwBxQGEjLCKF2pJ4+yrErskDnz5v403qvAid96cNdCMr8rmCYfY5RGzWz24mdIbxmDf6/4EAH+K9xperD5jg==" + }, + "d3-shape": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.5.tgz", + "integrity": "sha512-VKazVR3phgD+MUCldapHD7P9kcrvPcexeX/PkMJmkUov4JM8IxsSg1DvbYoYich9AtdTsa5nNk2++ImPiDiSxg==", + "requires": { + "d3-path": "1" + } + }, + "d3-timer": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.9.tgz", + "integrity": "sha512-rT34J5HnQUHhcLvhSB9GjCkN0Ddd5Y8nCwDBG2u6wQEeYxT/Lf51fTFFkldeib/sE/J0clIe0pnCfs6g/lRbyg==" + }, + "d3-transition": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.2.0.tgz", + "integrity": "sha512-VJ7cmX/FPIPJYuaL2r1o1EMHLttvoIuZhhuAlRoOxDzogV8iQS6jYulDm3xEU3TqL80IZIhI551/ebmCMrkvhw==", + "requires": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "d3-voronoi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", + "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" + }, + "dagre": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.4.tgz", + "integrity": "sha512-Dj0csFDrWYKdavwROb9FccHfTC4fJbyF/oJdL9LNZJ8WUvl968P6PAKEriGqfbdArVJEmmfA+UyumgWEwcHU6A==", + "requires": { + "graphlib": "^2.1.7", + "lodash": "^4.17.4" + } + }, + "damerau-levenshtein": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz", + "integrity": "sha512-CBCRqFnpu715iPmw1KrdOrzRqbdFwQTwAWyyyYS42+iAgHCuXZ+/TdMgQkUENPomxEz9z1BEzuQU2Xw0kUuAgA==", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" + }, + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "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" + } + }, + "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=", + "dev": true + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "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" + } + }, + "defer-to-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz", + "integrity": "sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + } + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "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.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "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=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "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 + }, + "diff-match-patch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.4.tgz", + "integrity": "sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true, + "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==", + "dev": true + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "dev": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.295", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.295.tgz", + "integrity": "sha512-KxlGE9GcZTv7xGwYJGMEABHJq2JuTMNF7jD8NwHk6sBY226mW+Dyp9kZmA2Od9tKHMCS7ltPnqFg+zq3jTWN7Q==", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "elliptic": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", + "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "dev": true, + "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": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "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==", + "dev": true, + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "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" + } + } + } + }, + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "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" + } + } + } + }, + "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==", + "dev": true, + "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 + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", + "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "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=", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "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==", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", + "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", + "dev": true + }, + "events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", + "dev": true + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true, + "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": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "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=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "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=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "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=", + "dev": true + }, + "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=", + "dev": true + }, + "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=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, + "figures": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", + "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "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==", + "dev": true, + "requires": { + "loader-utils": "^1.2.3", + "schema-utils": "^2.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz", + "integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "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": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "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" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + } + } + }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "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==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "fmin": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fmin/-/fmin-0.0.2.tgz", + "integrity": "sha1-Wbu0DUP/3ByUzQClaMQflfGXMBc=", + "requires": { + "contour_plot": "^0.0.1", + "json2module": "^0.0.3", + "rollup": "^0.25.8", + "tape": "^4.5.1", + "uglify-js": "^2.6.2" + } + }, + "fn-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", + "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=", + "dev": true + }, + "follow-redirects": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz", + "integrity": "sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==", + "dev": true, + "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==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "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=", + "dev": true, + "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=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "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=", + "dev": true, + "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": "2.1.1", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.1.tgz", + "integrity": "sha512-4FRPXWETxtigtJW/gxzEDsX1LVbPAM93VleB83kZB+ellqbHMkyt2aJfuzNLRvFPnGi6bcE5SvfxgbXPeKteJw==", + "dev": 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==" + }, + "g-status": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/g-status/-/g-status-2.0.2.tgz", + "integrity": "sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "matcher": "^1.0.0", + "simple-git": "^1.85.0" + } + }, + "genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, + "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==", + "dev": true + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.1.tgz", + "integrity": "sha512-09/VS4iek66Dh2bctjRkowueRJbY1JDGR1L/zRxO1Qk8Uxs6PnqaNSqalpizPT+CDjre3hnEsuzvhgomz9qYrA==", + "dev": true + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "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=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", + "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", + "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=", + "dev": true, + "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=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "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=", + "dev": true + } + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "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==", + "dev": true + }, + "graphlib": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.7.tgz", + "integrity": "sha512-TyI9jIy2J4j0qgPmOOrHTCtpPqJGN/aurBwc6ZT+bRii+di1I+Wv3obRhVrmBEXet+qkMaEX67dXrwsd3QQM6w==", + "requires": { + "lodash": "^4.17.5" + } + }, + "handle-thing": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", + "dev": true + }, + "handlebars": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.5.tgz", + "integrity": "sha512-0Ce31oWVB7YidkaTq33ZxEbN+UDxMMgThvCe8ptgQViymL5DPis9uLdTA13MiRPhgvqyxIegugrP97iK3JeBHg==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "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 + }, + "uglify-js": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.4.tgz", + "integrity": "sha512-9Yc2i881pF4BPGhjteCXQNaXx1DCwm3dtOyBaG2hitHjLWOczw/ki8vD1bqyT3u6K0Ms/FpCShkmfg+FtlOfYA==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.3", + "source-map": "~0.6.1" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "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==", + "dev": true, + "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=", + "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=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "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=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "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=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "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==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "highlight.js": { + "version": "9.15.10", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz", + "integrity": "sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw==" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "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=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "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=", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true + } + } + }, + "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=", + "dev": true + }, + "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==", + "dev": true, + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "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==", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "https-proxy-agent": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.3.tgz", + "integrity": "sha512-Ytgnz23gm2DVftnzqRRz2dOXZbGd2uiajSw/95bPp6v53zPRspQjLm/AfBgqbJ2qfeRXWIOMVLpp86+/5yX39Q==", + "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" + } + } + } + }, + "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" + } + }, + "husky": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-2.7.0.tgz", + "integrity": "sha512-LIi8zzT6PyFpcYKdvWRCn/8X+6SuG2TgYYMrM6ckEYhlp44UcEduVymZGIZNLiwOUjrEud+78w/AsAiqJA/kRg==", + "dev": true, + "requires": { + "cosmiconfig": "^5.2.0", + "execa": "^1.0.0", + "find-up": "^3.0.0", + "get-stdin": "^7.0.0", + "is-ci": "^2.0.0", + "pkg-dir": "^4.1.0", + "please-upgrade-node": "^3.1.1", + "read-pkg": "^5.1.1", + "run-node": "^1.0.0", + "slash": "^3.0.0" + }, + "dependencies": { + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.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==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "find-up": "^4.0.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==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, + "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==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "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=", + "dev": true, + "optional": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "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==", + "dev": true + }, + "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 + }, + "injection-js": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/injection-js/-/injection-js-2.2.2.tgz", + "integrity": "sha512-9K4fW2NNPG3JCvORx5G/T6q/PZYIr43RFgxBvtk3OV4omh5iqvpK4cChuBfhgPnRbXSgZRfuROh0XG5KNA8Xlg==", + "dev": true + }, + "inquirer": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.1.tgz", + "integrity": "sha512-uxNHBeQhRXIoHWTSNYUFhQVrHYFThIt6IVo2fFmSe8aBwdR3/w6b58hJpiL/fMukFkvGzjg+hSxFtwvVmKZmXw==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^4.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 + }, + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz", + "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^5.2.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" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.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==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "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==", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "dev": true + }, + "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==", + "dev": true + }, + "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=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.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.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "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=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "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==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "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=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-npm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", + "integrity": "sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "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==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true + }, + "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==", + "dev": true, + "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-reference": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz", + "integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==", + "dev": true, + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "^1.0.1" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "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==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "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=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "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-instrumenter-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", + "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", + "dev": true, + "requires": { + "convert-source-map": "^1.5.0", + "istanbul-lib-instrument": "^1.7.3", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "^5.0.0" + } + } + } + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "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": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "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 + } + } + }, + "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 + }, + "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==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "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": { + "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 + }, + "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.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "dev": true, + "requires": { + "handlebars": "^4.1.2" + } + }, + "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==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "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=", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "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==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "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==", + "dev": true + }, + "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=", + "dev": true + }, + "json2module": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/json2module/-/json2module-0.0.3.tgz", + "integrity": "sha1-APtfSpt638PwZHwpyxe80Zeb6bI=", + "requires": { + "rw": "^1.3.2" + } + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "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=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jszip": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.2.tgz", + "integrity": "sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA==", + "dev": true, + "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": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "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=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "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" + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "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" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": 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.3", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": 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" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": 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.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "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=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "dev": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "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 + }, + "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=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "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.4.2", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.4.2.tgz", + "integrity": "sha512-7g0gPj8+9JepCNJR9WjDyQ2RkZ375jpdurYQyAYv8PorUCadepl8vrD6LmMqOGcM17cnrynBawQYZHaumgDjBw==", + "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==", + "dev": true, + "requires": { + "source-map-support": "^0.5.5" + }, + "dependencies": { + "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.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "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" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^4.0.1" + } + }, + "less-plugin-npm-import": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/less-plugin-npm-import/-/less-plugin-npm-import-2.1.0.tgz", + "integrity": "sha1-gj5phskzGKmBccqFiEi2vq1Vvz4=", + "dev": true, + "requires": { + "promise": "~7.0.1", + "resolve": "~1.1.6" + }, + "dependencies": { + "promise": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.0.4.tgz", + "integrity": "sha1-Nj6EpMNsg1a4kP7WLJHOhdAu1Tk=", + "dev": true, + "requires": { + "asap": "~2.0.3" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "lint-staged": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.2.1.tgz", + "integrity": "sha512-n0tDGR/rTCgQNwXnUf/eWIpPNddGWxC32ANTNYsj2k02iZb7Cz5ox2tytwBu+2r0zDXMEMKw7Y9OD/qsav561A==", + "dev": true, + "requires": { + "chalk": "^2.3.1", + "commander": "^2.14.1", + "cosmiconfig": "^5.2.0", + "debug": "^3.1.0", + "dedent": "^0.7.0", + "del": "^3.0.0", + "execa": "^1.0.0", + "g-status": "^2.0.2", + "is-glob": "^4.0.0", + "is-windows": "^1.0.2", + "listr": "^0.14.2", + "listr-update-renderer": "^0.5.0", + "lodash": "^4.17.11", + "log-symbols": "^2.2.0", + "micromatch": "^3.1.8", + "npm-which": "^3.0.1", + "p-map": "^1.1.1", + "path-is-inside": "^1.0.2", + "pify": "^3.0.0", + "please-upgrade-node": "^3.0.2", + "staged-git-files": "1.1.2", + "string-argv": "^0.0.2", + "stringify-object": "^3.2.2", + "yup": "^0.27.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "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" + } + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "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=", + "dev": true + } + } + }, + "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" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "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" + } + }, + "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" + } + }, + "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 + }, + "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" + } + }, + "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" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "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-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "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" + } + }, + "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 + }, + "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" + } + }, + "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" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, + "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" + } + }, + "loglevel": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.4.tgz", + "integrity": "sha512-p0b6mOGKcGa+7nnmKbpzR6qloPbrgLcnio++E+14Vo/XffOGwZtRpUhr8dTH/x2oCMmEoIU0Zwm3ZauhvYD17g==", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "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==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "yallist": "^3.0.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==", + "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==", + "dev": true, + "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==", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "make-fetch-happen": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.1.tgz", + "integrity": "sha512-b4dfaMvUDR67zxUq1+GN7Ke9rH5WvGRmoHuMH7l+gmUCR2tCXFP6mpeJ9Dp+jB6z8mShRopSf1vLRBhRs8Cu5w==", + "dev": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^12.0.0", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.3", + "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==", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "matcher": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", + "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.4" + } + }, + "mathjax": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-2.7.5.tgz", + "integrity": "sha512-OzsJNitEHAJB3y4IIlPCAvS0yoXwYjlo2Y4kmm9KQzyIBZt2d8yKRalby3uTRNN4fZQiGL2iMXjpdP1u2Rq2DQ==" + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "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==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "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" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "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=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "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=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "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=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "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=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "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==", + "dev": true + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "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=", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + } + } + }, + "monaco-editor": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.18.1.tgz", + "integrity": "sha512-fmL+RFZ2Hrezy+X/5ZczQW51LUmvzfcqOurnkCIRFTyjdVjzR7JvENzI6+VKBJzJdPh6EYL4RoWl92b2Hrk9fw==" + }, + "monaco-editor-webpack-plugin": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.7.0.tgz", + "integrity": "sha512-oItymcnlL14Sjd7EF7q+CMhucfwR/2BxsqrXIBrWL6LQplFfAfV+grLEQRmVHeGSBZ/Gk9ptzfueXnWcoEcFuA==", + "dev": true, + "requires": { + "@types/webpack": "^4.4.19" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "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.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "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=", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "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" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "ng-packagr": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-5.7.0.tgz", + "integrity": "sha512-/75eqAyk2ef8J0aMLl7XCx1QXmqUUTsQDu+fNCFDIYpkpWBh0C8Rkdd72hMLPv3MMo63pfaNeiMXa0zzpQINyA==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "autoprefixer": "^9.6.0", + "browserslist": "^4.0.0", + "chalk": "^2.3.1", + "chokidar": "^3.0.0", + "clean-css": "^4.1.11", + "commander": "^3.0.0", + "fs-extra": "^8.0.0", + "glob": "^7.1.2", + "injection-js": "^2.2.1", + "less": "^3.8.0", + "less-plugin-npm-import": "^2.1.0", + "node-sass-tilde-importer": "^1.0.0", + "postcss": "^7.0.0", + "postcss-url": "^8.0.0", + "read-pkg-up": "^5.0.0", + "rimraf": "^3.0.0", + "rollup": "^1.12.1", + "rollup-plugin-commonjs": "^10.0.0", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^5.0.0", + "rollup-plugin-sourcemaps": "^0.4.2", + "rxjs": "^6.0.0", + "sass": "^1.17.3", + "stylus": "^0.54.5", + "terser": "^4.1.2", + "update-notifier": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "commander": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "rimraf": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", + "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rollup": { + "version": "1.25.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.25.2.tgz", + "integrity": "sha512-+7z6Wab/L45QCPcfpuTZKwKiB0tynj05s/+s2U3F2Bi7rOLPr9UcjUwO7/xpjlPNXA/hwnth6jBExFRGyf3tMg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "ng-zorro-antd": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/ng-zorro-antd/-/ng-zorro-antd-8.4.1.tgz", + "integrity": "sha512-P/EpGpqRRsx2NmyJyulhH56jNYV2a1e1lf9F2NOp1IIG3J1XKFAxHPCetaGeeeEbXT2voQWshD12iTf2Fb0xAQ==", + "requires": { + "@angular/cdk": "^8.0.0", + "@ant-design/icons-angular": "^8.0.2", + "date-fns": "^1.30.1", + "tslib": "^1.9.0" + } + }, + "ngx-build-plus": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/ngx-build-plus/-/ngx-build-plus-8.1.5.tgz", + "integrity": "sha512-jkMN43wBqCqIBYKnQwf+NiZYgbYY1nNTs/Jg41lt7mc9nxBQobs3Cypty3Hy22m9caFLWQR+3AQIttxmr3o9NA==", + "dev": true, + "requires": { + "@schematics/angular": "8.0.0", + "cross-spawn": "^6.0.5", + "rxjs": "6.4.0", + "webpack-dev-server": "^3.1.14", + "webpack-merge": "^4.2.1" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.0.0.tgz", + "integrity": "sha512-wYf4zzpYj5Y673DG8iteK0GsDDuXBKN/TOXm4lUwmXcz8QHTD+BfR6qA5TBDqlMGpU7CP1/0vgbv2px17CDETQ==", + "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.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.0.0.tgz", + "integrity": "sha512-IXJOs/DkDqNbfG76sNNY5ePZ37rjkMUopmtvhN6/U1hQFwTpGa9N0bCHFphcKraXeS6Jfox5XwFEStc/1xyhfw==", + "dev": true, + "requires": { + "@angular-devkit/core": "8.0.0", + "rxjs": "6.4.0" + } + }, + "@schematics/angular": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.0.0.tgz", + "integrity": "sha512-c/cFpe+u7Xh4xX3/kn9BSRY4YhdO0OsDbRK0pGLDJFFs5JGvwoURtNXn4/4dVlsj3PWyNhxK0Ljl3dyw3NQBHA==", + "dev": true, + "requires": { + "@angular-devkit/core": "8.0.0", + "@angular-devkit/schematics": "8.0.0" + } + }, + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "dev": true, + "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.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" + } + }, + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "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==", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true + } + } + }, + "node-releases": { + "version": "1.1.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.38.tgz", + "integrity": "sha512-/5NZAaOyTj134Oy5Cp/J8mso8OD/D9CSuL+6TOXXsTKO8yjc5e4up75SRPCganCjwFKMj2jbp5tR0dViVdox7g==", + "dev": true, + "requires": { + "semver": "^6.3.0" + } + }, + "node-sass-tilde-importer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/node-sass-tilde-importer/-/node-sass-tilde-importer-1.0.2.tgz", + "integrity": "sha512-Swcmr38Y7uB78itQeBm3mThjxBy9/Ah/ykPIaURY/L6Nec9AyRoL/jJ7ECfMR+oZeCTVQNxVMu/aHU+TLRVbdg==", + "dev": true, + "requires": { + "find-parent-dir": "^0.3.0" + } + }, + "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==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "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.0.6", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", + "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.6", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.6.tgz", + "integrity": "sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg==", + "dev": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npm-path": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "dev": true, + "requires": { + "which": "^1.2.10" + } + }, + "npm-pick-manifest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "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": "4.0.2", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.2.tgz", + "integrity": "sha512-Z0IFtPEozNdeZRPh3aHHxdG+ZRpzcbQaJLthsm3VhNf6DScicTFRHZzK82u8RsJUsUHkX+QH/zcB/5pmd20H4A==", + "dev": true, + "requires": { + "JSONStream": "^1.3.4", + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + } + } + }, + "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=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", + "dev": true, + "requires": { + "commander": "^2.9.0", + "npm-path": "^2.0.2", + "which": "^1.2.10" + } + }, + "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=", + "dev": true + }, + "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=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "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=", + "dev": true, + "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=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" + }, + "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=", + "dev": true, + "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==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "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==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "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==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true + }, + "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==", + "dev": true, + "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-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "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==", + "dev": true + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "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==", + "dev": true + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + } + }, + "pacote": { + "version": "9.5.5", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.5.tgz", + "integrity": "sha512-jAEP+Nqj4kyMWyNpfTU/Whx1jA7jEc5cCOlurm0/0oL+v8TAp1QSsK83N7bYe+2bEdFzMAtPG5TBebjzzGV0cA==", + "dev": true, + "requires": { + "bluebird": "^3.5.3", + "cacache": "^12.0.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.3", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^5.0.0", + "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": "^4.0.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": { + "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" + } + }, + "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.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha1-en7A0esG+lMlx9PgCbhZoJtdSes=" + }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "optional": true + }, + "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==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "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==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "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=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "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=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "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=", + "dev": true + } + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "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=", + "dev": true + }, + "picomatch": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "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==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "point-at-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/point-at-length/-/point-at-length-1.0.2.tgz", + "integrity": "sha1-kXbY1tfIFi8Stkb3B9ufDqcoEl4=", + "requires": { + "abs-svg-path": "~0.1.1", + "isarray": "~0.0.1", + "parse-svg-path": "~0.1.1" + } + }, + "portfinder": { + "version": "1.0.25", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", + "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", + "dev": true, + "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==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "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=", + "dev": true + }, + "postcss": { + "version": "7.0.17", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz", + "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "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==", + "dev": true, + "requires": { + "has-flag": "^3.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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "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==", + "dev": true, + "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==", + "dev": true + } + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + } + }, + "postcss-url": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-8.0.0.tgz", + "integrity": "sha512-E2cbOQ5aii2zNHh8F6fk1cxls7QVFZjLPSrqvmiza8OuXLzIpErij8BDS5Y3STPfJgpIMNCPEr8JlKQWEoozUw==", + "dev": true, + "requires": { + "mime": "^2.3.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.0", + "postcss": "^7.0.2", + "xxhashjs": "^0.2.1" + }, + "dependencies": { + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "dev": true + } + } + }, + "postcss-value-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz", + "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "prettier": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", + "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", + "dev": true + }, + "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==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "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==", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "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=", + "dev": true + }, + "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" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + } + } + }, + "property-expr": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-1.5.1.tgz", + "integrity": "sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==", + "dev": true + }, + "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.2", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.2.tgz", + "integrity": "sha512-zlIj64Cr6IOWP7RwxVeD8O4UskLYPoyIcg0HboWJL9T79F1F0VWtKkGTr/9GN6BKL+/Q/GmM7C9kFVCfDbP5sA==", + "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": { + "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" + } + }, + "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.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", + "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "dev": true + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "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=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true + } + } + }, + "raw-loader": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-3.1.0.tgz", + "integrity": "sha512-lzUVMuJ06HF4rYveaz9Tv0WRlUMxJ0Y1hgSkkgg+50iEdaI0TthyEDe08KIHb0XsF6rn8WYTqPCaGTZg3sX+qA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^2.0.1" + }, + "dependencies": { + "schema-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz", + "integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "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=", + "dev": true + } + } + }, + "read-package-json": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.0.tgz", + "integrity": "sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+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", + "slash": "^1.0.0" + } + }, + "read-package-tree": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", + "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", + "dev": true, + "requires": { + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "util-promisify": "^2.1.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-5.0.0.tgz", + "integrity": "sha512-XBQjqOBtTzyol2CpsQOw8LHV0XbDZVG7xMMjmXAJomlVY03WOBRmYgDJETlvcg0H63AJvPRwT7GFi5rvOzUOKg==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^5.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": 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" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "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": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, + "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==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "dev": true, + "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==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", + "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", + "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.1.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, + "registry-auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz", + "integrity": "sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw==", + "dev": true, + "requires": { + "rc": "^1.2.8", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "regjsgen": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", + "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", + "dev": true + }, + "regjsparser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "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 + } + } + }, + "regression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regression/-/regression-2.0.1.tgz", + "integrity": "sha1-jSnD6CJKEIUMNeM36FqLL6w7DIc=" + }, + "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=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "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.0", + "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.4.3", + "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=", + "dev": true + }, + "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=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "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=", + "dev": true, + "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=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "requires": { + "through": "~2.3.4" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "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 + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "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==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rollup": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.25.8.tgz", + "integrity": "sha1-v2zoO4dRDRY0Ru6qV37WpvxYNeA=", + "requires": { + "chalk": "^1.1.1", + "minimist": "^1.2.0", + "source-map-support": "^0.3.2" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz", + "integrity": "sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.5.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-sourcemaps": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.4.2.tgz", + "integrity": "sha1-YhJaqUCHqt97g+9N+vYptHMTXoc=", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.0.1", + "source-map-resolve": "^0.5.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", + "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", + "dev": true + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" + }, + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "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==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + } + } + }, + "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=", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "node-forge": "0.9.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "^5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "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==", + "dev": true, + "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": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "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==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", + "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "dev": true + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "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": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "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=", + "dev": true, + "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=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "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=", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "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==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "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=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "simple-git": { + "version": "1.126.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.126.0.tgz", + "integrity": "sha512-47mqHxgZnN8XRa9HbpWprzUv3Ooqz9RY/LSZgvA7jCkW8jcwLahMz7LKugY91KZehfG0sCVPtgXiU72hd6b1Bw==", + "dev": true, + "requires": { + "debug": "^4.0.1" + } + }, + "simple-statistics": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/simple-statistics/-/simple-statistics-6.1.1.tgz", + "integrity": "sha512-zGwn0DDRa9Zel4H4n2pjTFIyGoAGpnpjrGIctreCxj5XWrcx9v7Xy7270FkC967WMmcvuc8ZU7m0ZG+hGN7gAA==" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "smart-buffer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", + "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==", + "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==", + "dev": true, + "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": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "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=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "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 + } + } + }, + "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==", + "dev": true, + "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=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + } + }, + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "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 + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "dev": true, + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" + } + }, + "sockjs-client": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", + "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + } + } + }, + "socks": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz", + "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "4.0.2" + } + }, + "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=", + "dev": true, + "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==", + "dev": true + }, + "source-map": { + "version": "0.1.32", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", + "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", + "requires": { + "amdefine": ">=0.0.4" + } + }, + "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==", + "dev": true, + "requires": { + "async": "^2.5.0", + "loader-utils": "^1.1.0" + } + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "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.3.3", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.3.3.tgz", + "integrity": "sha1-NJAJd9W6PwfHdX7nLnO7GptTdU8=", + "requires": { + "source-map": "0.1.32" + } + }, + "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=", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "dev": true + }, + "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.1", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz", + "integrity": "sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==", + "dev": true, + "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" + } + }, + "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==", + "dev": true, + "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": { + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "dev": true, + "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==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "ssf": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.2.tgz", + "integrity": "sha512-rDhAPm9WyIsY8eZEKyE8Qsotb3j/wBdvMWBUsOhJdfhKGLfQidRjiBUV0y/MkyCLiXQ38FG6LWW/VYUtqlIDZQ==", + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "staged-git-files": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.2.tgz", + "integrity": "sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "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" + } + } + } + }, + "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=", + "dev": true + }, + "string-argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", + "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "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=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "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==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.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=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "loader-utils": "^1.2.3", + "schema-utils": "^2.0.1" + }, + "dependencies": { + "schema-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz", + "integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "stylus": { + "version": "0.54.5", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz", + "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=", + "dev": true, + "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=", + "dev": true, + "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" + } + } + } + }, + "stylus-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "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 + }, + "synchronous-promise": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.10.tgz", + "integrity": "sha512-6PC+JRGmNjiG3kJ56ZMNWDPL8hjyghF5cMXIFOKg+NiwwEZZIvxTWd0pinWKyD227odg9ygF8xVhhz7gb8Uq7A==", + "dev": true + }, + "systemjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/systemjs/-/systemjs-5.0.0.tgz", + "integrity": "sha512-hnD/IMQhH0UmawiIGlYVnkCPUbbO/WDQjOC+Q4PewHBdsagI1OHH1re1sg1AYFqq7p9ps6b1Bsx4xCeoeIZSCw==" + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + } + }, + "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" + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.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" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "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 + } + } + }, + "terser": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.8.tgz", + "integrity": "sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", + "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.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==", + "dev": true + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, + "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=", + "dev": true + }, + "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=", + "dev": true + }, + "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=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "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": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "topojson-client": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.0.1.tgz", + "integrity": "sha512-rfGGzyqefpxOaxvV9OTF9t+1g+WhjGEbAIuCcmKYrQkxr0nttjMMyzZsK+NhLW4cTl2g1bz2jQczPUtEshpbVQ==", + "requires": { + "commander": "2" + } + }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "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" + }, + "dependencies": { + "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.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "tsickle": { + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.37.0.tgz", + "integrity": "sha512-ufUZqLUNqh+kOfr52N/hJ5JbiDO32/CO7ZCteZBX9HA2kiejwEgDaJeJe1GAj2TIu683IgTA/LPKvlns6Liw0w==", + "dev": true, + "requires": { + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "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": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "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 + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "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=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "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=", + "dev": true + }, + "type-fest": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", + "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "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=", + "dev": true + }, + "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==", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": 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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "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" + } + } + } + }, + "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=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-notifier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-3.0.1.tgz", + "integrity": "sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ==", + "dev": true, + "requires": { + "boxen": "^3.0.0", + "chalk": "^2.0.1", + "configstore": "^4.0.0", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.1.0", + "is-npm": "^3.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "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=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + }, + "dependencies": { + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "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==", + "dev": true, + "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=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util-promisify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", + "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "dev": true + }, + "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=", + "dev": true + }, + "venn.js": { + "version": "0.2.20", + "resolved": "https://registry.npmjs.org/venn.js/-/venn.js-0.2.20.tgz", + "integrity": "sha512-bb5SYq/wamY9fvcuErb9a0FJkgIFHJjkLZWonQ+DoKKuDX3WPH2B4ouI1ce4K2iejBklQy6r1ly8nOGIyOCO6w==", + "requires": { + "d3-selection": "^1.0.2", + "d3-transition": "^1.0.1", + "fmin": "0.0.2" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "dev": true + }, + "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.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "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=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "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" + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "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" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": 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.3", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": 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" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": 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.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "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=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "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=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "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==", + "dev": true, + "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" + } + }, + "webpack-core": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", + "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", + "dev": true, + "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=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz", + "integrity": "sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.2", + "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==", + "dev": true + } + } + }, + "webpack-dev-server": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.8.0.tgz", + "integrity": "sha512-Hs8K9yI6pyMvGkaPTeTonhD6JXVsigXDApYk9JLW4M7viVBspQvb1WdAcWxqtmttxNW4zf2UFLsLNe0y87pIGQ==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.6", + "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.0", + "killable": "^1.0.1", + "loglevel": "^1.6.3", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.21", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.4", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "0.3.19", + "sockjs-client": "1.3.0", + "spdy": "^4.0.1", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.0", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "12.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "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=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "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" + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "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" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": 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.3", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": 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" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": 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.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": 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, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "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=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "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==", + "dev": true, + "requires": { + "has-flag": "^3.0.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=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "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" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-merge": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", + "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", + "dev": true, + "requires": { + "lodash": "^4.17.5" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "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==", + "dev": true + } + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + }, + "when": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", + "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "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=", + "dev": true + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wolfy87-eventemitter": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.1.0.tgz", + "integrity": "sha1-NcGsDdGsDBXjXZgVCPwiCEoToBE=" + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=" + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, + "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" + }, + "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.22", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz", + "integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "util.promisify": "~1.0.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==", + "dev": true + }, + "xxhashjs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", + "dev": true, + "requires": { + "cuint": "^0.2.2" + } + }, + "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==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + }, + "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 + }, + "yup": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.27.0.tgz", + "integrity": "sha512-v1yFnE4+u9za42gG/b/081E7uNW9mUj3qtkmelLbW5YPROZzSH/KUUyJu9Wt8vxFJcT9otL/eZopS0YK1L5yPQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.0.0", + "fn-name": "~2.0.1", + "lodash": "^4.17.11", + "property-expr": "^1.5.0", + "synchronous-promise": "^2.0.6", + "toposort": "^2.0.2" + } + }, + "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/zeppelin-web-angular/package.json b/zeppelin-web-angular/package.json new file mode 100644 index 00000000000..ae96fe7f87b --- /dev/null +++ b/zeppelin-web-angular/package.json @@ -0,0 +1,96 @@ +{ + "name": "zeppelin", + "version": "0.0.0", + "scripts": { + "postinstall": "npm run build:projects", + "ng": "./node_modules/.bin/ng", + "start": "ng serve --proxy-config proxy.conf.js --extra-webpack-config webpack.partial.js", + "build": "ng build --prod --extra-webpack-config webpack.partial.js", + "build:projects": "npm run build-project:sdk && npm run build-project:vis && npm run build-project:helium", + "build-helium-vis-example": " ng build --project helium-vis-example", + "build-project:sdk": " ng build --project zeppelin-sdk", + "build-project:vis": " ng build --project zeppelin-visualization", + "build-project:helium": "ng build --project zeppelin-helium", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e" + }, + "private": true, + "dependencies": { + "@angular/animations": "~8.2.10", + "@angular/cdk": "~8.2.3", + "@angular/common": "~8.2.10", + "@angular/compiler": "~8.2.10", + "@angular/core": "~8.2.10", + "@angular/forms": "~8.2.10", + "@angular/platform-browser": "~8.2.10", + "@angular/platform-browser-dynamic": "~8.2.10", + "@angular/router": "~8.2.10", + "@antv/data-set": "^0.10.2", + "@antv/g2": "^3.5.4", + "ansi-to-html": "^0.6.11", + "core-js": "^2.5.4", + "date-fns": "^1.30.1", + "diff-match-patch": "^1.0.4", + "highlight.js": "^9.15.8", + "lodash": "^4.17.11", + "mathjax": "2.7.5", + "monaco-editor": "^0.18.1", + "ng-zorro-antd": "^8.4.0", + "rxjs": "~6.5.3", + "systemjs": "^5.0.0", + "tslib": "^1.9.0", + "xlsx": "^0.14.3", + "zone.js": "~0.9.1" + }, + "devDependencies": { + "monaco-editor-webpack-plugin": "^1.7.0", + "ngx-build-plus": "^8.1.5", + "@angular-devkit/build-angular": "^0.803.9", + "@angular-devkit/build-ng-packagr": "~0.803.6", + "@angular/cli": "~8.3.9", + "@angular/compiler-cli": "~8.2.10", + "@angular/language-service": "~8.2.10", + "@types/date-fns": "^2.6.0", + "@types/highlight.js": "^9.12.3", + "@types/jasmine": "~3.3.8", + "@types/jasminewd2": "~2.0.3", + "@types/lodash": "^4.14.124", + "@types/mathjax": "^0.0.35", + "@types/node": "~8.9.4", + "codelyzer": "^5.0.0", + "dotenv": "^8.0.0", + "https-proxy-agent": "^2.2.1", + "husky": "^2.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", + "lint-staged": "^8.1.6", + "ng-packagr": "^5.4.0", + "prettier": "^1.17.0", + "protractor": "~5.4.0", + "ts-node": "~7.0.0", + "tsickle": "^0.37.0", + "tslint": "~5.15.0", + "typescript": "~3.5.3" + }, + "lint-staged": { + "src/**/*.{ts,js,json}": [ + "./node_modules/.bin/prettier --write", + "git add" + ], + "src/**/*.ts": [ + "tslint --project src/tslint.json --fix", + "git add" + ] + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + } +} diff --git a/zeppelin-web-angular/pom.xml b/zeppelin-web-angular/pom.xml new file mode 100644 index 00000000000..e0a1f7b3e84 --- /dev/null +++ b/zeppelin-web-angular/pom.xml @@ -0,0 +1,174 @@ + + + + + 4.0.0 + + + zeppelin + org.apache.zeppelin + 0.9.0-SNAPSHOT + .. + + + org.apache.zeppelin + zeppelin-web-angular + war + 0.9.0-SNAPSHOT + Zeppelin: web Application + + + + 3.1.0 + + + + true + false + ../bin + UTF-8 + + + https://nodejs.org/dist/ + https://registry.npmjs.org/npm/-/ + + + + + + + org.apache.maven.plugins + maven-war-plugin + + dist\zeppelin + dist\zeppelin\WEB-INF\web.xml + + + + + com.github.eirslett + frontend-maven-plugin + ${plugin.frontend.version} + + ${plugin.frontend.nodeDownloadRoot} + ${plugin.frontend.npmDownloadRoot} + + + + + install node + + install-node-and-npm + + + ${node.version} + ${npm.version} + + + + + npm install + + npm + + + ${web.e2e.enabled} + install --no-lockfile + + + + + npm build + + npm + + + ${web.e2e.enabled} + run build + + + + + npm test + + npm + + test + + ${web.e2e.disabled} + run test + + + + + npm e2e + + npm + + integration-test + + ${web.e2e.disabled} + run e2e + + + + + + + + + org.codehaus.mojo + cobertura-maven-plugin + + + cobertura + none + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + + + + maven-clean-plugin + + + + node + + + node_modules + + + + + + + maven-resources-plugin + ${plugin.resource.version} + + + + + diff --git a/zeppelin-web-angular/projects/helium-vis-example/README.md b/zeppelin-web-angular/projects/helium-vis-example/README.md new file mode 100644 index 00000000000..e1850116b2e --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/README.md @@ -0,0 +1,36 @@ + + +# HeliumVisExample + +This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.9. + +## Code scaffolding + +Run `ng generate component component-name --project helium-vis-example` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project helium-vis-example`. +> Note: Don't forget to add `--project helium-vis-example` or else it will be added to the default project in your `angular.json` file. + +## Build + +Run `ng build helium-vis-example` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Publishing + +After building your library with `ng build helium-vis-example`, go to the dist folder `cd dist/helium-vis-example` and run `npm publish`. + +## Running unit tests + +Run `ng test helium-vis-example` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## 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/zeppelin-web-angular/projects/helium-vis-example/karma.conf.js b/zeppelin-web-angular/projects/helium-vis-example/karma.conf.js new file mode 100644 index 00000000000..ed77432da6e --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/karma.conf.js @@ -0,0 +1,44 @@ +/* + * 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. + */ + +// 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/helium-vis-example'), + 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/zeppelin-web-angular/projects/helium-vis-example/ng-package.json b/zeppelin-web-angular/projects/helium-vis-example/ng-package.json new file mode 100644 index 00000000000..2193ef3df33 --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/helium-vis-example", + "lib": { + "entryFile": "src/public-api.ts" + } +} \ No newline at end of file diff --git a/zeppelin-web-angular/projects/helium-vis-example/package.json b/zeppelin-web-angular/projects/helium-vis-example/package.json new file mode 100644 index 00000000000..17f7cb02fbc --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/package.json @@ -0,0 +1,8 @@ +{ + "name": "helium-vis-example", + "version": "0.0.1", + "peerDependencies": { + "@angular/common": "^8.2.9", + "@angular/core": "^8.2.9" + } +} \ No newline at end of file diff --git a/zeppelin-web-angular/projects/helium-vis-example/src/json-vis.component.ts b/zeppelin-web-angular/projects/helium-vis-example/src/json-vis.component.ts new file mode 100644 index 00000000000..12234517668 --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/src/json-vis.component.ts @@ -0,0 +1,43 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core'; +import { TableData, Visualization, VISUALIZATION } from '@zeppelin/visualization'; + +@Component({ + selector: 'lib-helium-vis-example', + template: ` +
{{tableData | json}}
+ `, + styles: [` + pre { + background: #fff7e7; + padding: 10px; + border: 1px solid #ffd278; + color: #fa7e14; + border-radius: 3px; + } + `], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class JsonVisComponent implements OnInit { + tableData: TableData; + constructor(@Inject(VISUALIZATION) public visualization: Visualization, private cdr: ChangeDetectorRef) {} + + ngOnInit() { + } + + render(): void { + this.tableData = this.visualization.transformed; + } + +} diff --git a/zeppelin-web-angular/projects/helium-vis-example/src/json-vis.module.ts b/zeppelin-web-angular/projects/helium-vis-example/src/json-vis.module.ts new file mode 100644 index 00000000000..2578f26df39 --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/src/json-vis.module.ts @@ -0,0 +1,23 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NgModule } from '@angular/core'; +import { JsonVisComponent } from './json-vis.component'; +import { CommonModule } from '@angular/common'; + +@NgModule({ + imports: [CommonModule], + declarations: [JsonVisComponent], + entryComponents: [JsonVisComponent], + exports: [JsonVisComponent] +}) +export class JsonVisModule { } diff --git a/zeppelin-web-angular/projects/helium-vis-example/src/json-visualization.ts b/zeppelin-web-angular/projects/helium-vis-example/src/json-visualization.ts new file mode 100644 index 00000000000..9f97db4598f --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/src/json-visualization.ts @@ -0,0 +1,64 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkPortalOutlet } from '@angular/cdk/portal'; +import { ComponentFactoryResolver, ViewContainerRef } from '@angular/core'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { + TableTransformation, + Transformation, + Visualization, + VisualizationComponentPortal +} from '@zeppelin/visualization'; + +import { JsonVisComponent } from './json-vis.component'; + +export class JsonVisualization extends Visualization { + tableTransformation = new TableTransformation(this.getConfig()); + componentPortal = new VisualizationComponentPortal( + this, + JsonVisComponent, + this.portalOutlet, + this.viewContainerRef, + this.componentFactoryResolver + ); + constructor(config: GraphConfig, + private portalOutlet: CdkPortalOutlet, + private viewContainerRef: ViewContainerRef, + private componentFactoryResolver?: ComponentFactoryResolver) { + super(config); + } + + destroy(): void { + if (this.componentRef) { + this.componentRef.destroy(); + this.componentRef = null; + } + this.configChange$.complete(); + this.configChange$ = null; + } + + getTransformation(): Transformation { + return this.tableTransformation; + } + + refresh(): void {} + + render(data): void { + this.transformed = data; + if (!this.componentRef) { + this.componentRef = this.componentPortal.attachComponentPortal(); + } + this.componentRef.instance.render(); + } +} diff --git a/zeppelin-web-angular/projects/helium-vis-example/src/public-api.ts b/zeppelin-web-angular/projects/helium-vis-example/src/public-api.ts new file mode 100644 index 00000000000..82ba8d0ce42 --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/src/public-api.ts @@ -0,0 +1,30 @@ +/* + * 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. + */ + +/* + * Public API Surface of helium-vis-example + */ + +import { createHeliumPackage, HeliumPackageType } from '@zeppelin/helium'; +import { JsonVisComponent } from './json-vis.component'; +import { JsonVisModule } from './json-vis.module'; +import { JsonVisualization } from './json-visualization'; + +export default createHeliumPackage({ + name: 'helium-vis-example', + id: 'heliumVisExample', + icon: 'appstore', + type: HeliumPackageType.Visualization, + module: JsonVisModule, + component: JsonVisComponent, + visualization: JsonVisualization +}); diff --git a/zeppelin-web-angular/projects/helium-vis-example/src/test.ts b/zeppelin-web-angular/projects/helium-vis-example/src/test.ts new file mode 100644 index 00000000000..9be59f628dd --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/src/test.ts @@ -0,0 +1,33 @@ +/* + * 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. + */ + +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/zone'; +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/zeppelin-web-angular/projects/helium-vis-example/tsconfig.lib.json b/zeppelin-web-angular/projects/helium-vis-example/tsconfig.lib.json new file mode 100644 index 00000000000..bd23948e591 --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/tsconfig.lib.json @@ -0,0 +1,26 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "target": "es2015", + "declaration": true, + "inlineSources": true, + "types": [], + "lib": [ + "dom", + "es2018" + ] + }, + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true, + "enableResourceInlining": true + }, + "exclude": [ + "src/test.ts", + "**/*.spec.ts" + ] +} diff --git a/zeppelin-web-angular/projects/helium-vis-example/tsconfig.spec.json b/zeppelin-web-angular/projects/helium-vis-example/tsconfig.spec.json new file mode 100644 index 00000000000..16da33db072 --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/zeppelin-web-angular/projects/helium-vis-example/tslint.json b/zeppelin-web-angular/projects/helium-vis-example/tslint.json new file mode 100644 index 00000000000..124133f8499 --- /dev/null +++ b/zeppelin-web-angular/projects/helium-vis-example/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "lib", + "camelCase" + ], + "component-selector": [ + true, + "element", + "lib", + "kebab-case" + ] + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-helium/README.md b/zeppelin-web-angular/projects/zeppelin-helium/README.md new file mode 100644 index 00000000000..16ea0ea2bd6 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/README.md @@ -0,0 +1,36 @@ + + +# ZeppelinHelium + +This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.8. + +## Code scaffolding + +Run `ng generate component component-name --project zeppelin-helium` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project zeppelin-helium`. +> Note: Don't forget to add `--project zeppelin-helium` or else it will be added to the default project in your `angular.json` file. + +## Build + +Run `ng build zeppelin-helium` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Publishing + +After building your library with `ng build zeppelin-helium`, go to the dist folder `cd dist/zeppelin-helium` and run `npm publish`. + +## Running unit tests + +Run `ng test zeppelin-helium` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## 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/zeppelin-web-angular/projects/zeppelin-helium/karma.conf.js b/zeppelin-web-angular/projects/zeppelin-helium/karma.conf.js new file mode 100644 index 00000000000..3ddb74a1a49 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/karma.conf.js @@ -0,0 +1,44 @@ +/* + * 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. + */ + +// 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/zeppelin-helium'), + 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/zeppelin-web-angular/projects/zeppelin-helium/ng-package.json b/zeppelin-web-angular/projects/zeppelin-helium/ng-package.json new file mode 100644 index 00000000000..da717624c15 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/zeppelin-helium", + "lib": { + "entryFile": "src/public-api.ts" + } +} \ No newline at end of file diff --git a/zeppelin-web-angular/projects/zeppelin-helium/package.json b/zeppelin-web-angular/projects/zeppelin-helium/package.json new file mode 100644 index 00000000000..cd0b499afa9 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/package.json @@ -0,0 +1,12 @@ +{ + "name": "@zeppelin/helium", + "version": "0.0.0", + "peerDependencies": { + "@angular/common": "~8.2.8", + "@angular/core": "~8.2.8", + "@angular/forms": "~8.2.7", + "@angular/router": "~8.2.7", + "rxjs": "~6.5.3", + "ng-zorro-antd": "^8.3.0" + } +} \ No newline at end of file diff --git a/zeppelin-web-angular/projects/zeppelin-helium/src/common-deps.ts b/zeppelin-web-angular/projects/zeppelin-helium/src/common-deps.ts new file mode 100644 index 00000000000..677b3d7d1cf --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/src/common-deps.ts @@ -0,0 +1,43 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as common from '@angular/common'; +import * as core from '@angular/core'; +import * as forms from '@angular/forms'; +import * as router from '@angular/router'; +import * as rxjs from 'rxjs'; + +import * as dataSet from '@antv/data-set'; +import * as g2 from '@antv/g2'; +import * as sdk from '@zeppelin/sdk'; +import * as visualization from '@zeppelin/visualization'; +import * as lodash from 'lodash'; + +import * as ngZorro from 'ng-zorro-antd'; +import * as tslib from 'tslib'; +import * as zeppelinHelium from './public-api'; + +export const COMMON_DEPS = { + '@angular/core': core, + '@angular/common': common, + '@angular/forms': forms, + '@angular/router': router, + '@antv/data-set': dataSet, + '@antv/g2': g2, + '@zeppelin/sdk': sdk, + '@zeppelin/visualization': visualization, + '@zeppelin/helium': zeppelinHelium, + 'lodash': lodash, + 'ng-zorro-antd': ngZorro, + rxjs, + tslib +}; diff --git a/zeppelin-web-angular/projects/zeppelin-helium/src/index.ts b/zeppelin-web-angular/projects/zeppelin-helium/src/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/src/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/projects/zeppelin-helium/src/public-api.ts b/zeppelin-web-angular/projects/zeppelin-helium/src/public-api.ts new file mode 100644 index 00000000000..4b9b89fd7db --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/src/public-api.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +/* + * Public API Surface of zeppelin-helium + */ + +export * from './zeppelin-helium.service'; +export * from './zeppelin-helium.module'; diff --git a/zeppelin-web-angular/projects/zeppelin-helium/src/test.ts b/zeppelin-web-angular/projects/zeppelin-helium/src/test.ts new file mode 100644 index 00000000000..9be59f628dd --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/src/test.ts @@ -0,0 +1,33 @@ +/* + * 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. + */ + +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/zone'; +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/zeppelin-web-angular/projects/zeppelin-helium/src/zeppelin-helium.module.ts b/zeppelin-web-angular/projects/zeppelin-helium/src/zeppelin-helium.module.ts new file mode 100644 index 00000000000..e24ac800a78 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/src/zeppelin-helium.module.ts @@ -0,0 +1,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. + */ + +import { NgModule } from '@angular/core'; + +@NgModule({}) +export class ZeppelinHeliumModule { } diff --git a/zeppelin-web-angular/projects/zeppelin-helium/src/zeppelin-helium.service.ts b/zeppelin-web-angular/projects/zeppelin-helium/src/zeppelin-helium.service.ts new file mode 100644 index 00000000000..10f8997dbf7 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/src/zeppelin-helium.service.ts @@ -0,0 +1,96 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable, Type } from '@angular/core'; +import { Visualization } from '@zeppelin/visualization'; +import { COMMON_DEPS } from './common-deps'; +import { ZeppelinHeliumModule } from './zeppelin-helium.module'; + +// tslint:disable-next-line:no-any +const SystemJs = (window as any).System; + +// tslint:disable-next-line:no-any +export class ZeppelinHeliumPackage { + constructor( + public name: string, + public id: string, + // tslint:disable-next-line:no-any + public module: Type, + // tslint:disable-next-line:no-any + public component: Type, + // tslint:disable-next-line:no-any + public visualization?: any, + public icon = 'build' + ) { + } +} + +export enum HeliumPackageType { + Visualization +} + +// tslint:disable-next-line:no-any +export function createHeliumPackage(config: { + name: string; + id: string; + icon?: string; + type: HeliumPackageType; + // tslint:disable-next-line:no-any + module: Type; + // tslint:disable-next-line:no-any + component: Type; + // tslint:disable-next-line:no-any + visualization?: any +}) { + return new ZeppelinHeliumPackage( + config.name, + config.id, + config.module, + config.component, + config.visualization, + config.icon + ); +} + +@Injectable({ + providedIn: ZeppelinHeliumModule +}) +export class ZeppelinHeliumService { + + depsDefined = false; + + constructor() { } + + defineDeps() { + if (this.depsDefined) { + return; + } + Object.keys(COMMON_DEPS).forEach(externalKey => + // tslint:disable-next-line:no-any + (window as any).define(externalKey, [], () => COMMON_DEPS[ externalKey ]) + ); + this.depsDefined = true; + } + + loadPackage(name: string): Promise { + this.defineDeps(); + return SystemJs.import(`./assets/helium-packages/${name}.umd.js`) + .then(() => SystemJs.import(name)) + .then(plugin => { + if (plugin instanceof ZeppelinHeliumPackage) { + return Promise.resolve(plugin); + } else { + throw new TypeError('This module is not a valid helium package'); + } + }); + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.lib.json b/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.lib.json new file mode 100644 index 00000000000..45b781973db --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.lib.json @@ -0,0 +1,27 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "target": "es2015", + "declaration": true, + "inlineSources": true, + "types": [], + "lib": [ + "dom", + "es2018" + ] + }, + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true, + "enableResourceInlining": true, + "flatModuleId": "@zeppelin/helium" + }, + "exclude": [ + "src/test.ts", + "**/*.spec.ts" + ] +} diff --git a/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.spec.json b/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.spec.json new file mode 100644 index 00000000000..16da33db072 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/zeppelin-web-angular/projects/zeppelin-helium/tslint.json b/zeppelin-web-angular/projects/zeppelin-helium/tslint.json new file mode 100644 index 00000000000..124133f8499 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-helium/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "lib", + "camelCase" + ], + "component-selector": [ + true, + "element", + "lib", + "kebab-case" + ] + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/README.md b/zeppelin-web-angular/projects/zeppelin-sdk/README.md new file mode 100644 index 00000000000..91a87204e35 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/README.md @@ -0,0 +1,36 @@ + + +# ZeppelinSdk + +This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.9. + +## Code scaffolding + +Run `ng generate component component-name --project zeppelin-sdk` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project zeppelin-sdk`. +> Note: Don't forget to add `--project zeppelin-sdk` or else it will be added to the default project in your `angular.json` file. + +## Build + +Run `ng build zeppelin-sdk` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Publishing + +After building your library with `ng build zeppelin-sdk`, go to the dist folder `cd dist/zeppelin-sdk` and run `npm publish`. + +## Running unit tests + +Run `ng test zeppelin-sdk` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## 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/zeppelin-web-angular/projects/zeppelin-sdk/karma.conf.js b/zeppelin-web-angular/projects/zeppelin-sdk/karma.conf.js new file mode 100644 index 00000000000..bf69ea2ebb1 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/karma.conf.js @@ -0,0 +1,44 @@ +/* + * 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. + */ + +// 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/zeppelin-sdk'), + 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/zeppelin-web-angular/projects/zeppelin-sdk/ng-package.json b/zeppelin-web-angular/projects/zeppelin-sdk/ng-package.json new file mode 100644 index 00000000000..41dc5a032d3 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/zeppelin-sdk", + "lib": { + "entryFile": "src/public-api.ts" + } +} \ No newline at end of file diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/package.json b/zeppelin-web-angular/projects/zeppelin-sdk/package.json new file mode 100644 index 00000000000..9be3b66d006 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/package.json @@ -0,0 +1,8 @@ +{ + "name": "@zeppelin/sdk", + "version": "0.0.1", + "peerDependencies": { + "@angular/common": "^8.2.9", + "@angular/core": "^8.2.9" + } +} \ No newline at end of file diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/index.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/index.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-common.interface.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-common.interface.ts new file mode 100644 index 00000000000..0a5ad6dadd5 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-common.interface.ts @@ -0,0 +1,129 @@ +/* + * 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. + */ + +export type EditorMode = + | 'ace/mode/scala' + | 'ace/mode/python' + | 'ace/mode/r' + | 'ace/mode/sql' + | 'ace/mode/markdown' + | 'ace/mode/sh'; + +export type EditorCompletionKey = 'TAB' | string; +export type EditorLanguage = 'scala' | 'python' | 'r' | 'sql' | 'markdown' | 'sh' | string; + +export interface Ticket { + principal: string; + ticket: string; + redirectURL?: string; + roles: string; +} + +export interface ConfigurationsInfo { + configurations: { + 'zeppelin.war.tempdir': string; + 'zeppelin.notebook.azure.user': string; + 'zeppelin.helium.npm.installer.url': string; + 'zeppelin.notebook.git.remote.username': string; + 'zeppelin.interpreter.remoterunner': string; + 'zeppelin.notebook.s3.user': string; + 'zeppelin.server.port': string; + 'zeppelin.plugins.dir': string; + 'zeppelin.notebook.new_format.delete_old': string; + 'zeppelin.ssl.truststore.type': string; + 'zeppelin.ssl.keystore.path': string; + 'zeppelin.notebook.s3.bucket': string; + 'zeppelin.notebook.git.remote.access-token': string; + 'zeppelin.recovery.dir': string; + 'zeppelin.notebook.s3.timeout': string; + 'zeppelin.notebook.cron.enable': string; + 'zeppelin.server.addr': string; + 'zeppelin.username.force.lowercase': string; + 'zeppelin.ssl.keystore.type': string; + 'zeppelin.ssl.truststore.path': string; + 'zeppelin.notebook.dir': string; + 'zeppelin.interpreter.lifecyclemanager.class': string; + 'zeppelin.notebook.gcs.dir': string; + 'zeppelin.notebook.s3.sse': string; + 'zeppelin.websocket.max.text.message.size': string; + 'zeppelin.notebook.git.remote.origin': string; + 'zeppelin.server.authorization.header.clear': string; + isRevisionSupported: string; + 'zeppelin.interpreter.dep.mvnRepo': string; + 'zeppelin.ssl': string; + 'zeppelin.notebook.autoInterpreterBinding': string; + 'zeppelin.config.storage.class': string; + 'zeppelin.helium.node.installer.url': string; + 'zeppelin.cluster.heartbeat.interval': string; + 'zeppelin.notebook.storage': string; + 'zeppelin.notebook.new_format.convert': string; + 'zeppelin.interpreter.dir': string; + 'zeppelin.anonymous.allowed': string; + 'zeppelin.credentials.persist': string; + 'zeppelin.notebook.mongo.uri': string; + 'zeppelin.config.fs.dir': string; + 'zeppelin.server.allowed.origins': string; + 'zeppelin.notebook.mongo.database': string; + 'zeppelin.encoding': string; + 'zeppelin.server.jetty.request.header.size': string; + 'zeppelin.search.temp.path': string; + 'zeppelin.cluster.heartbeat.timeout': string; + 'zeppelin.notebook.s3.endpoint': string; + 'zeppelin.notebook.homescreen.hide': string; + 'zeppelin.scheduler.threadpool.size': string; + 'zeppelin.notebook.azure.share': string; + 'zeppelin.helium.yarnpkg.installer.url': string; + 'zeppelin.server.strict.transport': string; + 'zeppelin.interpreter.setting': string; + 'zeppelin.server.xxss.protection': string; + 'zeppelin.server.rpc.portRange': string; + 'zeppelin.war': string; + 'zeppelin.interpreter.output.limit': string; + 'zeppelin.dep.localrepo': string; + 'zeppelin.interpreter.max.poolsize': string; + 'zeppelin.server.ssl.port': string; + 'zeppelin.notebook.mongo.collection': string; + 'zeppelin.notebook.public': string; + 'zeppelin.helium.registry': string; + 'zeppelin.server.kerberos.principal': string; + 'zeppelin.server.default.dir.allowed': string; + 'zeppelin.ssl.client.auth': string; + 'zeppelin.server.context.path': string; + 'zeppelin.recovery.storage.class': string; + 'zeppelin.notebook.default.owner.username': string; + 'zeppelin.home': string; + 'zeppelin.interpreter.lifecyclemanager.timeout.threshold': string; + 'zeppelin.cluster.addr': string; + 'zeppelin.notebook.git.remote.url': string; + 'zeppelin.notebook.mongo.autoimport': string; + 'zeppelin.notebook.one.way.sync': string; + 'zeppelin.notebook.homescreen': string; + 'zeppelin.interpreter.connect.timeout': string; + 'zeppelin.server.xframe.options': string; + 'zeppelin.interpreter.lifecyclemanager.timeout.checkinterval': string; + 'zeppelin.server.kerberos.keytab': string; + 'zeppelin.interpreter.rpc.portRange': string; + 'zeppelin.interpreter.group.default': string; + 'zeppelin.conf.dir': string; + 'zeppelin.interpreter.localRepo': string; + 'zeppelin.notebook.collaborative.mode.enable': string; + 'zeppelin.search.use.disk': string; + }; +} + +export interface ErrorInfo { + info?: string; +} + +export interface AuthInfo { + info?: string; +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-data-type-map.interface.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-data-type-map.interface.ts new file mode 100644 index 00000000000..ddf934e2433 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-data-type-map.interface.ts @@ -0,0 +1,164 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AuthInfo, ConfigurationsInfo, ErrorInfo } from './message-common.interface'; +import { + CheckpointNote, + CloneNote, + CollaborativeModeStatus, + DeleteNote, + EditorSettingReceived, + EditorSettingSend, + FolderRename, + GetInterpreterBindings, + GetNode, + ListRevision, + ListRevisionHistory, + MoveFolderToTrash, + MoveNoteToTrash, + NewNote, + Note, + NotesInfo, + NoteRename, + NoteRevision, + NoteRevisionForCompare, + NoteRunningStatus, + NoteUpdate, + NoteUpdated, + ParagraphAdded, + ParagraphMoved, + RemoveFolder, + RemoveNoteForms, + RestoreFolder, + RestoreNote, + SaveNoteFormsReceived, + SaveNoteFormsSend, + SetNoteRevision, + SetNoteRevisionStatus, + UpdateParagraph, + UpdatePersonalizedMode +} from './message-notebook.interface'; +import { + AngularObjectClientBind, + AngularObjectClientUnbind, + AngularObjectRemove, + AngularObjectUpdate, + AngularObjectUpdated, + CancelParagraph, + CommitParagraph, + Completion, + CompletionReceived, + CopyParagraph, + InsertParagraph, + MoveParagraph, + ParagraphClearAllOutput, + ParagraphClearOutput, + ParagraphRemove, + ParagraphRemoved, + ParasInfo, + PatchParagraphReceived, + PatchParagraphSend, + Progress, + RunAllParagraphs, + RunParagraph +} from './message-paragraph.interface'; + +import { ListNoteJobs, ListUpdateNoteJobs } from './message-job.interface'; + +import { InterpreterBindings, InterpreterSetting } from './message-interpreter.interface'; +import { OP } from './message-operator.interface'; + +export type MixMessageDataTypeMap = MessageSendDataTypeMap & MessageReceiveDataTypeMap; + +export interface MessageReceiveDataTypeMap { + [OP.COMPLETION_LIST]: CompletionReceived; + [OP.NOTES_INFO]: NotesInfo; + [OP.CONFIGURATIONS_INFO]: ConfigurationsInfo; + [OP.NOTE]: Note; + [OP.NOTE_REVISION]: NoteRevision; + [OP.ERROR_INFO]: ErrorInfo; + [OP.LIST_NOTE_JOBS]: ListNoteJobs; + [OP.LIST_UPDATE_NOTE_JOBS]: ListUpdateNoteJobs; + [OP.INTERPRETER_SETTINGS]: InterpreterSetting; + [OP.LIST_REVISION_HISTORY]: ListRevision; + [OP.INTERPRETER_BINDINGS]: InterpreterBindings; + [OP.COLLABORATIVE_MODE_STATUS]: CollaborativeModeStatus; + [OP.SET_NOTE_REVISION]: SetNoteRevisionStatus; + [OP.PARAGRAPH_ADDED]: ParagraphAdded; + [OP.NOTE_RUNNING_STATUS]: NoteRunningStatus; + [OP.NEW_NOTE]: NoteRevision; + [OP.SAVE_NOTE_FORMS]: SaveNoteFormsSend; + [OP.PARAGRAPH]: UpdateParagraph; + [OP.PATCH_PARAGRAPH]: PatchParagraphSend; + [OP.PARAGRAPH_REMOVED]: ParagraphRemoved; + [OP.EDITOR_SETTING]: EditorSettingReceived; + [OP.PROGRESS]: Progress; + [OP.PARAGRAPH_MOVED]: ParagraphMoved; + [OP.AUTH_INFO]: AuthInfo; + [OP.NOTE_UPDATED]: NoteUpdated; + [OP.ANGULAR_OBJECT_UPDATE]: AngularObjectUpdate; + [OP.ANGULAR_OBJECT_REMOVE]: AngularObjectRemove; + [OP.PARAS_INFO]: ParasInfo; +} + +export interface MessageSendDataTypeMap { + [OP.PING]: undefined; + [OP.LIST_CONFIGURATIONS]: undefined; + [OP.LIST_NOTES]: undefined; + [OP.GET_HOME_NOTE]: undefined; + [OP.RESTORE_ALL]: undefined; + [OP.EMPTY_TRASH]: undefined; + [OP.RELOAD_NOTES_FROM_REPO]: undefined; + [OP.GET_NOTE]: GetNode; + [OP.NEW_NOTE]: NewNote; + [OP.MOVE_NOTE_TO_TRASH]: MoveNoteToTrash; + [OP.MOVE_FOLDER_TO_TRASH]: MoveFolderToTrash; + [OP.RESTORE_NOTE]: RestoreNote; + [OP.RESTORE_FOLDER]: RestoreFolder; + [OP.REMOVE_FOLDER]: RemoveFolder; + [OP.DEL_NOTE]: DeleteNote; + [OP.CLONE_NOTE]: CloneNote; + [OP.NOTE_UPDATE]: NoteUpdate; + [OP.UPDATE_PERSONALIZED_MODE]: UpdatePersonalizedMode; + [OP.NOTE_RENAME]: NoteRename; + [OP.FOLDER_RENAME]: FolderRename; + [OP.MOVE_PARAGRAPH]: MoveParagraph; + [OP.INSERT_PARAGRAPH]: InsertParagraph; + [OP.COPY_PARAGRAPH]: CopyParagraph; + [OP.ANGULAR_OBJECT_UPDATED]: AngularObjectUpdated; + [OP.ANGULAR_OBJECT_CLIENT_BIND]: AngularObjectClientBind; + [OP.ANGULAR_OBJECT_CLIENT_UNBIND]: AngularObjectClientUnbind; + [OP.CANCEL_PARAGRAPH]: CancelParagraph; + [OP.PARAGRAPH_EXECUTED_BY_SPELL]: {}; // TODO(hsuanxyz) + [OP.RUN_PARAGRAPH]: RunParagraph; + [OP.RUN_ALL_PARAGRAPHS]: RunAllParagraphs; + [OP.PARAGRAPH_REMOVE]: ParagraphRemove; + [OP.PARAGRAPH_CLEAR_OUTPUT]: ParagraphClearOutput; + [OP.PARAGRAPH_CLEAR_ALL_OUTPUT]: ParagraphClearAllOutput; + [OP.COMPLETION]: Completion; + [OP.COMMIT_PARAGRAPH]: CommitParagraph; + [OP.PATCH_PARAGRAPH]: PatchParagraphReceived; + [OP.IMPORT_NOTE]: {}; // TODO(hsuanxyz) + [OP.CHECKPOINT_NOTE]: CheckpointNote; + [OP.SET_NOTE_REVISION]: SetNoteRevision; + [OP.LIST_REVISION_HISTORY]: ListRevisionHistory; + [OP.NOTE_REVISION]: NoteRevision; + [OP.NOTE_REVISION_FOR_COMPARE]: NoteRevisionForCompare; + [OP.EDITOR_SETTING]: EditorSettingSend; + [OP.LIST_NOTE_JOBS]: undefined; + [OP.UNSUBSCRIBE_UPDATE_NOTE_JOBS]: undefined; + [OP.LIST_UPDATE_NOTE_JOBS]: undefined; + [OP.GET_INTERPRETER_BINDINGS]: GetInterpreterBindings; + [OP.GET_INTERPRETER_SETTINGS]: undefined; + [OP.SAVE_NOTE_FORMS]: SaveNoteFormsReceived; + [OP.REMOVE_NOTE_FORMS]: RemoveNoteForms; +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-interpreter.interface.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-interpreter.interface.ts new file mode 100644 index 00000000000..c59e459410e --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-interpreter.interface.ts @@ -0,0 +1,70 @@ +/* + * 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. + */ + +export interface InterpreterSetting { + interpreterSettings: InterpreterItem[]; +} + +export interface InterpreterItem { + id: string; + name: string; + group: string; + properties: Properties; + status: string; + interpreterGroup: InterpreterGroupItem[]; + dependencies: string[]; + option: Option; +} + +export interface InterpreterBindings { + interpreterBindings: InterpreterBindingItem[]; +} + +export interface InterpreterBindingItem { + id: string; + name: string; + selected: boolean; + interpreters: InterpreterGroupItem[]; +} + +interface Properties { + [name: string]: { + name: string; + value: boolean; + type: string; + }; +} + +interface InterpreterGroupItem { + name: string; + class: string; + defaultInterpreter: boolean; + editor?: Editor; +} + +interface Editor { + language?: string; + editOnDblClick?: boolean; + completionKey?: string; + completionSupport?: boolean; +} + +interface Option { + remote: boolean; + port: number; + isExistingProcess: boolean; + setPermission: boolean; + owners: string[]; + isUserImpersonate: boolean; + perNote?: string; + perUser?: string; +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-job.interface.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-job.interface.ts new file mode 100644 index 00000000000..c59122b3a38 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-job.interface.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +export interface ListNoteJobs { + noteJobs: NoteJobs; +} + +export interface ListUpdateNoteJobs { + noteRunningJobs: NoteJobs; +} + +export interface NoteJobs { + lastResponseUnixTime: number; + jobs: JobsItem[]; +} +export interface JobsItem { + noteId: string; + noteName: string; + noteType: string; + interpreter: string; + isRunningJob: boolean; + isRemoved: boolean; + unixTimeLastRun: number; + paragraphs: JobItemParagraphItem[]; +} +export interface JobItemParagraphItem { + id: string; + name: string; + status: JobStatus; +} + +export enum JobStatus { + READY = 'READY', + FINISHED = 'FINISHED', + ABORT = 'ABORT', + ERROR = 'ERROR', + PENDING = 'PENDING', + RUNNING = 'RUNNING' +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-notebook.interface.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-notebook.interface.ts new file mode 100644 index 00000000000..f7b22de6daf --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-notebook.interface.ts @@ -0,0 +1,209 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ParagraphItem } from './message-paragraph.interface'; + +interface ID { + id: string; +} + +interface Name { + name: string; +} + +export type GetNode = ID; +export type MoveNoteToTrash = ID; +export type MoveFolderToTrash = ID; +export type RestoreNote = ID; +export type RestoreFolder = ID; +export type DeleteNote = ID; +export type RemoveFolder = ID; +export type CloneNote = ID & Name; +export type FolderRename = ID & Name; +export type PersonalizedMode = 'true' | 'false'; + +export interface NoteRename extends Name, ID { + relative: boolean; +} + +export interface SendNote { + id: string; + noteParams: NoteParams; +} + +export interface NoteUpdated { + config: NoteConfig; + info: NoteInfo; + name: string; +} + +export interface Note { + note?: { + paragraphs: ParagraphItem[]; + name: string; + id: string; + defaultInterpreterGroup: string; + noteParams: NoteParams; + noteForms: NoteForms; + angularObjects: NoteAngularObjects; + config: NoteConfig; + info: NoteInfo; + }; +} + +export interface NoteAngularObjects { + // tslint:disable-next-line no-any + [key: string]: any; +} + +export interface NoteInfo { + // tslint:disable-next-line no-any + [key: string]: any; +} + +export interface NoteParams { + // tslint:disable-next-line no-any + [key: string]: any; +} + +export interface NoteForms { + // tslint:disable-next-line no-any + [key: string]: any; +} + +export interface RemoveNoteForms { + noteId: string; + formName: string; +} + +export interface SaveNoteFormsReceived { + noteId: string; + noteParams: NoteParams; +} + +export interface GetInterpreterBindings { + noteId: string; +} + +export interface EditorSettingSend { + paragraphId: string; + magic: string; +} + +export interface EditorSettingReceived { + paragraphId: string; + editor: { + completionSupport: boolean; + editOnDblClick: boolean; + language: string; + }; +} + +export interface NoteRevisionForCompare { + noteId: string; + revisionId: string; + position: string; +} + +export interface CollaborativeModeStatus { + status: boolean; + users: string[]; +} + +export interface ParagraphMoved { + index: number; + id: string; +} + +export interface UpdateParagraph { + paragraph: ParagraphItem; +} + +export interface SaveNoteFormsSend { + formsData: { + forms: NoteForms; + params: NoteParams; + }; +} + +export interface NoteRunningStatus { + status: boolean; +} + +export interface ParagraphAdded { + index: number; + paragraph: ParagraphItem; +} + +export interface SetNoteRevisionStatus { + status: boolean; +} + +export interface ListRevision { + revisionList: RevisionListItem[]; +} + +export interface RevisionListItem { + id: string; + message: string; + time?: number; +} + +export interface NoteRevision { + note?: Note['note']; + noteId: string; + revisionId: string; +} + +export interface ListRevisionHistory { + noteId: string; +} + +export interface SetNoteRevision { + noteId: string; + revisionId: string; +} + +export interface CheckpointNote { + noteId: string; + commitMessage: string; +} + +export interface NoteUpdate extends Name, ID { + config: NoteConfig; +} + +export interface NewNote extends Name { + defaultInterpreterGroup: string; +} + +export interface NotesInfo { + notes: NotesInfoItem[]; +} + +export interface NotesInfoItem extends ID { + path: string; +} + +export interface NoteConfig { + cron?: string; + releaseresource: boolean; + cronExecutingRoles?: string; + cronExecutingUser?: string; + isZeppelinNotebookCronEnable: boolean; + looknfeel: 'report' | 'default' | 'simple'; + personalizedMode: PersonalizedMode; +} + +export interface UpdatePersonalizedMode extends ID { + personalized: PersonalizedMode; +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-operator.interface.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-operator.interface.ts new file mode 100644 index 00000000000..d3ce82b6029 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-operator.interface.ts @@ -0,0 +1,482 @@ +/* + * 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. + */ + +// tslint:disable:no-redundant-jsdoc +/** + * Representation of event type. + */ +export enum OP { + /** + * [c-s] + * load note for home screen + */ + GET_HOME_NOTE = 'GET_HOME_NOTE', + + /** + * [c-s] + * client load note + * @param id note id + */ + GET_NOTE = 'GET_NOTE', + + /** + * [s-c] + * note info + * @param note serialized SendNote object + */ + NOTE = 'NOTE', + + /** + * [s-c] + * paragraph info + * @param paragraph serialized paragraph object + */ + PARAGRAPH = 'PARAGRAPH', + + /** + * [s-c] + * progress update + * @param id paragraph id + * @param progress percentage progress + */ + PROGRESS = 'PROGRESS', + + /** + * [c-s] + * create new notebook + */ + NEW_NOTE = 'NEW_NOTE', + + /** + * [c-s] + * delete notebook + * @param id note id + */ + DEL_NOTE = 'DEL_NOTE', + REMOVE_FOLDER = 'REMOVE_FOLDER', + MOVE_NOTE_TO_TRASH = 'MOVE_NOTE_TO_TRASH', + MOVE_FOLDER_TO_TRASH = 'MOVE_FOLDER_TO_TRASH', + RESTORE_FOLDER = 'RESTORE_FOLDER', + RESTORE_NOTE = 'RESTORE_NOTE', + RESTORE_ALL = 'RESTORE_ALL', + EMPTY_TRASH = 'EMPTY_TRASH', + + /** + * [c-s] + * clone new notebook + * @param id id of note to clone + * @param name name for the cloned note + */ + CLONE_NOTE = 'CLONE_NOTE', + + /** + * [c-s] + * import notebook + * @param object notebook + */ + IMPORT_NOTE = 'IMPORT_NOTE', + NOTE_UPDATE = 'NOTE_UPDATE', + NOTE_RENAME = 'NOTE_RENAME', + + /** + * [c-s] + * update personalized mode (boolean) + * @param note id and boolean personalized mode value + */ + UPDATE_PERSONALIZED_MODE = 'UPDATE_PERSONALIZED_MODE', + FOLDER_RENAME = 'FOLDER_RENAME', + + /** + * [c-s] + * run paragraph + * @param id paragraph id + * @param paragraph paragraph content.ie. script + * @param config paragraph config + * @param params paragraph params + */ + RUN_PARAGRAPH = 'RUN_PARAGRAPH', + + /** + * [c-s] + * commit paragraph + * @param id paragraph id + * @param title paragraph title + * @param paragraph paragraph content.ie. script + * @param config paragraph config + * @param params paragraph params + */ + COMMIT_PARAGRAPH = 'COMMIT_PARAGRAPH', + + /** + * [c-s] + * cancel paragraph run + * @param id paragraph id + */ + CANCEL_PARAGRAPH = 'CANCEL_PARAGRAPH', + + /** + * [c-s] + * move paragraph order + * @param id paragraph id + * @param index index the paragraph want to go + */ + MOVE_PARAGRAPH = 'MOVE_PARAGRAPH', + + /** + * [c-s] + * create new paragraph below current paragraph + * @param target index + */ + INSERT_PARAGRAPH = 'INSERT_PARAGRAPH', + + /** + * [c-s] + * create new para below current para as a copy of current para + * @param target index + * @param title paragraph title + * @param paragraph paragraph content.ie. script + * @param config paragraph config + * @param params paragraph params + */ + COPY_PARAGRAPH = 'COPY_PARAGRAPH', + + /** + * [c-s] + * ask paragraph editor setting + * @param magic magic keyword written in paragraph + * ex) spark.spark or spark + */ + EDITOR_SETTING = 'EDITOR_SETTING', + + /** + * [c-s] + * ask completion candidates + * @param id + * @param buf current code + * @param cursor cursor position in code + */ + COMPLETION = 'COMPLETION', + + /** + * [s-c] + * send back completion candidates list + * @param id + * @param completions list of string + */ + COMPLETION_LIST = 'COMPLETION_LIST', + + /** + * [c-s] + * ask list of note + */ + LIST_NOTES = 'LIST_NOTES', + + /** + * [c-s] + * reload notes from repo + */ + RELOAD_NOTES_FROM_REPO = 'RELOAD_NOTES_FROM_REPO', + + /** + * [s-c] + * list of note infos + * @param notes serialized List object + */ + NOTES_INFO = 'NOTES_INFO', + PARAGRAPH_REMOVE = 'PARAGRAPH_REMOVE', + + /** + * [c-s] + * clear output of paragraph + */ + PARAGRAPH_CLEAR_OUTPUT = 'PARAGRAPH_CLEAR_OUTPUT', + + /** [c-s] + * clear output of all paragraphs + */ + PARAGRAPH_CLEAR_ALL_OUTPUT = 'PARAGRAPH_CLEAR_ALL_OUTPUT', + + /** + * [s-c] + * ppend output + */ + PARAGRAPH_APPEND_OUTPUT = 'PARAGRAPH_APPEND_OUTPUT', + + /** + * [s-c] + * update (replace) output + */ + PARAGRAPH_UPDATE_OUTPUT = 'PARAGRAPH_UPDATE_OUTPUT', + PING = 'PING', + AUTH_INFO = 'AUTH_INFO', + + /** + * [s-c] + * add/update angular object + */ + ANGULAR_OBJECT_UPDATE = 'ANGULAR_OBJECT_UPDATE', + + /** [s-c] + * add angular object del + */ + ANGULAR_OBJECT_REMOVE = 'ANGULAR_OBJECT_REMOVE', + + /** + * [c-s] + * angular object value updated + */ + ANGULAR_OBJECT_UPDATED = 'ANGULAR_OBJECT_UPDATED', + + /** + * [c-s] + * angular object updated from AngularJS z object + */ + ANGULAR_OBJECT_CLIENT_BIND = 'ANGULAR_OBJECT_CLIENT_BIND', + + /** + * [c-s] + * angular object unbind from AngularJS z object + */ + ANGULAR_OBJECT_CLIENT_UNBIND = 'ANGULAR_OBJECT_CLIENT_UNBIND', + + /** + * [c-s] + * ask all key/value pairs of configurations + */ + LIST_CONFIGURATIONS = 'LIST_CONFIGURATIONS', + + /** + * [s-c] + * all key/value pairs of configurations + * @param settings serialized Map object + */ + CONFIGURATIONS_INFO = 'CONFIGURATIONS_INFO', + + /** + * [c-s] + * checkpoint note to storage repository + * @param noteId + * @param checkpointName + */ + CHECKPOINT_NOTE = 'CHECKPOINT_NOTE', + + /** + * [c-s] + * list revision history of the notebook + * @param noteId + */ + LIST_REVISION_HISTORY = 'LIST_REVISION_HISTORY', + + /** + * [c-s] + * get certain revision of note + * @param noteId + * @param revisionId + */ + NOTE_REVISION = 'NOTE_REVISION', + + /** + * [c-s] + * set current notebook head to this revision + * @param noteId + * @param revisionId + */ + SET_NOTE_REVISION = 'SET_NOTE_REVISION', + + /** + * [c-s] + * get certain revision of note for compare + * @param noteId + * @param revisionId + * @param position + */ + NOTE_REVISION_FOR_COMPARE = 'NOTE_REVISION_FOR_COMPARE', + + /** + * [s-c] + * append output + */ + APP_APPEND_OUTPUT = 'APP_APPEND_OUTPUT', + + /** + * [s-c] + * update (replace) output + */ + APP_UPDATE_OUTPUT = 'APP_UPDATE_OUTPUT', + + /** + * [s-c] + * on app load + */ + APP_LOAD = 'APP_LOAD', + + /** + * [s-c] + * on app status change + */ + APP_STATUS_CHANGE = 'APP_STATUS_CHANGE', + + /** + * [s-c] + * get note job management information + */ + LIST_NOTE_JOBS = 'LIST_NOTE_JOBS', + + /** + * [c-s] + * get job management information for until unixtime + */ + LIST_UPDATE_NOTE_JOBS = 'LIST_UPDATE_NOTE_JOBS', + + /** + * [c-s] + * unsubscribe job information for job management + * @param unixTime + */ + UNSUBSCRIBE_UPDATE_NOTE_JOBS = 'UNSUBSCRIBE_UPDATE_NOTE_JOBS', + + /** + * [c-s] + * get interpreter bindings + */ + GET_INTERPRETER_BINDINGS = 'GET_INTERPRETER_BINDINGS', + + /** + * [s-c] + * interpreter bindings + */ + INTERPRETER_BINDINGS = 'INTERPRETER_BINDINGS', + + /** + * [c-s] + * get interpreter settings + */ + GET_INTERPRETER_SETTINGS = 'GET_INTERPRETER_SETTINGS', + + /** + * [s-c] + * interpreter settings + */ + INTERPRETER_SETTINGS = 'INTERPRETER_SETTINGS', + + /** + * [s-c] + * error information to be sent + */ + ERROR_INFO = 'ERROR_INFO', + + /** + * [s-c] + * error information to be sent + */ + SESSION_LOGOUT = 'SESSION_LOGOUT', + + /** + * [s-c] + * Change websocket to watcher mode. + */ + WATCHER = 'WATCHER', + + /** + * [s-c] + * paragraph is added + */ + PARAGRAPH_ADDED = 'PARAGRAPH_ADDED', + + /** + * [s-c] + * paragraph deleted + */ + PARAGRAPH_REMOVED = 'PARAGRAPH_REMOVED', + + /** + * [s-c] + * paragraph moved + */ + PARAGRAPH_MOVED = 'PARAGRAPH_MOVED', + + /** + * [s-c] + * paragraph updated(name, config) + */ + NOTE_UPDATED = 'NOTE_UPDATED', + + /** + * [c-s] + * run all paragraphs + */ + RUN_ALL_PARAGRAPHS = 'RUN_ALL_PARAGRAPHS', + + /** + * [c-s] + * paragraph was executed by spell + */ + PARAGRAPH_EXECUTED_BY_SPELL = 'PARAGRAPH_EXECUTED_BY_SPELL', + + /** + * [s-c] + * run paragraph using spell + */ + RUN_PARAGRAPH_USING_SPELL = 'RUN_PARAGRAPH_USING_SPELL', + + /** + * [s-c] + * paragraph runtime infos + */ + PARAS_INFO = 'PARAS_INFO', + + /** + * save note forms + */ + SAVE_NOTE_FORMS = 'SAVE_NOTE_FORMS', + + /** + * remove note forms + */ + REMOVE_NOTE_FORMS = 'REMOVE_NOTE_FORMS', + + /** + * [s-c] + * start to download an interpreter + */ + INTERPRETER_INSTALL_STARTED = 'INTERPRETER_INSTALL_STARTED', + + /** + * [s-c] + * Status of an interpreter installation + */ + INTERPRETER_INSTALL_RESULT = 'INTERPRETER_INSTALL_RESULT', + + /** + * [s-c] + * collaborative mode status + */ + COLLABORATIVE_MODE_STATUS = 'COLLABORATIVE_MODE_STATUS', + + /** + * [c-s][s-c] + * patch editor text + */ + PATCH_PARAGRAPH = 'PATCH_PARAGRAPH', + + /** + * [s-c] + * sequential run status will be change + */ + NOTE_RUNNING_STATUS = 'NOTE_RUNNING_STATUS', + + /** + * [s-c] + * Notice + */ + NOTICE = 'NOTICE' +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-paragraph.interface.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-paragraph.interface.ts new file mode 100644 index 00000000000..bcc01995892 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/message-paragraph.interface.ts @@ -0,0 +1,467 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { EditorCompletionKey, EditorLanguage, EditorMode } from './message-common.interface'; + +export enum DynamicFormsType { + TextBox = 'TextBox', + Password = 'Password', + Select = 'Select', + CheckBox = 'CheckBox' +} + +export interface DynamicFormsItem { + defaultValue: string | string[]; + hidden: boolean; + name: string; + type: DynamicFormsType; + argument?: string; + options?: Array<{ value: string; displayName?: string }>; +} + +export interface DynamicForms { + [key: string]: DynamicFormsItem; +} + +export interface DynamicFormParams { + [key: string]: string | string[]; +} + +export interface ParagraphEditorSetting { + language?: EditorLanguage; + editOnDblClick?: boolean; + isOutputHidden?: boolean; + completionKey?: EditorCompletionKey; + completionSupport?: boolean; + params?: DynamicFormParams; + forms?: DynamicForms; +} + +// TODO(hsuanxyz) +export interface ParagraphParams { + // tslint:disable-next-line no-any + [key: string]: any; +} + +export interface ParagraphConfigResults { + [index: string]: ParagraphConfigResult; +} + +export interface ParagraphConfigResult { + graph: GraphConfig; +} + +export interface ParagraphConfig { + editorSetting?: ParagraphEditorSetting; + colWidth?: number; + editorMode?: EditorMode; + fontSize?: number; + results?: ParagraphConfigResults; + enabled?: boolean; + tableHide?: boolean; + lineNumbers?: boolean; + editorHide?: boolean; + title?: boolean; + runOnSelectionChange?: boolean; + isZeppelinNotebookCronEnable?: boolean; +} + +export interface ParagraphResults { + code?: string; + msg?: ParagraphIResultsMsgItem[]; + + [index: number]: {}; +} + +export enum DatasetType { + NETWORK = 'NETWORK', + TABLE = 'TABLE', + HTML = 'HTML', + TEXT = 'TEXT', + ANGULAR = 'ANGULAR', + IMG = 'IMG' +} + +export class ParagraphIResultsMsgItem { + type: DatasetType = DatasetType.TEXT; + data = ''; +} + +export interface ParasInfo { + id: string; + infos: RuntimeInfos; +} + +export interface RuntimeInfos { + jobUrl: RuntimeInfosJobUrl; +} + +interface RuntimeInfosJobUrl { + propertyName: string; + label: string; + tooltip: string; + group: string; + values: RuntimeInfosValuesItem[]; + interpreterSettingId: string; +} + +interface RuntimeInfosValuesItem { + jobUrl: string; +} + +export interface ParagraphItem { + text: string; + user: string; + dateUpdated: string; + config: ParagraphConfig; + settings: ParagraphEditorSetting; + results?: ParagraphResults; + // tslint:disable-next-line no-any + apps: any[]; + progressUpdateIntervalMs: number; + jobName: string; + id: string; + dateCreated: string; + dateStarted?: string; + dateFinished?: string; + errorMessage?: string; + runtimeInfos?: RuntimeInfos; + status: string; + title?: string; + focus?: boolean; + // tslint:disable-next-line no-any TODO(hsuanxyz) + aborted: any; + // tslint:disable-next-line no-any TODO(hsuanxyz) + lineNumbers: any; + // tslint:disable-next-line no-any TODO(hsuanxyz) + fontSize: any; +} + +export interface SendParagraph { + id: string; + title?: string; + paragraph: string; + config: ParagraphConfig; + params: ParagraphParams; +} + +export interface CopyParagraph { + index: number; + title?: string; + paragraph: string; + config: ParagraphConfig; + params: ParagraphParams; +} + +export interface RunParagraph extends SendParagraph { + // tslint:disable-next-line no-any + [key: string]: any; +} + +export interface CommitParagraph extends SendParagraph { + noteId: string; +} + +export interface RunAllParagraphs { + noteId: string; + paragraphs: string; +} + +export interface InsertParagraph { + index: number; +} + +export interface MoveParagraph { + id: string; + index: number; +} + +export interface AngularObjectUpdated { + noteId: string; + paragraphId: string; + name: string; + value: string; + interpreterGroupId: string; +} + +export interface AngularObjectRemove { + noteId: string; + paragraphId: string; + name: string; +} + +export interface AngularObjectUpdate { + noteId: string; + paragraphId: string; + interpreterGroupId: string; + angularObject: { + name: string; + // tslint:disable-next-line:no-any + object: any; + noteId: string; + paragraphId: string; + }; +} + +export interface AngularObjectClientBind { + noteId: string; + name: string; + value: string; + paragraphId: string; +} + +export interface AngularObjectClientUnbind { + noteId: string; + name: string; + paragraphId: string; +} + +export interface CancelParagraph { + id: string; +} + +export interface ParagraphRemove { + id: string; +} + +export interface ParagraphClearOutput { + id: string; +} + +export interface ParagraphClearAllOutput { + id: string; +} + +export interface Completion { + id: string; + buf: string; + cursor: number; +} + +export interface CompletionItem { + meta: string; + value: string; + name: string; +} + +export interface CompletionReceived { + completions: CompletionItem[]; + id: string; +} + +export interface PatchParagraphReceived { + id: string; + noteId: string; + patch: string; +} + +export interface PatchParagraphSend { + paragraphId: string; + patch: string; +} + +export interface ParagraphRemoved { + id: string; +} + +export type VisualizationMode = + | 'table' + | 'lineChart' + | 'stackedAreaChart' + | 'multiBarChart' + | 'scatterChart' + | 'pieChart' + | string; + +export class GraphConfig { + mode: VisualizationMode = 'table'; + height = 300; + optionOpen = false; + setting: GraphConfigSetting = {}; + keys: GraphConfigKeysItem[] = []; + groups: GraphConfigGroupsItem[] = []; + values: GraphConfigValuesItem[] = []; + commonSetting: GraphConfigCommonSetting; +} + +export interface Progress { + id: string; + progress: number; +} + +interface GraphConfigSetting { + table?: VisualizationTable; + lineChart?: VisualizationLineChart; + stackedAreaChart?: VisualizationStackedAreaChart; + multiBarChart?: VisualizationMultiBarChart; + scatterChart?: VisualizationScatterChart; +} + +interface VisualizationTable { + tableGridState: TableGridState; + tableColumnTypeState: TableColumnTypeState; + updated: boolean; + initialized: boolean; + tableOptionSpecHash: string; + tableOptionValue: TableOptionValue; +} + +interface TableGridState { + columns: ColumnsItem[]; + scrollFocus: ScrollFocus; + // tslint:disable-next-line + selection: any[]; + grouping: Grouping; + treeView: TreeView; + pagination: Pagination; +} + +interface ColumnsItem { + name: string; + visible: boolean; + width: string; + sort: Sort; + filters: FiltersItem[]; + pinned: string; +} + +interface Sort { + // tslint:disable-next-line + [key: string]: any; +} + +interface FiltersItem { + // tslint:disable-next-line + [key: string]: any; +} + +interface ScrollFocus { + // tslint:disable-next-line + [key: string]: any; +} + +interface Grouping { + // tslint:disable-next-line + grouping: any[]; + // tslint:disable-next-line + aggregations: any[]; + rowExpandedStates: RowExpandedStates; +} + +interface RowExpandedStates { + // tslint:disable-next-line + [key: string]: any; +} + +interface TreeView { + // tslint:disable-next-line + [key: string]: any; +} + +interface Pagination { + paginationCurrentPage: number; + paginationPageSize: number; +} + +interface TableColumnTypeState { + updated: boolean; + names: Names; +} + +interface Names { + index: string; + value: string; + random: string; + count: string; +} + +interface TableOptionValue { + useFilter: boolean; + showPagination: boolean; + showAggregationFooter: boolean; +} + +export type XLabelStatus = 'default' | 'rotate' | 'hide'; + +export class XAxisSetting { + rotate = { degree: '-45' }; + xLabelStatus: XLabelStatus = 'default'; +} + +export class VisualizationLineChart extends XAxisSetting { + forceY = false; + lineWithFocus = false; + isDateFormat = false; + dateFormat = ''; +} + +export class VisualizationStackedAreaChart extends XAxisSetting { + style: 'stream' | 'expand' | 'stack' = 'stack'; +} + +export class VisualizationMultiBarChart extends XAxisSetting { + stacked = false; +} + +export class VisualizationScatterChart { + xAxis?: XAxis; + yAxis?: YAxis; + group?: Group; + size?: Size; +} + +interface XAxis { + name: string; + index: number; + aggr: string; +} + +interface YAxis { + name: string; + index: number; + aggr: string; +} + +interface Group { + name: string; + index: number; + aggr: string; +} + +interface Size { + name: string; + index: number; + aggr: string; +} + +interface GraphConfigKeysItem { + name: string; + index: number; + aggr: string; +} + +interface GraphConfigGroupsItem { + name: string; + index: number; + aggr: string; +} + +interface GraphConfigValuesItem { + name: string; + index: number; + aggr: string; +} + +interface GraphConfigCommonSetting { + // tslint:disable-next-line + [key: string]: any; +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/public-api.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/public-api.ts new file mode 100644 index 00000000000..4160fa7f035 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/public-api.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +export * from './message-common.interface'; +export * from './message-data-type-map.interface'; +export * from './message-notebook.interface'; +export * from './message-operator.interface'; +export * from './message-paragraph.interface'; +export * from './websocket-message.interface'; +export * from './message-job.interface'; +export * from './message-interpreter.interface'; diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/websocket-message.interface.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/websocket-message.interface.ts new file mode 100644 index 00000000000..bdc71e1f428 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/interfaces/websocket-message.interface.ts @@ -0,0 +1,21 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { MixMessageDataTypeMap } from './message-data-type-map.interface'; + +export interface WebSocketMessage { + op: K; + data?: MixMessageDataTypeMap[K]; + ticket?: string; // default 'anonymous' + principal?: string; // default 'anonymous' + roles?: string; // default '[]' +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/message.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/message.ts new file mode 100644 index 00000000000..65ceec605de --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/message.ts @@ -0,0 +1,502 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { interval, Observable, Subject, Subscription } from 'rxjs'; +import { delay, filter, map, mergeMap, retryWhen, take } from 'rxjs/operators'; +import { webSocket, WebSocketSubject } from 'rxjs/webSocket'; + +import { Ticket } from './interfaces/message-common.interface'; +import { + MessageReceiveDataTypeMap, + MessageSendDataTypeMap, + MixMessageDataTypeMap +} from './interfaces/message-data-type-map.interface'; +import { NoteConfig, PersonalizedMode, SendNote } from './interfaces/message-notebook.interface'; +import { OP } from './interfaces/message-operator.interface'; +import { ParagraphConfig, ParagraphParams, SendParagraph } from './interfaces/message-paragraph.interface'; +import { WebSocketMessage } from './interfaces/websocket-message.interface'; + +export type ArgumentsType = T extends (...args: infer U) => void ? U : never; + +export type SendArgumentsType = MessageSendDataTypeMap[K] extends undefined + ? ArgumentsType<(op: K) => void> + : ArgumentsType<(op: K, data: MessageSendDataTypeMap[K]) => void>; + +export type ReceiveArgumentsType< + K extends keyof MessageReceiveDataTypeMap +> = MessageReceiveDataTypeMap[K] extends undefined ? () => void : (data?: MessageReceiveDataTypeMap[K]) => void; + +export class Message { + public connectedStatus = false; + public connectedStatus$ = new Subject(); + private ws: WebSocketSubject>; + private open$ = new Subject(); + private close$ = new Subject(); + private sent$ = new Subject>(); + private received$ = new Subject>(); + private pingIntervalSubscription = new Subscription(); + private wsUrl: string; + private ticket: Ticket; + + constructor() { + this.open$.subscribe(() => { + this.connectedStatus = true; + this.connectedStatus$.next(this.connectedStatus); + this.pingIntervalSubscription.unsubscribe(); + this.pingIntervalSubscription = interval(1000 * 10).subscribe(() => this.ping()); + }); + this.close$.subscribe(() => { + this.connectedStatus = false; + this.connectedStatus$.next(this.connectedStatus); + this.pingIntervalSubscription.unsubscribe(); + }); + } + + bootstrap(ticket: Ticket, wsUrl: string) { + this.setTicket(ticket); + this.setWsUrl(wsUrl); + this.connect(); + } + + getWsInstance(): WebSocketSubject> { + return this.ws; + } + + setWsUrl(wsUrl: string): void { + this.wsUrl = wsUrl; + } + + setTicket(ticket: Ticket): void { + this.ticket = ticket; + } + + interceptReceived( + data: WebSocketMessage + ): WebSocketMessage { + return data; + } + + connect() { + this.ws = webSocket({ + url: this.wsUrl, + openObserver: this.open$, + closeObserver: this.close$ + }); + + this.ws + .pipe( + // reconnect + retryWhen(errors => + errors.pipe( + mergeMap(() => + this.close$.pipe( + take(1), + delay(4000) + ) + ) + ) + ) + ) + .subscribe((e: WebSocketMessage) => { + console.log('Receive:', e); + this.received$.next(this.interceptReceived(e)); + }); + } + + ping() { + this.send(OP.PING); + } + + opened(): Observable { + return this.open$.asObservable(); + } + + closed(): Observable { + return this.close$.asObservable(); + } + + sent(): Observable> { + return this.sent$.asObservable(); + } + + received(): Observable> { + return this.received$.asObservable(); + } + + send(...args: SendArgumentsType): void { + const [op, data] = args; + const message: WebSocketMessage = { + op, + data: data as MixMessageDataTypeMap[K], + ...this.ticket + }; + console.log('Send:', message); + + this.ws.next(message); + this.sent$.next(message); + } + + receive(op: K): Observable[K]> { + return this.received$.pipe( + filter(message => message.op === op), + map(message => message.data) + ) as Observable[K]>; + } + + destroy(): void { + this.ws.complete(); + this.ws = null; + } + + getHomeNote(): void { + this.send(OP.GET_HOME_NOTE); + } + + newNote(noteName: string, defaultInterpreterGroup: string): void { + this.send(OP.NEW_NOTE, { + name: noteName, + defaultInterpreterGroup + }); + } + + moveNoteToTrash(noteId: string): void { + this.send(OP.MOVE_NOTE_TO_TRASH, { + id: noteId + }); + } + + restoreNote(noteId: string): void { + this.send(OP.RESTORE_NOTE, { + id: noteId + }); + } + + deleteNote(noteId): void { + this.send(OP.DEL_NOTE, { + id: noteId + }); + } + + restoreFolder(folderPath: string): void { + this.send(OP.RESTORE_FOLDER, { + id: folderPath + }); + } + + removeFolder(folderPath: string): void { + this.send(OP.REMOVE_FOLDER, { + id: folderPath + }); + } + + moveFolderToTrash(folderPath: string): void { + this.send(OP.MOVE_FOLDER_TO_TRASH, { + id: folderPath + }); + } + + restoreAll(): void { + this.send(OP.RESTORE_ALL); + } + + emptyTrash(): void { + this.send(OP.EMPTY_TRASH); + } + + cloneNote(noteIdToClone, newNoteName): void { + this.send(OP.CLONE_NOTE, { id: noteIdToClone, name: newNoteName }); + } + + /** + * get nodes list + */ + listNodes(): void { + this.send(OP.LIST_NOTES); + } + + reloadAllNotesFromRepo(): void { + this.send(OP.RELOAD_NOTES_FROM_REPO); + } + + getNote(noteId: string): void { + this.send(OP.GET_NOTE, { id: noteId }); + } + + updateNote(noteId: string, noteName: string, noteConfig: NoteConfig): void { + this.send(OP.NOTE_UPDATE, { id: noteId, name: noteName, config: noteConfig }); + } + + updatePersonalizedMode(noteId: string, modeValue: PersonalizedMode): void { + this.send(OP.UPDATE_PERSONALIZED_MODE, { id: noteId, personalized: modeValue }); + } + + noteRename(noteId: string, noteName: string, relative: boolean): void { + this.send(OP.NOTE_RENAME, { id: noteId, name: noteName, relative: relative }); + } + + folderRename(folderId: string, folderPath: string): void { + this.send(OP.FOLDER_RENAME, { id: folderId, name: folderPath }); + } + + moveParagraph(paragraphId: string, newIndex: number): void { + this.send(OP.MOVE_PARAGRAPH, { id: paragraphId, index: newIndex }); + } + + insertParagraph(newIndex: number): void { + this.send(OP.INSERT_PARAGRAPH, { index: newIndex }); + } + + copyParagraph( + newIndex: number, + paragraphTitle: string, + paragraphData: string, + paragraphConfig: ParagraphConfig, + paragraphParams: ParagraphParams + ): void { + this.send(OP.COPY_PARAGRAPH, { + index: newIndex, + title: paragraphTitle, + paragraph: paragraphData, + config: paragraphConfig, + params: paragraphParams + }); + } + + angularObjectUpdate( + noteId: string, + paragraphId: string, + name: string, + value: string, + interpreterGroupId: string + ): void { + this.send(OP.ANGULAR_OBJECT_UPDATED, { + noteId: noteId, + paragraphId: paragraphId, + name: name, + value: value, + interpreterGroupId: interpreterGroupId + }); + } + + // tslint:disable-next-line:no-any + angularObjectClientBind(noteId: string, name: string, value: any, paragraphId: string): void { + this.send(OP.ANGULAR_OBJECT_CLIENT_BIND, { + noteId: noteId, + name: name, + value: value, + paragraphId: paragraphId + }); + } + + angularObjectClientUnbind(noteId: string, name: string, paragraphId: string): void { + this.send(OP.ANGULAR_OBJECT_CLIENT_UNBIND, { + noteId: noteId, + name: name, + paragraphId: paragraphId + }); + } + + cancelParagraph(paragraphId): void { + this.send(OP.CANCEL_PARAGRAPH, { id: paragraphId }); + } + + paragraphExecutedBySpell( + paragraphId, + paragraphTitle, + paragraphText, + paragraphResultsMsg, + paragraphStatus, + paragraphErrorMessage, + paragraphConfig, + paragraphParams, + paragraphDateStarted, + paragraphDateFinished + ): void { + this.send(OP.PARAGRAPH_EXECUTED_BY_SPELL, { + id: paragraphId, + title: paragraphTitle, + paragraph: paragraphText, + results: { + code: paragraphStatus, + msg: paragraphResultsMsg.map(dataWithType => { + const serializedData = dataWithType.data; + return { type: dataWithType.type, serializedData }; + }) + }, + status: paragraphStatus, + errorMessage: paragraphErrorMessage, + config: paragraphConfig, + params: paragraphParams, + dateStarted: paragraphDateStarted, + dateFinished: paragraphDateFinished + }); + } + + runParagraph( + paragraphId: string, + paragraphTitle: string, + paragraphData: string, + paragraphConfig: ParagraphConfig, + paragraphParams: ParagraphParams + ): void { + this.send(OP.RUN_PARAGRAPH, { + id: paragraphId, + title: paragraphTitle, + paragraph: paragraphData, + config: paragraphConfig, + params: paragraphParams + }); + } + + runAllParagraphs(noteId: string, paragraphs: SendParagraph[]): void { + this.send(OP.RUN_ALL_PARAGRAPHS, { + noteId: noteId, + paragraphs: JSON.stringify(paragraphs) + }); + } + + paragraphRemove(paragraphId: string): void { + this.send(OP.PARAGRAPH_REMOVE, { id: paragraphId }); + } + + paragraphClearOutput(paragraphId: string): void { + this.send(OP.PARAGRAPH_CLEAR_OUTPUT, { id: paragraphId }); + } + + paragraphClearAllOutput(noteId: string): void { + this.send(OP.PARAGRAPH_CLEAR_ALL_OUTPUT, { id: noteId }); + } + + completion(paragraphId: string, buf: string, cursor: number): void { + this.send(OP.COMPLETION, { + id: paragraphId, + buf: buf, + cursor: cursor + }); + } + + commitParagraph( + paragraphId: string, + paragraphTitle: string, + paragraphData: string, + paragraphConfig: ParagraphConfig, + paragraphParams: ParagraphConfig, + noteId: string + ): void { + return this.send(OP.COMMIT_PARAGRAPH, { + id: paragraphId, + noteId: noteId, + title: paragraphTitle, + paragraph: paragraphData, + config: paragraphConfig, + params: paragraphParams + }); + } + + patchParagraph(paragraphId: string, noteId: string, patch: string): void { + // javascript add "," if change contains several patches + // but java library requires patch list without "," + const normalPatch = patch.replace(/,@@/g, '@@'); + return this.send(OP.PATCH_PARAGRAPH, { + id: paragraphId, + noteId: noteId, + patch: normalPatch + }); + } + + importNote(note: SendNote): void { + this.send(OP.IMPORT_NOTE, { + note: note + }); + } + + checkpointNote(noteId: string, commitMessage: string): void { + this.send(OP.CHECKPOINT_NOTE, { + noteId: noteId, + commitMessage: commitMessage + }); + } + + setNoteRevision(noteId: string, revisionId: string): void { + this.send(OP.SET_NOTE_REVISION, { + noteId: noteId, + revisionId: revisionId + }); + } + + listRevisionHistory(noteId: string): void { + this.send(OP.LIST_REVISION_HISTORY, { + noteId: noteId + }); + } + + noteRevision(noteId: string, revisionId: string): void { + this.send(OP.NOTE_REVISION, { + noteId: noteId, + revisionId: revisionId + }); + } + + noteRevisionForCompare(noteId: string, revisionId: string, position: string): void { + this.send(OP.NOTE_REVISION_FOR_COMPARE, { + noteId: noteId, + revisionId: revisionId, + position: position + }); + } + + editorSetting(paragraphId: string, replName: string): void { + this.send(OP.EDITOR_SETTING, { + paragraphId: paragraphId, + magic: replName + }); + } + + listNoteJobs(): void { + this.send(OP.LIST_NOTE_JOBS); + } + + unsubscribeUpdateNoteJobs(): void { + this.send(OP.UNSUBSCRIBE_UPDATE_NOTE_JOBS); + } + + getInterpreterBindings(noteId: string): void { + this.send(OP.GET_INTERPRETER_BINDINGS, { noteId: noteId }); + } + + saveInterpreterBindings(noteId, selectedSettingIds): void { + // this.send(OP.SAVE_INTERPRETER_BINDINGS, + // {noteId: noteId, selectedSettingIds: selectedSettingIds}); + } + + listConfigurations(): void { + this.send(OP.LIST_CONFIGURATIONS); + } + + getInterpreterSettings(): void { + this.send(OP.GET_INTERPRETER_SETTINGS); + } + + saveNoteForms(note: SendNote): void { + this.send(OP.SAVE_NOTE_FORMS, { + noteId: note.id, + noteParams: note.noteParams + }); + } + + removeNoteForms(note, formName): void { + this.send(OP.REMOVE_NOTE_FORMS, { + noteId: note.id, + formName: formName + }); + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/src/public-api.ts b/zeppelin-web-angular/projects/zeppelin-sdk/src/public-api.ts new file mode 100644 index 00000000000..c5417873004 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/src/public-api.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +export * from './message'; +// https://github.com/ng-packagr/ng-packagr/issues/1093 +export * from './interfaces/public-api'; diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.lib.json b/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.lib.json new file mode 100644 index 00000000000..784751866f8 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.lib.json @@ -0,0 +1,27 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "target": "es2015", + "declaration": true, + "inlineSources": true, + "types": [], + "lib": [ + "dom", + "es2018" + ] + }, + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true, + "enableResourceInlining": true, + "flatModuleId": "@zeppelin/sdk" + }, + "exclude": [ + "src/test.ts", + "**/*.spec.ts" + ] +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.spec.json b/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.spec.json new file mode 100644 index 00000000000..16da33db072 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/zeppelin-web-angular/projects/zeppelin-sdk/tslint.json b/zeppelin-web-angular/projects/zeppelin-sdk/tslint.json new file mode 100644 index 00000000000..124133f8499 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-sdk/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "lib", + "camelCase" + ], + "component-selector": [ + true, + "element", + "lib", + "kebab-case" + ] + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/README.md b/zeppelin-web-angular/projects/zeppelin-visualization/README.md new file mode 100644 index 00000000000..aa8e560c926 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/README.md @@ -0,0 +1,36 @@ + + +# ZeppelinVisualization + +This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.8. + +## Code scaffolding + +Run `ng generate component component-name --project zeppelin-visualization` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project zeppelin-visualization`. +> Note: Don't forget to add `--project zeppelin-visualization` or else it will be added to the default project in your `angular.json` file. + +## Build + +Run `ng build zeppelin-visualization` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Publishing + +After building your library with `ng build zeppelin-visualization`, go to the dist folder `cd dist/zeppelin-visualization` and run `npm publish`. + +## Running unit tests + +Run `ng test zeppelin-visualization` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## 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/zeppelin-web-angular/projects/zeppelin-visualization/karma.conf.js b/zeppelin-web-angular/projects/zeppelin-visualization/karma.conf.js new file mode 100644 index 00000000000..e04c06a8f52 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/karma.conf.js @@ -0,0 +1,44 @@ +/* + * 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. + */ + +// 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/zeppelin-visualization'), + 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/zeppelin-web-angular/projects/zeppelin-visualization/ng-package.json b/zeppelin-web-angular/projects/zeppelin-visualization/ng-package.json new file mode 100644 index 00000000000..78b3ecf185e --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/zeppelin-visualization", + "lib": { + "entryFile": "src/public-api.ts" + } +} \ No newline at end of file diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/package.json b/zeppelin-web-angular/projects/zeppelin-visualization/package.json new file mode 100644 index 00000000000..1d4232be543 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/package.json @@ -0,0 +1,8 @@ +{ + "name": "@zeppelin/visualization", + "version": "0.0.1", + "peerDependencies": { + "@angular/common": "^8.2.8", + "@angular/core": "^8.2.8" + } +} \ No newline at end of file diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/data-set.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/data-set.ts new file mode 100644 index 00000000000..98d4632fcab --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/data-set.ts @@ -0,0 +1,17 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ParagraphIResultsMsgItem } from '@zeppelin/sdk'; + +export abstract class DataSet { + abstract loadParagraphResult(paragraphResult: ParagraphIResultsMsgItem): void; +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/g2-visualization-base.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/g2-visualization-base.ts new file mode 100644 index 00000000000..d663788be0e --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/g2-visualization-base.ts @@ -0,0 +1,57 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { GraphConfig } from '@zeppelin/sdk'; + +import { G2VisualizationComponentBase } from './g2-visualization-component-base'; +import { PivotTransformation } from './pivot-transformation'; +import { Transformation } from './transformation'; +import { Visualization } from './visualization'; +import { VisualizationComponentPortal } from './visualization-component-portal'; + +export abstract class G2VisualizationBase extends Visualization { + pivot = new PivotTransformation(this.getConfig()); + abstract componentPortal: VisualizationComponentPortal; + + constructor(config: GraphConfig) { + super(config); + } + + destroy(): void { + if (this.componentRef) { + this.componentRef.destroy(); + this.componentRef = null; + } + this.configChange$.complete(); + this.configChange$ = null; + } + + getTransformation(): Transformation { + return this.pivot; + } + + refresh(): void { + if (this.componentRef) { + this.componentRef.instance.refresh(); + } + } + + render(data): void { + this.transformed = data; + if (this.componentRef) { + this.componentRef.instance.refreshSetting(); + this.componentRef.instance.render(); + } else { + this.componentRef = this.componentPortal.attachComponentPortal(); + } + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/g2-visualization-component-base.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/g2-visualization-component-base.ts new file mode 100644 index 00000000000..8e52dcdc9de --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/g2-visualization-component-base.ts @@ -0,0 +1,93 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ElementRef, OnDestroy } from '@angular/core'; + +import * as G2 from '@antv/g2'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { Visualization } from './visualization'; + +export abstract class G2VisualizationComponentBase implements OnDestroy { + abstract container: ElementRef; + chart: G2.Chart; + config: GraphConfig; + + constructor(public visualization: Visualization) {} + + abstract renderBefore(chart: G2.Chart): void; + + abstract refreshSetting(): void; + abstract setScale(): void; + + render() { + this.config = this.visualization.getConfig(); + this.refreshSetting(); + this.initChart(); + this.chart.source(this.visualization.transformed); + this.renderBefore(this.chart); + this.chart.render(); + this.renderAfter(); + } + + renderAfter(): void {} + + getKey(): string { + let key = ''; + if (this.config.keys && this.config.keys[0]) { + key = this.config.keys[0].name; + } + return key; + } + + refresh(): void { + this.config = this.visualization.getConfig(); + this.chart.changeHeight(this.config.height || 400); + setTimeout(() => { + this.setScale(); + this.chart.forceFit(); + }); + } + + initChart() { + if (this.chart) { + this.chart.clear(); + } else { + if (this.container && this.container.nativeElement) { + this.chart = new G2.Chart({ + forceFit: true, + container: this.container.nativeElement, + height: this.config.height || 400, + padding: { + top: 80, + left: 50, + right: 50, + bottom: 50 + } + }); + this.chart.legend({ + position: 'top-right' + // tslint:disable-next-line + } as any); + } else { + throw new Error(`Can't find the container, Please make sure on correct assignment.`); + } + } + } + + ngOnDestroy(): void { + if (this.chart) { + this.chart.destroy(); + this.chart = null; + } + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/index.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/pivot-transformation.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/pivot-transformation.ts new file mode 100644 index 00000000000..cade722cd81 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/pivot-transformation.ts @@ -0,0 +1,199 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DataSet } from '@antv/data-set'; +import { get } from 'lodash'; + +import { TableData } from './table-data'; +import { Transformation } from './transformation'; + +// tslint:disable-next-line:no-any +export class PivotTransformation extends Transformation { + constructor(config) { + super(config); + } + + removeUnknown(array: Array<{ name: string }>, tableData: TableData): void { + for (let i = 0; i < array.length; i++) { + // remove non existing column + let found = false; + for (let j = 0; j < tableData.columns.length; j++) { + const a = array[i]; + const b = tableData.columns[j]; + if (a.name === b) { + found = true; + break; + } + } + if (!found) { + array.splice(i, 1); + i--; + } + } + } + + setDefaultConfig(tableData: TableData) { + const config = this.getConfig(); + config.keys = config.keys || []; + config.groups = config.groups || []; + config.values = config.values || []; + this.removeUnknown(config.keys, tableData); + this.removeUnknown(config.values, tableData); + this.removeUnknown(config.groups, tableData); + if (config.keys.length === 0 && config.groups.length === 0 && config.values.length === 0) { + if (config.keys.length === 0 && tableData.columns[0]) { + config.keys = [ + { + name: tableData.columns[0], + index: 0, + aggr: 'sum' + } + ]; + } + + if (config.values.length === 0 && tableData.columns[1]) { + config.values = [ + { + name: tableData.columns[1], + index: 1, + aggr: 'sum' + } + ]; + } + } + } + + // tslint:disable-next-line:no-any + transform(tableData: TableData): any { + const config = this.getConfig(); + this.setDefaultConfig(tableData); + const ds = new DataSet(); + let dv = ds.createView().source(tableData.rows); + + let firstKey = ''; + if (config.keys && config.keys[0]) { + firstKey = config.keys[0].name; + } + let keys = []; + let groups = []; + let values = []; + let aggregates = []; + if (config.mode !== 'scatterChart') { + keys = config.keys.map(e => e.name); + groups = config.groups.map(e => e.name); + values = config.values.map(v => `${v.name}(${v.aggr})`); + aggregates = config.values.map(v => (v.aggr === 'avg' ? 'mean' : v.aggr)); + } else { + const xAxis = get(config.setting, 'scatterChart.xAxis.name', tableData.columns[0]); + const yAxis = get(config.setting, 'scatterChart.yAxis.name', tableData.columns[1]); + const group = get(config.setting, 'scatterChart.group.name'); + keys = xAxis ? [xAxis] : []; + values = yAxis ? [yAxis] : []; + groups = group ? [group] : []; + } + + dv.transform({ + type: 'map', + callback: row => { + Object.keys(row).forEach(k => { + if (config.keys.map(e => e.name).indexOf(k) === -1) { + const numberValue = Number.parseFloat(row[k]); + row[k] = Number.isFinite(numberValue) ? numberValue : row[k]; + } + }); + return row; + } + }); + + if (config.mode !== 'scatterChart') { + dv.transform({ + type: 'aggregate', + fields: config.values.map(v => v.name), + operations: aggregates, + as: values, + groupBy: [...keys, ...groups] + }); + + // dv.transform({ + // type: 'fill-rows', + // groupBy: groups, + // orderBy: keys, + // fillBy: 'order' + // }); + + dv.transform({ + type: 'fill-rows', + groupBy: [...keys, ...groups], + fillBy: 'group' + }); + + config.values + .map(v => `${v.name}(${v.aggr})`) + .forEach(field => { + dv.transform({ + field, + type: 'impute', + groupBy: keys, + method: 'value', + value: config.mode === 'stackedAreaChart' ? 0 : null + }); + }); + } + + dv.transform({ + type: 'fold', + fields: values, + key: '__key__', + value: '__value__' + }); + + dv.transform({ + type: 'partition', + groupBy: groups + }); + + const groupsData = []; + Object.keys(dv.rows).forEach(groupKey => { + const groupName = groupKey.replace(/^_/, ''); + dv.rows[groupKey].forEach(row => { + groupsData.push({ + ...row, + __key__: groupName ? `${row.__key__}.${groupName}` : row.__key__ + }); + }); + }); + + groupsData.sort( + (a, b) => + dv.origin.findIndex(o => o[firstKey] === a[firstKey]) - dv.origin.findIndex(o => o[firstKey] === b[firstKey]) + ); + + dv = ds + .createView({ + state: { + filterData: null + } + }) + .source(groupsData); + + if (config.mode === 'stackedAreaChart' || config.mode === 'pieChart') { + dv.transform({ + type: 'percent', + field: '__value__', + dimension: '__key__', + groupBy: keys, + as: '__percent__' + }); + } + return dv; + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/public-api.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/public-api.ts new file mode 100644 index 00000000000..c28b0e2a649 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/public-api.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +/* + * Public API Surface of zeppelin-visualization + */ + +export * from './data-set'; +export * from './transformation'; +export * from './visualization-component-portal'; +export * from './visualization'; +export * from './table-data'; +export * from './table-transformation'; +export * from './pivot-transformation'; +export * from './g2-visualization-base'; +export * from './g2-visualization-component-base'; diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/table-data.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/table-data.ts new file mode 100644 index 00000000000..f0bd5ad4227 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/table-data.ts @@ -0,0 +1,35 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DataSet as AntvDataSet } from '@antv/data-set'; + +import { DatasetType, ParagraphIResultsMsgItem } from '@zeppelin/sdk'; +import { DataSet } from './data-set'; + +export class TableData extends DataSet { + columns: string[] = []; + // tslint:disable-next-line + rows: any[] = []; + + loadParagraphResult({ data, type }: ParagraphIResultsMsgItem): void { + if (type !== DatasetType.TABLE) { + console.error('Can not load paragraph result'); + return; + } + const ds = new AntvDataSet(); + const dv = ds.createView().source(data, { + type: 'tsv' + }); + this.columns = dv.origin && dv.origin.columns ? dv.origin.columns : []; + this.rows = dv.rows || []; + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/table-transformation.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/table-transformation.ts new file mode 100644 index 00000000000..19111ecad88 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/table-transformation.ts @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TableData } from './table-data'; +import { Transformation } from './transformation'; + +// tslint:disable-next-line:no-any +export class TableTransformation extends Transformation { + constructor(config) { + super(config); + } + + // tslint:disable-next-line:no-any + transform(tableData: TableData): any { + return tableData; + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/transformation.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/transformation.ts new file mode 100644 index 00000000000..522ac021326 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/transformation.ts @@ -0,0 +1,46 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { GraphConfig } from '@zeppelin/sdk'; + +import { DataSet } from './data-set'; + +export interface Setting { + // tslint:disable-next-line:no-any + template: any; + // tslint:disable-next-line:no-any + scope: any; +} + +export abstract class Transformation { + dataset: DataSet; + constructor(private config: GraphConfig) {} + + // tslint:disable-next-line:no-any + abstract transform(tableData): any; + + setConfig(config) { + this.config = config; + } + + setTableData(dataset: DataSet) { + this.dataset = dataset; + } + + getTableData(): DataSet { + return this.dataset; + } + + getConfig() { + return this.config; + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/visualization-component-portal.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/visualization-component-portal.ts new file mode 100644 index 00000000000..a9418d98307 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/visualization-component-portal.ts @@ -0,0 +1,46 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkPortalOutlet, ComponentPortal, ComponentType, PortalInjector } from '@angular/cdk/portal'; +import { ComponentFactoryResolver, InjectionToken, ViewContainerRef } from '@angular/core'; + +import { Visualization } from './visualization'; + +export const VISUALIZATION = new InjectionToken('Visualization'); + +export class VisualizationComponentPortal { + constructor( + private visualization: T, + private component: ComponentType, + private portalOutlet: CdkPortalOutlet, + private viewContainerRef: ViewContainerRef, + private componentFactoryResolver?: ComponentFactoryResolver + ) {} + + createInjector() { + const userInjector = this.viewContainerRef && this.viewContainerRef.injector; + // tslint:disable-next-line + const injectionTokens = new WeakMap([[VISUALIZATION, this.visualization]]); + return new PortalInjector(userInjector, injectionTokens); + } + + getComponentPortal() { + const injector = this.createInjector(); + return new ComponentPortal(this.component, null, injector, this.componentFactoryResolver); + } + + attachComponentPortal() { + const componentRef = this.portalOutlet.attachComponentPortal(this.getComponentPortal()); + componentRef.changeDetectorRef.markForCheck(); + return componentRef; + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/src/visualization.ts b/zeppelin-web-angular/projects/zeppelin-visualization/src/visualization.ts new file mode 100644 index 00000000000..bb483e58766 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/src/visualization.ts @@ -0,0 +1,44 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentRef } from '@angular/core'; +import { Subject } from 'rxjs'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { Transformation } from './transformation'; + +// tslint:disable-next-line +export abstract class Visualization { + // tslint:disable-next-line + transformed: any; + componentRef: ComponentRef; + configChange$ = new Subject(); + constructor(private config: GraphConfig) {} + + abstract getTransformation(): Transformation; + abstract render(tableData): void; + abstract refresh(): void; + abstract destroy(): void; + + configChanged() { + return this.configChange$.asObservable(); + } + + setConfig(config: GraphConfig) { + this.config = config; + this.refresh(); + } + + getConfig() { + return this.config; + } +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.lib.json b/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.lib.json new file mode 100644 index 00000000000..15689086f6e --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.lib.json @@ -0,0 +1,27 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "target": "es2015", + "declaration": true, + "inlineSources": true, + "types": [], + "lib": [ + "dom", + "es2018" + ] + }, + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true, + "enableResourceInlining": true, + "flatModuleId": "@zeppelin/visualization" + }, + "exclude": [ + "src/test.ts", + "**/*.spec.ts" + ] +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.spec.json b/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.spec.json new file mode 100644 index 00000000000..16da33db072 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/zeppelin-web-angular/projects/zeppelin-visualization/tslint.json b/zeppelin-web-angular/projects/zeppelin-visualization/tslint.json new file mode 100644 index 00000000000..124133f8499 --- /dev/null +++ b/zeppelin-web-angular/projects/zeppelin-visualization/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "lib", + "camelCase" + ], + "component-selector": [ + true, + "element", + "lib", + "kebab-case" + ] + } +} diff --git a/zeppelin-web-angular/proxy.conf.js b/zeppelin-web-angular/proxy.conf.js new file mode 100644 index 00000000000..c3d571ce3e5 --- /dev/null +++ b/zeppelin-web-angular/proxy.conf.js @@ -0,0 +1,59 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const dotenv = require('dotenv'); +const HttpsProxyAgent = require('https-proxy-agent'); +dotenv.config(); + +const proxyConfig = [ + { + context: ['/'], + target: 'http://localhost:8080', + secure: false, + changeOrigin: true + }, + { + context: '/ws', + target: 'ws://localhost:8080', + secure: false, + ws:true, + changeOrigin: true + } +]; + +function httpUrlToWSUrl(url) { + return url.replace(/(http)(s)?\:\/\//, "ws$2://"); +} + +function setupForCorporateProxy(proxyConfig) { + const proxyServer = process.env.SERVER_PROXY; + const httpProxy = process.env.HTTP_PROXY; + if (proxyServer) { + let agent = null; + if (httpProxy) { + agent = new HttpsProxyAgent(httpProxy); + } + proxyConfig.forEach(function(entry) { + if (entry.context === '/ws') { + entry.target = httpUrlToWSUrl(proxyServer) + } else { + entry.target = proxyServer; + } + if (agent) { + entry.agent = agent; + } + }); + } + return proxyConfig; +} + +module.exports = setupForCorporateProxy(proxyConfig); diff --git a/zeppelin-web-angular/screenshot.png b/zeppelin-web-angular/screenshot.png new file mode 100644 index 00000000000..4c157c5fdef Binary files /dev/null and b/zeppelin-web-angular/screenshot.png differ diff --git a/zeppelin-web-angular/src/.editorconfig b/zeppelin-web-angular/src/.editorconfig new file mode 100644 index 00000000000..8b14efe23aa --- /dev/null +++ b/zeppelin-web-angular/src/.editorconfig @@ -0,0 +1,12 @@ +# Editor configuration, see https://editorconfig.org + +[*] +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/zeppelin-web-angular/src/.gitignore b/zeppelin-web-angular/src/.gitignore new file mode 100644 index 00000000000..85158b7a442 --- /dev/null +++ b/zeppelin-web-angular/src/.gitignore @@ -0,0 +1,43 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp +/out-tsc + +# 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 + +# 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/zeppelin-web-angular/src/app/app-http.interceptor.ts b/zeppelin-web-angular/src/app/app-http.interceptor.ts new file mode 100644 index 00000000000..520eea89418 --- /dev/null +++ b/zeppelin-web-angular/src/app/app-http.interceptor.ts @@ -0,0 +1,53 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { throwError, Observable } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; + +import { isNil } from 'lodash'; + +import { environment } from '@zeppelin/environment'; +import { TicketService } from '@zeppelin/services'; + +@Injectable() +export class AppHttpInterceptor implements HttpInterceptor { + constructor(private ticketService: TicketService) {} + + // tslint:disable-next-line:no-any + intercept(httpRequest: HttpRequest, next: HttpHandler): Observable> { + let httpRequestUpdated = httpRequest.clone({ withCredentials: true }); + if (environment.production) { + httpRequestUpdated = httpRequest.clone({ setHeaders: { 'X-Requested-With': 'XMLHttpRequest' } }); + } + return next.handle(httpRequestUpdated).pipe( + map(event => { + if (event instanceof HttpResponse) { + return event.clone({ body: event.body.body }); + } else { + return event; + } + }), + catchError(event => { + const redirect = event.headers.get('Location'); + if (event.status === 401 && !isNil(redirect)) { + // Handle page redirect + window.location.href = redirect; + } else if (event.status === 405 && !event.url.contains('logout')) { + this.ticketService.logout().subscribe(); + } + return throwError(event); + }) + ); + } +} diff --git a/zeppelin-web-angular/src/app/app-message.interceptor.ts b/zeppelin-web-angular/src/app/app-message.interceptor.ts new file mode 100644 index 00000000000..0e9843d8960 --- /dev/null +++ b/zeppelin-web-angular/src/app/app-message.interceptor.ts @@ -0,0 +1,68 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { Router } from '@angular/router'; + +import { NzModalService, NzNotificationService } from 'ng-zorro-antd'; + +import { MessageInterceptor } from '@zeppelin/interfaces'; +import { MessageReceiveDataTypeMap, OP, WebSocketMessage } from '@zeppelin/sdk'; +import { TicketService } from '@zeppelin/services'; + +@Injectable() +export class AppMessageInterceptor implements MessageInterceptor { + constructor( + private router: Router, + private nzNotificationService: NzNotificationService, + private ticketService: TicketService, + private nzModalService: NzModalService + ) {} + + received(data: WebSocketMessage): WebSocketMessage { + if (data.op === OP.NEW_NOTE) { + const rData = data.data as MessageReceiveDataTypeMap[OP.NEW_NOTE]; + this.router.navigate(['/notebook', rData.note.id]).then(); + } else if (data.op === OP.AUTH_INFO) { + const rData = data.data as MessageReceiveDataTypeMap[OP.AUTH_INFO]; + if (this.ticketService.ticket.roles === '[]') { + this.nzModalService.confirm({ + nzClosable: false, + nzMaskClosable: false, + nzTitle: 'Insufficient privileges', + nzContent: rData.info + }); + } else { + this.nzModalService.create({ + nzClosable: false, + nzMaskClosable: false, + nzTitle: 'Insufficient privileges', + nzContent: rData.info, + nzOkText: 'Login', + nzOnOk: () => { + this.router.navigate(['/login']).then(); + }, + nzOnCancel: () => { + this.router.navigate(['/']).then(); + } + }); + } + } else if (data.op === OP.ERROR_INFO) { + // tslint:disable-next-line:no-any + const rData = (data.data as any) as MessageReceiveDataTypeMap[OP.ERROR_INFO]; + if (rData.info) { + this.nzNotificationService.warning('ERROR', rData.info); + } + } + return data; + } +} diff --git a/zeppelin-web-angular/src/app/app-routing.module.ts b/zeppelin-web-angular/src/app/app-routing.module.ts new file mode 100644 index 00000000000..4a580cf9c8f --- /dev/null +++ b/zeppelin-web-angular/src/app/app-routing.module.ts @@ -0,0 +1,36 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NgModule } from '@angular/core'; +import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; + +const routes: Routes = [ + { + path: '', + loadChildren: () => import('./pages/workspace/workspace.module').then(m => m.WorkspaceModule) + }, + { + path: 'login', + loadChildren: () => import('./pages/login/login.module').then(m => m.LoginModule) + } +]; + +@NgModule({ + imports: [ + RouterModule.forRoot(routes, { + useHash: true, + preloadingStrategy: PreloadAllModules + }) + ], + exports: [RouterModule] +}) +export class AppRoutingModule {} diff --git a/zeppelin-web-angular/src/app/app-runtime-compiler.providers.ts b/zeppelin-web-angular/src/app/app-runtime-compiler.providers.ts new file mode 100644 index 00000000000..bde0d988f2f --- /dev/null +++ b/zeppelin-web-angular/src/app/app-runtime-compiler.providers.ts @@ -0,0 +1,41 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Compiler, + CompilerFactory, + CompilerOptions, + COMPILER_OPTIONS, + StaticProvider, + ViewEncapsulation +} from '@angular/core'; +import { JitCompilerFactory } from '@angular/platform-browser-dynamic'; + +const compilerOptions: CompilerOptions = { + useJit: true, + defaultEncapsulation: ViewEncapsulation.None +}; + +export function createCompiler(compilerFactory: CompilerFactory) { + return compilerFactory.createCompiler([compilerOptions]); +} + +export const RUNTIME_COMPILER_PROVIDERS: StaticProvider[] = [ + { provide: COMPILER_OPTIONS, useValue: compilerOptions, multi: true }, + { provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] }, + { provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] } +]; + +// TODO(hsuanxyz) +// buildOptimizer false +// import 'core-js/es7/reflect'; +// https://github.com/angular/angular/issues/27584#issuecomment-446462051 diff --git a/zeppelin-web-angular/src/app/app.component.html b/zeppelin-web-angular/src/app/app.component.html new file mode 100644 index 00000000000..d101c77150d --- /dev/null +++ b/zeppelin-web-angular/src/app/app.component.html @@ -0,0 +1,15 @@ + + + +Getting Ticket Data ... +Logging out ... diff --git a/zeppelin-web-angular/src/app/app.component.less b/zeppelin-web-angular/src/app/app.component.less new file mode 100644 index 00000000000..f9587c7330a --- /dev/null +++ b/zeppelin-web-angular/src/app/app.component.less @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + .content { + background: @layout-body-background; + min-height: 100vh; + display: block; + position: relative; + + &.blur { + filter: blur(6px); + } + } +}); diff --git a/zeppelin-web-angular/src/app/app.component.spec.ts b/zeppelin-web-angular/src/app/app.component.spec.ts new file mode 100644 index 00000000000..3dfbc76cc22 --- /dev/null +++ b/zeppelin-web-angular/src/app/app.component.spec.ts @@ -0,0 +1,30 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { async, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [RouterTestingModule], + declarations: [AppComponent] + }).compileComponents(); + })); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + }); +}); diff --git a/zeppelin-web-angular/src/app/app.component.ts b/zeppelin-web-angular/src/app/app.component.ts new file mode 100644 index 00000000000..dc9fcb3afbb --- /dev/null +++ b/zeppelin-web-angular/src/app/app.component.ts @@ -0,0 +1,39 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component } from '@angular/core'; +import { NavigationEnd, NavigationStart, Router } from '@angular/router'; +import { filter, map } from 'rxjs/operators'; + +import { TicketService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.less'] +}) +export class AppComponent { + logout$ = this.ticketService.logout$; + loading$ = this.router.events.pipe( + filter(data => data instanceof NavigationEnd || data instanceof NavigationStart), + map(data => { + if (data instanceof NavigationStart) { + // load ticket when redirect to workspace + return data.url === '/'; + } else if (data instanceof NavigationEnd) { + return false; + } + }) + ); + + constructor(private router: Router, private ticketService: TicketService) {} +} diff --git a/zeppelin-web-angular/src/app/app.module.ts b/zeppelin-web-angular/src/app/app.module.ts new file mode 100644 index 00000000000..ae3347c350b --- /dev/null +++ b/zeppelin-web-angular/src/app/app.module.ts @@ -0,0 +1,88 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { registerLocaleData } from '@angular/common'; +import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; +import en from '@angular/common/locales/en'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { BrowserModule } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { Router, RouterModule } from '@angular/router'; + +import { ZeppelinHeliumModule } from '@zeppelin/helium'; +import { en_US, NzModalService, NzNotificationService, NZ_I18N } from 'ng-zorro-antd'; + +import { MESSAGE_INTERCEPTOR, TRASH_FOLDER_ID_TOKEN } from '@zeppelin/interfaces'; +import { loadMonacoLanguage } from '@zeppelin/languages'; +import { TicketService } from '@zeppelin/services'; +import { ShareModule } from '@zeppelin/share'; + +import { NZ_CODE_EDITOR_CONFIG } from '@zeppelin/share/code-editor'; +import { AppHttpInterceptor } from './app-http.interceptor'; +import { AppMessageInterceptor } from './app-message.interceptor'; +import { AppRoutingModule } from './app-routing.module'; +import { RUNTIME_COMPILER_PROVIDERS } from './app-runtime-compiler.providers'; +import { AppComponent } from './app.component'; + +export const loadMonaco = () => { + loadMonacoLanguage(); +}; + +registerLocaleData(en); + +@NgModule({ + declarations: [AppComponent], + imports: [ + BrowserModule, + FormsModule, + HttpClientModule, + BrowserAnimationsModule, + ShareModule, + AppRoutingModule, + RouterModule, + ZeppelinHeliumModule + ], + providers: [ + ...RUNTIME_COMPILER_PROVIDERS, + { + provide: NZ_I18N, + useValue: en_US + }, + { + provide: HTTP_INTERCEPTORS, + useClass: AppHttpInterceptor, + multi: true, + deps: [TicketService] + }, + { + provide: NZ_CODE_EDITOR_CONFIG, + useValue: { + defaultEditorOption: { + scrollBeyondLastLine: false + }, + onLoad: loadMonaco + } + }, + { + provide: MESSAGE_INTERCEPTOR, + useClass: AppMessageInterceptor, + deps: [Router, NzNotificationService, TicketService, NzModalService] + }, + { + provide: TRASH_FOLDER_ID_TOKEN, + useValue: '~Trash' + } + ], + bootstrap: [AppComponent] +}) +export class AppModule {} diff --git a/zeppelin-web-angular/src/app/core/copy-text/copy-text-to-clipboard.ts b/zeppelin-web-angular/src/app/core/copy-text/copy-text-to-clipboard.ts new file mode 100644 index 00000000000..fb1e6208e78 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/copy-text/copy-text-to-clipboard.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +export function copyTextToClipboard(text: string): void { + const textArea: HTMLTextAreaElement = document.createElement('textarea'); + + // + // *** This styling is an extra step which is likely not required. *** + // + // Why is it here? To ensure: + // 1. the element is able to have focus and selection. + // 2. if element was to flash render it has minimal visual impact. + // 3. less flakyness with selection and copying which **might** occur if + // the textarea element is not visible. + // + // The likelihood is the element won't even render, not even a flash, + // so some of these are just precautions. However in IE the element + // is visible whilst the popup box asking the user for permission for + // the web page to copy to the clipboard. + // + + // Place in top-left corner of screen regardless of scroll position. + textArea.style.position = 'fixed'; + textArea.style.top = '0'; + textArea.style.left = '0'; + + // Ensure it has a small width and height. Setting to 1px / 1em + // doesn't work as this gives a negative w/h on some browsers. + textArea.style.width = '2em'; + textArea.style.height = '2em'; + + // We don't need padding, reducing the size if it does flash render. + textArea.style.padding = '0'; + + // Clean up any borders. + textArea.style.border = 'none'; + textArea.style.outline = 'none'; + textArea.style.boxShadow = 'none'; + + // Avoid flash of white box if rendered for any reason. + textArea.style.background = 'transparent'; + + textArea.value = text; + + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + try { + document.execCommand('copy'); + } catch (err) { + window.prompt('Copy to clipboard: Ctrl+C, Enter', text); + } + + document.body.removeChild(textArea); +} diff --git a/zeppelin-web-angular/src/app/core/copy-text/index.ts b/zeppelin-web-angular/src/app/core/copy-text/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/copy-text/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/core/copy-text/public-api.ts b/zeppelin-web-angular/src/app/core/copy-text/public-api.ts new file mode 100644 index 00000000000..aa47aad6726 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/copy-text/public-api.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './copy-text-to-clipboard'; diff --git a/zeppelin-web-angular/src/app/core/destroy-hook/destroy-hook.component.ts b/zeppelin-web-angular/src/app/core/destroy-hook/destroy-hook.component.ts new file mode 100644 index 00000000000..7f394c0c4c9 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/destroy-hook/destroy-hook.component.ts @@ -0,0 +1,23 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { OnDestroy } from '@angular/core'; +import { Subject } from 'rxjs'; + +export class DestroyHookComponent implements OnDestroy { + readonly destroy$ = new Subject(); + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } +} diff --git a/zeppelin-web-angular/src/app/core/destroy-hook/index.ts b/zeppelin-web-angular/src/app/core/destroy-hook/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/destroy-hook/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/core/destroy-hook/public-api.ts b/zeppelin-web-angular/src/app/core/destroy-hook/public-api.ts new file mode 100644 index 00000000000..c4b93aa16d8 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/destroy-hook/public-api.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './destroy-hook.component'; diff --git a/zeppelin-web-angular/src/app/core/index.ts b/zeppelin-web-angular/src/app/core/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/core/message-listener/index.ts b/zeppelin-web-angular/src/app/core/message-listener/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/message-listener/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/core/message-listener/message-listener.ts b/zeppelin-web-angular/src/app/core/message-listener/message-listener.ts new file mode 100644 index 00000000000..5c29be8aaa0 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/message-listener/message-listener.ts @@ -0,0 +1,59 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { OnDestroy } from '@angular/core'; +import { Subscriber } from 'rxjs'; + +import { MessageReceiveDataTypeMap, ReceiveArgumentsType } from '@zeppelin/sdk'; +import { MessageService } from '@zeppelin/services'; + +export class MessageListenersManager implements OnDestroy { + __zeppelinMessageListeners__: Array<() => void>; + __zeppelinMessageListeners$__ = new Subscriber(); + constructor(public messageService: MessageService) { + if (this.__zeppelinMessageListeners__) { + this.__zeppelinMessageListeners__.forEach(fn => fn.apply(this)); + } + } + + ngOnDestroy(): void { + this.__zeppelinMessageListeners$__.unsubscribe(); + this.__zeppelinMessageListeners$__ = null; + } +} + +export function MessageListener(op: K) { + return function( + target: MessageListenersManager, + propertyKey: string, + descriptor: TypedPropertyDescriptor> + ) { + const oldValue = descriptor.value as ReceiveArgumentsType; + + const fn = function() { + // tslint:disable:no-invalid-this + this.__zeppelinMessageListeners$__.add( + this.messageService.receive(op).subscribe(data => { + oldValue.apply(this, [data]); + }) + ); + }; + + if (!target.__zeppelinMessageListeners__) { + target.__zeppelinMessageListeners__ = [fn]; + } else { + target.__zeppelinMessageListeners__.push(fn); + } + + return descriptor; + }; +} diff --git a/zeppelin-web-angular/src/app/core/message-listener/public-api.ts b/zeppelin-web-angular/src/app/core/message-listener/public-api.ts new file mode 100644 index 00000000000..61a92db9183 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/message-listener/public-api.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './message-listener'; diff --git a/zeppelin-web-angular/src/app/core/public-api.ts b/zeppelin-web-angular/src/app/core/public-api.ts new file mode 100644 index 00000000000..c5141035cc3 --- /dev/null +++ b/zeppelin-web-angular/src/app/core/public-api.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +export * from './message-listener'; +export * from './destroy-hook'; +export * from './copy-text'; diff --git a/zeppelin-web-angular/src/app/helium-manager/helium-manager.module.ts b/zeppelin-web-angular/src/app/helium-manager/helium-manager.module.ts new file mode 100644 index 00000000000..940a29249fc --- /dev/null +++ b/zeppelin-web-angular/src/app/helium-manager/helium-manager.module.ts @@ -0,0 +1,27 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Compiler, CompilerFactory, COMPILER_OPTIONS, NgModule } from '@angular/core'; +import { JitCompilerFactory } from '@angular/platform-browser-dynamic'; + +export function createCompiler(compilerFactory: CompilerFactory) { + return compilerFactory.createCompiler(); +} + +@NgModule({ + providers: [ + { provide: COMPILER_OPTIONS, useValue: {}, multi: true }, + { provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] }, + { provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] } + ] +}) +export class HeliumManagerModule {} diff --git a/zeppelin-web-angular/src/app/helium-manager/helium-manager.service.ts b/zeppelin-web-angular/src/app/helium-manager/helium-manager.service.ts new file mode 100644 index 00000000000..1a1a03c55c3 --- /dev/null +++ b/zeppelin-web-angular/src/app/helium-manager/helium-manager.service.ts @@ -0,0 +1,75 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Compiler, Injectable, Injector, NgModuleFactory, OnDestroy, Type } from '@angular/core'; +import { ZeppelinHeliumPackage, ZeppelinHeliumService } from '@zeppelin/helium'; +import { of, BehaviorSubject } from 'rxjs'; +import { HeliumManagerModule } from './helium-manager.module'; + +export interface CompiledPackage { + // tslint:disable-next-line:no-any + moduleFactory: NgModuleFactory; + // tslint:disable-next-line:no-any + component: Type; + injector?: Injector; + name: string; + _raw: ZeppelinHeliumPackage; +} + +@Injectable({ + providedIn: HeliumManagerModule +}) +export class HeliumManagerService implements OnDestroy { + private packages$ = new BehaviorSubject([]); + + constructor(private zeppelinHeliumService: ZeppelinHeliumService, private compiler: Compiler) {} + + initPackages() { + this.getEnabledPackages().subscribe(packages => { + packages.forEach(name => { + this.zeppelinHeliumService.loadPackage(name).then(heliumPackage => { + const loaded = this.packages$.value; + if (!loaded.find(p => p.name === heliumPackage.name)) { + this.compilePackage(heliumPackage); + } + }); + }); + }); + } + + getEnabledPackages() { + // return of(['helium-vis-example']); + return of([]); + } + + packagesLoadChange() { + return this.packages$.asObservable(); + } + + compilePackage(pack: ZeppelinHeliumPackage) { + this.compiler.compileModuleAsync(pack.module).then(moduleFactory => { + this.packages$.next([ + ...this.packages$.value, + { + moduleFactory, + name: pack.name, + component: pack.component, + _raw: pack + } + ]); + }); + } + + ngOnDestroy(): void { + this.packages$.complete(); + } +} diff --git a/zeppelin-web-angular/src/app/helium-manager/index.ts b/zeppelin-web-angular/src/app/helium-manager/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/helium-manager/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/helium-manager/public-api.ts b/zeppelin-web-angular/src/app/helium-manager/public-api.ts new file mode 100644 index 00000000000..8ba1a21026a --- /dev/null +++ b/zeppelin-web-angular/src/app/helium-manager/public-api.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +export * from './helium-manager.service'; +export * from './helium-manager.module'; diff --git a/zeppelin-web-angular/src/app/interfaces/index.ts b/zeppelin-web-angular/src/app/interfaces/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/interfaces/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/interfaces/interpreter.ts b/zeppelin-web-angular/src/app/interfaces/interpreter.ts new file mode 100644 index 00000000000..2e1d661d678 --- /dev/null +++ b/zeppelin-web-angular/src/app/interfaces/interpreter.ts @@ -0,0 +1,104 @@ +/* + * 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. + */ + +export type InterpreterPropertyTypes = 'textarea' | 'string' | 'number' | 'url' | 'password' | 'checkbox'; + +export interface Interpreter { + id: string; + name: string; + group: string; + properties: Properties; + status: string; + errorReason?: string; + interpreterGroup: InterpreterGroupItem[]; + dependencies: DependenciesItem[]; + option: Option; +} + +export interface InterpreterMap { + [key: string]: Interpreter; +} + +export interface CreateInterpreterRepositoryForm { + id: string; + url: string; + snapshot: boolean; + username: string; + password: string; + proxyProtocol: string; + proxyHost: string; + proxyPort: string; + proxyLogin: string; + proxyPassword: string; +} + +export interface InterpreterRepository { + id: string; + type: string; + url: string; + releasePolicy: ReleasePolicy; + snapshotPolicy: SnapshotPolicy; + // tslint:disable-next-line + mirroredRepositories: any[]; + repositoryManager: boolean; +} +interface ReleasePolicy { + enabled: boolean; + updatePolicy: string; + checksumPolicy: string; +} +interface SnapshotPolicy { + enabled: boolean; + updatePolicy: string; + checksumPolicy: string; +} + +interface Properties { + [key: string]: { + name: string; + value: boolean; + type: string; + defaultValue?: string; + description?: string; + }; +} + +interface InterpreterGroupItem { + name: string; + class: string; + defaultInterpreter: boolean; + editor: Editor; +} +interface Editor { + language: string; + editOnDblClick: boolean; + completionKey?: string; + completionSupport?: boolean; +} + +interface DependenciesItem { + groupArtifactVersion: string; + local: boolean; + exclusions: string[]; +} + +interface Option { + remote: boolean; + port: number; + isExistingProcess: boolean; + setPermission: boolean; + // tslint:disable-next-line:no-any + owners: any[]; + isUserImpersonate: boolean; + perNote?: string; + perUser?: string; +} diff --git a/zeppelin-web-angular/src/app/interfaces/message-interceptor.ts b/zeppelin-web-angular/src/app/interfaces/message-interceptor.ts new file mode 100644 index 00000000000..85618dfa44a --- /dev/null +++ b/zeppelin-web-angular/src/app/interfaces/message-interceptor.ts @@ -0,0 +1,20 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { InjectionToken } from '@angular/core'; +import { MessageReceiveDataTypeMap, WebSocketMessage } from '@zeppelin/sdk'; + +export interface MessageInterceptor { + received(data: WebSocketMessage): WebSocketMessage; +} + +export const MESSAGE_INTERCEPTOR = new InjectionToken('MESSAGE_INTERCEPTOR'); diff --git a/zeppelin-web-angular/src/app/interfaces/node-list.ts b/zeppelin-web-angular/src/app/interfaces/node-list.ts new file mode 100644 index 00000000000..3330e03aa75 --- /dev/null +++ b/zeppelin-web-angular/src/app/interfaces/node-list.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +export interface NodeList { + root: RootNode; + flatList: FlatListNodeItem[]; + flatFolderMap: FlatFolderNodeMap; +} + +export interface RootNode { + children: NodeItem[]; +} + +export interface NodeItem { + id: string; + title: string; + isLeaf?: boolean; + expanded?: boolean; + children?: NodeItem[]; + isTrash: boolean; + path?: string; +} + +interface FlatListNodeItem { + id: string; + path: string; + isTrash: boolean; +} + +interface FlatFolderNodeMap { + [title: string]: NodeItem; +} diff --git a/zeppelin-web-angular/src/app/interfaces/public-api.ts b/zeppelin-web-angular/src/app/interfaces/public-api.ts new file mode 100644 index 00000000000..1e07b8e496a --- /dev/null +++ b/zeppelin-web-angular/src/app/interfaces/public-api.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export * from './ticket'; +export * from './trash-folder-id'; +export * from './interpreter'; +export * from './message-interceptor'; +export * from './security'; diff --git a/zeppelin-web-angular/src/app/interfaces/security.ts b/zeppelin-web-angular/src/app/interfaces/security.ts new file mode 100644 index 00000000000..ff7db2a97d2 --- /dev/null +++ b/zeppelin-web-angular/src/app/interfaces/security.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +export interface SecurityUserList { + roles: string[]; + users: string[]; +} + +export interface Permissions { + readers: string[]; + owners: string[]; + writers: string[]; + runners: string[]; +} diff --git a/zeppelin-web-angular/src/app/interfaces/ticket.ts b/zeppelin-web-angular/src/app/interfaces/ticket.ts new file mode 100644 index 00000000000..0f4883e0d2b --- /dev/null +++ b/zeppelin-web-angular/src/app/interfaces/ticket.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +export class ITicket { + principal = ''; + ticket = ''; + redirectURL = ''; + roles = ''; +} + +export class IZeppelinVersion { + 'git-commit-id': string; + 'git-timestamp': string; + 'version': string; +} + +export class ITicketWrapped extends ITicket { + init = false; + screenUsername = ''; +} diff --git a/zeppelin-web-angular/src/app/interfaces/trash-folder-id.ts b/zeppelin-web-angular/src/app/interfaces/trash-folder-id.ts new file mode 100644 index 00000000000..035b92a1789 --- /dev/null +++ b/zeppelin-web-angular/src/app/interfaces/trash-folder-id.ts @@ -0,0 +1,15 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { InjectionToken } from '@angular/core'; + +export const TRASH_FOLDER_ID_TOKEN = new InjectionToken('TRASH_FOLDER_ID'); diff --git a/zeppelin-web-angular/src/app/languages/index.ts b/zeppelin-web-angular/src/app/languages/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/languages/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/languages/load.ts b/zeppelin-web-angular/src/app/languages/load.ts new file mode 100644 index 00000000000..5dad459c888 --- /dev/null +++ b/zeppelin-web-angular/src/app/languages/load.ts @@ -0,0 +1,20 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { languages } from 'monaco-editor'; +import { conf as ScalaConf, language as ScalaLanguage } from './scala'; + +export const loadMonacoLanguage = () => { + languages.register({ id: 'scala' }); + languages.setMonarchTokensProvider('scala', ScalaLanguage); + languages.setLanguageConfiguration('scala', ScalaConf); +}; diff --git a/zeppelin-web-angular/src/app/languages/public-api.ts b/zeppelin-web-angular/src/app/languages/public-api.ts new file mode 100644 index 00000000000..973c93158ba --- /dev/null +++ b/zeppelin-web-angular/src/app/languages/public-api.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +export * from './scala'; +export * from './load'; diff --git a/zeppelin-web-angular/src/app/languages/scala.ts b/zeppelin-web-angular/src/app/languages/scala.ts new file mode 100644 index 00000000000..581049129e0 --- /dev/null +++ b/zeppelin-web-angular/src/app/languages/scala.ts @@ -0,0 +1,236 @@ +/* + * 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. + */ + +'use strict'; + +import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration; +import ILanguage = monaco.languages.IMonarchLanguage; + +export const conf: IRichLanguageConfiguration = { + // the default separators except `@$` + wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [['{', '}'], ['[', ']'], ['(', ')']], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" }, + { open: '<', close: '>' } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.scala', + + keywords: [ + // From https://www.scala-lang.org/files/archive/spec/2.11/01-lexical-syntax.html + 'abstract', + 'case', + 'catch', + 'class', + 'def', + 'do', + 'else', + 'extends', + 'false', + 'final', + 'finally', + 'for', + 'forSome', + 'if', + 'implicit', + 'import', + 'lazy', + 'macro', + 'match', + 'new', + 'null', + 'object', + 'override', + 'package', + 'private', + 'protected', + 'return', + 'sealed', + 'super', + 'this', + 'throw', + 'trait', + 'try', + 'true', + 'type', + 'val', + 'var', + 'while', + 'with', + 'yield' + ], + + operators: [ + '_', + ':', + '=', + '=>', + '<-', + '<:', + '<%', + '>:', + '#', + '@', + + // Copied from java.ts, to be validated + '=', + '>', + '<', + '!', + '~', + '?', + ':', + '==', + '<=', + '>=', + '!=', + '&&', + '||', + '++', + '--', + '+', + '-', + '*', + '/', + '&', + '|', + '^', + '%', + '<<', + '>>', + '>>>', + '+=', + '-=', + '*=', + '/=', + '&=', + '|=', + '^=', + '%=', + '<<=', + '>>=', + '>>>=' + ], + + // we include these common regular expressions + symbols: /[=>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // @ annotations. + [/@\s*[a-zA-Z_\$][\w\$]*/, 'annotation'], + + // numbers + [/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/, 'number.float'], + [/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/, 'number.float'], + [/0[xX](@hexdigits)[Ll]?/, 'number.hex'], + [/0(@octaldigits)[Ll]?/, 'number.octal'], + [/0[bB](@binarydigits)[Ll]?/, 'number.binary'], + [/(@digits)[fFdD]/, 'number.float'], + [/(@digits)[lL]?/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"/, 'string', '@string'], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\/\*\*(?!\/)/, 'comment.doc', '@scaladoc'], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + // [/\/\*/, 'comment', '@push' ], // nested comment not allowed :-( + // [/\/\*/, 'comment.invalid' ], // this breaks block comments in the shape of /* //*/ + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + // Identical copy of comment above, except for the addition of .doc + scaladoc: [ + [/[^\/*]+/, 'comment.doc'], + // [/\/\*/, 'comment.doc', '@push' ], // nested comment not allowed :-( + [/\/\*/, 'comment.doc.invalid'], + [/\*\//, 'comment.doc', '@pop'], + [/[\/*]/, 'comment.doc'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string', '@pop'] + ] + } +} as ILanguage; diff --git a/zeppelin-web-angular/src/app/pages/login/login-routing.module.ts b/zeppelin-web-angular/src/app/pages/login/login-routing.module.ts new file mode 100644 index 00000000000..06dd0304db8 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/login/login-routing.module.ts @@ -0,0 +1,29 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { LoginComponent } from './login.component'; + +const routes: Routes = [ + { + path: '', + component: LoginComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class LoginRoutingModule {} diff --git a/zeppelin-web-angular/src/app/pages/login/login.component.html b/zeppelin-web-angular/src/app/pages/login/login.component.html new file mode 100644 index 00000000000..faa16b67189 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/login/login.component.html @@ -0,0 +1,46 @@ + + +
+
+
+
+ + User Name + + + + + + + + Password + + + + + + + + + + + +
+
+ +
+
diff --git a/zeppelin-web-angular/src/app/pages/login/login.component.less b/zeppelin-web-angular/src/app/pages/login/login.component.less new file mode 100644 index 00000000000..7aac210300d --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/login/login.component.less @@ -0,0 +1,69 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + .content { + height: 100vh; + width: 100vw; + + &:after { + content: ""; + display: block; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: url("../../../assets/images/bg.jpg"); + background-size: cover; + filter: blur(4px); + background-repeat: no-repeat; + background-position: center; + } + + .inner { + width: 800px; + height: 300px; + position: absolute; + z-index: 1; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + box-shadow: @box-shadow-base; + + .form { + width: 500px; + position: absolute; + left: 0; + height: 100%; + background: @component-background; + padding: 36px; + } + + .sidebar { + width: 300px; + position: absolute; + right: 0; + height: 100%; + background: @primary-color; + padding: 24px 36px; + color: @text-color-dark; + + h1 { + color: @heading-color-dark; + } + } + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/login/login.component.ts b/zeppelin-web-angular/src/app/pages/login/login.component.ts new file mode 100644 index 00000000000..937724974b6 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/login/login.component.ts @@ -0,0 +1,47 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; + +import { TicketService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class LoginComponent implements OnInit { + userName: string; + password: string; + loading = false; + + login() { + this.loading = true; + this.ticketService.login(this.userName, this.password).subscribe( + () => { + this.loading = false; + this.cdr.markForCheck(); + this.router.navigate(['/']).then(); + }, + () => { + this.loading = false; + this.cdr.markForCheck(); + } + ); + } + + constructor(private ticketService: TicketService, private cdr: ChangeDetectorRef, private router: Router) {} + + ngOnInit() {} +} diff --git a/zeppelin-web-angular/src/app/pages/login/login.module.ts b/zeppelin-web-angular/src/app/pages/login/login.module.ts new file mode 100644 index 00000000000..46f40a055d5 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/login/login.module.ts @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { NzButtonModule, NzFormModule, NzIconModule, NzInputModule } from 'ng-zorro-antd'; + +import { LoginRoutingModule } from './login-routing.module'; +import { LoginComponent } from './login.component'; + +@NgModule({ + declarations: [LoginComponent], + imports: [CommonModule, LoginRoutingModule, FormsModule, NzFormModule, NzInputModule, NzButtonModule, NzIconModule] +}) +export class LoginModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/home/home-routing.module.ts b/zeppelin-web-angular/src/app/pages/workspace/home/home-routing.module.ts new file mode 100644 index 00000000000..23a345f025a --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/home/home-routing.module.ts @@ -0,0 +1,29 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { HomeComponent } from './home.component'; + +const routes: Routes = [ + { + path: '', + component: HomeComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class HomeRoutingModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/home/home.component.html b/zeppelin-web-angular/src/app/pages/workspace/home/home.component.html new file mode 100644 index 00000000000..5a26044c970 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/home/home.component.html @@ -0,0 +1,41 @@ + + +
+
+

+ Welcome to Zeppelin! +

+ Zeppelin is web-based notebook that enables interactive data analytics.
+ You can make beautiful data-driven, interactive, collaborative document with SQL, code and even more!
+
+
+
+

Notebook

+ +
+
+

Help

+ Get started with Zeppelin + documentation
+ +

Community

+ Please feel free to help us to improve Zeppelin,
+ Any contribution are welcome!

+ Mailing list
+ Issues + tracking
+ Github +
+
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/home/home.component.less b/zeppelin-web-angular/src/app/pages/workspace/home/home.component.less new file mode 100644 index 00000000000..3f79862ddc6 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/home/home.component.less @@ -0,0 +1,37 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + .content { + margin: 12px; + border: 1px solid @border-color-base; + padding: 24px; + background-color: @component-background; + position: relative; + background-image: url(../../../../assets/images/zeppelin_svg_logo_bg.svg); + background-repeat: no-repeat; + background-position: right bottom; + } + .welcome { + margin-bottom: 12px; + } + .more-info { + h3 { + margin-top: 0.5em; + } + } + .refresh-note { + margin-left: 6px + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/home/home.component.ts b/zeppelin-web-angular/src/app/pages/workspace/home/home.component.ts new file mode 100644 index 00000000000..ecc40995d68 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/home/home.component.ts @@ -0,0 +1,48 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { OP } from '@zeppelin/sdk'; +import { MessageService, TicketService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class HomeComponent extends MessageListenersManager implements OnInit { + loading = false; + + reloadNoteList() { + this.messageService.reloadAllNotesFromRepo(); + this.loading = true; + } + + @MessageListener(OP.NOTES_INFO) + getNotes() { + this.loading = false; + this.cdr.markForCheck(); + } + + constructor( + public ticketService: TicketService, + public messageService: MessageService, + private cdr: ChangeDetectorRef + ) { + super(messageService); + } + + ngOnInit() {} +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/home/home.module.ts b/zeppelin-web-angular/src/app/pages/workspace/home/home.module.ts new file mode 100644 index 00000000000..24e59a71853 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/home/home.module.ts @@ -0,0 +1,27 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { NzGridModule, NzIconModule, NzToolTipModule } from 'ng-zorro-antd'; + +import { ShareModule } from '@zeppelin/share'; + +import { HomeRoutingModule } from './home-routing.module'; +import { HomeComponent } from './home.component'; + +@NgModule({ + declarations: [HomeComponent], + imports: [CommonModule, HomeRoutingModule, NzGridModule, NzIconModule, NzToolTipModule, ShareModule] +}) +export class HomeModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.html b/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.html new file mode 100644 index 00000000000..57a0b6339d7 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.html @@ -0,0 +1,158 @@ + + +
+ + + ID + + + + + + + + URL + + + + + + + + + + + + + + + + + Snapshot + + + + + + + + Username + + + + + + + + Password + + + + + + + + + Protocol + + + + + + + + + + + Host + + + + + + + + Port + + + + + + + + Login + + + + + + + + Password + + + + + +
+ + diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.less b/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.less new file mode 100644 index 00000000000..f348ef32466 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.less @@ -0,0 +1,19 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + nz-form-item { + margin-bottom: 5px; + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.ts b/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.ts new file mode 100644 index 00000000000..8dd38c97766 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.ts @@ -0,0 +1,78 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { takeUntil } from 'rxjs/operators'; + +import { NzModalRef } from 'ng-zorro-antd'; + +import { DestroyHookComponent } from '@zeppelin/core'; +import { CreateInterpreterRepositoryForm } from '@zeppelin/interfaces'; +import { InterpreterService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-interpreter-create-repository-modal', + templateUrl: './create-repository-modal.component.html', + styleUrls: ['./create-repository-modal.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InterpreterCreateRepositoryModalComponent extends DestroyHookComponent implements OnInit { + validateForm: FormGroup; + submitting = false; + urlProtocol = 'http://'; + + handleCancel() { + this.nzModalRef.close(); + } + + handleSubmit() { + const data = this.validateForm.getRawValue() as CreateInterpreterRepositoryForm; + // set url protocol + data.url = `${this.urlProtocol}${data.url}`; + // reset proxy port + const proxyPort = Number.parseInt(data.proxyPort, 10); + data.proxyPort = Number.isNaN(proxyPort) ? null : `${proxyPort}`; + this.interpreterService + .addRepository(data) + .pipe(takeUntil(this.destroy$)) + .subscribe(() => { + this.nzModalRef.close('Done'); + }); + } + + constructor( + private formBuilder: FormBuilder, + private nzModalRef: NzModalRef, + private interpreterService: InterpreterService + ) { + super(); + } + + ngOnInit() { + this.validateForm = this.formBuilder.group({ + id: ['', [Validators.required]], + url: ['', [Validators.required]], + snapshot: [false, [Validators.required]], + username: '', + password: '', + proxyProtocol: 'HTTP', + proxyHost: '', + proxyPort: [ + null, + [Validators.pattern('^()([1-9]|[1-5]?[0-9]{2,4}|6[1-4][0-9]{3}|65[1-4][0-9]{2}|655[1-2][0-9]|6553[1-5])$')] + ], + proxyLogin: '', + proxyPassword: '' + }); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter-routing.module.ts b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter-routing.module.ts new file mode 100644 index 00000000000..c9c995825cb --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter-routing.module.ts @@ -0,0 +1,29 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { InterpreterComponent } from './interpreter.component'; + +const routes: Routes = [ + { + path: '', + component: InterpreterComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class InterpreterRoutingModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.component.html b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.component.html new file mode 100644 index 00000000000..144a57d2fca --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.component.html @@ -0,0 +1,66 @@ + + + + + + + + + + +
+ +

Repositories

+

Available repository lists. These repositories are used to resolve external dependencies of interpreter.

+ + {{repo.id}} + + + + +
+
+
+ + + Create + + + + + +
diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.component.less b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.component.less new file mode 100644 index 00000000000..8d5f88d6044 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.component.less @@ -0,0 +1,51 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + .search-input { + width: 256px; + } + + @media (max-width:959px){ + .search-input { + width: 100%; + } + } + + nz-tag.repo-item { + border-color: transparent; + background: @primary-6; + color: @text-color-inverse; + ::ng-deep i.anticon-close { + color: @text-color-inverse; + &:hover { + color: @icon-color-hover; + } + } + } + + .editable-tag { + background: @white; + border-style: dashed; + } + + .content { + padding: @card-padding-base / 2; + + .create-interpreter { + text-align: center; + margin-bottom: 10px; + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.component.ts b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.component.ts new file mode 100644 index 00000000000..8e216282d19 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.component.ts @@ -0,0 +1,186 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { Subject } from 'rxjs'; +import { debounceTime } from 'rxjs/operators'; + +import { collapseMotion, NzMessageService, NzModalService } from 'ng-zorro-antd'; + +import { Interpreter, InterpreterPropertyTypes, InterpreterRepository } from '@zeppelin/interfaces'; +import { InterpreterService } from '@zeppelin/services'; + +import { InterpreterCreateRepositoryModalComponent } from './create-repository-modal/create-repository-modal.component'; + +@Component({ + selector: 'zeppelin-interpreter', + templateUrl: './interpreter.component.html', + styleUrls: ['./interpreter.component.less'], + animations: [collapseMotion], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InterpreterComponent implements OnInit, OnDestroy { + searchInterpreter = ''; + search$ = new Subject(); + showRepository = false; + showCreateSetting = false; + propertyTypes: InterpreterPropertyTypes[] = []; + interpreterSettings: Interpreter[] = []; + repositories: InterpreterRepository[] = []; + availableInterpreters: Interpreter[] = []; + filteredInterpreterSettings: Interpreter[] = []; + + onSearchChange(value: string) { + this.search$.next(value); + } + + filterInterpreters(value: string) { + this.filteredInterpreterSettings = this.interpreterSettings.filter(e => e.name.search(value) !== -1); + this.cdr.markForCheck(); + } + + triggerRepository(): void { + this.showRepository = !this.showRepository; + this.cdr.markForCheck(); + } + + removeRepository(repo: InterpreterRepository): void { + this.nzModalService.confirm({ + nzTitle: repo.id, + nzContent: 'Do you want to delete this repository?', + nzOnOk: () => { + this.interpreterService.removeRepository(repo.id).subscribe(() => { + this.repositories = this.repositories.filter(e => e.id !== repo.id); + this.cdr.markForCheck(); + }); + } + }); + } + + addInterpreterSetting(data: Interpreter): void { + this.interpreterService.addInterpreterSetting(data).subscribe(res => { + this.interpreterSettings.push(res); + this.showCreateSetting = false; + this.filterInterpreters(this.searchInterpreter); + this.cdr.markForCheck(); + }); + } + + updateInterpreter(data: Interpreter): void { + this.interpreterService.updateInterpreter(data).subscribe(res => { + const current = this.interpreterSettings.find(e => e.name === res.name); + if (current) { + current.status = res.status; + current.errorReason = res.errorReason; + current.option = res.option; + current.properties = res.properties; + current.dependencies = res.dependencies; + } + this.filterInterpreters(this.searchInterpreter); + this.cdr.markForCheck(); + }); + } + + removeInterpreterSetting(settingId: string): void { + this.nzModalService.confirm({ + nzTitle: 'Remove Interpreter', + nzContent: 'Do you want to delete this interpreter setting?', + nzOnOk: () => { + this.interpreterService.removeInterpreterSetting(settingId).subscribe(() => { + const index = this.interpreterSettings.findIndex(e => e.name === settingId); + this.interpreterSettings.splice(index, 1); + this.filterInterpreters(this.searchInterpreter); + this.cdr.markForCheck(); + }); + } + }); + } + + restartInterpreterSetting(settingId: string): void { + this.nzModalService.confirm({ + nzTitle: 'Restart Interpreter', + nzContent: 'Do you want to restart this interpreter?', + nzOnOk: () => { + this.interpreterService.restartInterpreterSetting(settingId).subscribe(() => { + this.nzMessageService.info('Interpreter stopped. Will be lazily started on next run.'); + }); + } + }); + } + + createRepository(): void { + const modalRef = this.nzModalService.create({ + nzTitle: 'Add New Repository', + nzContent: InterpreterCreateRepositoryModalComponent, + nzFooter: null, + nzWidth: '600px' + }); + modalRef.afterClose.subscribe(data => { + if (data === 'Done') { + this.getRepositories(); + } + }); + } + + getPropertyTypes(): void { + this.interpreterService.getAvailableInterpreterPropertyTypes().subscribe(data => { + this.propertyTypes = data; + this.cdr.markForCheck(); + }); + } + + getInterpreterSettings(): void { + this.interpreterService.getInterpretersSetting().subscribe(data => { + this.interpreterSettings = data; + this.filteredInterpreterSettings = data; + this.cdr.markForCheck(); + }); + } + + getAvailableInterpreters(): void { + this.interpreterService.getAvailableInterpreters().subscribe(data => { + this.availableInterpreters = Object.keys(data) + .sort() + .map(key => data[key]); + this.cdr.markForCheck(); + }); + } + + getRepositories(): void { + this.interpreterService.getRepositories().subscribe(data => { + this.repositories = data; + this.cdr.markForCheck(); + }); + } + + constructor( + private interpreterService: InterpreterService, + private cdr: ChangeDetectorRef, + private nzModalService: NzModalService, + private nzMessageService: NzMessageService + ) {} + + ngOnInit() { + this.getPropertyTypes(); + this.getInterpreterSettings(); + this.getAvailableInterpreters(); + this.getRepositories(); + + this.search$.pipe(debounceTime(150)).subscribe(value => this.filterInterpreters(value)); + } + + ngOnDestroy(): void { + this.search$.next(); + this.search$.complete(); + this.search$ = null; + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.module.ts b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.module.ts new file mode 100644 index 00000000000..37a9a0e10a1 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/interpreter.module.ts @@ -0,0 +1,73 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { + NzAlertModule, + NzBadgeModule, + NzButtonModule, + NzCardModule, + NzCheckboxModule, + NzDividerModule, + NzDropDownModule, + NzFormModule, + NzIconModule, + NzInputModule, + NzMessageModule, + NzModalModule, + NzRadioModule, + NzSelectModule, + NzSwitchModule, + NzTableModule, + NzTagModule, + NzToolTipModule +} from 'ng-zorro-antd'; + +import { ShareModule } from '@zeppelin/share'; + +import { InterpreterCreateRepositoryModalComponent } from './create-repository-modal/create-repository-modal.component'; +import { InterpreterRoutingModule } from './interpreter-routing.module'; +import { InterpreterComponent } from './interpreter.component'; +import { InterpreterItemComponent } from './item/item.component'; + +@NgModule({ + declarations: [InterpreterComponent, InterpreterCreateRepositoryModalComponent, InterpreterItemComponent], + entryComponents: [InterpreterCreateRepositoryModalComponent], + imports: [ + CommonModule, + FormsModule, + ReactiveFormsModule, + InterpreterRoutingModule, + ShareModule, + NzFormModule, + NzSelectModule, + NzSwitchModule, + NzToolTipModule, + NzCheckboxModule, + NzRadioModule, + NzBadgeModule, + NzButtonModule, + NzModalModule, + NzInputModule, + NzDividerModule, + NzTagModule, + NzCardModule, + NzDropDownModule, + NzIconModule, + NzTableModule, + NzMessageModule, + NzAlertModule + ] +}) +export class InterpreterModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.html b/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.html new file mode 100644 index 00000000000..2e4e374520b --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.html @@ -0,0 +1,447 @@ + + + + +
+

+ {{ interpreter.name }} + + , %{{ interpreter.name }}.{{ item.name }} + %{{ interpreter.name }} + + + + + + +

+
+
+ + + + + +
+ + + +
+
+ + +

Create new interpreter

+
+ + Interpreter Name + + + + {{ formGroup.get('name')?.errors?.message }} + + + + + Interpreter group + + + + + + +
+
+

Option

+

+ + + + The interpreter will be instantiated + + {{ interpreterRunningOption }} + + + + +

+ + in + + + {{ optionFormGroup.get('perUser').value }} + + + + {{ optionFormGroup.get('perNote').value }} + + + + + + + + {{ optionFormGroup.get('perUser').value }} + + + + {{ optionFormGroup.get('perNote').value }} + + + + + + + process + + and Per Note in + + {{ optionFormGroup.get('perNote').value }} + + + + + + process + + . + + + + + + +

+
+ + + + + + + + + + + + + + + Host + + + + + + Port + + + + + + + + + + + + + + + Owners + + + + + + Enter comma separated users and groups in the fields. Empty field (*) implies anyone can run this + interpreter. + + + + +
+ + +

Properties

+
+ + + + Name + Value + Description + Action + + + + + {{ control.get('key').value }} + + + + + + + + + + + + ****** + + {{control.get('value').value}} + + {{ control.get('value').value }} + + + + {{ control.get('description').value }} + + + + + + + + + +
+ + + + + + + + + + + +
+ + N/A + + + + + + +
+
+
+ + +

Dependencies

+
+ + + + Artifact + Exclude + Action + + + + + + + + + + + + + + + + + {{ control.get('groupArtifactVersion').value }} + {{ control.get('exclusions').value }} + + + + + + + + + + + + + + + +
+
+ + +
diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.less b/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.less new file mode 100644 index 00000000000..856506e92f2 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.less @@ -0,0 +1,105 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + display: block; + margin-bottom: @card-padding-base; + position: relative; + + ::ng-deep .interpreter-item { + &.edit { + background: @orange-1; + } + .ant-card-body { + margin-top: -@card-padding-base; + } + } + + .error-alter { + margin-top: @card-padding-base; + } + + .interpreter-status { + margin-left: 5px; + } + + .card-title { + display: inline-block; + h3 { + color: @primary-color; + margin-bottom: 0; + font-size: 1.4em; + .interpreter-group-item { + font-size: 60%; + font-weight: 400; + color: @text-color-secondary; + } + } + } + + h3.form-title { + margin: @card-padding-base 0; + } + + nz-form-item { + margin-bottom: 5px; + } + + form td textarea.ant-input { + margin-bottom: 0; + resize: none; + } + + .interpreter-form, .option-form { + input, nz-select { + width: 256px; + } + @media (max-width:959px){ + input, nz-select { + width: 100%; + } + } + } + + .edit-properties-value { + display: flex; + align-items: center; + + .value-input { + flex: 1; + } + + .type-selector { + width: 150px; + margin-left: 5px; + } + } + + .extra-wrap { + button + button { + margin-bottom: 0; + margin-left: 8px; + } + } + + .item-footer { + padding: 24px 0px 12px 0px; + text-align: right; + button + button { + margin-bottom: 0; + margin-left: 8px; + } + } + +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.ts b/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.ts new file mode 100644 index 00000000000..fb9fb0097d1 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/interpreter/item/item.component.ts @@ -0,0 +1,405 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { AbstractControl, FormArray, FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms'; +import { DestroyHookComponent } from '@zeppelin/core'; +import { Interpreter } from '@zeppelin/interfaces'; +import { InterpreterService, SecurityService, TicketService } from '@zeppelin/services'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { debounceTime, filter, map, switchMap, takeUntil, tap } from 'rxjs/operators'; +import { InterpreterComponent } from '../interpreter.component'; + +@Component({ + selector: 'zeppelin-interpreter-item', + templateUrl: './item.component.html', + styleUrls: ['./item.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InterpreterItemComponent extends DestroyHookComponent implements OnInit, OnDestroy { + @Input() mode: 'create' | 'view' | 'edit' = 'view'; + @Input() interpreter: Interpreter; + + formGroup: FormGroup; + optionFormGroup: FormGroup; + editingPropertiesFormGroup: FormGroup; + editingDependenceFormGroup: FormGroup; + propertiesFormArray: FormArray; + dependenciesFormArray: FormArray; + userList$: Observable; + userSearchChange$ = new BehaviorSubject(''); + runningOptionMap = { + sharedModeName: 'shared', + globallyModeName: 'Globally', + perNoteModeName: 'Per Note', + perUserModeName: 'Per User' + }; + + sessionOptionMap = { + isolated: 'isolated', + scoped: 'scoped', + shared: 'shared' + }; + + interpreterRunningOption = 'Globally'; + + switchToEditMode(): void { + this.setupEditableForm(); + this.formGroup.enable(); + this.mode = 'edit'; + this.cdr.markForCheck(); + } + + handleRestart() { + this.parent.restartInterpreterSetting(this.interpreter.name); + } + + handleRemove() { + this.parent.removeInterpreterSetting(this.interpreter.name); + } + + handleSave() { + const formData = this.formGroup.getRawValue(); + const properties = {}; + + formData.properties + .sort(e => e.key) + .forEach(e => { + const { key, value, type } = e; + properties[key] = { + value, + type, + name: key + }; + }); + formData.properties = properties; + + formData.dependencies.forEach(e => { + e.exclusions = e.exclusions.split(',').filter(s => s !== ''); + }); + + if (this.mode === 'create') { + this.parent.addInterpreterSetting(formData); + } else { + this.parent.updateInterpreter(formData); + this.mode = 'view'; + } + } + + handleCancel() { + if (this.mode === 'create') { + this.parent.showCreateSetting = false; + } else { + this.mode = 'view'; + this.buildForm(); + this.formGroup.disable(); + } + } + + interpretersTrackFn(_: number, item: Interpreter) { + return item.name; + } + + onUserSearch(value: string): void { + this.userSearchChange$.next(value); + } + + removeProperty(index: number): void { + this.propertiesFormArray.removeAt(index); + this.cdr.markForCheck(); + } + + removeDependence(index: number): void { + this.dependenciesFormArray.removeAt(index); + this.cdr.markForCheck(); + } + + onTypeChange(type: string) { + let valueSet: string | boolean | number; + switch (type) { + case 'number': + valueSet = 0; + break; + case 'checkbox': + valueSet = false; + break; + default: + valueSet = ''; + } + this.editingPropertiesFormGroup.get('value').setValue(valueSet); + } + + addDependence(): void { + this.editingDependenceFormGroup.updateValueAndValidity(); + if (this.editingDependenceFormGroup.valid) { + const data = this.editingDependenceFormGroup.getRawValue(); + const current = this.dependenciesFormArray.controls.find( + control => control.get('groupArtifactVersion').value === data.groupArtifactVersion + ); + if (current) { + current.get('exclusions').setValue(data.exclusions); + } else { + this.dependenciesFormArray.push( + this.formBuilder.group({ + groupArtifactVersion: [data.groupArtifactVersion, [Validators.required]], + exclusions: data.exclusions + }) + ); + } + this.editingDependenceFormGroup.reset({ + exclusions: '', + groupArtifactVersion: '' + }); + } + } + + addProperties(): void { + this.editingPropertiesFormGroup.updateValueAndValidity(); + if (this.editingPropertiesFormGroup.valid) { + const data = this.editingPropertiesFormGroup.getRawValue(); + + const current = this.propertiesFormArray.controls.find(control => control.get('key').value === data.key); + if (current) { + current.get('value').setValue(data.value); + current.get('type').setValue(data.type); + } else { + this.propertiesFormArray.push( + this.formBuilder.group({ + key: [data.key, [Validators.required]], + value: data.value || '', + description: null, + type: data.type + }) + ); + } + this.editingPropertiesFormGroup.reset({ + key: '', + value: '', + description: null, + type: 'string' + }); + } + } + + setInterpreterRunningOption(perNote: string, perUser: string) { + const { sharedModeName, globallyModeName, perNoteModeName, perUserModeName } = this.runningOptionMap; + + this.optionFormGroup.get('perNote').setValue(perNote); + this.optionFormGroup.get('perUser').setValue(perUser); + + // Globally == shared_perNote + shared_perUser + if (perNote === sharedModeName && perUser === sharedModeName) { + this.interpreterRunningOption = globallyModeName; + return; + } + + const ticket = this.ticketService.originTicket; + + if (ticket.ticket === 'anonymous' && ticket.roles === '[]') { + if (perNote !== undefined && typeof perNote === 'string' && perNote !== '') { + this.interpreterRunningOption = perNoteModeName; + return; + } + } else if (ticket.ticket !== 'anonymous') { + if (perNote !== undefined && typeof perNote === 'string' && perNote !== '') { + if (perUser !== undefined && typeof perUser === 'string' && perUser !== '') { + this.interpreterRunningOption = perUserModeName; + return; + } + this.interpreterRunningOption = perNoteModeName; + return; + } + } + + this.optionFormGroup.get('perNote').setValue(sharedModeName); + this.optionFormGroup.get('perUser').setValue(sharedModeName); + this.interpreterRunningOption = globallyModeName; + } + + setPerNoteOrUserOption(type: 'perNote' | 'perUser', value: string) { + this.optionFormGroup.get(type).setValue(value); + switch (value) { + case this.sessionOptionMap.isolated: + this.optionFormGroup.get('session').setValue(false); + this.optionFormGroup.get('process').setValue(true); + break; + case this.sessionOptionMap.scoped: + this.optionFormGroup.get('session').setValue(true); + this.optionFormGroup.get('process').setValue(false); + break; + case this.sessionOptionMap.shared: + this.optionFormGroup.get('session').setValue(false); + this.optionFormGroup.get('process').setValue(false); + break; + } + } + + nameValidator(control: AbstractControl): ValidationErrors | null { + if (this.mode !== 'create') { + return null; + } + const name = (control.value as string).trim(); + const exist = this.parent.interpreterSettings.find(e => e.name === name); + if (exist) { + return { exist: true, message: `Name '${name}' already exists` }; + } else { + return null; + } + } + + buildForm(): void { + let name = ''; + let group = ''; + this.optionFormGroup = this.formBuilder.group({ + isExistingProcess: false, + isUserImpersonate: false, + owners: [[]], + perNote: '', + perUser: '', + port: [ + null, + [Validators.pattern('^()([1-9]|[1-5]?[0-9]{2,4}|6[1-4][0-9]{3}|65[1-4][0-9]{2}|655[1-2][0-9]|6553[1-5])$')] + ], + host: '', + remote: true, + setPermission: false, + session: false, + process: false + }); + + this.propertiesFormArray = this.formBuilder.array([]); + this.dependenciesFormArray = this.formBuilder.array([]); + + if (this.mode === 'view' && this.interpreter) { + name = this.interpreter.name; + group = this.interpreter.group; + + // set option fields + this.optionFormGroup.reset({ + ...this.interpreter.option, + port: this.interpreter.option.port === -1 ? null : this.interpreter.option.port + }); + + // set dependencies fields + this.interpreter.dependencies.forEach(e => { + this.dependenciesFormArray.push( + this.formBuilder.group({ + exclusions: [e.exclusions.join(',')], + groupArtifactVersion: [e.groupArtifactVersion, [Validators.required]] + }) + ); + }); + + // set properties fields + Object.keys(this.interpreter.properties).forEach(key => { + const item = this.interpreter.properties[key]; + this.propertiesFormArray.push( + this.formBuilder.group({ + key: key, + value: item.value, + description: null, + type: item.type + }) + ); + }); + } + + this.formGroup = this.formBuilder.group({ + name: [name, [Validators.required, c => this.nameValidator(c)]], + group: [group, [Validators.required]], + option: this.optionFormGroup, + properties: this.propertiesFormArray, + dependencies: this.dependenciesFormArray + }); + } + + setupEditableForm(): void { + this.userList$ = this.userSearchChange$.pipe( + debounceTime(500), + filter(value => !!value), + switchMap(value => this.securityService.searchUsers(value)), + map(data => data.users), + tap(() => { + this.cdr.markForCheck(); + }) + ); + + this.editingPropertiesFormGroup = this.formBuilder.group({ + key: ['', [Validators.required]], + value: '', + description: null, + type: 'string' + }); + + this.editingDependenceFormGroup = this.formBuilder.group({ + groupArtifactVersion: ['', [Validators.required]], + exclusions: [''] + }); + + if (this.mode === 'create') { + this.formGroup + .get('group') + .valueChanges.pipe(takeUntil(this.destroy$)) + .subscribe(value => { + // remove all controls + while (this.propertiesFormArray.length) { + this.propertiesFormArray.removeAt(0); + } + + const interpreters = this.parent.availableInterpreters.filter(e => e.group === value); + interpreters.forEach(interpreter => { + Object.keys(interpreter.properties).forEach(key => { + this.propertiesFormArray.push( + this.formBuilder.group({ + key: [key, [Validators.required]], + value: interpreter.properties[key].defaultValue, + description: interpreter.properties[key].description, + type: interpreter.properties[key].type + }) + ); + }); + }); + this.cdr.markForCheck(); + }); + } + } + + constructor( + public parent: InterpreterComponent, + public ticketService: TicketService, + private securityService: SecurityService, + private interpreterService: InterpreterService, + private formBuilder: FormBuilder, + private cdr: ChangeDetectorRef + ) { + super(); + } + + ngOnInit() { + this.buildForm(); + const option = this.optionFormGroup.getRawValue(); + this.setInterpreterRunningOption(option.perNote, option.perUser); + + if (this.mode !== 'view') { + this.setupEditableForm(); + this.formGroup.enable(); + } else { + this.formGroup.disable(); + } + } + + ngOnDestroy(): void { + this.userSearchChange$.complete(); + this.userSearchChange$ = null; + super.ngOnDestroy(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager-routing.module.ts b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager-routing.module.ts new file mode 100644 index 00000000000..5d12c451d5c --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager-routing.module.ts @@ -0,0 +1,29 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { JobManagerComponent } from './job-manager.component'; + +const routes: Routes = [ + { + path: '', + component: JobManagerComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class JobManagerRoutingModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.component.html b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.component.html new file mode 100644 index 00000000000..a5eba0e5f04 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.component.html @@ -0,0 +1,75 @@ + + + +
+ + + + + + + + + + + + Interpreter + + + + + + + + + Sort + + + + + + + + Total + + {{ filteredJobs.length }} + + + + + + + + +
+
+
+ + + + + + + + + + +
diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.component.less b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.component.less new file mode 100644 index 00000000000..0bdc612836a --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.component.less @@ -0,0 +1,50 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + .header-form { + .interpreter-select { + min-width: 100px; + } + .sort-select { + min-width: 155px; + } + } + + .content { + padding: @card-padding-base / 2; + + ::ng-deep .ant-skeleton-paragraph { + margin-bottom: 0; + } + + nz-empty { + margin-top: 76px; + } + } + + @media (max-width: 1230px) { + .status-legend { + display: none; + } + } + .status-legend { + float: right; + margin-right: 0; + zeppelin-job-manager-job-status { + margin-left: 10px; + display: inline-block; + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.component.ts b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.component.ts new file mode 100644 index 00000000000..8e426fd383c --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.component.ts @@ -0,0 +1,138 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; + +import { NzModalService } from 'ng-zorro-antd'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { JobsItem, JobStatus, ListNoteJobs, ListUpdateNoteJobs, OP } from '@zeppelin/sdk'; +import { JobManagerService, MessageService } from '@zeppelin/services'; + +enum JobDateSortKeys { + RECENTLY_UPDATED = 'Recently Update', + OLDEST_UPDATED = 'Oldest Updated' +} + +interface FilterForm { + noteName: string; + interpreter: string; + sortBy: string; +} + +@Component({ + selector: 'zeppelin-job-manager', + templateUrl: './job-manager.component.html', + styleUrls: ['./job-manager.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class JobManagerComponent extends MessageListenersManager implements OnInit, OnDestroy { + form: FormGroup; + jobStatusKeys = Object.keys(JobStatus).map(k => JobStatus[k]); + sortKeys = Object.keys(JobDateSortKeys).map(k => JobDateSortKeys[k]); + interpreters: string[] = []; + filteredJobs: JobsItem[] = []; + filterString: string = ''; + jobs: JobsItem[] = []; + loading = true; + + @MessageListener(OP.LIST_NOTE_JOBS) + setJobs(data: ListNoteJobs) { + this.jobs = data.noteJobs.jobs.filter(j => typeof j.interpreter !== 'undefined'); + const interpreters = this.jobs.map(job => job.interpreter); + this.interpreters = Array.from(new Set(interpreters)); + this.loading = false; + this.filterJobs(); + } + + @MessageListener(OP.LIST_UPDATE_NOTE_JOBS) + updateJobs(data: ListUpdateNoteJobs) { + data.noteRunningJobs.jobs.forEach(updateJob => { + const currentJobIndex = this.jobs.findIndex(job => job.noteId === updateJob.noteId); + if (currentJobIndex === -1) { + this.jobs.push(updateJob); + } else { + if (updateJob.isRemoved) { + this.jobs.splice(currentJobIndex, 1); + } else { + this.jobs[currentJobIndex] = updateJob; + } + } + }); + this.filterJobs(); + } + + filterJobs() { + const filterData = this.form.getRawValue() as FilterForm; + this.filterString = filterData.noteName; + const isSortByAsc = filterData.sortBy === JobDateSortKeys.OLDEST_UPDATED; + this.filteredJobs = this.jobs + .filter(job => { + const escapedString = filterData.noteName.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$&'); + const noteNameReg = new RegExp(escapedString, 'gi'); + return ( + (filterData.interpreter === '*' || job.interpreter === filterData.interpreter) && + job.noteName.match(noteNameReg) + ); + }) + .sort((x, y) => (isSortByAsc ? x.unixTimeLastRun - y.unixTimeLastRun : y.unixTimeLastRun - x.unixTimeLastRun)); + this.cdr.markForCheck(); + } + + onStart(noteId: string): void { + this.nzModalService.confirm({ + nzTitle: 'Job Dialog', + nzContent: 'Run all paragraphs?', + nzOnOk: () => { + this.jobManagerService.startJob(noteId).subscribe(); + } + }); + } + + onStop(noteId: string): void { + this.nzModalService.confirm({ + nzTitle: 'Job Dialog', + nzContent: 'Stop all paragraphs?', + nzOnOk: () => { + this.jobManagerService.stopJob(noteId).subscribe(); + } + }); + } + + constructor( + public messageService: MessageService, + private jobManagerService: JobManagerService, + private fb: FormBuilder, + private cdr: ChangeDetectorRef, + private nzModalService: NzModalService + ) { + super(messageService); + } + + ngOnInit() { + this.form = this.fb.group({ + noteName: [''], + interpreter: ['*'], + sortBy: [JobDateSortKeys.RECENTLY_UPDATED] + }); + + this.form.valueChanges.subscribe(() => this.filterJobs()); + + this.messageService.listNoteJobs(); + } + + ngOnDestroy(): void { + this.messageService.unsubscribeUpdateNoteJobs(); + super.ngOnDestroy(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.module.ts b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.module.ts new file mode 100644 index 00000000000..5ce1f07028d --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-manager.module.ts @@ -0,0 +1,73 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; +import { IconDefinition } from '@ant-design/icons-angular'; +import { ClockCircleOutline, FileOutline, FileUnknownOutline, SearchOutline } from '@ant-design/icons-angular/icons'; +import { + NzBadgeModule, + NzCardModule, + NzDividerModule, + NzEmptyModule, + NzFormModule, + NzGridModule, + NzHighlightModule, + NzIconModule, + NzInputModule, + NzModalModule, + NzProgressModule, + NzSelectModule, + NzSkeletonModule, + NzToolTipModule, + NZ_ICONS +} from 'ng-zorro-antd'; + +import { ShareModule } from '@zeppelin/share'; + +import { JobManagerRoutingModule } from './job-manager-routing.module'; +import { JobManagerComponent } from './job-manager.component'; +import { JobManagerJobStatusComponent } from './job-status/job-status.component'; +import { JobManagerJobComponent } from './job/job.component'; + +const icons: IconDefinition[] = [SearchOutline, FileOutline, FileUnknownOutline, ClockCircleOutline]; + +@NgModule({ + declarations: [JobManagerComponent, JobManagerJobComponent, JobManagerJobStatusComponent], + imports: [ + CommonModule, + FormsModule, + ReactiveFormsModule, + NzHighlightModule, + ShareModule, + NzIconModule, + NzInputModule, + NzBadgeModule, + NzGridModule, + NzModalModule, + RouterModule, + NzSelectModule, + NzInputModule, + NzFormModule, + JobManagerRoutingModule, + NzDividerModule, + NzCardModule, + NzToolTipModule, + NzProgressModule, + NzSkeletonModule, + NzEmptyModule + ], + providers: [{ provide: NZ_ICONS, useValue: icons }] +}) +export class JobManagerModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.html b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.html new file mode 100644 index 00000000000..2bd375de558 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.html @@ -0,0 +1,17 @@ + + + + diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.less b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.less new file mode 100644 index 00000000000..0f2d8c0d122 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.less @@ -0,0 +1,23 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + display: inline-block; + nz-badge.ready { + ::ng-deep .ant-badge-status-success { + background: fade(@success-color, 20%); + border: 1px solid @success-color; + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.ts b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.ts new file mode 100644 index 00000000000..18828cd9827 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job-status/job-status.component.ts @@ -0,0 +1,37 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; + +import { JobStatus } from '@zeppelin/sdk'; + +@Component({ + selector: 'zeppelin-job-manager-job-status', + templateUrl: './job-status.component.html', + styleUrls: ['./job-status.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class JobManagerJobStatusComponent { + @Input() status: JobStatus; + @Input() showText = false; + jobStatus = JobStatus; + statusMap = { + [JobStatus.READY]: 'success', + [JobStatus.FINISHED]: 'success', + [JobStatus.ABORT]: 'warning', + [JobStatus.ERROR]: 'error', + [JobStatus.PENDING]: 'default', + [JobStatus.RUNNING]: 'processing' + }; + + constructor() {} +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.html b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.html new file mode 100644 index 00000000000..4d76c7694aa --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.html @@ -0,0 +1,58 @@ + + + +
+ + + - + + {{note.interpreter || 'interpreter is not set'}} + + + {{relativeTime}} + {{note.isRunningJob ? 'RUNNING' : 'READY'}} + {{progress | percent: '1.0-0'}} + + +
+ +
+ + diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.less b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.less new file mode 100644 index 00000000000..bf958132e1c --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.less @@ -0,0 +1,70 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + display: block; + margin-bottom: 10px; + position: relative; + + ::ng-deep .job-item .ant-card-body { + padding: @card-padding-base / 2; + } + + .job-title { + margin-bottom: 10px; + } + + .note-icon { + margin-right: 5px; + } + + .right-tools { + display: inline-block; + float: right; + color: @text-color-secondary; + & > * { + margin-left: 5px; + } + .job-control-btn { + cursor: pointer; + color: @processing-color; + &.running { + color: @error-color; + } + } + } + + .interpreter { + color: @text-color; + &.unset { + color: @text-color-secondary; + } + } + + zeppelin-job-manager-job-status { + ::ng-deep .ant-badge-status-text { + margin-left: 0; + } + margin: 0 4px; + } + + .footer-progress { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + margin-bottom: -5px; + padding: 0 1px; + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.ts b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.ts new file mode 100644 index 00000000000..e2990c24922 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/job-manager/job/job.component.ts @@ -0,0 +1,83 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges +} from '@angular/core'; + +import * as distanceInWords from 'date-fns/distance_in_words'; + +import { JobsItem, JobStatus } from '@zeppelin/sdk'; + +@Component({ + selector: 'zeppelin-job-manager-job', + templateUrl: './job.component.html', + styleUrls: ['./job.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class JobManagerJobComponent implements OnInit, OnChanges { + @Input() note: JobsItem; + @Input() highlight: string | null = null; + @Output() readonly start = new EventEmitter(); + @Output() readonly stop = new EventEmitter(); + + icon = 'file'; + relativeTime = ''; + progress = 0; + + setIcon(): void { + const noteType = this.note.noteType; + if (noteType === 'normal') { + this.icon = 'file'; + } else if (noteType === 'cron') { + this.icon = 'close-circle'; + } else { + this.icon = 'file-unknown'; + } + } + + setRelativeTime(): void { + this.relativeTime = distanceInWords(new Date(), new Date(this.note.unixTimeLastRun)); + } + + setProgress(): void { + const runningCount = this.note.paragraphs.filter( + paragraph => [JobStatus.FINISHED, JobStatus.RUNNING].indexOf(paragraph.status) !== -1 + ).length; + this.progress = runningCount / this.note.paragraphs.length; + } + + onStartClick(): void { + this.start.emit(this.note.noteId); + } + + onStopClick(): void { + this.stop.emit(this.note.noteId); + } + + constructor() {} + + ngOnInit() {} + + ngOnChanges(changes: SimpleChanges): void { + this.setIcon(); + this.setRelativeTime(); + this.setProgress(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.html new file mode 100644 index 00000000000..0238f171aca --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.html @@ -0,0 +1,239 @@ + + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
  • + {{r.message}} + + {{(r.time * 1000 | date: 'MMMM dd yyyy, h:mm:ss a') || 'Current'}} +
  • +
+
+
+ + + + + + + + + + + + + +
+ Run note with cron scheduler. + Either choose from preset or write your own + + cron expression + + . +
+ - Preset + {{cr.name}} +
+
+ - Preset + +

+ {{note.info.cron}} +

+
+
+ +
+
+
+
+
+
+ + + + + + +
    +
  • {{lf}}
  • +
+
+
+
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.less new file mode 100644 index 00000000000..5161d77070a --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.less @@ -0,0 +1,105 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.scheduler { + width: 300px; + + .cron-preset { + margin-right: 6px; + + &.selected { + font-weight: bold; + } + } + + > div { + line-height: 24px; + + span { + margin-right: 6px; + } + + input { + display: inline-block; + width: 160px; + } + } +} + +.themeMixin({ + nz-dropdown-button { + height: 24px; + line-height: 22px; + margin-left: -1px; + } + .bar { + height: 50px; + background: @component-background; + box-shadow: -2px 4px 2px 0 rgba(0, 0, 0, 0.06); + padding: 0 15px; + position: absolute; + width: 100%; + top: 0; + line-height: 50px; + + &.simple { + box-shadow: none; + + .control { + display: none; + } + + .setting { + display: none; + } + + &:hover { + .control { + display: block; + } + + .setting { + display: block; + } + } + } + + .title { + float: left; + width: auto; + max-width: 40%; + } + + .control { + float: left; + + nz-button-group { + margin-right: 24px; + + &:last-child { + margin-right: 0; + } + } + } + + .setting { + float: right; + + button { + box-shadow: none; + border: none; + } + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.ts new file mode 100644 index 00000000000..f4968d7988f --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/action-bar/action-bar.component.ts @@ -0,0 +1,293 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + EventEmitter, + Inject, + Input, + OnInit, + Output +} from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { NzMessageService, NzModalService } from 'ng-zorro-antd'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { TRASH_FOLDER_ID_TOKEN } from '@zeppelin/interfaces'; +import { Note, OP, RevisionListItem } from '@zeppelin/sdk'; +import { MessageService, NoteActionService, NoteStatusService, SaveAsService, TicketService } from '@zeppelin/services'; + +import { NoteCreateComponent } from '@zeppelin/share/note-create/note-create.component'; + +@Component({ + selector: 'zeppelin-notebook-action-bar', + templateUrl: './action-bar.component.html', + styleUrls: ['./action-bar.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookActionBarComponent extends MessageListenersManager implements OnInit { + @Input() note: Note['note']; + @Input() isOwner = true; + @Input() looknfeel: string; + @Input() noteRevisions: RevisionListItem[] = []; + @Input() currentRevision: string; + @Input() collaborativeMode = false; + @Input() collaborativeModeUsers = []; + @Input() revisionView = false; + @Input() activatedExtension: 'interpreter' | 'permissions' | 'revisions' | 'hide' = 'hide'; + @Output() readonly activatedExtensionChange = new EventEmitter< + 'interpreter' | 'permissions' | 'revisions' | 'hide' + >(); + @Output() readonly editorHideChange = new EventEmitter(); + @Output() readonly tableHideChange = new EventEmitter(); + lfOption: Array<'report' | 'default' | 'simple'> = ['default', 'simple', 'report']; + isNoteParagraphRunning = false; + principal = this.ticketService.ticket.principal; + editorHide = false; + commitVisible = false; + tableHide = false; + isRevisionSupported = JSON.parse(this.ticketService.configuration.isRevisionSupported); + cronOption = [ + { name: 'None', value: undefined }, + { name: '1m', value: '0 0/1 * * * ?' }, + { name: '5m', value: '0 0/5 * * * ?' }, + { name: '1h', value: '0 0 0/1 * * ?' }, + { name: '3h', value: '0 0 0/3 * * ?' }, + { name: '6h', value: '0 0 0/6 * * ?' }, + { name: '12h', value: '0 0 0/12 * * ?' }, + { name: '1d', value: '0 0 0 * * ?' } + ]; + + updateNoteName(name: string) { + const trimmedNewName = name.trim(); + if (trimmedNewName.length > 0 && this.note.name !== trimmedNewName) { + this.note.name = trimmedNewName; + this.messageService.noteRename(this.note.id, this.note.name, true); + } + } + + visitRevision(revision: RevisionListItem) { + if (revision.id) { + if (revision.id === 'Head') { + this.router.navigate(['/notebook', this.activatedRoute.snapshot.params.noteId]).then(); + } else { + this.router.navigate(['/notebook', this.activatedRoute.snapshot.params.noteId, 'revision', revision.id]).then(); + } + } else { + this.nzMessageService.warning('There is a problem with this Revision'); + } + } + + checkpointNote(value: string, e: MouseEvent) { + e.preventDefault(); + this.commitVisible = false; + this.messageService.checkpointNote(this.note.id, value); + } + + setNoteRevision() { + const { revisionId } = this.activatedRoute.snapshot.params; + if (revisionId) { + this.nzModalService.confirm({ + nzTitle: 'Set revision', + nzContent: 'Set notebook head to current revision?', + nzOnOk: () => { + this.messageService.setNoteRevision(this.note.id, revisionId); + } + }); + } + } + + toggleExtension(extension: 'interpreter' | 'permissions' | 'revisions' | 'hide') { + if (this.activatedExtension === extension) { + this.activatedExtension = 'hide'; + } else { + this.activatedExtension = extension; + } + this.activatedExtensionChange.emit(this.activatedExtension); + } + + @MessageListener(OP.PARAGRAPH) + paragraphUpdate() { + this.updateIsNoteParagraphRunning(); + this.cdr.markForCheck(); + } + + runAllParagraphs() { + this.messageService.runAllParagraphs( + this.note.id, + this.note.paragraphs.map(p => { + return { + id: p.id, + title: p.title, + paragraph: p.text, + config: p.config, + params: p.settings.params + }; + }) + ); + } + + clearAllParagraphOutput() { + this.messageService.paragraphClearAllOutput(this.note.id); + } + + setCronScheduler(cronExpr: string) { + if (cronExpr) { + if (!this.note.config.cronExecutingUser) { + this.note.config.cronExecutingUser = this.ticketService.ticket.principal; + } + if (!this.note.config.cronExecutingRoles) { + this.note.config.cronExecutingRoles = this.ticketService.ticket.roles; + } + } else { + this.note.config.cronExecutingUser = ''; + this.note.config.cronExecutingRoles = ''; + } + this.note.config.cron = cronExpr; + this.setConfig(); + } + + setReleaseResource(releaseresource: boolean) { + this.note.config.releaseresource = releaseresource; + this.setConfig(); + } + + setConfig() { + // TODO(hsuanxyz) + } + + cloneNote() { + this.nzModalService.create({ + nzTitle: 'Clone Note', + nzContent: NoteCreateComponent, + nzComponentParams: { + cloneNote: this.note + }, + nzFooter: null + }); + } + + exportNote() { + const sizeLimit = +this.ticketService.configuration['zeppelin.websocket.max.text.message.size']; + const jsonContent = JSON.stringify(this.note); + if (jsonContent.length > sizeLimit) { + this.nzModalService.confirm({ + nzTitle: `Note size exceeds importable limit (${sizeLimit})`, + nzContent: 'Do you still want to export this note?', + nzOnOk: () => { + this.saveAsService.saveAs(jsonContent, this.note.name, 'zpln'); + } + }); + } else { + this.saveAsService.saveAs(jsonContent, this.note.name, 'zpln'); + } + } + + toggleAllEditor() { + this.editorHide = !this.editorHide; + this.editorHideChange.emit(this.editorHide); + } + + toggleAllTable() { + this.tableHide = !this.tableHide; + this.tableHideChange.emit(this.tableHide); + } + + searchCode() { + // TODO(hsuanxyz) + } + + deleteNote() { + this.messageService.deleteNote(this.note.id); + } + + moveNoteToTrash() { + this.messageService.moveNoteToTrash(this.note.id); + } + + get isTrash() { + return this.noteStatusService.isTrash(this.note); + } + + get viewOnly(): boolean { + return this.noteStatusService.viewOnly(this.note); + } + + updateIsNoteParagraphRunning() { + this.isNoteParagraphRunning = this.noteStatusService.isNoteParagraphRunning(this.note); + } + + showShortCut() { + // TODO(hsuanxyz) + } + + togglePermissions() { + this.toggleExtension('permissions'); + } + + setLookAndFeel(lf: 'report' | 'default' | 'simple') { + this.note.config.looknfeel = lf; + if (!this.activatedRoute.snapshot.params.revisionId) { + this.messageService.updateNote(this.note.id, this.note.name, this.note.config); + } + } + + toggleNotePersonalizedMode() { + const modeText = this.note.config.personalizedMode === 'true' ? 'collaborate' : 'personalize'; + if (this.isOwner) { + this.nzModalService.confirm({ + nzTitle: 'Setting the result display', + nzContent: `Do you want to ${modeText} your analysis?`, + nzOnOk: () => { + if (this.note.config.personalizedMode === undefined || this.note.config.personalizedMode === 'true') { + this.note.config.personalizedMode = 'false'; + } else { + this.note.config.personalizedMode = 'true'; + } + this.messageService.updatePersonalizedMode(this.note.id, this.note.config.personalizedMode); + } + }); + } + } + + get getCronOptionNameFromValue() { + if (!this.note.config.cron) { + return ''; + } else if (this.cronOption.find(cron => cron.value === this.note.config.cron)) { + return this.cronOption.find(cron => cron.value === this.note.config.cron).name; + } else { + return this.note.config.cron; + } + } + + constructor( + public messageService: MessageService, + private nzModalService: NzModalService, + private ticketService: TicketService, + private nzMessageService: NzMessageService, + private router: Router, + private cdr: ChangeDetectorRef, + private noteActionService: NoteActionService, + private noteStatusService: NoteStatusService, + @Inject(TRASH_FOLDER_ID_TOKEN) public TRASH_FOLDER_ID: string, + private activatedRoute: ActivatedRoute, + private saveAsService: SaveAsService + ) { + super(messageService); + } + + ngOnInit(): void { + this.updateIsNoteParagraphRunning(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/add-paragraph/add-paragraph.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/add-paragraph/add-paragraph.component.html new file mode 100644 index 00000000000..76d6475a7c5 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/add-paragraph/add-paragraph.component.html @@ -0,0 +1,17 @@ + + + diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/add-paragraph/add-paragraph.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/add-paragraph/add-paragraph.component.less new file mode 100644 index 00000000000..c51b70e61a6 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/add-paragraph/add-paragraph.component.less @@ -0,0 +1,50 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + .add-paragraph { + height: 32px; + text-align: center; + margin: -12px 0; + color: @primary-color; + font-weight: 500; + position: relative;; + + .inner { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 10; + display: none; + line-height: 30px; + background: @blue-1; + border: 1px solid @border-color-split; + box-shadow: @btn-shadow; + padding: 0 12px; + + &.disabled { + cursor: default; + color: @disabled-color; + } + } + + &:hover { + .inner { + display: block; + } + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/add-paragraph/add-paragraph.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/add-paragraph/add-paragraph.component.ts new file mode 100644 index 00000000000..bb77a832979 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/add-paragraph/add-paragraph.component.ts @@ -0,0 +1,34 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; + +@Component({ + selector: 'zeppelin-notebook-add-paragraph', + templateUrl: './add-paragraph.component.html', + styleUrls: ['./add-paragraph.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookAddParagraphComponent implements OnInit { + @Output() readonly addParagraph = new EventEmitter(); + @Input() disabled = false; + + clickAdd() { + if (!this.disabled) { + this.addParagraph.emit(); + } + } + + constructor() {} + + ngOnInit() {} +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/interpreter-binding/interpreter-binding.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/interpreter-binding/interpreter-binding.component.html new file mode 100644 index 00000000000..263390cbce6 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/interpreter-binding/interpreter-binding.component.html @@ -0,0 +1,55 @@ + + +
+
+

Settings

+
+ +
+

Interpreter binding

+

+ Bind interpreter for this note. + Click to Bind/Unbind interpreter. + Drag and drop to reorder interpreters.
+ The first interpreter on the list becomes default. To create/remove interpreters, go to + Interpreter + menu. +

+
+
+
+
+ + + +
+ +
+
+
+
+ + +
+
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/interpreter-binding/interpreter-binding.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/interpreter-binding/interpreter-binding.component.less new file mode 100644 index 00000000000..fcaea0a913f --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/interpreter-binding/interpreter-binding.component.less @@ -0,0 +1,30 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + .interpreter-binding { + .interpreter-list { + background: @layout-body-background; + padding: 12px; + } + + .submit-interpreter { + margin-top: 12px; + + button { + margin-right: 12px; + } + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/interpreter-binding/interpreter-binding.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/interpreter-binding/interpreter-binding.component.ts new file mode 100644 index 00000000000..377a869d1a4 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/interpreter-binding/interpreter-binding.component.ts @@ -0,0 +1,81 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { moveItemInArray, CdkDragDrop } from '@angular/cdk/drag-drop'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core'; + +import { NzModalService } from 'ng-zorro-antd'; + +import { InterpreterBindingItem } from '@zeppelin/sdk'; +import { InterpreterService, MessageService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-notebook-interpreter-binding', + templateUrl: './interpreter-binding.component.html', + styleUrls: ['./interpreter-binding.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookInterpreterBindingComponent { + private restarting = false; + @Input() noteId: string; + @Input() interpreterBindings: InterpreterBindingItem[] = []; + @Input() activatedExtension: 'interpreter' | 'permissions' | 'revisions' | 'hide' = 'hide'; + @Output() readonly activatedExtensionChange = new EventEmitter< + 'interpreter' | 'permissions' | 'revisions' | 'hide' + >(); + + restartInterpreter(interpreter: InterpreterBindingItem) { + this.nzModalService.create({ + nzTitle: 'Restart interpreter', + nzContent: `Do you want to restart ${interpreter.name} interpreter?`, + nzOkLoading: this.restarting, + nzOnOk: () => + new Promise(resolve => { + this.restarting = true; + this.interpreterService.restartInterpreter(interpreter.id, this.noteId).subscribe( + data => { + this.restarting = false; + this.cdr.markForCheck(); + resolve(); + }, + () => { + this.restarting = false; + resolve(); + } + ); + }) + }); + } + + drop(event: CdkDragDrop) { + moveItemInArray(this.interpreterBindings, event.previousIndex, event.currentIndex); + } + + saveSetting() { + const selectedSettingIds = this.interpreterBindings.filter(item => item.selected).map(item => item.id); + this.messageService.saveInterpreterBindings(this.noteId, selectedSettingIds); + this.messageService.getInterpreterBindings(this.noteId); + this.closeSetting(); + } + + closeSetting() { + this.activatedExtension = 'hide'; + this.activatedExtensionChange.emit('hide'); + } + + constructor( + private nzModalService: NzModalService, + private interpreterService: InterpreterService, + private cdr: ChangeDetectorRef, + private messageService: MessageService + ) {} +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook-routing.module.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook-routing.module.ts new file mode 100644 index 00000000000..6c177b6ba80 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook-routing.module.ts @@ -0,0 +1,37 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { NotebookComponent } from './notebook.component'; + +const routes: Routes = [ + { + path: ':noteId', + component: NotebookComponent + }, + { + path: ':noteId/paragraph/:paragraphId', + component: NotebookComponent + }, + { + path: ':noteId/revision/:revisionId', + component: NotebookComponent + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class NotebookRoutingModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html new file mode 100644 index 00000000000..3bad5eec173 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.html @@ -0,0 +1,54 @@ + + +
+ +
+ + + +
+
+
+ +
+
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.less new file mode 100644 index 00000000000..582bbb74910 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.less @@ -0,0 +1,36 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + + +.themeMixin({ + .notebook-container { + background: @layout-body-background; + display: block; + position: relative; + padding-top: 50px; + min-height: calc(~"100vh - 50px"); + + &.simple { + background: @component-background; + } + } + .extension-area { + padding: 24px; + background: @component-background; + box-shadow: -2px 4px 2px 0 rgba(0, 0, 0, 0.06); + } + .paragraph-area { + margin: 6px 0 0 0; + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.ts new file mode 100644 index 00000000000..a894971b8e9 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.component.ts @@ -0,0 +1,315 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + QueryList, + ViewChildren +} from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { isNil } from 'lodash'; +import { Subject } from 'rxjs'; +import { distinctUntilKeyChanged, takeUntil } from 'rxjs/operators'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { Permissions } from '@zeppelin/interfaces'; +import { InterpreterBindingItem, MessageReceiveDataTypeMap, Note, OP, RevisionListItem } from '@zeppelin/sdk'; +import { + MessageService, + NoteStatusService, + NoteVarShareService, + SecurityService, + TicketService +} from '@zeppelin/services'; + +import { NotebookParagraphComponent } from './paragraph/paragraph.component'; + +@Component({ + selector: 'zeppelin-notebook', + templateUrl: './notebook.component.html', + styleUrls: ['./notebook.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookComponent extends MessageListenersManager implements OnInit, OnDestroy { + @ViewChildren(NotebookParagraphComponent) listOfNotebookParagraphComponent: QueryList; + private destroy$ = new Subject(); + note: Note['note']; + permissions: Permissions; + isOwner = true; + noteRevisions: RevisionListItem[] = []; + currentRevision: string; + collaborativeMode = false; + revisionView = false; + collaborativeModeUsers = []; + isNoteDirty = false; + saveTimer = null; + interpreterBindings: InterpreterBindingItem[] = []; + activatedExtension: 'interpreter' | 'permissions' | 'revisions' | 'hide' = 'hide'; + + @MessageListener(OP.NOTE) + getNote(data: MessageReceiveDataTypeMap[OP.NOTE]) { + const note = data.note; + if (isNil(note)) { + this.router.navigate(['/']).then(); + } else { + this.note = note; + const { paragraphId } = this.activatedRoute.snapshot.params; + if (paragraphId) { + this.note = this.cleanParagraphExcept(paragraphId); + this.initializeLookAndFeel(); + } else { + this.initializeLookAndFeel(); + this.getInterpreterBindings(); + this.getPermissions(); + this.note.config.personalizedMode = + this.note.config.personalizedMode === undefined ? 'false' : this.note.config.personalizedMode; + } + this.cdr.markForCheck(); + } + } + + @MessageListener(OP.INTERPRETER_BINDINGS) + loadInterpreterBindings(data: MessageReceiveDataTypeMap[OP.INTERPRETER_BINDINGS]) { + this.interpreterBindings = data.interpreterBindings; + if (!this.interpreterBindings.some(item => item.selected)) { + this.activatedExtension = 'interpreter'; + } + this.cdr.markForCheck(); + } + + @MessageListener(OP.PARAGRAPH_REMOVED) + removeParagraph(data: MessageReceiveDataTypeMap[OP.PARAGRAPH_REMOVED]) { + const { paragraphId } = this.activatedRoute.snapshot.params; + if (paragraphId || this.revisionView) { + return; + } + this.note.paragraphs = this.note.paragraphs.filter(p => p.id !== data.id); + this.cdr.markForCheck(); + } + + @MessageListener(OP.PARAGRAPH_ADDED) + addParagraph(data: MessageReceiveDataTypeMap[OP.PARAGRAPH_ADDED]) { + const { paragraphId } = this.activatedRoute.snapshot.params; + if (paragraphId || this.revisionView) { + return; + } + this.note.paragraphs.splice(data.index, 0, data.paragraph).map(p => { + return { + ...p, + focus: p.id === data.paragraph.id + }; + }); + this.note.paragraphs = [...this.note.paragraphs]; + this.cdr.markForCheck(); + // TODO(hsuanxyz) focus on paragraph + } + + @MessageListener(OP.SAVE_NOTE_FORMS) + saveNoteForms(data: MessageReceiveDataTypeMap[OP.SAVE_NOTE_FORMS]) { + this.note.noteForms = data.formsData.forms; + this.note.noteParams = data.formsData.params; + } + + @MessageListener(OP.NOTE_REVISION) + getNoteRevision(data: MessageReceiveDataTypeMap[OP.NOTE_REVISION]) { + const note = data.note; + if (isNil(note)) { + this.router.navigate(['/']).then(); + } else { + this.note = data.note; + this.initializeLookAndFeel(); + this.cdr.markForCheck(); + } + } + + @MessageListener(OP.SET_NOTE_REVISION) + setNoteRevision() { + const { noteId } = this.activatedRoute.snapshot.params; + this.router.navigate(['/notebook', noteId]).then(); + } + + @MessageListener(OP.PARAGRAPH_MOVED) + moveParagraph(data: MessageReceiveDataTypeMap[OP.PARAGRAPH_MOVED]) { + if (!this.revisionView) { + const movedPara = this.note.paragraphs.find(p => p.id === data.id); + if (movedPara) { + const listOfRestPara = this.note.paragraphs.filter(p => p.id !== data.id); + this.note.paragraphs = [...listOfRestPara.slice(0, data.index), movedPara, ...listOfRestPara.slice(data.index)]; + this.cdr.markForCheck(); + } + } + } + + @MessageListener(OP.COLLABORATIVE_MODE_STATUS) + getCollaborativeModeStatus(data: MessageReceiveDataTypeMap[OP.COLLABORATIVE_MODE_STATUS]) { + this.collaborativeMode = Boolean(data.status); + this.collaborativeModeUsers = data.users; + this.cdr.markForCheck(); + } + + @MessageListener(OP.PATCH_PARAGRAPH) + patchParagraph() { + this.collaborativeMode = true; + this.cdr.markForCheck(); + } + + @MessageListener(OP.NOTE_UPDATED) + noteUpdated(data: MessageReceiveDataTypeMap[OP.NOTE_UPDATED]) { + if (data.name !== this.note.name) { + this.note.name = data.name; + } + this.note.config = data.config; + this.note.info = data.info; + this.initializeLookAndFeel(); + this.cdr.markForCheck(); + } + + @MessageListener(OP.LIST_REVISION_HISTORY) + listRevisionHistory(data: MessageReceiveDataTypeMap[OP.LIST_REVISION_HISTORY]) { + this.noteRevisions = data.revisionList; + if (this.noteRevisions) { + if (this.noteRevisions.length === 0 || this.noteRevisions[0].id !== 'Head') { + this.noteRevisions.splice(0, 0, { id: 'Head', message: 'Head' }); + } + const { revisionId } = this.activatedRoute.snapshot.params; + if (revisionId) { + this.currentRevision = this.noteRevisions.find(r => r.id === revisionId).message; + } else { + this.currentRevision = 'Head'; + } + } + this.cdr.markForCheck(); + } + + saveParagraph(id: string) { + this.listOfNotebookParagraphComponent + .toArray() + .find(p => p.paragraph.id === id) + .saveParagraph(); + } + + killSaveTimer() { + if (this.saveTimer) { + clearTimeout(this.saveTimer); + this.saveTimer = null; + } + } + + startSaveTimer() { + this.killSaveTimer(); + this.isNoteDirty = true; + this.saveTimer = setTimeout(() => { + this.saveNote(); + }, 10000); + } + + saveNote() { + if (this.note && this.note.paragraphs && this.listOfNotebookParagraphComponent) { + this.listOfNotebookParagraphComponent.toArray().forEach(p => { + p.saveParagraph(); + }); + this.isNoteDirty = null; + this.cdr.markForCheck(); + } + } + + getInterpreterBindings() { + this.messageService.getInterpreterBindings(this.note.id); + } + + getPermissions() { + this.securityService.getPermissions(this.note.id).subscribe(data => { + this.permissions = data; + this.isOwner = !( + this.permissions.owners.length && this.permissions.owners.indexOf(this.ticketService.ticket.principal) < 0 + ); + this.cdr.markForCheck(); + }); + } + + get viewOnly(): boolean { + return this.noteStatusService.viewOnly(this.note); + } + + initializeLookAndFeel() { + this.note.config.looknfeel = this.note.config.looknfeel || 'default'; + if (this.note.paragraphs && this.note.paragraphs[0]) { + this.note.paragraphs[0].focus = true; + } + } + + cleanParagraphExcept(paragraphId) { + const targetParagraph = this.note.paragraphs.find(p => p.id === paragraphId); + const config = targetParagraph.config || {}; + config.editorHide = true; + config.tableHide = false; + const paragraphs = [{ ...targetParagraph, config }]; + return { ...this.note, paragraphs }; + } + + setAllParagraphTableHide(tableHide: boolean) { + this.listOfNotebookParagraphComponent.forEach(p => p.setTableHide(tableHide)); + } + + setAllParagraphEditorHide(editorHide: boolean) { + this.listOfNotebookParagraphComponent.forEach(p => p.setEditorHide(editorHide)); + } + + constructor( + private activatedRoute: ActivatedRoute, + public messageService: MessageService, + private cdr: ChangeDetectorRef, + private noteStatusService: NoteStatusService, + private noteVarShareService: NoteVarShareService, + private ticketService: TicketService, + private securityService: SecurityService, + private router: Router + ) { + super(messageService); + } + + ngOnInit() { + this.activatedRoute.params + .pipe( + takeUntil(this.destroy$), + distinctUntilKeyChanged('noteId') + ) + .subscribe(() => { + this.noteVarShareService.clear(); + }); + this.activatedRoute.params.pipe(takeUntil(this.destroy$)).subscribe(param => { + const { noteId, revisionId } = param; + if (revisionId) { + this.messageService.noteRevision(noteId, revisionId); + } else { + this.messageService.getNote(noteId); + } + this.revisionView = !!revisionId; + this.cdr.markForCheck(); + this.messageService.listRevisionHistory(noteId); + // TODO(hsuanxyz) scroll to current paragraph + }); + this.revisionView = !!this.activatedRoute.snapshot.params.revisionId; + } + + ngOnDestroy(): void { + super.ngOnDestroy(); + this.killSaveTimer(); + this.saveNote(); + this.destroy$.next(); + this.destroy$.complete(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.module.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.module.ts new file mode 100644 index 00000000000..ccdd4de9dfd --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/notebook.module.ts @@ -0,0 +1,106 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { PortalModule } from '@angular/cdk/portal'; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +import { + NzButtonModule, + NzCheckboxModule, + NzDividerModule, + NzDropDownModule, + NzFormModule, + NzGridModule, + NzIconModule, + NzInputModule, + NzNoAnimationModule, + NzPopconfirmModule, + NzPopoverModule, + NzProgressModule, + NzRadioModule, + NzSelectModule, + NzSwitchModule, + NzToolTipModule +} from 'ng-zorro-antd'; +import { NzCodeEditorModule } from 'ng-zorro-antd/code-editor'; +import { NzResizableModule } from 'ng-zorro-antd/resizable'; + +import { ShareModule } from '@zeppelin/share'; + +import { VisualizationModule } from 'src/app/visualizations/visualization.module'; +import { NotebookAddParagraphComponent } from './add-paragraph/add-paragraph.component'; +import { NotebookInterpreterBindingComponent } from './interpreter-binding/interpreter-binding.component'; +import { NotebookParagraphCodeEditorComponent } from './paragraph/code-editor/code-editor.component'; +import { NotebookParagraphControlComponent } from './paragraph/control/control.component'; +import { NotebookParagraphDynamicFormsComponent } from './paragraph/dynamic-forms/dynamic-forms.component'; +import { NotebookParagraphFooterComponent } from './paragraph/footer/footer.component'; +import { NotebookParagraphComponent } from './paragraph/paragraph.component'; +import { NotebookParagraphProgressComponent } from './paragraph/progress/progress.component'; +import { NotebookParagraphResultComponent } from './paragraph/result/result.component'; +import { NotebookPermissionsComponent } from './permissions/permissions.component'; +import { NotebookRevisionsComparatorComponent } from './revisions-comparator/revisions-comparator.component'; + +import { NotebookActionBarComponent } from './action-bar/action-bar.component'; +import { NotebookRoutingModule } from './notebook-routing.module'; +import { NotebookComponent } from './notebook.component'; +import { NotebookShareModule } from './share/share.module'; + +@NgModule({ + declarations: [ + NotebookComponent, + NotebookActionBarComponent, + NotebookInterpreterBindingComponent, + NotebookPermissionsComponent, + NotebookRevisionsComparatorComponent, + NotebookParagraphComponent, + NotebookAddParagraphComponent, + NotebookParagraphCodeEditorComponent, + NotebookParagraphResultComponent, + NotebookParagraphProgressComponent, + NotebookParagraphFooterComponent, + NotebookParagraphControlComponent, + NotebookParagraphDynamicFormsComponent + ], + imports: [ + CommonModule, + PortalModule, + NotebookRoutingModule, + ShareModule, + VisualizationModule, + NotebookShareModule, + NzButtonModule, + NzIconModule, + NzDropDownModule, + NzNoAnimationModule, + NzToolTipModule, + NzPopconfirmModule, + NzFormModule, + NzPopoverModule, + NzInputModule, + FormsModule, + ReactiveFormsModule, + NzDividerModule, + NzCheckboxModule, + NzProgressModule, + NzSwitchModule, + NzSelectModule, + NzGridModule, + NzRadioModule, + DragDropModule, + NzResizableModule, + NzCodeEditorModule + ] +}) +export class NotebookModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.html new file mode 100644 index 00000000000..4d382f2b82f --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.html @@ -0,0 +1,16 @@ + + + + diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.less new file mode 100644 index 00000000000..72a1f689dc8 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.less @@ -0,0 +1,31 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +:host { + display: block; +} + +.themeMixin({ + + zeppelin-monaco-editor { + display: block; + border-left: 4px solid @border-color-split; + overflow: hidden; + + &.dirty { + border-left-color: @warning-color; + } + } + +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts new file mode 100644 index 00000000000..6dabb4b2bbc --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/code-editor/code-editor.component.ts @@ -0,0 +1,238 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + EventEmitter, + Input, + NgZone, + OnChanges, + OnDestroy, + Output, + SimpleChanges +} from '@angular/core'; + +import { editor as MonacoEditor, IDisposable } from 'monaco-editor'; +import IStandaloneCodeEditor = MonacoEditor.IStandaloneCodeEditor; +import IEditor = monaco.editor.IEditor; + +import { InterpreterBindingItem } from '@zeppelin/sdk'; +import { CompletionService, MessageService } from '@zeppelin/services'; + +import { NotebookParagraphControlComponent } from '../control/control.component'; + +@Component({ + selector: 'zeppelin-notebook-paragraph-code-editor', + templateUrl: './code-editor.component.html', + styleUrls: ['./code-editor.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookParagraphCodeEditorComponent implements OnChanges, OnDestroy, AfterViewInit { + // TODO(hsuanxyz): + // 1. cursor position + @Input() readOnly = false; + @Input() language = 'text'; + @Input() paragraphControl: NotebookParagraphControlComponent; + @Input() lineNumbers = false; + @Input() focus = false; + @Input() collaborativeMode = false; + @Input() text: string; + @Input() fontSize: number; + @Input() dirty = false; + @Input() interpreterBindings: InterpreterBindingItem[] = []; + @Input() pid: string; + @Output() readonly textChanged = new EventEmitter(); + @Output() readonly editorBlur = new EventEmitter(); + private editor: IStandaloneCodeEditor; + private monacoDisposables: IDisposable[] = []; + height = 0; + interpreterName: string; + + autoAdjustEditorHeight() { + if (this.editor) { + this.ngZone.run(() => { + this.height = + this.editor.getTopForLineNumber(Number.MAX_SAFE_INTEGER) + this.editor.getConfiguration().lineHeight * 2; + this.editor.layout(); + this.cdr.markForCheck(); + }); + } + } + + initEditorListener() { + const editor = this.editor; + this.monacoDisposables.push( + editor.onDidFocusEditorText(() => { + this.ngZone.runOutsideAngular(() => { + editor.updateOptions({ renderLineHighlight: 'all' }); + }); + }), + editor.onDidBlurEditorText(() => { + this.editorBlur.emit(); + this.ngZone.runOutsideAngular(() => { + editor.updateOptions({ renderLineHighlight: 'none' }); + }); + }), + editor.onDidChangeModelContent(() => { + this.ngZone.run(() => { + this.text = editor.getModel().getValue(); + this.textChanged.emit(this.text); + this.setParagraphMode(true); + this.autoAdjustEditorHeight(); + setTimeout(() => { + this.autoAdjustEditorHeight(); + }); + }); + }) + ); + } + + setEditorValue() { + if (this.editor && this.editor.getModel() && this.editor.getModel().getValue() !== this.text) { + this.editor.getModel().setValue(this.text || ''); + } + } + + initializedEditor(editor: IEditor) { + this.editor = editor as IStandaloneCodeEditor; + this.paragraphControl.updateListOfMenu(monaco); + if (this.paragraphControl) { + this.paragraphControl.listOfMenu.forEach((item, index) => { + this.editor.addAction({ + id: item.icon, + label: item.label, + keybindings: item.keyBindings, + precondition: null, + keybindingContext: null, + contextMenuGroupId: 'navigation', + contextMenuOrder: index, + run: () => item.trigger() + }); + }); + } + + this.updateEditorOptions(); + this.setParagraphMode(); + this.initEditorListener(); + this.initEditorFocus(); + this.initCompletionService(); + this.setEditorValue(); + setTimeout(() => { + this.autoAdjustEditorHeight(); + }); + } + + initCompletionService(): void { + this.completionService.registerAsCompletionReceiver(this.editor.getModel(), this.paragraphControl.pid); + } + + initEditorFocus() { + if (this.focus && this.editor) { + this.editor.focus(); + } + } + + updateEditorOptions() { + if (this.editor) { + this.editor.updateOptions({ + readOnly: this.readOnly, + fontSize: this.fontSize, + renderLineHighlight: this.focus ? 'all' : 'none', + minimap: { enabled: false }, + lineNumbers: this.lineNumbers ? 'on' : 'off', + glyphMargin: false, + folding: false, + scrollBeyondLastLine: false + }); + } + } + + getInterpreterName(paragraphText: string) { + const match = /^\s*%(.+?)(\s|\()/g.exec(paragraphText); + if (match) { + return match[1].trim(); + // get default interpreter name if paragraph text doesn't start with '%' + // TODO(hsuanxyz): dig into the cause what makes interpreterBindings to have no element + } else if (this.interpreterBindings && this.interpreterBindings.length !== 0) { + return this.interpreterBindings[0].name; + } + return ''; + } + + setParagraphMode(changed = false) { + if (this.editor && !changed) { + const model = this.editor.getModel(); + if (this.language) { + // TODO(hsuanxyz): config convertMap + const convertMap = { + sh: 'shell' + }; + monaco.editor.setModelLanguage(model, convertMap[this.language] || this.language); + } + } else { + const interpreterName = this.getInterpreterName(this.text); + if (this.interpreterName !== interpreterName) { + this.interpreterName = interpreterName; + this.getEditorSetting(interpreterName); + } + } + } + + getEditorSetting(interpreterName: string) { + this.messageService.editorSetting(this.pid, interpreterName); + } + + layout() { + if (this.editor) { + setTimeout(() => { + this.editor.layout(); + }); + } + } + + constructor( + private cdr: ChangeDetectorRef, + private ngZone: NgZone, + private messageService: MessageService, + private completionService: CompletionService + ) {} + + ngOnChanges(changes: SimpleChanges): void { + const { text, interpreterBindings, language, readOnly, focus, lineNumbers, fontSize } = changes; + if (readOnly || focus || lineNumbers || fontSize) { + this.updateEditorOptions(); + } + if (focus) { + this.initEditorFocus(); + } + if (text) { + this.setEditorValue(); + } + + if (interpreterBindings || language) { + this.setParagraphMode(); + } + if (text || fontSize) { + this.autoAdjustEditorHeight(); + } + } + + ngOnDestroy(): void { + this.completionService.unregister(this.editor.getModel()); + this.monacoDisposables.forEach(d => d.dispose()); + } + + ngAfterViewInit(): void {} +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.html new file mode 100644 index 00000000000..5ec5f52fccf --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.html @@ -0,0 +1,85 @@ + + + +
{{status}}
+
{{progress}}%
+ + + + + + + + + + + + + + + +
    +
  • + {{ pid }} +
  • +
  • +
  • + Run on selection change + +
  • +
  • + Width + + + +
  • +
  • + Font size + + + +
  • + +
  • + + {{menu.label}} + {{menu.shortCut}} +
  • +
    +
+
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.less new file mode 100644 index 00000000000..700a6b666e8 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.less @@ -0,0 +1,73 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +:host { + display: flex; +} + +.list-item { + display: flex; + justify-content: space-between; +} + +.setting-menu { + width: 270px; + + li { + font-size: 12px; + + i { + margin-right: 6px; + } + } +} + +.short-cut { + opacity: 0.7; +} + +.paragraph-id { + text-align: center; +} + +.themeMixin({ + .job-link { + margin-right: 12px; + + a { + color: @link-color; + } + } + .status { + color: @text-color-secondary; + margin-right: 12px; + } + .progress { + color: @text-color-secondary; + margin-right: 12px; + } + + a { + margin-left: 8px; + color: @text-color-secondary; + + .run-para { + color: @primary-color; + } + + .cancel-para { + color: @warning-color; + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts new file mode 100644 index 00000000000..085fa266b2e --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/control/control.component.ts @@ -0,0 +1,304 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnChanges, + OnInit, + Output +} from '@angular/core'; +import { copyTextToClipboard } from '@zeppelin/core'; + +import { NzMessageService, NzModalService } from 'ng-zorro-antd'; + +import { ActivatedRoute } from '@angular/router'; +import { RuntimeInfos } from '@zeppelin/sdk'; +import { MessageService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-notebook-paragraph-control', + exportAs: 'paragraphControl', + templateUrl: './control.component.html', + styleUrls: ['./control.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookParagraphControlComponent implements OnInit, OnChanges { + @Input() status: string; + @Input() progress = 0; + @Input() revisionView = false; + @Input() enabled = true; + @Input() pid: string; + @Input() tableHide = false; + @Input() editorHide = false; + @Input() colWidth: number; + @Input() fontSize: number; + @Input() runOnSelectionChange = true; + @Input() isEntireNoteRunning = true; + @Input() runtimeInfos: RuntimeInfos; + @Input() colWidthOption = []; + @Input() first = false; + @Input() last = false; + @Input() title = false; + @Input() lineNumbers = false; + @Input() paragraphLength: number; + @Output() readonly colWidthChange = new EventEmitter(); + @Output() readonly titleChange = new EventEmitter(); + @Output() readonly enabledChange = new EventEmitter(); + @Output() readonly fontSizeChange = new EventEmitter(); + @Output() readonly tableHideChange = new EventEmitter(); + @Output() readonly runParagraph = new EventEmitter(); + @Output() readonly lineNumbersChange = new EventEmitter(); + @Output() readonly cancelParagraph = new EventEmitter(); + @Output() readonly editorHideChange = new EventEmitter(); + @Output() readonly runOnSelectionChangeChange = new EventEmitter(); + @Output() readonly moveUp = new EventEmitter(); + @Output() readonly moveDown = new EventEmitter(); + @Output() readonly insertNew = new EventEmitter(); + @Output() readonly runAllAbove = new EventEmitter(); + @Output() readonly runAllBelowAndCurrent = new EventEmitter(); + @Output() readonly cloneParagraph = new EventEmitter(); + fontSizeOption = [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; + dropdownVisible = false; + isMac = navigator.appVersion.indexOf('Mac') !== -1; + listOfMenu: Array<{ + label: string; + show: boolean; + disabled: boolean; + icon: string; + shortCut: string; + keyBindings: number[]; + trigger(): void; + }> = []; + + updateListOfMenu(monaco?) { + this.listOfMenu = [ + { + label: 'Move up', + show: !this.first, + disabled: this.isEntireNoteRunning, + icon: 'up', + trigger: () => this.trigger(this.moveUp), + shortCut: `Ctrl+${this.isMac ? 'Option' : 'Alt'}+K`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KEY_K] : [] + }, + { + label: 'Move down', + show: !this.last, + disabled: this.isEntireNoteRunning, + icon: 'down', + trigger: () => this.trigger(this.moveDown), + shortCut: `Ctrl+${this.isMac ? 'Option' : 'Alt'}+J`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KEY_J] : [] + }, + { + label: 'Insert new', + show: true, + disabled: this.isEntireNoteRunning, + icon: 'plus', + trigger: () => this.trigger(this.insertNew), + shortCut: `Ctrl+${this.isMac ? 'Option' : 'Alt'}+B`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KEY_B] : [] + }, + { + label: 'Run all above', + show: !this.first, + disabled: this.isEntireNoteRunning, + icon: 'up-square', + trigger: () => this.trigger(this.runAllAbove), + shortCut: `Ctrl+Shift+Enter`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Shift | monaco.KeyCode.Enter] : [] + }, + { + label: 'Run all below', + show: !this.last, + disabled: this.isEntireNoteRunning, + icon: 'down-square', + trigger: () => this.trigger(this.runAllBelowAndCurrent), + shortCut: `Ctrl+Shift+Enter`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Shift | monaco.KeyCode.Enter] : [] + }, + { + label: 'Clone paragraph', + show: true, + disabled: this.isEntireNoteRunning, + icon: 'copy', + trigger: () => this.trigger(this.cloneParagraph), + shortCut: `Ctrl+Shift+C`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Shift | monaco.KeyCode.KEY_C] : [] + }, + { + label: this.title ? 'Hide Title' : 'Show Title', + show: true, + disabled: false, + icon: 'font-colors', + trigger: () => this.toggleTitle(), + shortCut: `Ctrl+${this.isMac ? 'Option' : 'Alt'}+T`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KEY_T] : [] + }, + { + label: this.lineNumbers ? 'Hide line numbers' : 'Show line numbers', + show: true, + disabled: false, + icon: 'ordered-list', + trigger: () => this.toggleLineNumbers(), + shortCut: `Ctrl+${this.isMac ? 'Option' : 'Alt'}+M`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KEY_M] : [] + }, + { + label: this.enabled ? 'Disable run' : 'Enable run', + show: true, + disabled: this.isEntireNoteRunning, + icon: 'api', + trigger: () => this.toggleEnabled(), + shortCut: `Ctrl+${this.isMac ? 'Option' : 'Alt'}+R`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KEY_R] : [] + }, + { + label: 'Link this paragraph', + show: true, + disabled: false, + icon: 'export', + trigger: () => this.goToSingleParagraph(), + shortCut: `Ctrl+${this.isMac ? 'Option' : 'Alt'}+W`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KEY_W] : [] + }, + { + label: 'Clear output', + show: true, + disabled: this.isEntireNoteRunning, + icon: 'fire', + trigger: () => this.clearParagraphOutput(), + shortCut: `Ctrl+${this.isMac ? 'Option' : 'Alt'}+L`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KEY_L] : [] + }, + { + label: 'Remove', + show: this.paragraphLength > 1, + disabled: this.isEntireNoteRunning, + icon: 'delete', + trigger: () => this.removeParagraph(), + shortCut: `Ctrl+${this.isMac ? 'Option' : 'Alt'}+D`, + keyBindings: monaco ? [monaco.KeyMod.WinCtrl | monaco.KeyMod.Alt | monaco.KeyCode.KEY_D] : [] + } + ]; + } + + toggleEditor() { + this.editorHide = !this.editorHide; + this.editorHideChange.emit(this.editorHide); + } + + toggleOutput() { + this.tableHide = !this.tableHide; + this.tableHideChange.emit(this.tableHide); + } + + toggleRunOnSelectionChange() { + this.runOnSelectionChange = !this.runOnSelectionChange; + this.runOnSelectionChangeChange.emit(this.runOnSelectionChange); + } + + toggleTitle() { + this.title = !this.title; + this.titleChange.emit(this.title); + } + + toggleLineNumbers() { + this.lineNumbers = !this.lineNumbers; + this.lineNumbersChange.emit(this.lineNumbers); + } + + toggleEnabled() { + if (!this.isEntireNoteRunning) { + this.enabled = !this.enabled; + this.enabledChange.emit(this.enabled); + } + } + + goToSingleParagraph() { + // TODO(hsuanxyz) asIframe + const { noteId } = this.activatedRoute.snapshot.params; + const redirectToUrl = `${location.protocol}//${location.host}${location.pathname}#/notebook/${noteId}/paragraph/${this.pid}`; + window.open(redirectToUrl); + } + + changeColWidth(colWidth: number) { + this.colWidth = +colWidth; + this.colWidthChange.emit(this.colWidth); + this.dropdownVisible = false; + } + + changeFontSize(fontSize: number) { + this.fontSize = +fontSize; + this.fontSizeChange.emit(this.fontSize); + } + + copyClipboard(id: string) { + copyTextToClipboard(id); + this.nzMessageService.info('Paragraph id copied'); + } + + clearParagraphOutput() { + if (!this.isEntireNoteRunning) { + this.messageService.paragraphClearOutput(this.pid); + } + } + + removeParagraph() { + if (!this.isEntireNoteRunning) { + if (this.paragraphLength === 1) { + this.nzModalService.warning({ + nzTitle: `Warning`, + nzContent: `All the paragraphs can't be deleted` + }); + } else { + this.nzModalService.confirm({ + nzTitle: 'Delete Paragraph', + nzContent: 'Do you want to delete this paragraph?', + nzOnOk: () => { + this.messageService.paragraphRemove(this.pid); + this.cdr.markForCheck(); + // TODO(hsuanxyz) moveFocusToNextParagraph + } + }); + } + } + } + + trigger(event: EventEmitter) { + if (!this.isEntireNoteRunning) { + this.dropdownVisible = false; + event.emit(); + } + } + + constructor( + private cdr: ChangeDetectorRef, + private nzMessageService: NzMessageService, + private activatedRoute: ActivatedRoute, + private messageService: MessageService, + private nzModalService: NzModalService + ) {} + + ngOnInit() { + this.updateListOfMenu(); + } + + ngOnChanges(): void { + this.updateListOfMenu(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/dynamic-forms/dynamic-forms.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/dynamic-forms/dynamic-forms.component.html new file mode 100644 index 00000000000..3a4cfdd5ff0 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/dynamic-forms/dynamic-forms.component.html @@ -0,0 +1,51 @@ + + +
+
+ + + + + + + + + + +
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/dynamic-forms/dynamic-forms.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/dynamic-forms/dynamic-forms.component.less new file mode 100644 index 00000000000..060b2f8485d --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/dynamic-forms/dynamic-forms.component.less @@ -0,0 +1,24 @@ +/* + * 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. + */ + +:host { + display: block; + .form-item { + margin-bottom: 24px; + nz-select { + width: 100%; + } + ::ng-deep .ant-checkbox-wrapper { + margin-left: 0; + } + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/dynamic-forms/dynamic-forms.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/dynamic-forms/dynamic-forms.component.ts new file mode 100644 index 00000000000..0dab7ec7221 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/dynamic-forms/dynamic-forms.component.ts @@ -0,0 +1,120 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + HostListener, + Input, + OnChanges, + OnDestroy, + OnInit, + Output, + SimpleChanges +} from '@angular/core'; +import { Subject } from 'rxjs'; +import { debounceTime, takeUntil } from 'rxjs/operators'; + +import { NzCheckBoxOptionInterface } from 'ng-zorro-antd'; + +import { DynamicForms, DynamicFormsItem, DynamicFormsType, DynamicFormParams } from '@zeppelin/sdk'; + +@Component({ + selector: 'zeppelin-notebook-paragraph-dynamic-forms', + templateUrl: './dynamic-forms.component.html', + styleUrls: ['./dynamic-forms.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookParagraphDynamicFormsComponent implements OnInit, OnChanges, OnDestroy { + private destroy$ = new Subject(); + + @Input() formDefs: DynamicForms; + @Input() paramDefs: DynamicFormParams; + @Input() runOnChange = false; + @Input() disable = false; + @Output() readonly formChange = new EventEmitter(); + + formChange$ = new Subject(); + forms: DynamicFormsItem[] = []; + formType = DynamicFormsType; + checkboxGroups: { + [key: string]: NzCheckBoxOptionInterface[]; + } = {}; + + @HostListener('keydown.enter') + onEnter() { + if (!this.runOnChange) { + this.formChange.emit(); + } + } + + trackByNameFn(_index, form: DynamicFormsItem) { + return form.name; + } + + setForms() { + this.forms = Object.values(this.formDefs); + this.checkboxGroups = {}; + this.forms.forEach(e => { + if (!this.paramDefs[e.name]) { + this.paramDefs[e.name] = e.defaultValue; + } + if (e.type === DynamicFormsType.CheckBox) { + this.checkboxGroups[e.name] = e.options.map(opt => { + let checked = false; + if (this.paramDefs[e.name] && Array.isArray(this.paramDefs[e.name])) { + const param = this.paramDefs[e.name] as string[]; + checked = param.indexOf(opt.value) !== -1; + } + return { + checked, + label: opt.displayName || opt.value, + value: opt.value + }; + }); + } + }); + } + + checkboxChange(value: NzCheckBoxOptionInterface[], name) { + this.paramDefs[name] = value.filter(e => e.checked).map(e => e.value); + this.onFormChange(); + } + + onFormChange() { + if (this.runOnChange) { + this.formChange$.next(); + } + } + + constructor() {} + + ngOnInit() { + this.setForms(); + this.formChange$ + .pipe( + debounceTime(800), + takeUntil(this.destroy$) + ) + .subscribe(() => this.formChange.emit()); + } + + ngOnChanges(changes: SimpleChanges): void { + this.setForms(); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/footer/footer.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/footer/footer.component.html new file mode 100644 index 00000000000..677356b1d5d --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/footer/footer.component.html @@ -0,0 +1,16 @@ + + + diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/footer/footer.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/footer/footer.component.less new file mode 100644 index 00000000000..767a5491765 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/footer/footer.component.less @@ -0,0 +1,21 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + .footer { + color: @text-color-secondary; + font-size: 12px; + margin-top: 12px; + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/footer/footer.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/footer/footer.component.ts new file mode 100644 index 00000000000..1be51ca9c31 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/footer/footer.component.ts @@ -0,0 +1,74 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; + +import * as distanceInWordsStrict from 'date-fns/distance_in_words_strict'; +import * as distanceInWordsToNow from 'date-fns/distance_in_words_to_now'; +import * as format from 'date-fns/format'; + +@Component({ + selector: 'zeppelin-notebook-paragraph-footer', + templateUrl: './footer.component.html', + styleUrls: ['./footer.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookParagraphFooterComponent implements OnChanges { + @Input() dateStarted: string; + @Input() dateFinished: string; + @Input() dateUpdated: string; + @Input() showExecutionTime = false; + @Input() showElapsedTime = false; + @Input() user: string; + executionTime: string; + elapsedTime: string; + + isResultOutdated() { + return this.dateUpdated !== undefined && Date.parse(this.dateUpdated) > Date.parse(this.dateStarted); + } + + getExecutionTime() { + const end = this.dateFinished; + const start = this.dateStarted; + const timeMs = Date.parse(end) - Date.parse(start); + if (isNaN(timeMs) || timeMs < 0) { + if (this.isResultOutdated()) { + return 'outdated'; + } + return ''; + } + + const durationFormat = distanceInWordsStrict(start, end); + const endFormat = format(this.dateFinished, 'MMMM DD YYYY, h:mm:ss A'); + + const user = this.user === undefined || this.user === null ? 'anonymous' : this.user; + let desc = `Took ${durationFormat}. Last updated by ${user} at ${endFormat}.`; + + if (this.isResultOutdated()) { + desc += ' (outdated)'; + } + + return desc; + } + + getElapsedTime() { + // TODO(hsuanxyz) dateStarted undefined after start + return `Started ${distanceInWordsToNow(this.dateStarted || new Date())} ago.`; + } + + constructor() {} + + ngOnChanges() { + this.executionTime = this.getExecutionTime(); + this.elapsedTime = this.getElapsedTime(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html new file mode 100644 index 00000000000..861f955e261 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.html @@ -0,0 +1,99 @@ + + +
+ +
+ + + + + + + + + + + +
+ +
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.less new file mode 100644 index 00000000000..f24d693f1e8 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.less @@ -0,0 +1,72 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +:host { + display: block; + padding: 0 4px; +} + +.themeMixin({ + .paragraph { + background: @component-background; + border: 1px solid @border-color-split; + box-shadow: @card-shadow; + padding: 32px 12px 12px 12px; + position: relative; + + zeppelin-notebook-paragraph-code-editor + zeppelin-notebook-paragraph-dynamic-forms { + margin-top: 24px; + } + + zeppelin-notebook-paragraph-progress + zeppelin-notebook-paragraph-dynamic-forms { + margin-top: 24px; + } + + &.simple { + box-shadow: none; + border-color: transparent; + + zeppelin-notebook-paragraph-control, zeppelin-notebook-paragraph-footer { + visibility: hidden; + } + + &:hover { + border: 1px solid @border-color-split; + box-shadow: @card-shadow; + + zeppelin-notebook-paragraph-control, zeppelin-notebook-paragraph-footer { + visibility: visible; + } + } + } + + &.report { + &:hover { + box-shadow: none; + border-color: transparent; + + zeppelin-notebook-paragraph-control, zeppelin-notebook-paragraph-footer { + visibility: hidden; + } + } + } + + zeppelin-notebook-paragraph-control { + position: absolute; + right: 12px; + top: 8px; + z-index: 10; + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.ts new file mode 100644 index 00000000000..21d57bb6e17 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/paragraph.component.ts @@ -0,0 +1,653 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnChanges, + OnDestroy, + OnInit, + Output, + QueryList, + ViewChild, + ViewChildren +} from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +import DiffMatchPatch from 'diff-match-patch'; +import { isEmpty, isEqual } from 'lodash'; +import { NzModalService } from 'ng-zorro-antd'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { + AngularObjectRemove, + AngularObjectUpdate, + GraphConfig, + InterpreterBindingItem, + MessageReceiveDataTypeMap, + Note, + OP, + ParagraphConfig, + ParagraphConfigResult, + ParagraphEditorSetting, + ParagraphItem, + ParagraphIResultsMsgItem +} from '@zeppelin/sdk'; +import { + HeliumService, + MessageService, + NgZService, + NoteStatusService, + NoteVarShareService, + ParagraphStatus +} from '@zeppelin/services'; +import { SpellResult } from '@zeppelin/spell/spell-result'; + +import { NzResizeEvent } from 'ng-zorro-antd/resizable'; +import { NotebookParagraphCodeEditorComponent } from './code-editor/code-editor.component'; +import { NotebookParagraphResultComponent } from './result/result.component'; + +@Component({ + selector: 'zeppelin-notebook-paragraph', + templateUrl: './paragraph.component.html', + styleUrls: ['./paragraph.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookParagraphComponent extends MessageListenersManager implements OnInit, OnChanges, OnDestroy { + @ViewChild(NotebookParagraphCodeEditorComponent, { static: false }) + notebookParagraphCodeEditorComponent: NotebookParagraphCodeEditorComponent; + @ViewChildren(NotebookParagraphResultComponent) notebookParagraphResultComponents: QueryList< + NotebookParagraphResultComponent + >; + @Input() paragraph: ParagraphItem; + @Input() note: Note['note']; + @Input() looknfeel: string; + @Input() revisionView: boolean; + @Input() viewOnly: boolean; + @Input() last: boolean; + @Input() collaborativeMode = false; + @Input() first: boolean; + @Input() interpreterBindings: InterpreterBindingItem[] = []; + @Output() readonly saveNoteTimer = new EventEmitter(); + @Output() readonly triggerSaveParagraph = new EventEmitter(); + + private destroy$ = new Subject(); + dirtyText: string; + originalText: string; + isEntireNoteRunning = false; + diffMatchPatch = new DiffMatchPatch(); + isParagraphRunning = false; + results = []; + configs = {}; + progress = 0; + colWidthOption = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + editorSetting: ParagraphEditorSetting = {}; + + @MessageListener(OP.PROGRESS) + onProgress(data: MessageReceiveDataTypeMap[OP.PROGRESS]) { + if (data.id === this.paragraph.id) { + this.progress = data.progress; + this.cdr.markForCheck(); + } + } + + @MessageListener(OP.NOTE_RUNNING_STATUS) + noteRunningStatusChange(data: MessageReceiveDataTypeMap[OP.NOTE_RUNNING_STATUS]) { + this.isEntireNoteRunning = data.status; + this.cdr.markForCheck(); + } + + @MessageListener(OP.PARAS_INFO) + updateParaInfos(data: MessageReceiveDataTypeMap[OP.PARAS_INFO]) { + if (this.paragraph.id === data.id) { + this.paragraph.runtimeInfos = data.infos; + this.cdr.markForCheck(); + } + } + + @MessageListener(OP.EDITOR_SETTING) + getEditorSetting(data: MessageReceiveDataTypeMap[OP.EDITOR_SETTING]) { + if (this.paragraph.id === data.paragraphId) { + this.paragraph.config.editorSetting = { ...this.paragraph.config.editorSetting, ...data.editor }; + this.cdr.markForCheck(); + } + } + + @MessageListener(OP.PARAGRAPH) + paragraphData(data: MessageReceiveDataTypeMap[OP.PARAGRAPH]) { + const oldPara = this.paragraph; + const newPara = data.paragraph; + if (this.isUpdateRequired(oldPara, newPara)) { + this.updateParagraph(oldPara, newPara, () => { + if (newPara.results && newPara.results.msg) { + // tslint:disable-next-line:no-for-in-array + for (const i in newPara.results.msg) { + if (newPara.results.msg[i]) { + const newResult = newPara.results.msg ? newPara.results.msg[i] : new ParagraphIResultsMsgItem(); + const oldResult = + oldPara.results && oldPara.results.msg ? oldPara.results.msg[i] : new ParagraphIResultsMsgItem(); + const newConfig = newPara.config.results ? newPara.config.results[i] : { graph: new GraphConfig() }; + const oldConfig = oldPara.config.results ? oldPara.config.results[i] : { graph: new GraphConfig() }; + if (!isEqual(newResult, oldResult) || !isEqual(newConfig, oldConfig)) { + const resultComponent = this.notebookParagraphResultComponents.toArray()[i]; + if (resultComponent) { + resultComponent.updateResult(newConfig, newResult); + } + } + } + } + } + this.cdr.markForCheck(); + }); + this.cdr.markForCheck(); + } + } + + @MessageListener(OP.PATCH_PARAGRAPH) + patchParagraph(data: MessageReceiveDataTypeMap[OP.PATCH_PARAGRAPH]) { + if (data.paragraphId === this.paragraph.id) { + let patch = data.patch; + patch = this.diffMatchPatch.patch_fromText(patch); + if (!this.paragraph.text) { + this.paragraph.text = ''; + } + this.paragraph.text = this.diffMatchPatch.patch_apply(patch, this.paragraph.text)[0]; + this.originalText = this.paragraph.text; + this.cdr.markForCheck(); + } + } + + @MessageListener(OP.ANGULAR_OBJECT_UPDATE) + angularObjectUpdate(data: AngularObjectUpdate) { + if (data.paragraphId === this.paragraph.id) { + const { name, object } = data.angularObject; + this.ngZService.setContextValue(name, object, data.paragraphId, false); + } + } + + @MessageListener(OP.ANGULAR_OBJECT_REMOVE) + angularObjectRemove(data: AngularObjectRemove) { + if (data.paragraphId === this.paragraph.id) { + this.ngZService.unsetContextValue(data.name, data.paragraphId, false); + } + } + + updateParagraph(oldPara: ParagraphItem, newPara: ParagraphItem, updateCallback: () => void) { + // 1. can't update on revision view + if (!this.revisionView) { + // 2. get status, refreshed + const statusChanged = newPara.status !== oldPara.status; + const resultRefreshed = + newPara.dateFinished !== oldPara.dateFinished || + isEmpty(newPara.results) !== isEmpty(oldPara.results) || + newPara.status === ParagraphStatus.ERROR || + (newPara.status === ParagraphStatus.FINISHED && statusChanged); + + // 3. update texts managed by paragraph + this.updateAllScopeTexts(oldPara, newPara); + // 4. execute callback to update result + updateCallback(); + + // 5. update remaining paragraph objects + this.updateParagraphObjectWhenUpdated(newPara); + + // 6. handle scroll down by key properly if new paragraph is added + if (statusChanged || resultRefreshed) { + // when last paragraph runs, zeppelin automatically appends new paragraph. + // this broadcast will focus to the newly inserted paragraph + // TODO(hsuanxyz) + } + this.cdr.markForCheck(); + } + } + + textChanged(text: string) { + this.dirtyText = text; + this.paragraph.text = text; + if (this.dirtyText !== this.originalText) { + if (this.collaborativeMode) { + this.sendPatch(); + } else { + this.startSaveTimer(); + } + } + } + + sendPatch() { + this.originalText = this.originalText ? this.originalText : ''; + const patch = this.diffMatchPatch.patch_make(this.originalText, this.dirtyText).toString(); + this.originalText = this.dirtyText; + this.messageService.patchParagraph(this.paragraph.id, this.note.id, patch); + } + + startSaveTimer() { + this.saveNoteTimer.emit(); + } + + saveParagraph() { + const dirtyText = this.paragraph.text; + if (dirtyText === undefined || dirtyText === this.originalText) { + return; + } + this.commitParagraph(); + this.originalText = dirtyText; + this.dirtyText = undefined; + this.cdr.markForCheck(); + } + + runAllAbove() { + const index = this.note.paragraphs.findIndex(p => p.id === this.paragraph.id); + const toRunParagraphs = this.note.paragraphs.filter((p, i) => i < index); + + const paragraphs = toRunParagraphs.map(p => { + return { + id: p.id, + title: p.title, + paragraph: p.text, + config: p.config, + params: p.settings.params + }; + }); + this.nzModalService.confirm({ + nzTitle: 'Run all above?', + nzContent: 'Are you sure to run all above paragraphs?', + nzOnOk: () => { + this.messageService.runAllParagraphs(this.note.id, paragraphs); + } + }); + // TODO(hsuanxyz): save cursor + } + + doubleClickParagraph() { + if (this.paragraph.config.editorSetting.editOnDblClick && this.revisionView !== true) { + this.paragraph.config.editorHide = false; + this.paragraph.config.tableHide = true; + // TODO(hsuanxyz): focus editor + } + } + + runAllBelowAndCurrent() { + const index = this.note.paragraphs.findIndex(p => p.id === this.paragraph.id); + const toRunParagraphs = this.note.paragraphs.filter((p, i) => i >= index); + + const paragraphs = toRunParagraphs.map(p => { + return { + id: p.id, + title: p.title, + paragraph: p.text, + config: p.config, + params: p.settings.params + }; + }); + this.nzModalService.confirm({ + nzTitle: 'Run current and all below?', + nzContent: 'Are you sure to run current and all below?', + nzOnOk: () => { + this.messageService.runAllParagraphs(this.note.id, paragraphs); + } + }); + // TODO(hsuanxyz): save cursor + } + + cloneParagraph(position: string = 'below') { + let newIndex = -1; + for (let i = 0; i < this.note.paragraphs.length; i++) { + if (this.note.paragraphs[i].id === this.paragraph.id) { + // determine position of where to add new paragraph; default is below + if (position === 'above') { + newIndex = i; + } else { + newIndex = i + 1; + } + break; + } + } + + if (newIndex < 0 || newIndex > this.note.paragraphs.length) { + return; + } + + const config = this.paragraph.config; + config.editorHide = false; + + this.messageService.copyParagraph( + newIndex, + this.paragraph.title, + this.paragraph.text, + config, + this.paragraph.settings.params + ); + } + + runParagraph(paragraphText?: string, propagated: boolean = false) { + const text = paragraphText || this.paragraph.text; + if (text && !this.isParagraphRunning) { + const magic = SpellResult.extractMagic(text); + + if (this.heliumService.getSpellByMagic(magic)) { + this.runParagraphUsingSpell(text, magic, propagated); + } else { + this.runParagraphUsingBackendInterpreter(text); + } + + this.originalText = text; + this.dirtyText = undefined; + + if (this.paragraph.config.editorSetting.editOnDblClick) { + this.paragraph.config.editorHide = true; + this.paragraph.config.tableHide = false; + this.commitParagraph(); + } else if (this.editorSetting.isOutputHidden && !this.paragraph.config.editorSetting.editOnDblClick) { + // %md/%angular repl make output to be hidden by default after running + // so should open output if repl changed from %md/%angular to another + this.paragraph.config.editorHide = false; + this.paragraph.config.tableHide = false; + this.commitParagraph(); + } + this.editorSetting.isOutputHidden = this.paragraph.config.editorSetting.editOnDblClick; + } + } + + runParagraphUsingSpell(paragraphText: string, magic: string, propagated: boolean) { + // TODO(hsuanxyz) + } + + runParagraphUsingBackendInterpreter(paragraphText: string) { + this.messageService.runParagraph( + this.paragraph.id, + this.paragraph.title, + paragraphText, + this.paragraph.config, + this.paragraph.settings.params + ); + } + + cancelParagraph() { + if (!this.isEntireNoteRunning) { + this.messageService.cancelParagraph(this.paragraph.id); + } + } + + updateAllScopeTexts(oldPara: ParagraphItem, newPara: ParagraphItem) { + if (oldPara.text !== newPara.text) { + if (this.dirtyText) { + // check if editor has local update + if (this.dirtyText === newPara.text) { + // when local update is the same from remote, clear local update + this.paragraph.text = newPara.text; + this.dirtyText = undefined; + this.originalText = newPara.text; + } else { + // if there're local update, keep it. + this.paragraph.text = newPara.text; + } + } else { + this.paragraph.text = newPara.text; + this.originalText = newPara.text; + } + } + this.cdr.markForCheck(); + } + + updateParagraphObjectWhenUpdated(newPara: ParagraphItem) { + if (this.paragraph.config.colWidth !== newPara.config.colWidth) { + this.changeColWidth(false); + } + this.paragraph.aborted = newPara.aborted; + this.paragraph.user = newPara.user; + this.paragraph.dateUpdated = newPara.dateUpdated; + this.paragraph.dateCreated = newPara.dateCreated; + this.paragraph.dateFinished = newPara.dateFinished; + this.paragraph.dateStarted = newPara.dateStarted; + this.paragraph.errorMessage = newPara.errorMessage; + this.paragraph.jobName = newPara.jobName; + this.paragraph.title = newPara.title; + this.paragraph.lineNumbers = newPara.lineNumbers; + this.paragraph.status = newPara.status; + this.paragraph.fontSize = newPara.fontSize; + if (newPara.status !== ParagraphStatus.RUNNING) { + this.paragraph.results = newPara.results; + } + this.paragraph.settings = newPara.settings; + this.paragraph.runtimeInfos = newPara.runtimeInfos; + this.isParagraphRunning = this.noteStatusService.isParagraphRunning(newPara); + this.paragraph.config = newPara.config; + this.initializeDefault(this.paragraph.config); + this.setResults(); + this.cdr.markForCheck(); + } + + isUpdateRequired(oldPara: ParagraphItem, newPara: ParagraphItem): boolean { + return ( + newPara.id === oldPara.id && + (newPara.dateCreated !== oldPara.dateCreated || + newPara.text !== oldPara.text || + newPara.dateFinished !== oldPara.dateFinished || + newPara.dateStarted !== oldPara.dateStarted || + newPara.dateUpdated !== oldPara.dateUpdated || + newPara.status !== oldPara.status || + newPara.jobName !== oldPara.jobName || + newPara.title !== oldPara.title || + isEmpty(newPara.results) !== isEmpty(oldPara.results) || + newPara.errorMessage !== oldPara.errorMessage || + !isEqual(newPara.settings, oldPara.settings) || + !isEqual(newPara.config, oldPara.config) || + !isEqual(newPara.runtimeInfos, oldPara.runtimeInfos)) + ); + } + + insertParagraph(position: string) { + if (this.revisionView === true) { + return; + } + let newIndex = -1; + for (let i = 0; i < this.note.paragraphs.length; i++) { + if (this.note.paragraphs[i].id === this.paragraph.id) { + // determine position of where to add new paragraph; default is below + if (position === 'above') { + newIndex = i; + } else { + newIndex = i + 1; + } + break; + } + } + + if (newIndex < 0 || newIndex > this.note.paragraphs.length) { + return; + } + this.messageService.insertParagraph(newIndex); + this.cdr.markForCheck(); + } + + setResults() { + if (this.paragraph.results) { + this.results = this.paragraph.results.msg; + this.configs = this.paragraph.config.results; + } + if (!this.paragraph.config) { + this.paragraph.config = {}; + } + } + + setTitle(title: string) { + this.paragraph.title = title; + this.commitParagraph(); + this.cdr.markForCheck(); + } + + commitParagraph() { + const { + id, + title, + text, + config, + settings: { params } + } = this.paragraph; + this.messageService.commitParagraph(id, title, text, config, params, this.note.id); + } + + initializeDefault(config: ParagraphConfig) { + const forms = this.paragraph.settings.forms; + + if (!config.colWidth) { + config.colWidth = 12; + } + + if (!config.fontSize) { + config.fontSize = 9; + } + + if (config.enabled === undefined) { + config.enabled = true; + } + + for (const idx in forms) { + if (forms[idx]) { + if (forms[idx].options) { + if (config.runOnSelectionChange === undefined) { + config.runOnSelectionChange = true; + } + } + } + } + + if (!config.results) { + config.results = {}; + } + + if (!config.editorSetting) { + config.editorSetting = {}; + } else if (config.editorSetting.editOnDblClick) { + this.editorSetting.isOutputHidden = config.editorSetting.editOnDblClick; + } + } + + moveUpParagraph() { + const newIndex = this.note.paragraphs.findIndex(p => p.id === this.paragraph.id) - 1; + if (newIndex < 0 || newIndex >= this.note.paragraphs.length) { + return; + } + // save dirtyText of moving paragraphs. + const prevParagraph = this.note.paragraphs[newIndex]; + // TODO(hsuanxyz): save pre paragraph? + this.saveParagraph(); + this.triggerSaveParagraph.emit(prevParagraph.id); + this.messageService.moveParagraph(this.paragraph.id, newIndex); + } + + moveDownParagraph() { + const newIndex = this.note.paragraphs.findIndex(p => p.id === this.paragraph.id) + 1; + if (newIndex < 0 || newIndex >= this.note.paragraphs.length) { + return; + } + // save dirtyText of moving paragraphs. + const nextParagraph = this.note.paragraphs[newIndex]; + // TODO(hsuanxyz): save pre paragraph? + this.saveParagraph(); + this.triggerSaveParagraph.emit(nextParagraph.id); + this.messageService.moveParagraph(this.paragraph.id, newIndex); + } + + changeColWidth(needCommit: boolean, updateResult = true) { + if (needCommit) { + this.commitParagraph(); + } + if (this.notebookParagraphCodeEditorComponent) { + this.notebookParagraphCodeEditorComponent.layout(); + } + + if (updateResult) { + this.notebookParagraphResultComponents.forEach(comp => { + comp.setGraphConfig(); + }); + } + } + + onSizeChange(resize: NzResizeEvent) { + this.paragraph.config.colWidth = resize.col; + this.changeColWidth(true, false); + this.cdr.markForCheck(); + } + + onConfigChange(configResult: ParagraphConfigResult, index: number) { + this.paragraph.config.results[index] = configResult; + this.commitParagraph(); + this.cdr.markForCheck(); + } + + setEditorHide(editorHide: boolean) { + this.paragraph.config.editorHide = editorHide; + this.cdr.markForCheck(); + } + + setTableHide(tableHide: boolean) { + this.paragraph.config.tableHide = tableHide; + this.cdr.markForCheck(); + } + + trackByIndexFn(index: number) { + return index; + } + + constructor( + private heliumService: HeliumService, + private noteStatusService: NoteStatusService, + public messageService: MessageService, + private nzModalService: NzModalService, + private noteVarShareService: NoteVarShareService, + private cdr: ChangeDetectorRef, + private ngZService: NgZService + ) { + super(messageService); + } + + ngOnInit() { + this.setResults(); + this.originalText = this.paragraph.text; + this.isEntireNoteRunning = this.noteStatusService.isEntireNoteRunning(this.note); + this.isParagraphRunning = this.noteStatusService.isParagraphRunning(this.paragraph); + this.noteVarShareService.set(this.paragraph.id + '_paragraphScope', this); + this.initializeDefault(this.paragraph.config); + this.ngZService + .runParagraphAction() + .pipe(takeUntil(this.destroy$)) + .subscribe(id => { + if (id === this.paragraph.id) { + this.runParagraph(); + } + }); + this.ngZService + .contextChanged() + .pipe(takeUntil(this.destroy$)) + .subscribe(change => { + if (change.paragraphId === this.paragraph.id && change.emit) { + if (change.set) { + this.messageService.angularObjectClientBind(this.note.id, change.key, change.value, change.paragraphId); + } else { + this.messageService.angularObjectClientUnbind(this.note.id, change.key, change.paragraphId); + } + } + }); + } + + ngOnChanges(): void {} + + ngOnDestroy(): void { + super.ngOnDestroy(); + this.ngZService.removeParagraph(this.paragraph.id); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/progress/progress.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/progress/progress.component.html new file mode 100644 index 00000000000..07c886a22d0 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/progress/progress.component.html @@ -0,0 +1,16 @@ + + + diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/progress/progress.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/progress/progress.component.less new file mode 100644 index 00000000000..019b5ca53b5 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/progress/progress.component.less @@ -0,0 +1,12 @@ +/* + * 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. + */ + diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/progress/progress.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/progress/progress.component.ts new file mode 100644 index 00000000000..ce205a0ad59 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/progress/progress.component.ts @@ -0,0 +1,32 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; + +@Component({ + selector: 'zeppelin-notebook-paragraph-progress', + templateUrl: './progress.component.html', + styleUrls: ['./progress.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookParagraphProgressComponent implements OnChanges { + @Input() progress = 0; + displayProgress = 0; + + ngOnChanges(): void { + if (this.progress > 0 && this.progress < 100) { + this.displayProgress = this.progress; + } else { + this.displayProgress = 100; + } + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/result/result.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/result/result.component.html new file mode 100644 index 00000000000..028c3e50089 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/result/result.component.html @@ -0,0 +1,74 @@ + + +
+
+ + + +
+ + + + + + +
    +
  • CSV
  • +
  • TSV
  • +
+
+ + + Setting + + +
+
+ + + + + +
+
+
img
+
+
+ +
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/result/result.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/result/result.component.less new file mode 100644 index 00000000000..f1970729ab9 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/result/result.component.less @@ -0,0 +1,78 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + display: block; + + .nz-resizable-preview { + left: -12px; + padding-right: 10px; + border: none; + &::before { + content: ' '; + display: block; + border: 1px dashed #d1d1d1; + width: 100%; + height: 100%; + } + } + + ::ng-deep { + .inner-html, .text-plain { + + overflow: auto; + + ol, ul, dl { + padding-left: 20px; + } + + img { + max-width: 100%; + height: auto; + width: auto; + } + } + } + + .text-plain { + font-size: 12px; + color: @text-color; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; + } + .setting-bar { + display: flex; + margin: 10px 0; + + .export-dropdown { + margin: 0 20px; + + .export-dropdown-icon-btn { + width: 32px; + height: 32px; + padding: 0; + font-size: 16px; + } + } + + .setting-trigger { + line-height: 32px; + + i { + font-size: 12px; + } + } + + } + +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/result/result.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/result/result.component.ts new file mode 100644 index 00000000000..850bc18a394 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/paragraph/result/result.component.ts @@ -0,0 +1,360 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkPortalOutlet } from '@angular/cdk/portal'; +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + EventEmitter, + Injector, + Input, + OnDestroy, + OnInit, + Output, + ViewChild, + ViewContainerRef +} from '@angular/core'; +import { DomSanitizer, SafeHtml, SafeUrl } from '@angular/platform-browser'; +import { Subject, Subscription } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +import * as Convert from 'ansi-to-html'; +import * as hljs from 'highlight.js'; +import { NzResizeEvent } from 'ng-zorro-antd/resizable'; +import { utils, writeFile, WorkSheet, WritingOptions } from 'xlsx'; + +import { + DatasetType, + GraphConfig, + ParagraphConfigResult, + ParagraphIResultsMsgItem, + VisualizationLineChart, + VisualizationMode, + VisualizationMultiBarChart, + VisualizationScatterChart, + VisualizationStackedAreaChart +} from '@zeppelin/sdk'; + +import { ZeppelinHeliumService } from '@zeppelin/helium'; +import { TableData, Visualization } from '@zeppelin/visualization'; + +import { HeliumManagerService } from '@zeppelin/helium-manager'; +import { DynamicTemplate, NgZService, RuntimeCompilerService } from '@zeppelin/services'; +import { AreaChartVisualization } from '@zeppelin/visualizations/area-chart/area-chart-visualization'; +import { BarChartVisualization } from '@zeppelin/visualizations/bar-chart/bar-chart-visualization'; +import { LineChartVisualization } from '@zeppelin/visualizations/line-chart/line-chart-visualization'; +import { PieChartVisualization } from '@zeppelin/visualizations/pie-chart/pie-chart-visualization'; +import { ScatterChartVisualization } from '@zeppelin/visualizations/scatter-chart/scatter-chart-visualization'; +import { TableVisualization } from '@zeppelin/visualizations/table/table-visualization'; + +@Component({ + selector: 'zeppelin-notebook-paragraph-result', + templateUrl: './result.component.html', + styleUrls: ['./result.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookParagraphResultComponent implements OnInit, AfterViewInit, OnDestroy { + @Input() result: ParagraphIResultsMsgItem; + @Input() config: ParagraphConfigResult; + @Input() id: string; + @Input() currentCol = 12; + @Output() readonly configChange = new EventEmitter(); + @Output() readonly sizeChange = new EventEmitter(); + @ViewChild(CdkPortalOutlet, { static: false }) portalOutlet: CdkPortalOutlet; + + private destroy$ = new Subject(); + datasetType = DatasetType; + angularComponent: DynamicTemplate; + innerHTML: string | SafeHtml = ''; + plainText: string | SafeHtml = ''; + imgData: string | SafeUrl = ''; + tableData = new TableData(); + // tslint:disable-next-line:no-any + visualizations: any[] = [ + { + id: 'table', + name: 'Table', + icon: 'table', + Class: TableVisualization, + changeSubscription: null, + instance: undefined + }, + { + id: 'multiBarChart', + name: 'Bar Chart', + icon: 'bar-chart', + Class: BarChartVisualization, + changeSubscription: null, + instance: undefined + }, + { + id: 'pieChart', + name: 'Pie Chart', + icon: 'pie-chart', + Class: PieChartVisualization, + changeSubscription: null, + instance: undefined + }, + { + id: 'lineChart', + name: 'Line Chart', + icon: 'line-chart', + Class: LineChartVisualization, + changeSubscription: null, + instance: undefined + }, + { + id: 'stackedAreaChart', + name: 'Area Chart', + icon: 'area-chart', + Class: AreaChartVisualization, + changeSubscription: null, + instance: undefined + }, + { + id: 'scatterChart', + name: 'Scatter Chart', + icon: 'dot-chart', + Class: ScatterChartVisualization, + changeSubscription: null, + instance: undefined + } + ]; + + constructor( + private viewContainerRef: ViewContainerRef, + private cdr: ChangeDetectorRef, + private runtimeCompilerService: RuntimeCompilerService, + private sanitizer: DomSanitizer, + private injector: Injector, + private ngZService: NgZService, + private zeppelinHeliumService: ZeppelinHeliumService, + private heliumManagerService: HeliumManagerService + ) { + this.heliumManagerService + .packagesLoadChange() + .pipe(takeUntil(this.destroy$)) + .subscribe(packages => { + packages.forEach(pack => { + this.visualizations.push({ + id: pack._raw.id, + name: pack.name, + icon: pack._raw.icon, + Class: pack._raw.visualization, + componentFactoryResolver: pack.moduleFactory.create(this.injector).componentFactoryResolver, + changeSubscription: null, + instance: undefined + }); + }); + this.cdr.markForCheck(); + }); + } + + ngOnInit() { + this.ngZService + .contextChanged() + .pipe(takeUntil(this.destroy$)) + .subscribe(change => { + if (change.paragraphId === this.id) { + this.cdr.markForCheck(); + } + }); + } + + exportFile(type: 'csv' | 'tsv'): void { + if (this.tableData && this.tableData.rows) { + const wb = utils.book_new(); + let ws: WorkSheet; + ws = utils.json_to_sheet(this.tableData.rows); + utils.book_append_sheet(wb, ws, 'Sheet1'); + writeFile(wb, `export.${type}`, { + bookType: 'csv', + FS: type === 'tsv' ? '\t' : ',' + } as WritingOptions); + } + } + + switchMode(mode: VisualizationMode) { + this.config.graph.mode = mode; + this.renderGraph(); + this.configChange.emit(this.config); + } + + switchSetting() { + this.config.graph.optionOpen = !this.config.graph.optionOpen; + this.renderGraph(); + this.configChange.emit(this.config); + } + + updateResult(config: ParagraphConfigResult, result: ParagraphIResultsMsgItem) { + this.config = config; + this.result = result; + this.renderDefaultDisplay(); + } + + renderDefaultDisplay() { + switch (this.result.type) { + case DatasetType.TABLE: + this.renderGraph(); + break; + case DatasetType.TEXT: + this.renderText(); + break; + case DatasetType.HTML: + this.renderHTML(); + break; + case DatasetType.IMG: + this.renderImg(); + break; + case DatasetType.ANGULAR: + this.renderAngular(); + break; + } + this.cdr.markForCheck(); + } + + renderHTML(): void { + const div = document.createElement('div'); + div.innerHTML = this.result.data; + const codeEle: HTMLElement = div.querySelector('pre code'); + if (codeEle) { + hljs.highlightBlock(codeEle); + } + this.innerHTML = this.sanitizer.bypassSecurityTrustHtml(div.innerHTML); + } + + renderAngular(): void { + this.runtimeCompilerService.createAndCompileTemplate(this.id, this.result.data).then(data => { + this.angularComponent = data; + // this.angularComponent.moduleFactory + this.cdr.markForCheck(); + }); + } + + renderText(): void { + // tslint:disable-next-line:no-any + const convert: any = new Convert(); + this.plainText = this.sanitizer.bypassSecurityTrustHtml(convert.toHtml(this.result.data)); + } + + renderImg(): void { + this.imgData = this.sanitizer.bypassSecurityTrustUrl(`data:image/png;base64,${this.result.data}`); + } + + setGraphConfig() { + const visualizationItem = this.visualizations.find(v => v.id === this.config.graph.mode); + if (!visualizationItem || !visualizationItem.instance) { + return; + } + visualizationItem.instance.setConfig(this.config.graph); + } + + renderGraph() { + this.setDefaultConfig(); + let instance: Visualization; + const visualizationItem = this.visualizations.find(v => v.id === this.config.graph.mode); + if (!visualizationItem) { + return; + } + this.destroyVisualizations(this.config.graph.mode); + if (!visualizationItem.instance) { + // tslint:disable-next-line:no-any + instance = new visualizationItem.Class( + this.config.graph, + this.portalOutlet, + this.viewContainerRef, + visualizationItem.componentFactoryResolver + ); + visualizationItem.instance = instance; + visualizationItem.changeSubscription = instance.configChanged().subscribe(config => { + this.config.graph = config; + this.renderGraph(); + this.configChange.emit({ + graph: config + }); + }); + } else { + instance = visualizationItem.instance; + instance.setConfig(this.config.graph); + } + this.tableData.loadParagraphResult(this.result); + const transformation = instance.getTransformation(); + transformation.setConfig(this.config.graph); + transformation.setTableData(this.tableData); + const transformed = transformation.transform(this.tableData); + instance.render(transformed); + } + + destroyVisualizations(omit?: string) { + this.visualizations.forEach(v => { + if (v.id !== omit && v.instance) { + if (v.changeSubscription instanceof Subscription) { + v.changeSubscription.unsubscribe(); + v.changeSubscription = null; + } + if (typeof v.instance.destroy === 'function') { + v.instance.destroy(); + } + v.instance = undefined; + } + }); + } + + setDefaultConfig() { + if (!this.config || !this.config.graph) { + this.config = { graph: new GraphConfig() }; + } + if (!this.config.graph.setting) { + this.config.graph.setting = {}; + } + if (!this.config.graph.setting[this.config.graph.mode]) { + switch (this.config.graph.mode) { + case 'multiBarChart': + this.config.graph.setting[this.config.graph.mode] = new VisualizationMultiBarChart(); + break; + case 'stackedAreaChart': + this.config.graph.setting[this.config.graph.mode] = new VisualizationStackedAreaChart(); + break; + case 'lineChart': + this.config.graph.setting[this.config.graph.mode] = new VisualizationLineChart(); + break; + case 'scatterChart': + this.config.graph.setting[this.config.graph.mode] = new VisualizationScatterChart(); + break; + default: + break; + } + } + } + + onResize($event: NzResizeEvent) { + const { width, height, col } = $event; + if (this.result.type === DatasetType.TABLE) { + this.config.graph.height = height; + this.setGraphConfig(); + } + this.sizeChange.emit({ width, height, col }); + } + + ngAfterViewInit(): void { + this.renderDefaultDisplay(); + } + + ngOnDestroy(): void { + this.destroyVisualizations(); + this.destroy$.next(); + this.destroy$.complete(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/permissions/permissions.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/permissions/permissions.component.html new file mode 100644 index 00000000000..c3e699d4aef --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/permissions/permissions.component.html @@ -0,0 +1,88 @@ + + +
+
+

Note Permissions (Only note owners can change)

+
+ +
+

+ Enter comma separated users and groups in the fields.
+ Empty field (*) implies anyone can do the operation. +

+
+
+
+ + Owners + + + + + + + + + + Owners can change permissions,read, run and write the note. + + + + Writers + + + + + + + + + + Writers can read, run and write the note. + + + + Runners + + + + + + + + + + Runners can read and run the note. + + + + Readers + + + + + + + + + + Readers can only read the note. + + +
+
+ + +
+
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/permissions/permissions.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/permissions/permissions.component.less new file mode 100644 index 00000000000..146cd37f4af --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/permissions/permissions.component.less @@ -0,0 +1,33 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + .permissions-form { + background: @layout-body-background; + padding: 12px; + margin-bottom: 12px; + } + nz-form-item { + margin-bottom: 12px; + + &:last-child { + margin-bottom: 0; + } + } + .submit-permissions { + button { + margin-right: 12px; + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/permissions/permissions.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/permissions/permissions.component.ts new file mode 100644 index 00000000000..eb749c108fb --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/permissions/permissions.component.ts @@ -0,0 +1,135 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnChanges, + OnInit, + Output +} from '@angular/core'; + +import { NzMessageService, NzModalService } from 'ng-zorro-antd'; + +import { Permissions } from '@zeppelin/interfaces'; +import { SecurityService, TicketService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-notebook-permissions', + templateUrl: './permissions.component.html', + styleUrls: ['./permissions.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookPermissionsComponent implements OnInit, OnChanges { + @Input() permissions: Permissions; + @Input() noteId: string; + @Input() activatedExtension: 'interpreter' | 'permissions' | 'revisions' | 'hide' = 'hide'; + @Output() readonly activatedExtensionChange = new EventEmitter< + 'interpreter' | 'permissions' | 'revisions' | 'hide' + >(); + permissionsBack: Permissions; + listOfUserAndRole = []; + + savePermissions() { + const principal = this.ticketService.ticket.principal; + const isAnonymous = principal === 'anonymous'; + if (isAnonymous || this.ticketService.ticket.principal.trim().length === 0) { + this.blockAnonUsers(); + } + if (this.isOwnerEmpty()) { + this.nzModalService.create({ + nzTitle: 'Setting Owners Permissions', + nzContent: `Please fill the [Owners] field. If not, it will set as current user. Current user : [ ${this.ticketService.ticket.principal.trim()} ]`, + nzOnOk: () => { + this.permissions.owners = [this.ticketService.ticket.principal]; + this.setPermissions(); + }, + nzOnCancel: () => { + this.resetPermissions(); + } + }); + } else { + this.setPermissions(); + } + } + + closePermissions() { + this.activatedExtension = 'hide'; + this.activatedExtensionChange.emit('hide'); + } + + blockAnonUsers() { + this.nzModalService.create({ + nzTitle: 'No permission', + nzContent: 'Only authenticated user can set the permission.', + nzOkText: 'Read Doc', + nzOnOk: () => { + const url = `https://zeppelin.apache.org/docs/${this.ticketService.version}/security/notebook_authorization.html`; + window.open(url); + } + }); + } + + setPermissions() { + this.securityService.setPermissions(this.noteId, this.permissions).subscribe(() => { + this.nzMessageService.success('Permissions Saved Successfully'); + this.closePermissions(); + }); + } + + resetPermissions() { + this.permissions = { ...this.permissionsBack }; + } + + isOwnerEmpty() { + return !this.permissions.owners.some(o => o.trim().length > 0); + } + + searchUser(search: string) { + this.securityService.searchUsers(search).subscribe(data => { + const results = []; + if (data.users.length) { + results.push({ + text: 'Users :', + children: data.users + }); + } + if (data.roles.length) { + results.push({ + text: 'Roles :', + children: data.roles + }); + } + this.listOfUserAndRole = results; + this.cdr.markForCheck(); + }); + } + + constructor( + private securityService: SecurityService, + private cdr: ChangeDetectorRef, + private nzMessageService: NzMessageService, + private ticketService: TicketService, + private nzModalService: NzModalService + ) {} + + ngOnInit() { + this.permissionsBack = { ...this.permissions }; + } + + ngOnChanges(): void { + this.permissionsBack = { ...this.permissions }; + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/revisions-comparator/revisions-comparator.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/revisions-comparator/revisions-comparator.component.html new file mode 100644 index 00000000000..6f0e1be83f1 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/revisions-comparator/revisions-comparator.component.html @@ -0,0 +1,20 @@ + + +
+
+

Revisions comparator

+
+ +
+
+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/revisions-comparator/revisions-comparator.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/revisions-comparator/revisions-comparator.component.less new file mode 100644 index 00000000000..019b5ca53b5 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/revisions-comparator/revisions-comparator.component.less @@ -0,0 +1,12 @@ +/* + * 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. + */ + diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/revisions-comparator/revisions-comparator.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/revisions-comparator/revisions-comparator.component.ts new file mode 100644 index 00000000000..1876b3cbbdb --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/revisions-comparator/revisions-comparator.component.ts @@ -0,0 +1,25 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'zeppelin-notebook-revisions-comparator', + templateUrl: './revisions-comparator.component.html', + styleUrls: ['./revisions-comparator.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NotebookRevisionsComparatorComponent implements OnInit { + constructor() {} + + ngOnInit() {} +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/share/elastic-input/elastic-input.component.html b/zeppelin-web-angular/src/app/pages/workspace/notebook/share/elastic-input/elastic-input.component.html new file mode 100644 index 00000000000..c605d28771b --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/share/elastic-input/elastic-input.component.html @@ -0,0 +1,23 @@ + + +
+ +

{{value || 'Untitled'}}

+
diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/share/elastic-input/elastic-input.component.less b/zeppelin-web-angular/src/app/pages/workspace/notebook/share/elastic-input/elastic-input.component.less new file mode 100644 index 00000000000..6efdd89a7aa --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/share/elastic-input/elastic-input.component.less @@ -0,0 +1,56 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + .elastic { + margin-right: 24px; + overflow: hidden; + max-width: 100%; + + &.min { + margin-bottom: 6px; + margin-right: 0; + p, input { + font-size: 16px; + padding: 0 1px; + } + + input { + height: 24px; + margin: 0; + padding: 0; + } + } + + p, input { + font-size: 28px; + width: 100%; + font-weight: 700; + } + + p { + margin: 0 1px; + padding: 0 11px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + input { + height: 36px; + margin: 7px 0; + padding: 0 10px; + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/share/elastic-input/elastic-input.component.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/share/elastic-input/elastic-input.component.ts new file mode 100644 index 00000000000..ef4dce4e988 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/share/elastic-input/elastic-input.component.ts @@ -0,0 +1,88 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ChangeDetectionStrategy, + Component, + ElementRef, + EventEmitter, + Input, + OnChanges, + Output, + Renderer2, + SimpleChanges, + ViewChild +} from '@angular/core'; + +@Component({ + selector: 'zeppelin-elastic-input', + templateUrl: './elastic-input.component.html', + styleUrls: ['./elastic-input.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ElasticInputComponent implements OnChanges { + @Input() value: string; + @Input() readonly = false; + @Input() min = false; + @Output() readonly valueUpdate = new EventEmitter(); + @ViewChild('inputElement', { read: ElementRef, static: false }) inputElement: ElementRef; + @ViewChild('pElement', { read: ElementRef, static: false }) pElement: ElementRef; + @ViewChild('elasticElement', { read: ElementRef, static: true }) elasticElement: ElementRef; + showEditor = false; + editValue: string; + + cancelEdit() { + this.editValue = this.value; + this.showEditor = false; + } + + updateValue(value: string) { + const trimmedNewName = value.trim(); + if (trimmedNewName.length > 0 && this.value !== trimmedNewName) { + this.editValue = trimmedNewName; + } + } + + setEditorState(showEditor: boolean) { + if (!this.readonly) { + this.showEditor = showEditor; + if (!this.showEditor) { + this.valueUpdate.emit(this.editValue); + } else { + const width = this.pElement.nativeElement.getBoundingClientRect().width; + this.renderer.setStyle(this.elasticElement.nativeElement, 'width', `${width}px`); + setTimeout(() => { + this.inputElement.nativeElement.focus(); + this.renderer.setStyle(this.inputElement.nativeElement, 'width', `${width}px`); + }); + } + } + } + + updateInputWidth() { + const width = this.inputElement.nativeElement.scrollWidth; + if (width > this.inputElement.nativeElement.getBoundingClientRect().width) { + this.renderer.removeStyle(this.elasticElement.nativeElement, 'width'); + this.renderer.setStyle(this.inputElement.nativeElement, 'width', `${width}px`); + } + } + + constructor(private renderer: Renderer2) {} + + ngOnChanges(changes: SimpleChanges) { + if (changes.value) { + this.showEditor = false; + this.editValue = this.value; + this.renderer.removeStyle(this.elasticElement.nativeElement, 'width'); + } + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/notebook/share/share.module.ts b/zeppelin-web-angular/src/app/pages/workspace/notebook/share/share.module.ts new file mode 100644 index 00000000000..c97c48ec89a --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/notebook/share/share.module.ts @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { NzInputModule } from 'ng-zorro-antd'; + +import { ElasticInputComponent } from './elastic-input/elastic-input.component'; + +@NgModule({ + declarations: [ElasticInputComponent], + exports: [ElasticInputComponent], + imports: [CommonModule, NzInputModule, FormsModule] +}) +export class NotebookShareModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/workspace-routing.module.ts b/zeppelin-web-angular/src/app/pages/workspace/workspace-routing.module.ts new file mode 100644 index 00000000000..0340a8d1499 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/workspace-routing.module.ts @@ -0,0 +1,51 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { WorkspaceComponent } from './workspace.component'; +import { WorkspaceGuard } from './workspace.guard'; + +const routes: Routes = [ + { + path: '', + component: WorkspaceComponent, + canActivate: [WorkspaceGuard], + children: [ + { + path: '', + loadChildren: () => import('@zeppelin/pages/workspace/home/home.module').then(m => m.HomeModule) + }, + { + path: 'notebook', + loadChildren: () => import('@zeppelin/pages/workspace/notebook/notebook.module').then(m => m.NotebookModule) + }, + { + path: 'jobmanager', + loadChildren: () => + import('@zeppelin/pages/workspace/job-manager/job-manager.module').then(m => m.JobManagerModule) + }, + { + path: 'interpreter', + loadChildren: () => + import('@zeppelin/pages/workspace/interpreter/interpreter.module').then(m => m.InterpreterModule) + } + ] + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class WorkspaceRoutingModule {} diff --git a/zeppelin-web-angular/src/app/pages/workspace/workspace.component.html b/zeppelin-web-angular/src/app/pages/workspace/workspace.component.html new file mode 100644 index 00000000000..6bcae47ad44 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/workspace.component.html @@ -0,0 +1,17 @@ + + +
+ + +
+Connecting WebSocket ... diff --git a/zeppelin-web-angular/src/app/pages/workspace/workspace.component.less b/zeppelin-web-angular/src/app/pages/workspace/workspace.component.less new file mode 100644 index 00000000000..63064aabd16 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/workspace.component.less @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + .content { + background: @layout-body-background; + min-height: 100vh; + display: block; + position: relative; + + &.blur { + filter: blur(4px); + } + } +}); diff --git a/zeppelin-web-angular/src/app/pages/workspace/workspace.component.ts b/zeppelin-web-angular/src/app/pages/workspace/workspace.component.ts new file mode 100644 index 00000000000..03c5b9b0f75 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/workspace.component.ts @@ -0,0 +1,48 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +import { HeliumManagerService } from '@zeppelin/helium-manager'; +import { MessageService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-workspace', + templateUrl: './workspace.component.html', + styleUrls: ['./workspace.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class WorkspaceComponent implements OnInit, OnDestroy { + private destroy$ = new Subject(); + websocketConnected = false; + + constructor( + public messageService: MessageService, + private cdr: ChangeDetectorRef, + private heliumManagerService: HeliumManagerService + ) {} + + ngOnInit() { + this.messageService.connectedStatus$.pipe(takeUntil(this.destroy$)).subscribe(data => { + this.websocketConnected = data; + this.cdr.markForCheck(); + }); + this.heliumManagerService.initPackages(); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/workspace.guard.ts b/zeppelin-web-angular/src/app/pages/workspace/workspace.guard.ts new file mode 100644 index 00000000000..b491d750cc4 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/workspace.guard.ts @@ -0,0 +1,36 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { of, Observable } from 'rxjs'; +import { catchError, mapTo, tap } from 'rxjs/operators'; + +import { MessageService, TicketService } from '@zeppelin/services'; + +@Injectable({ + providedIn: 'root' +}) +export class WorkspaceGuard implements CanActivate { + constructor(private ticketService: TicketService, private router: Router, private messageService: MessageService) {} + + canActivate( + next: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable | Promise | boolean | UrlTree { + return this.ticketService.getTicket().pipe( + mapTo(true), + tap(() => this.messageService.bootstrap()), + catchError(() => of(this.router.createUrlTree(['/login']))) + ); + } +} diff --git a/zeppelin-web-angular/src/app/pages/workspace/workspace.module.ts b/zeppelin-web-angular/src/app/pages/workspace/workspace.module.ts new file mode 100644 index 00000000000..f6e01e28861 --- /dev/null +++ b/zeppelin-web-angular/src/app/pages/workspace/workspace.module.ts @@ -0,0 +1,37 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { HttpClientModule } from '@angular/common/http'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; + +import { HeliumManagerModule } from '@zeppelin/helium-manager'; +import { ShareModule } from '@zeppelin/share'; + +import { WorkspaceRoutingModule } from './workspace-routing.module'; +import { WorkspaceComponent } from './workspace.component'; + +@NgModule({ + declarations: [WorkspaceComponent], + imports: [ + CommonModule, + WorkspaceRoutingModule, + FormsModule, + HttpClientModule, + ShareModule, + RouterModule, + HeliumManagerModule + ] +}) +export class WorkspaceModule {} diff --git a/zeppelin-web-angular/src/app/services/array-ordering.service.ts b/zeppelin-web-angular/src/app/services/array-ordering.service.ts new file mode 100644 index 00000000000..766f729fd90 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/array-ordering.service.ts @@ -0,0 +1,62 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Inject, Injectable } from '@angular/core'; +import { TRASH_FOLDER_ID_TOKEN } from '@zeppelin/interfaces'; + +@Injectable({ + providedIn: 'root' +}) +export class ArrayOrderingService { + noteListOrdering(note) { + if (note.id === this.TRASH_FOLDER_ID) { + return '\uFFFF'; + } + return this.getNoteName(note); + } + + getNoteName(note) { + if (note.name === undefined || note.name.trim() === '') { + return 'Note ' + note.id; + } else { + return note.name; + } + } + + noteComparator = (v1, v2) => { + const note1 = v1.value || v1; + const note2 = v2.value || v2; + + if (note1.id === this.TRASH_FOLDER_ID) { + return 1; + } + + if (note2.id === this.TRASH_FOLDER_ID) { + return -1; + } + + if (note1.children === undefined && note2.children !== undefined) { + return 1; + } + + if (note1.children !== undefined && note2.children === undefined) { + return -1; + } + + const noteName1 = this.getNoteName(note1); + const noteName2 = this.getNoteName(note2); + + return noteName1.localeCompare(noteName2); + }; + + constructor(@Inject(TRASH_FOLDER_ID_TOKEN) private TRASH_FOLDER_ID: string) {} +} diff --git a/zeppelin-web-angular/src/app/services/base-rest.ts b/zeppelin-web-angular/src/app/services/base-rest.ts new file mode 100644 index 00000000000..7f0ba1b0a19 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/base-rest.ts @@ -0,0 +1,45 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseUrlService } from './base-url.service'; + +/** + * @private + */ +export class BaseRest { + constructor(public baseUrlService: BaseUrlService) {} + + /** + * ```ts + * this.restUrl`/user/${username}` + * this.restUrl(['/user/'], username) + * this.restUrl(`/user/${username}`) + * ``` + * @param str` + * @param values + */ + restUrl(str: TemplateStringsArray | string, ...values): string { + let output = this.baseUrlService.getRestApiBase(); + + if (typeof str === 'string') { + return `${output}${str}`; + } + + let index; + for (index = 0; index < values.length; index++) { + output += str[index] + values[index]; + } + + output += str[index]; + return output; + } +} diff --git a/zeppelin-web-angular/src/app/services/base-url.service.ts b/zeppelin-web-angular/src/app/services/base-url.service.ts new file mode 100644 index 00000000000..c6c6a3d83f7 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/base-url.service.ts @@ -0,0 +1,46 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class BaseUrlService { + getPort() { + let port = Number(location.port); + if (!port) { + port = 80; + if (location.protocol === 'https:') { + port = 443; + } + } + return port; + } + + getWebsocketUrl() { + const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; + return `${wsProtocol}//${location.hostname}:${this.getPort()}${this.skipTrailingSlash(location.pathname)}/ws`; + } + + getBase() { + return `${location.protocol}//${location.hostname}:${this.getPort()}${location.pathname}`; + } + + getRestApiBase() { + return this.skipTrailingSlash(this.getBase()) + '/api'; + } + + skipTrailingSlash(path) { + return path.replace(/\/$/, ''); + } +} diff --git a/zeppelin-web-angular/src/app/services/completion.service.ts b/zeppelin-web-angular/src/app/services/completion.service.ts new file mode 100644 index 00000000000..9f772ecb95e --- /dev/null +++ b/zeppelin-web-angular/src/app/services/completion.service.ts @@ -0,0 +1,97 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { Subject } from 'rxjs'; +import { filter, map, take } from 'rxjs/operators'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { CompletionReceived, OP } from '@zeppelin/sdk'; + +import { MessageService } from './message.service'; + +@Injectable({ + providedIn: 'root' +}) +export class CompletionService extends MessageListenersManager { + private completionLanguages = ['python', 'scala']; + private completionItem$ = new Subject(); + private receivers = new WeakMap(); + private bound = false; + + constructor(messageService: MessageService) { + super(messageService); + } + + @MessageListener(OP.COMPLETION_LIST) + onCompletion(data?: CompletionReceived): void { + console.log('on receive!', data.id); + this.completionItem$.next(data); + } + + registerAsCompletionReceiver(model: monaco.editor.ITextModel, pid: string): void { + if (this.receivers.has(model)) { + return; + } + + if (!this.bound) { + this.bindMonacoCompletion(); + this.bound = true; + } + + this.receivers.set(model, pid); + } + + unregister(model: monaco.editor.ITextModel): void { + this.receivers.delete(model); + } + + private bindMonacoCompletion(): void { + // tslint:disable-next-line:no-this-assignment + const that = this; + + this.completionLanguages.forEach(l => { + monaco.languages.registerCompletionItemProvider(l, { + provideCompletionItems(model: monaco.editor.ITextModel, position: monaco.Position) { + const id = that.getIdForModel(model); + + if (!id) { + return { suggestions: null }; + } + + that.messageService.completion(id, model.getValue(), model.getOffsetAt(position)); + + return that.completionItem$ + .pipe( + filter(d => d.id === id), + take(1), + map(d => { + return { + suggestions: d.completions.map(i => ({ + kind: monaco.languages.CompletionItemKind.Keyword, + label: i.name, + insertText: i.name, + range: undefined + })) + }; + }) + ) + .toPromise(); + } + }); + }); + } + + private getIdForModel(model?: monaco.editor.ITextModel): string | null { + return this.receivers.get(model); + } +} diff --git a/zeppelin-web-angular/src/app/services/helium.service.ts b/zeppelin-web-angular/src/app/services/helium.service.ts new file mode 100644 index 00000000000..327c6987f88 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/helium.service.ts @@ -0,0 +1,24 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class HeliumService { + getSpellByMagic(magic: string): string { + return null; + } + + constructor() {} +} diff --git a/zeppelin-web-angular/src/app/services/index.ts b/zeppelin-web-angular/src/app/services/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/services/interpreter.service.ts b/zeppelin-web-angular/src/app/services/interpreter.service.ts new file mode 100644 index 00000000000..82f93bbfae4 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/interpreter.service.ts @@ -0,0 +1,84 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; + +import { + CreateInterpreterRepositoryForm, + Interpreter, + InterpreterMap, + InterpreterPropertyTypes, + InterpreterRepository +} from '@zeppelin/interfaces'; +import { InterpreterItem } from '@zeppelin/sdk'; + +import { BaseRest } from './base-rest'; +import { BaseUrlService } from './base-url.service'; + +@Injectable({ + providedIn: 'root' +}) +export class InterpreterService extends BaseRest { + constructor(baseUrlService: BaseUrlService, private http: HttpClient) { + super(baseUrlService); + } + + getRepositories() { + return this.http.get(this.restUrl`/interpreter/repository`); + } + + addRepository(repo: CreateInterpreterRepositoryForm) { + return this.http.post(this.restUrl`/interpreter/repository`, repo); + } + + removeRepository(repoId: string) { + return this.http.delete(this.restUrl`/interpreter/repository/${repoId}`); + } + + getInterpretersSetting() { + return this.http.get(this.restUrl`/interpreter/setting`); + } + + getAvailableInterpreters() { + return this.http.get(this.restUrl`/interpreter`); + } + + getAvailableInterpreterPropertyTypes() { + return this.http.get(this.restUrl`/interpreter/property/types`); + } + + addInterpreterSetting(interpreter: Interpreter) { + return this.http.post(this.restUrl`/interpreter/setting`, interpreter); + } + + updateInterpreter(interpreter: Interpreter) { + const { option, properties, dependencies } = interpreter; + return this.http.put(this.restUrl`/interpreter/setting/${interpreter.name}`, { + option, + properties, + dependencies + }); + } + + restartInterpreter(interpreterId: string, noteId: string) { + return this.http.put(this.restUrl`/interpreter/setting/restart/${interpreterId}`, { noteId }); + } + + removeInterpreterSetting(settingId: string) { + return this.http.delete(this.restUrl`/interpreter/setting/${settingId}`); + } + + restartInterpreterSetting(settingId: string) { + return this.http.put(this.restUrl`/interpreter/setting/restart/${settingId}`, null); + } +} diff --git a/zeppelin-web-angular/src/app/services/job-manager.service.ts b/zeppelin-web-angular/src/app/services/job-manager.service.ts new file mode 100644 index 00000000000..b61523219c2 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/job-manager.service.ts @@ -0,0 +1,34 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; + +import { BaseRest } from './base-rest'; +import { BaseUrlService } from './base-url.service'; + +@Injectable({ + providedIn: 'root' +}) +export class JobManagerService extends BaseRest { + constructor(baseUrlService: BaseUrlService, private http: HttpClient) { + super(baseUrlService); + } + + startJob(noteId: string) { + return this.http.post(this.restUrl`/notebook/job/${noteId}`, {}); + } + + stopJob(noteId: string) { + return this.http.delete(this.restUrl`/notebook/job/${noteId}`, {}); + } +} diff --git a/zeppelin-web-angular/src/app/services/message.service.ts b/zeppelin-web-angular/src/app/services/message.service.ts new file mode 100644 index 00000000000..fd47803749f --- /dev/null +++ b/zeppelin-web-angular/src/app/services/message.service.ts @@ -0,0 +1,331 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Inject, Injectable, OnDestroy, Optional } from '@angular/core'; +import { Observable } from 'rxjs'; + +import { MessageInterceptor, MESSAGE_INTERCEPTOR } from '@zeppelin/interfaces'; +import { + Message, + MessageReceiveDataTypeMap, + MessageSendDataTypeMap, + NoteConfig, + ParagraphConfig, + ParagraphParams, + PersonalizedMode, + SendArgumentsType, + SendNote, + SendParagraph, + WebSocketMessage +} from '@zeppelin/sdk'; + +import { BaseUrlService } from './base-url.service'; +import { TicketService } from './ticket.service'; + +@Injectable({ + providedIn: 'root' +}) +export class MessageService extends Message implements OnDestroy { + constructor( + private baseUrlService: BaseUrlService, + private ticketService: TicketService, + @Optional() @Inject(MESSAGE_INTERCEPTOR) private messageInterceptor: MessageInterceptor + ) { + super(); + } + + interceptReceived( + data: WebSocketMessage + ): WebSocketMessage { + return this.messageInterceptor ? this.messageInterceptor.received(data) : super.interceptReceived(data); + } + + bootstrap(): void { + super.bootstrap(this.ticketService.originTicket, this.baseUrlService.getWebsocketUrl()); + } + + ping() { + super.ping(); + } + + closed(): Observable { + return super.closed(); + } + + sent(): Observable> { + return super.sent(); + } + + received(): Observable> { + return super.received(); + } + + send(...args: SendArgumentsType): void { + super.send(...args); + } + + receive(op: K): Observable[K]> { + return super.receive(op); + } + + opened(): Observable { + return super.opened(); + } + + ngOnDestroy(): void { + super.destroy(); + } + + getHomeNote(): void { + super.getHomeNote(); + } + + newNote(noteName: string, defaultInterpreterGroup: string): void { + super.newNote(noteName, defaultInterpreterGroup); + } + + moveNoteToTrash(noteId: string): void { + super.moveNoteToTrash(noteId); + } + + restoreNote(noteId: string): void { + super.restoreNote(noteId); + } + + deleteNote(noteId): void { + super.deleteNote(noteId); + } + + restoreFolder(folderPath: string): void { + super.restoreFolder(folderPath); + } + + removeFolder(folderPath: string): void { + super.removeFolder(folderPath); + } + + moveFolderToTrash(folderPath: string): void { + super.moveFolderToTrash(folderPath); + } + + restoreAll(): void { + super.restoreAll(); + } + + emptyTrash(): void { + super.emptyTrash(); + } + + cloneNote(noteIdToClone, newNoteName): void { + super.cloneNote(noteIdToClone, newNoteName); + } + + listNodes(): void { + super.listNodes(); + } + + reloadAllNotesFromRepo(): void { + super.reloadAllNotesFromRepo(); + } + + getNote(noteId: string): void { + super.getNote(noteId); + } + + updateNote(noteId: string, noteName: string, noteConfig: NoteConfig): void { + super.updateNote(noteId, noteName, noteConfig); + } + + updatePersonalizedMode(noteId: string, modeValue: PersonalizedMode): void { + super.updatePersonalizedMode(noteId, modeValue); + } + + noteRename(noteId: string, noteName: string, relative?: boolean): void { + super.noteRename(noteId, noteName, relative); + } + + folderRename(folderId: string, folderPath: string): void { + super.folderRename(folderId, folderPath); + } + + moveParagraph(paragraphId: string, newIndex: number): void { + super.moveParagraph(paragraphId, newIndex); + } + + insertParagraph(newIndex: number): void { + super.insertParagraph(newIndex); + } + + copyParagraph( + newIndex: number, + paragraphTitle: string, + paragraphData: string, + paragraphConfig: ParagraphConfig, + paragraphParams: ParagraphParams + ): void { + super.copyParagraph(newIndex, paragraphTitle, paragraphData, paragraphConfig, paragraphParams); + } + + angularObjectUpdate( + noteId: string, + paragraphId: string, + name: string, + value: string, + interpreterGroupId: string + ): void { + super.angularObjectUpdate(noteId, paragraphId, name, value, interpreterGroupId); + } + + // tslint:disable-next-line:no-any + angularObjectClientBind(noteId: string, name: string, value: any, paragraphId: string): void { + super.angularObjectClientBind(noteId, name, value, paragraphId); + } + + angularObjectClientUnbind(noteId: string, name: string, paragraphId: string): void { + super.angularObjectClientUnbind(noteId, name, paragraphId); + } + + cancelParagraph(paragraphId): void { + super.cancelParagraph(paragraphId); + } + + paragraphExecutedBySpell( + paragraphId, + paragraphTitle, + paragraphText, + paragraphResultsMsg, + paragraphStatus, + paragraphErrorMessage, + paragraphConfig, + paragraphParams, + paragraphDateStarted, + paragraphDateFinished + ): void { + super.paragraphExecutedBySpell( + paragraphId, + paragraphTitle, + paragraphText, + paragraphResultsMsg, + paragraphStatus, + paragraphErrorMessage, + paragraphConfig, + paragraphParams, + paragraphDateStarted, + paragraphDateFinished + ); + } + + runParagraph( + paragraphId: string, + paragraphTitle: string, + paragraphData: string, + paragraphConfig: ParagraphConfig, + paragraphParams: ParagraphParams + ): void { + super.runParagraph(paragraphId, paragraphTitle, paragraphData, paragraphConfig, paragraphParams); + } + + runAllParagraphs(noteId: string, paragraphs: SendParagraph[]): void { + super.runAllParagraphs(noteId, paragraphs); + } + + paragraphRemove(paragraphId: string): void { + super.paragraphRemove(paragraphId); + } + + paragraphClearOutput(paragraphId: string): void { + super.paragraphClearOutput(paragraphId); + } + + paragraphClearAllOutput(noteId: string): void { + super.paragraphClearAllOutput(noteId); + } + + completion(paragraphId: string, buf: string, cursor: number): void { + super.completion(paragraphId, buf, cursor); + } + + commitParagraph( + paragraphId: string, + paragraphTitle: string, + paragraphData: string, + paragraphConfig: ParagraphConfig, + paragraphParams: ParagraphConfig, + noteId: string + ): void { + super.commitParagraph(paragraphId, paragraphTitle, paragraphData, paragraphConfig, paragraphParams, noteId); + } + + patchParagraph(paragraphId: string, noteId: string, patch: string): void { + super.patchParagraph(paragraphId, noteId, patch); + } + + importNote(note: SendNote): void { + super.importNote(note); + } + + checkpointNote(noteId: string, commitMessage: string): void { + super.checkpointNote(noteId, commitMessage); + } + + setNoteRevision(noteId: string, revisionId: string): void { + super.setNoteRevision(noteId, revisionId); + } + + listRevisionHistory(noteId: string): void { + super.listRevisionHistory(noteId); + } + + noteRevision(noteId: string, revisionId: string): void { + super.noteRevision(noteId, revisionId); + } + + noteRevisionForCompare(noteId: string, revisionId: string, position: string): void { + super.noteRevisionForCompare(noteId, revisionId, position); + } + + editorSetting(paragraphId: string, replName: string): void { + super.editorSetting(paragraphId, replName); + } + + listNoteJobs(): void { + super.listNoteJobs(); + } + + unsubscribeUpdateNoteJobs(): void { + super.unsubscribeUpdateNoteJobs(); + } + + getInterpreterBindings(noteId: string): void { + super.getInterpreterBindings(noteId); + } + + saveInterpreterBindings(noteId, selectedSettingIds): void { + super.saveInterpreterBindings(noteId, selectedSettingIds); + } + + listConfigurations(): void { + super.listConfigurations(); + } + + getInterpreterSettings(): void { + super.getInterpreterSettings(); + } + + saveNoteForms(note: SendNote): void { + super.saveNoteForms(note); + } + + removeNoteForms(note, formName): void { + super.removeNoteForms(note, formName); + } +} diff --git a/zeppelin-web-angular/src/app/services/ng-z.service.ts b/zeppelin-web-angular/src/app/services/ng-z.service.ts new file mode 100644 index 00000000000..fe1ad9917d3 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/ng-z.service.ts @@ -0,0 +1,85 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable, OnDestroy } from '@angular/core'; +import { Subject } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class NgZService implements OnDestroy { + private paragraphMap = new Map(); + private contextChange$ = new Subject<{ + paragraphId: string; + key: string; + // tslint:disable-next-line:no-any + value: any; + emit: boolean; + set: boolean; + }>(); + private runParagraph$ = new Subject(); + + constructor() {} + + contextChanged() { + return this.contextChange$.asObservable(); + } + + runParagraphAction() { + return this.runParagraph$.asObservable(); + } + + removeParagraph(paragraphId: string) { + this.paragraphMap.delete(paragraphId); + } + + runParagraph(paragraphId: string) { + this.runParagraph$.next(paragraphId); + } + + bindParagraph(paragraphId: string, context: {}) { + this.paragraphMap.set(paragraphId, context); + } + + setContextValue(key: string, value, paragraphId: string, emit = true) { + const context = this.paragraphMap.get(paragraphId); + if (context) { + context[key] = value; + } + this.contextChange$.next({ + paragraphId, + key, + value, + emit, + set: true + }); + } + + unsetContextValue(key: string, paragraphId: string, emit = true) { + const context = this.paragraphMap.get(paragraphId); + if (context) { + context[key] = undefined; + } + this.contextChange$.next({ + paragraphId, + key, + emit, + value: undefined, + set: false + }); + } + + ngOnDestroy(): void { + this.paragraphMap.clear(); + this.contextChange$.complete(); + } +} diff --git a/zeppelin-web-angular/src/app/services/note-action.service.ts b/zeppelin-web-angular/src/app/services/note-action.service.ts new file mode 100644 index 00000000000..8a2bd102841 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/note-action.service.ts @@ -0,0 +1,72 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; + +import { NzModalService } from 'ng-zorro-antd'; + +import { FolderRenameComponent } from '@zeppelin/share/folder-rename/folder-rename.component'; +import { NoteCreateComponent } from '@zeppelin/share/note-create/note-create.component'; +import { NoteImportComponent } from '@zeppelin/share/note-import/note-import.component'; +import { NoteRenameComponent } from '@zeppelin/share/note-rename/note-rename.component'; + +@Injectable({ + providedIn: 'root' +}) +export class NoteActionService { + renameNote(id: string, path: string, name: string) { + this.nzModalService.create({ + nzTitle: 'Rename note', + nzContent: NoteRenameComponent, + nzComponentParams: { + id, + newName: path || name + }, + nzWidth: '800px', + nzFooter: null + }); + } + + renameFolder(path: string) { + this.nzModalService.create({ + nzTitle: 'Rename folder', + nzContent: FolderRenameComponent, + nzComponentParams: { + folderId: path, + newFolderPath: path + }, + nzWidth: '800px', + nzFooter: null + }); + } + + importNote() { + this.nzModalService.create({ + nzTitle: 'Import New Note', + nzContent: NoteImportComponent, + nzWidth: '800px', + nzFooter: null + }); + } + + createNote(path?: string) { + this.nzModalService.create({ + nzTitle: 'Create New Note', + nzContent: NoteCreateComponent, + nzComponentParams: { path }, + nzWidth: '800px', + nzFooter: null + }); + } + + constructor(private nzModalService: NzModalService) {} +} diff --git a/zeppelin-web-angular/src/app/services/note-list.service.ts b/zeppelin-web-angular/src/app/services/note-list.service.ts new file mode 100644 index 00000000000..83070b51148 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/note-list.service.ts @@ -0,0 +1,97 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Inject, Injectable } from '@angular/core'; + +import { TRASH_FOLDER_ID_TOKEN } from '@zeppelin/interfaces'; +import { NotesInfoItem } from '@zeppelin/sdk'; + +import { NodeList } from '../interfaces/node-list'; +import { ArrayOrderingService } from './array-ordering.service'; + +@Injectable({ + providedIn: 'root' +}) +export class NoteListService { + notes: NodeList = { + root: { children: [] }, + flatList: [], + flatFolderMap: {} + }; + + setNotes(notesList: NotesInfoItem[]) { + // a flat list to boost searching + this.notes.flatList = notesList.map(note => { + const isTrash = note.path ? note.path.split('/')[1] === this.TRASH_FOLDER_ID : false; + return { ...note, isTrash }; + }); + + // construct the folder-based tree + this.notes.root = { children: [] }; + this.notes.flatFolderMap = {}; + notesList.reduce((root, note) => { + const notePath = note.path || note.id; + const nodes = notePath.match(/([^\/][^\/]*)/g); + + // recursively add nodes + this.addNode(root, nodes, note.id); + + return root; + }, this.notes.root); + this.notes.root.children.sort(this.arrayOrderingService.noteComparator); + } + + addNode(curDir, nodes, noteId) { + if (nodes.length === 1) { + // the leaf + curDir.children.push({ + id: noteId, + title: nodes[0], + isLeaf: true, + nodeType: 'note', + path: curDir.id ? `${curDir.id}/${nodes[0]}` : nodes[0], + isTrash: curDir.id ? curDir.id.split('/')[0] === this.TRASH_FOLDER_ID : false + }); + } else { + // a folder node + const node = nodes.shift(); + const dir = curDir.children.find(c => { + return c.title === node && c.children !== undefined; + }); + if (dir !== undefined) { + // found an existing dir + this.addNode(dir, nodes, noteId); + } else { + const id = curDir.id ? `${curDir.id}/${node}` : node; + const newDir = { + id, + title: node, + expanded: false, + nodeType: id === this.TRASH_FOLDER_ID ? 'trash' : 'folder', + children: [], + isTrash: curDir.id ? curDir.id.split('/')[0] === this.TRASH_FOLDER_ID : false + }; + + // add the folder to flat folder map + this.notes.flatFolderMap[newDir.id] = newDir; + + curDir.children.push(newDir); + this.addNode(newDir, nodes, noteId); + } + } + } + + constructor( + @Inject(TRASH_FOLDER_ID_TOKEN) public TRASH_FOLDER_ID: string, + private arrayOrderingService: ArrayOrderingService + ) {} +} diff --git a/zeppelin-web-angular/src/app/services/note-status.service.ts b/zeppelin-web-angular/src/app/services/note-status.service.ts new file mode 100644 index 00000000000..e5ff4a90bb6 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/note-status.service.ts @@ -0,0 +1,65 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Inject, Injectable } from '@angular/core'; + +import { TRASH_FOLDER_ID_TOKEN } from '@zeppelin/interfaces'; +import { Note, ParagraphItem } from '@zeppelin/sdk'; + +export const ParagraphStatus = { + READY: 'READY', + PENDING: 'PENDING', + RUNNING: 'RUNNING', + FINISHED: 'FINISHED', + ABORT: 'ABORT', + ERROR: 'ERROR' +}; + +@Injectable({ + providedIn: 'root' +}) +export class NoteStatusService { + isParagraphRunning(paragraph: ParagraphItem) { + if (!paragraph) { + return false; + } + const status = paragraph.status; + if (!status) { + return false; + } + + return status === ParagraphStatus.PENDING || status === ParagraphStatus.RUNNING; + } + + isTrash(note: Note['note']) { + // TODO(hsuanxyz) https://github.com/apache/zeppelin/pull/3365/files + return note.name.split('/')[1] === this.TRASH_FOLDER_ID; + } + + viewOnly(note: Note['note']): boolean { + return note.config.looknfeel === 'report'; + } + + isNoteParagraphRunning(note: Note['note']): boolean { + if (!note) { + return false; + } else { + return note.paragraphs.some(p => this.isParagraphRunning(p)); + } + } + + isEntireNoteRunning(note: Note['note']): boolean { + return !!(note.info && note.info.isRunning && note.info.isRunning === true); + } + + constructor(@Inject(TRASH_FOLDER_ID_TOKEN) public TRASH_FOLDER_ID: string) {} +} diff --git a/zeppelin-web-angular/src/app/services/note-var-share.service.ts b/zeppelin-web-angular/src/app/services/note-var-share.service.ts new file mode 100644 index 00000000000..edb7bed7fb4 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/note-var-share.service.ts @@ -0,0 +1,38 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class NoteVarShareService { + private store = new Map(); + + clear() { + this.store.clear(); + } + + set(key, value) { + this.store.set(key, value); + } + + get(key) { + return this.store.get(key); + } + + del(key) { + return this.store.delete(key); + } + + constructor() {} +} diff --git a/zeppelin-web-angular/src/app/services/public-api.ts b/zeppelin-web-angular/src/app/services/public-api.ts new file mode 100644 index 00000000000..d56ec7e5c6f --- /dev/null +++ b/zeppelin-web-angular/src/app/services/public-api.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +export * from './base-url.service'; +export * from './ticket.service'; +export * from './message.service'; +export * from './job-manager.service'; +export * from './interpreter.service'; +export * from './security.service'; +export * from './note-status.service'; +export * from './save-as.service'; +export * from './helium.service'; +export * from './note-var-share.service'; +export * from './note-action.service'; +export * from './completion.service'; +export * from './ng-z.service'; +export * from './array-ordering.service'; +export * from './note-list.service'; +export * from './runtime-compiler.service'; diff --git a/zeppelin-web-angular/src/app/services/runtime-compiler.service.ts b/zeppelin-web-angular/src/app/services/runtime-compiler.service.ts new file mode 100644 index 00000000000..9c91b697bca --- /dev/null +++ b/zeppelin-web-angular/src/app/services/runtime-compiler.service.ts @@ -0,0 +1,74 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { + Compiler, + Component, + Injectable, + ModuleWithComponentFactories, + NgModule, + NgModuleFactory, + Type +} from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { NgZorroAntdModule } from 'ng-zorro-antd'; + +import { NgZService } from './ng-z.service'; + +export class DynamicTemplate { + constructor( + public readonly template: string, + // tslint:disable-next-line:no-any + public readonly component: Type, + // tslint:disable-next-line:no-any + public readonly moduleFactory?: NgModuleFactory + ) {} +} + +@Injectable({ + providedIn: 'root' +}) +export class RuntimeCompilerService { + // tslint:disable-next-line:no-any + private compiledModule?: ModuleWithComponentFactories; + + public async createAndCompileTemplate(paragraphId: string, template: string): Promise { + const ngZService = this.ngZService; + const dynamicComponent = Component({ template: template })( + class DynamicTemplateComponent { + z = { + set: (key: string, value, id: string) => ngZService.setContextValue(key, value, id), + unset: (key: string, id: string) => ngZService.unsetContextValue(key, id), + run: (id: string) => ngZService.runParagraph(id) + }; + + constructor() { + ngZService.bindParagraph(paragraphId, this); + Object.freeze(this.z); + } + } + ); + const dynamicModule = NgModule({ + declarations: [dynamicComponent], + exports: [dynamicComponent], + entryComponents: [dynamicComponent], + imports: [CommonModule, NgZorroAntdModule, FormsModule] + })(class DynamicModule {}); + + this.compiledModule = await this.compiler.compileModuleAndAllComponentsAsync(dynamicModule); + return new DynamicTemplate(template, dynamicComponent, this.compiledModule.ngModuleFactory); + } + + constructor(private compiler: Compiler, private ngZService: NgZService) {} +} diff --git a/zeppelin-web-angular/src/app/services/save-as.service.ts b/zeppelin-web-angular/src/app/services/save-as.service.ts new file mode 100644 index 00000000000..53dc05c9bdd --- /dev/null +++ b/zeppelin-web-angular/src/app/services/save-as.service.ts @@ -0,0 +1,37 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class SaveAsService { + saveAs(content: string, filename: string, extension: string) { + const BOM = '\uFEFF'; + const fileName = `${filename}.${extension}`; + const binaryData = []; + binaryData.push(BOM); + binaryData.push(content); + const blob = new Blob(binaryData, { type: 'octet/stream' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + document.body.appendChild(a); + a.style.display = 'none'; + a.href = url; + a.download = fileName; + a.click(); + window.URL.revokeObjectURL(url); + } + + constructor() {} +} diff --git a/zeppelin-web-angular/src/app/services/security.service.ts b/zeppelin-web-angular/src/app/services/security.service.ts new file mode 100644 index 00000000000..c267ad05fa8 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/security.service.ts @@ -0,0 +1,40 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; + +import { Permissions, SecurityUserList } from '@zeppelin/interfaces'; + +import { BaseRest } from './base-rest'; +import { BaseUrlService } from './base-url.service'; + +@Injectable({ + providedIn: 'root' +}) +export class SecurityService extends BaseRest { + constructor(baseUrlService: BaseUrlService, private http: HttpClient) { + super(baseUrlService); + } + + searchUsers(term: string) { + return this.http.get(this.restUrl`/security/userlist/${term}`); + } + + getPermissions(id: string) { + return this.http.get(this.restUrl`/notebook/${id}/permissions`); + } + + setPermissions(id: string, permissions: Permissions) { + return this.http.put(this.restUrl`/notebook/${id}/permissions`, permissions); + } +} diff --git a/zeppelin-web-angular/src/app/services/ticket.service.ts b/zeppelin-web-angular/src/app/services/ticket.service.ts new file mode 100644 index 00000000000..9254cdc6ee7 --- /dev/null +++ b/zeppelin-web-angular/src/app/services/ticket.service.ts @@ -0,0 +1,116 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Router } from '@angular/router'; +import { forkJoin, BehaviorSubject, Subject } from 'rxjs'; +import { map, tap } from 'rxjs/operators'; + +import { NzMessageService } from 'ng-zorro-antd'; + +import { ITicket, ITicketWrapped, IZeppelinVersion } from '@zeppelin/interfaces'; +import { ConfigurationsInfo } from '@zeppelin/sdk'; + +import { BaseUrlService } from './base-url.service'; + +@Injectable({ + providedIn: 'root' +}) +export class TicketService { + configuration: ConfigurationsInfo['configurations']; + ticket = new ITicketWrapped(); + originTicket = new ITicket(); + ticket$ = new Subject(); + logout$ = new BehaviorSubject(false); + version: string; + + setConfiguration(conf: ConfigurationsInfo) { + this.configuration = conf.configurations; + } + + getTicket() { + return forkJoin([ + this.httpClient.get(`${this.baseUrlService.getRestApiBase()}/security/ticket`), + this.getZeppelinVersion() + ]).pipe( + tap(data => { + const [ticket, version] = data; + this.version = version; + this.setTicket(ticket); + }) + ); + } + + setTicket(ticket: ITicket) { + if (ticket.redirectURL) { + window.location.href = ticket.redirectURL + window.location.href; + } + let screenUsername = ticket.principal; + if (ticket.principal.indexOf('#Pac4j') === 0) { + const re = ', name=(.*?),'; + screenUsername = ticket.principal.match(re)[1]; + } + this.originTicket = ticket; + this.ticket = { ...ticket, screenUsername, ...{ init: true } }; + this.ticket$.next(this.ticket); + } + + clearTicket() { + this.ticket = new ITicketWrapped(); + this.originTicket = new ITicket(); + } + + logout() { + this.logout$.next(true); + const nextAction = () => { + this.nzMessageService.success('Logout Success'); + this.clearTicket(); + this.logout$.next(false); + this.router.navigate(['/login']).then(); + }; + return this.httpClient + .post(`${this.baseUrlService.getRestApiBase()}/login/logout`, {}) + .pipe(tap(() => nextAction(), () => nextAction())); + } + + login(userName: string, password: string) { + return this.httpClient + .post(`${this.baseUrlService.getRestApiBase()}/login`, `password=${password}&userName=${userName}`, { + headers: { 'Content-Type': 'application/x-www-form-urlencoded' } + }) + .pipe( + tap( + data => { + this.nzMessageService.success('Login Success'); + this.setTicket(data); + }, + () => { + this.nzMessageService.warning("The username and password that you entered don't match."); + } + ) + ); + } + + getZeppelinVersion() { + return this.httpClient + .get(`${this.baseUrlService.getRestApiBase()}/version`) + .pipe(map(data => data.version)); + } + + constructor( + private httpClient: HttpClient, + private baseUrlService: BaseUrlService, + private router: Router, + private nzMessageService: NzMessageService + ) {} +} diff --git a/zeppelin-web-angular/src/app/share/about-zeppelin/about-zeppelin.component.html b/zeppelin-web-angular/src/app/share/about-zeppelin/about-zeppelin.component.html new file mode 100644 index 00000000000..c7d8cc5d73c --- /dev/null +++ b/zeppelin-web-angular/src/app/share/about-zeppelin/about-zeppelin.component.html @@ -0,0 +1,28 @@ + + + diff --git a/zeppelin-web-angular/src/app/share/about-zeppelin/about-zeppelin.component.less b/zeppelin-web-angular/src/app/share/about-zeppelin/about-zeppelin.component.less new file mode 100644 index 00000000000..73be35e8bc8 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/about-zeppelin/about-zeppelin.component.less @@ -0,0 +1,38 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + .modal { + .about-logo { + img { + width: 95%; + } + } + + .content { + text-align: center; + + h3 { + font-family: 'Patua One', cursive; + color: #3071A9; + font-size: 30px; + margin: 0 auto; + } + + .about-version { + font-weight: 500; + } + } + } +}); diff --git a/zeppelin-web-angular/src/app/share/about-zeppelin/about-zeppelin.component.ts b/zeppelin-web-angular/src/app/share/about-zeppelin/about-zeppelin.component.ts new file mode 100644 index 00000000000..41e8e777324 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/about-zeppelin/about-zeppelin.component.ts @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; +import { TicketService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-about-zeppelin', + templateUrl: './about-zeppelin.component.html', + styleUrls: ['./about-zeppelin.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AboutZeppelinComponent implements OnInit { + constructor(public ticketService: TicketService) {} + + ngOnInit() {} +} diff --git a/zeppelin-web-angular/src/app/share/code-editor/code-editor.component.html b/zeppelin-web-angular/src/app/share/code-editor/code-editor.component.html new file mode 100644 index 00000000000..1b40367eb04 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/code-editor/code-editor.component.html @@ -0,0 +1,19 @@ + + +
+ +
+ +
+ +
diff --git a/zeppelin-web-angular/src/app/share/code-editor/code-editor.component.ts b/zeppelin-web-angular/src/app/share/code-editor/code-editor.component.ts new file mode 100644 index 00000000000..2fdbaa5950d --- /dev/null +++ b/zeppelin-web-angular/src/app/share/code-editor/code-editor.component.ts @@ -0,0 +1,244 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + forwardRef, + AfterViewInit, + ChangeDetectionStrategy, + Component, + ElementRef, + EventEmitter, + Input, + NgZone, + OnDestroy, + Output, + TemplateRef, + ViewEncapsulation +} from '@angular/core'; +import { NG_VALUE_ACCESSOR } from '@angular/forms'; +import { combineLatest, fromEvent, BehaviorSubject, Subject } from 'rxjs'; +import { debounceTime, distinctUntilChanged, filter, map, takeUntil } from 'rxjs/operators'; + +import { warn, InputBoolean } from 'ng-zorro-antd/core'; + +import { CodeEditorService } from './code-editor.service'; +import { DiffEditorOptions, EditorOptions, JoinedEditorOptions, NzEditorMode } from './nz-code-editor.definitions'; + +// Import types from monaco editor. +import { editor } from 'monaco-editor'; +import IEditor = editor.IEditor; +import IDiffEditor = editor.IDiffEditor; +import ITextModel = editor.ITextModel; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + selector: 'zeppelin-code-editor', + exportAs: 'CodeEditor', + templateUrl: './code-editor.component.html', + host: { + '[class.ant-code-editor]': 'true' + }, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CodeEditorComponent), + multi: true + } + ] +}) +export class CodeEditorComponent implements OnDestroy, AfterViewInit { + @Input() nzEditorMode: NzEditorMode = 'normal'; + @Input() nzOriginalText = ''; + @Input() @InputBoolean() nzLoading = false; + @Input() @InputBoolean() nzFullControl = false; + @Input() nzToolkit: TemplateRef; + + @Input() set nzEditorOption(value: JoinedEditorOptions) { + this.editorOption$.next(value); + } + + @Output() readonly nzEditorInitialized = new EventEmitter(); + + editorOptionCached: JoinedEditorOptions = {}; + + private readonly el: HTMLElement; + private destroy$ = new Subject(); + private resize$ = new Subject(); + private editorOption$ = new BehaviorSubject({}); + private editorInstance: IEditor | IDiffEditor; + private value = ''; + private modelSet = false; + + constructor(private nzCodeEditorService: CodeEditorService, private ngZone: NgZone, elementRef: ElementRef) { + this.el = elementRef.nativeElement; + } + + /** + * Initialize a monaco editor instance. + */ + ngAfterViewInit(): void { + this.nzCodeEditorService.requestToInit().subscribe(option => this.setup(option)); + } + + ngOnDestroy(): void { + if (this.editorInstance) { + this.editorInstance.dispose(); + } + + this.destroy$.next(); + this.destroy$.complete(); + } + + writeValue(value: string): void { + this.value = value; + this.setValue(); + } + + // tslint:disable-next-line no-any + registerOnChange(fn: (value: string) => void): any { + this.onChange = fn; + } + + // tslint:disable-next-line no-any + registerOnTouched(fn: any): void { + this.onTouch = fn; + } + + onChange(_value: string): void {} + + onTouch(): void {} + + layout(): void { + this.resize$.next(); + } + + private setup(option: JoinedEditorOptions): void { + this.editorOptionCached = option; + this.registerOptionChanges(); + this.initMonacoEditorInstance(); + this.registerResizeChange(); + this.setValue(); + + if (!this.nzFullControl) { + this.setValueEmitter(); + } + this.nzEditorInitialized.emit(this.editorInstance); + } + + private registerOptionChanges(): void { + combineLatest([this.editorOption$, this.nzCodeEditorService.option$]) + .pipe(takeUntil(this.destroy$)) + .subscribe(([selfOpt, defaultOpt]) => { + this.editorOptionCached = { + ...this.editorOptionCached, + ...defaultOpt, + ...selfOpt + }; + this.updateOptionToMonaco(); + }); + } + + private initMonacoEditorInstance(): void { + this.ngZone.runOutsideAngular(() => { + this.editorInstance = + this.nzEditorMode === 'normal' + ? editor.create(this.el, { ...this.editorOptionCached }) + : editor.createDiffEditor(this.el, { + ...(this.editorOptionCached as DiffEditorOptions) + }); + }); + } + + private registerResizeChange(): void { + this.ngZone.runOutsideAngular(() => { + fromEvent(window, 'resize') + .pipe( + debounceTime(300), + takeUntil(this.destroy$) + ) + .subscribe(() => { + this.layout(); + }); + + this.resize$ + .pipe( + takeUntil(this.destroy$), + filter(() => !!this.editorInstance), + map(() => ({ + width: this.el.clientWidth, + height: this.el.clientHeight + })), + distinctUntilChanged((a, b) => a.width === b.width && a.height === b.height), + debounceTime(50) + ) + .subscribe(() => { + this.editorInstance.layout(); + }); + }); + } + + private setValue(): void { + if (!this.editorInstance) { + return; + } + + if (this.nzFullControl && this.value) { + warn(`should not set value when you are using full control mode! It would result in ambiguous data flow!`); + return; + } + + if (this.nzEditorMode === 'normal') { + if (this.modelSet) { + (this.editorInstance.getModel() as ITextModel).setValue(this.value); + } else { + (this.editorInstance as IEditor).setModel( + editor.createModel(this.value, (this.editorOptionCached as EditorOptions).language) + ); + this.modelSet = true; + } + } else { + if (this.modelSet) { + const model = (this.editorInstance as IDiffEditor).getModel()!; + model.modified.setValue(this.value); + model.original.setValue(this.nzOriginalText); + } else { + const language = (this.editorOptionCached as EditorOptions).language; + (this.editorInstance as IDiffEditor).setModel({ + original: editor.createModel(this.value, language), + modified: editor.createModel(this.nzOriginalText, language) + }); + } + } + } + + private setValueEmitter(): void { + const model = (this.nzEditorMode === 'normal' + ? (this.editorInstance as IEditor).getModel() + : (this.editorInstance as IDiffEditor).getModel()!.modified) as ITextModel; + + model.onDidChangeContent(() => { + this.emitValue(model.getValue()); + }); + } + + private emitValue(value: string): void { + this.value = value; + this.onChange(value); + } + + private updateOptionToMonaco(): void { + if (this.editorInstance) { + this.editorInstance.updateOptions({ ...this.editorOptionCached }); + } + } +} diff --git a/zeppelin-web-angular/src/app/share/code-editor/code-editor.module.ts b/zeppelin-web-angular/src/app/share/code-editor/code-editor.module.ts new file mode 100644 index 00000000000..6af049bc1b4 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/code-editor/code-editor.module.ts @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { NzIconModule } from 'ng-zorro-antd/icon'; +import { NzSpinModule } from 'ng-zorro-antd/spin'; + +import { CodeEditorComponent } from './code-editor.component'; + +@NgModule({ + declarations: [CodeEditorComponent], + imports: [CommonModule, NzIconModule, NzSpinModule], + exports: [CodeEditorComponent] +}) +export class CodeEditorModule {} diff --git a/zeppelin-web-angular/src/app/share/code-editor/code-editor.service.ts b/zeppelin-web-angular/src/app/share/code-editor/code-editor.service.ts new file mode 100644 index 00000000000..f24d9ec4d89 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/code-editor/code-editor.service.ts @@ -0,0 +1,104 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DOCUMENT } from '@angular/common'; +import { Inject, Injectable } from '@angular/core'; +import { of as observableOf, BehaviorSubject, Observable, Subject } from 'rxjs'; +import { map, tap } from 'rxjs/operators'; + +import { + JoinedEditorOptions, + NzCodeEditorConfig, + NzCodeEditorLoadingStatus, + NZ_CODE_EDITOR_CONFIG +} from './nz-code-editor.definitions'; + +import { editor } from 'monaco-editor'; + +// tslint:disable no-any +function tryTriggerFunc(fn?: (...args: any[]) => any): (...args: any) => void { + return (...args: any[]) => { + if (fn) { + fn(...args); + } + }; +} +// tslint:enable no-any + +@Injectable({ + providedIn: 'root' +}) +export class CodeEditorService { + private document: Document; + private firstEditorInitialized = false; + private loaded$ = new Subject(); + private loadingStatus = NzCodeEditorLoadingStatus.UNLOAD; + private option: JoinedEditorOptions; + + option$ = new BehaviorSubject(this.option); + + constructor( + @Inject(NZ_CODE_EDITOR_CONFIG) private config: NzCodeEditorConfig, + @Inject(DOCUMENT) _document: any // tslint:disable-line no-any + ) { + this.document = _document; + this.option = this.config.defaultEditorOption || {}; + } + + // TODO(hsuanxyz): use config service later. + updateDefaultOption(option: JoinedEditorOptions): void { + this.option = { ...this.option, ...option }; + this.option$.next(this.option); + + if (option.theme) { + editor.setTheme(option.theme); + } + } + + requestToInit(): Observable { + if (this.loadingStatus === NzCodeEditorLoadingStatus.LOADED) { + this.onInit(); + return observableOf(this.getLatestOption()); + } + + if (this.loadingStatus === NzCodeEditorLoadingStatus.UNLOAD) { + this.loadingStatus = NzCodeEditorLoadingStatus.LOADED; + this.loaded$.next(true); + this.loaded$.complete(); + this.onLoad(); + this.onInit(); + return observableOf(this.getLatestOption()); + } + + return this.loaded$.asObservable().pipe( + tap(() => this.onInit()), + map(() => this.getLatestOption()) + ); + } + + private onInit(): void { + if (!this.firstEditorInitialized) { + this.firstEditorInitialized = true; + tryTriggerFunc(this.config.onFirstEditorInit)(); + } + + tryTriggerFunc(this.config.onInit)(); + } + + private onLoad(): void { + tryTriggerFunc(this.config.onLoad)(); + } + + private getLatestOption(): JoinedEditorOptions { + return { ...this.option }; + } +} diff --git a/zeppelin-web-angular/src/app/share/code-editor/index.ts b/zeppelin-web-angular/src/app/share/code-editor/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/code-editor/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/share/code-editor/nz-code-editor.definitions.ts b/zeppelin-web-angular/src/app/share/code-editor/nz-code-editor.definitions.ts new file mode 100644 index 00000000000..103b10db1d4 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/code-editor/nz-code-editor.definitions.ts @@ -0,0 +1,46 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { InjectionToken } from '@angular/core'; +import { SafeUrl } from '@angular/platform-browser'; +import { editor } from 'monaco-editor'; +import IEditorConstructionOptions = editor.IEditorConstructionOptions; +import IDiffEditorConstructionOptions = editor.IDiffEditorConstructionOptions; + +export type EditorOptions = IEditorConstructionOptions; +export type DiffEditorOptions = IDiffEditorConstructionOptions; +export type JoinedEditorOptions = EditorOptions | DiffEditorOptions; + +export type NzEditorMode = 'normal' | 'diff'; + +export enum NzCodeEditorLoadingStatus { + UNLOAD = 'unload', + LOADING = 'loading', + LOADED = 'LOADED' +} + +export interface NzCodeEditorConfig { + assetsRoot?: string | SafeUrl; + defaultEditorOption?: JoinedEditorOptions; + onLoad?(): void; + onFirstEditorInit?(): void; + onInit?(): void; +} + +export const NZ_CODE_EDITOR_CONFIG = new InjectionToken('nz-code-editor-config', { + providedIn: 'root', + factory: NZ_CODE_EDITOR_CONFIG_FACTORY +}); + +export function NZ_CODE_EDITOR_CONFIG_FACTORY(): NzCodeEditorConfig { + return {}; +} diff --git a/zeppelin-web-angular/src/app/share/code-editor/public-api.ts b/zeppelin-web-angular/src/app/share/code-editor/public-api.ts new file mode 100644 index 00000000000..b2144c936c7 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/code-editor/public-api.ts @@ -0,0 +1,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. + */ + +export * from './nz-code-editor.definitions'; +export * from './code-editor.component'; +export * from './code-editor.module'; +export * from './code-editor.service'; diff --git a/zeppelin-web-angular/src/app/share/folder-rename/folder-rename.component.html b/zeppelin-web-angular/src/app/share/folder-rename/folder-rename.component.html new file mode 100644 index 00000000000..71c4eac1a72 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/folder-rename/folder-rename.component.html @@ -0,0 +1,32 @@ + + +
+ + Please enter a new name + + + + + + + + + + +
+ + + The folder will be merged into {{newFolderPath}}. Are you sure? + diff --git a/zeppelin-web-angular/src/app/share/folder-rename/folder-rename.component.less b/zeppelin-web-angular/src/app/share/folder-rename/folder-rename.component.less new file mode 100644 index 00000000000..019b5ca53b5 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/folder-rename/folder-rename.component.less @@ -0,0 +1,12 @@ +/* + * 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. + */ + diff --git a/zeppelin-web-angular/src/app/share/folder-rename/folder-rename.component.ts b/zeppelin-web-angular/src/app/share/folder-rename/folder-rename.component.ts new file mode 100644 index 00000000000..250dac36854 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/folder-rename/folder-rename.component.ts @@ -0,0 +1,80 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; + +import { NzModalRef } from 'ng-zorro-antd'; + +import { MessageService } from '@zeppelin/services/message.service'; +import { NoteListService } from '@zeppelin/services/note-list.service'; + +@Component({ + selector: 'zeppelin-folder-rename', + templateUrl: './folder-rename.component.html', + styleUrls: ['./folder-rename.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FolderRenameComponent implements OnInit { + @Input() newFolderPath: string; + @Input() folderId: string; + willMerged = false; + + checkMerged() { + const newFolderPath = this.normalizeFolderId(this.newFolderPath); + this.willMerged = this.folderId !== this.newFolderPath && !!this.noteListService.notes.flatFolderMap[newFolderPath]; + this.cdr.markForCheck(); + } + + rename() { + this.messageService.folderRename(this.folderId, this.newFolderPath); + this.nzModalRef.destroy(); + } + + normalizeFolderId(folderId) { + let normalizeFolderId = folderId.trim(); + + while (normalizeFolderId.indexOf('\\') > -1) { + normalizeFolderId = normalizeFolderId.replace('\\', '/'); + } + + while (normalizeFolderId.indexOf('///') > -1) { + normalizeFolderId = normalizeFolderId.replace('///', '/'); + } + + normalizeFolderId = normalizeFolderId.replace('//', '/'); + + if (normalizeFolderId === '/') { + return '/'; + } + + if (normalizeFolderId[0] === '/') { + normalizeFolderId = normalizeFolderId.substring(1); + } + + if (normalizeFolderId.slice(-1) === '/') { + normalizeFolderId = normalizeFolderId.slice(0, -1); + } + + return normalizeFolderId; + } + + constructor( + private noteListService: NoteListService, + private cdr: ChangeDetectorRef, + private messageService: MessageService, + private nzModalRef: NzModalRef + ) {} + + ngOnInit() { + this.checkMerged(); + } +} diff --git a/zeppelin-web-angular/src/app/share/header/header.component.html b/zeppelin-web-angular/src/app/share/header/header.component.html new file mode 100644 index 00000000000..71e8cd7c614 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/header/header.component.html @@ -0,0 +1,77 @@ + + +
+ + +
+ + + + + + + +
+ +
diff --git a/zeppelin-web-angular/src/app/share/header/header.component.less b/zeppelin-web-angular/src/app/share/header/header.component.less new file mode 100644 index 00000000000..e4754b15ec9 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/header/header.component.less @@ -0,0 +1,110 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +.themeMixin({ + .small-icon { + margin-left: 6px; + font-size: 12px; + margin-right: 0; + transform: scale(0.8); + } + .node-list-trigger { + height: 100%; + display: inline-block; + margin: 0 -20px; + padding: 0 20px; + color: @text-color; + } + .header { + position: relative; + z-index: 999; + width: 100%; + height: 50px; + background: @component-background; + padding: 0 15px; + overflow: hidden; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.06) + } + .brand { + float: left; + width: 200px; + } + .logo { + height: 50px; + width: 75px; + background-size: 50px 30px; + background-repeat: no-repeat; + background-position: center; + background-image: url("../../../assets/images/zeppelin_svg_logo.svg"); + float: left; + } + .title { + float: left; + line-height: 50px; + font-family: 'Patua One', cursive; + font-size: 25px; + color: @primary-color; + } + .nav { + float: left; + + ul { + position: relative; + top: 2px; + border-bottom: none; + } + + a { + font-weight: 500; + } + } + .search { + float: right; + padding: 9px; + width: 300px; + margin-right: 24px; + } + .user { + float: right; + + .status { + line-height: 50px; + height: 50px; + display: inline-block; + color: @text-color; + } + } + .modal { + .about-logo { + img { + width: 95%; + } + } + + .content { + text-align: center; + + h3 { + font-family: 'Patua One', cursive; + color: #3071A9; + font-size: 30px; + margin: 0 auto; + } + + .about-version { + font-weight: 500; + } + } + } +}); diff --git a/zeppelin-web-angular/src/app/share/header/header.component.ts b/zeppelin-web-angular/src/app/share/header/header.component.ts new file mode 100644 index 00000000000..d9e4cc7e693 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/header/header.component.ts @@ -0,0 +1,86 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { NavigationEnd, Router } from '@angular/router'; +import { NzModalService } from 'ng-zorro-antd'; + +import { Subject } from 'rxjs'; +import { filter, takeUntil } from 'rxjs/operators'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { MessageReceiveDataTypeMap, OP } from '@zeppelin/sdk'; +import { MessageService, TicketService } from '@zeppelin/services'; +import { AboutZeppelinComponent } from '@zeppelin/share/about-zeppelin/about-zeppelin.component'; + +@Component({ + selector: 'zeppelin-header', + templateUrl: './header.component.html', + styleUrls: ['./header.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class HeaderComponent extends MessageListenersManager implements OnInit, OnDestroy { + private destroy$ = new Subject(); + connectStatus = 'error'; + noteListVisible = false; + + about() { + this.nzModalService.create({ + nzTitle: 'About Zeppelin', + nzWidth: '600px', + nzContent: AboutZeppelinComponent, + nzFooter: null + }); + } + + logout() { + this.ticketService.logout().subscribe(); + } + + @MessageListener(OP.CONFIGURATIONS_INFO) + getConfiguration(data: MessageReceiveDataTypeMap[OP.CONFIGURATIONS_INFO]) { + this.ticketService.setConfiguration(data); + } + + constructor( + public ticketService: TicketService, + private nzModalService: NzModalService, + public messageService: MessageService, + private router: Router, + private cdr: ChangeDetectorRef + ) { + super(messageService); + } + + ngOnInit() { + this.messageService.listConfigurations(); + this.messageService.connectedStatus$.pipe(takeUntil(this.destroy$)).subscribe(status => { + this.connectStatus = status ? 'success' : 'error'; + this.cdr.markForCheck(); + }); + this.router.events + .pipe( + filter(e => e instanceof NavigationEnd), + takeUntil(this.destroy$) + ) + .subscribe(() => { + this.noteListVisible = false; + this.cdr.markForCheck(); + }); + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + super.ngOnDestroy(); + } +} diff --git a/zeppelin-web-angular/src/app/share/index.ts b/zeppelin-web-angular/src/app/share/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/share/math-jax/math-jax.directive.ts b/zeppelin-web-angular/src/app/share/math-jax/math-jax.directive.ts new file mode 100644 index 00000000000..7352122a8da --- /dev/null +++ b/zeppelin-web-angular/src/app/share/math-jax/math-jax.directive.ts @@ -0,0 +1,24 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AfterViewChecked, Directive, ElementRef } from '@angular/core'; + +@Directive({ + selector: '[zeppelinMathJax]' +}) +export class MathJaxDirective implements AfterViewChecked { + constructor(private el: ElementRef) {} + + ngAfterViewChecked(): void { + MathJax.Hub.Queue(['Typeset', MathJax.Hub, this.el.nativeElement]); + } +} diff --git a/zeppelin-web-angular/src/app/share/node-list/node-list.component.html b/zeppelin-web-angular/src/app/share/node-list/node-list.component.html new file mode 100644 index 00000000000..70be6910499 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/node-list/node-list.component.html @@ -0,0 +1,139 @@ + + + diff --git a/zeppelin-web-angular/src/app/share/node-list/node-list.component.less b/zeppelin-web-angular/src/app/share/node-list/node-list.component.less new file mode 100644 index 00000000000..aec40c15ccf --- /dev/null +++ b/zeppelin-web-angular/src/app/share/node-list/node-list.component.less @@ -0,0 +1,82 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import 'theme-mixin'; + +:host { + display: block; +} + +.themeMixin({ + .content { + width: 100%; + position: relative; + + &.header-mode { + .operation { + display: none; + } + } + } + .rename { + width: 200px; + } + nz-tree { + display: block; + } + nz-input-group { + width: 100%; + margin-top: 12px; + margin-bottom: 6px; + } + .node { + line-height: 24px; + display: inline-block; + width: calc(~"100% - 24px"); + + &.not-matched { + opacity: 0.5; + filter: grayscale(1); + } + + i { + margin-right: 6px; + } + + .operation { + margin-left: 12px; + + i { + font-size: 12px; + display: none; + + &:hover { + color: @link-active-color; + } + } + } + + &.active { + .name { + color: @link-active-color; + } + } + + &:hover, &.active { + .operation { + i { + display: inline-block; + } + } + } + } +}); diff --git a/zeppelin-web-angular/src/app/share/node-list/node-list.component.ts b/zeppelin-web-angular/src/app/share/node-list/node-list.component.ts new file mode 100644 index 00000000000..c9206fd1fce --- /dev/null +++ b/zeppelin-web-angular/src/app/share/node-list/node-list.component.ts @@ -0,0 +1,117 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; + +import { NzModalService, NzTreeNode } from 'ng-zorro-antd'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { MessageReceiveDataTypeMap, OP } from '@zeppelin/sdk'; +import { MessageService, NoteActionService, NoteListService } from '@zeppelin/services'; + +@Component({ + selector: 'zeppelin-node-list', + templateUrl: './node-list.component.html', + providers: [NoteListService], + styleUrls: ['./node-list.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NodeListComponent extends MessageListenersManager implements OnInit { + @Input() headerMode = false; + searchValue: string; + nodes = []; + activatedId: string; + + activeNote(id: string) { + this.activatedId = id; + } + + moveFolderToTrash(id: string) { + return this.messageService.moveFolderToTrash(id); + } + + restoreFolder(id: string) { + return this.messageService.restoreFolder(id); + } + + removeFolder(id: string) { + return this.messageService.removeFolder(id); + } + + paragraphClearAllOutput(id: string) { + return this.messageService.paragraphClearAllOutput(id); + } + + moveNoteToTrash(id: string) { + return this.messageService.moveNoteToTrash(id); + } + + restoreNote(id: string) { + return this.messageService.restoreNote(id); + } + + deleteNote(id: string) { + return this.messageService.deleteNote(id); + } + + restoreAll() { + return this.messageService.restoreAll(); + } + + emptyTrash() { + return this.messageService.emptyTrash(); + } + + toggleFolder(node: NzTreeNode) { + node.isExpanded = !node.isExpanded; + this.cdr.markForCheck(); + } + + renameNote(id: string, path: string, name: string) { + this.noteActionService.renameNote(id, path, name); + } + + renameFolder(path) { + this.noteActionService.renameFolder(path); + } + + importNote() { + this.noteActionService.importNote(); + } + + createNote(path?: string) { + this.noteActionService.createNote(path); + } + + @MessageListener(OP.NOTES_INFO) + getNotes(data: MessageReceiveDataTypeMap[OP.NOTES_INFO]) { + this.noteListService.setNotes(data.notes); + this.nodes = this.noteListService.notes.root.children.map(item => { + return { ...item, key: item.id }; + }); + this.cdr.markForCheck(); + } + + constructor( + private noteListService: NoteListService, + public messageService: MessageService, + private nzModalService: NzModalService, + private noteActionService: NoteActionService, + private cdr: ChangeDetectorRef + ) { + super(messageService); + } + + ngOnInit() { + this.messageService.listNodes(); + } +} diff --git a/zeppelin-web-angular/src/app/share/note-create/note-create.component.html b/zeppelin-web-angular/src/app/share/note-create/note-create.component.html new file mode 100644 index 00000000000..54fe7cde684 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/note-create/note-create.component.html @@ -0,0 +1,44 @@ + + +
+ + + Clone Note + Import As + + + + + + + Default Interpreter + + + + + + + + + + + + + +
+ diff --git a/zeppelin-web-angular/src/app/share/note-create/note-create.component.less b/zeppelin-web-angular/src/app/share/note-create/note-create.component.less new file mode 100644 index 00000000000..019b5ca53b5 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/note-create/note-create.component.less @@ -0,0 +1,12 @@ +/* + * 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. + */ + diff --git a/zeppelin-web-angular/src/app/share/note-create/note-create.component.ts b/zeppelin-web-angular/src/app/share/note-create/note-create.component.ts new file mode 100644 index 00000000000..42d9a95c91b --- /dev/null +++ b/zeppelin-web-angular/src/app/share/note-create/note-create.component.ts @@ -0,0 +1,105 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; + +import { NzModalRef } from 'ng-zorro-antd'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { InterpreterItem, MessageReceiveDataTypeMap, Note, OP } from '@zeppelin/sdk'; +import { MessageService } from '@zeppelin/services/message.service'; +import { NoteListService } from '@zeppelin/services/note-list.service'; + +@Component({ + selector: 'zeppelin-note-create', + templateUrl: './note-create.component.html', + styleUrls: ['./note-create.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NoteCreateComponent extends MessageListenersManager implements OnInit { + @Input() path: string; + @Input() cloneNote: Note['note']; + noteName: string; + defaultInterpreter: string; + listOfInterpreter: InterpreterItem[] = []; + + @MessageListener(OP.INTERPRETER_SETTINGS) + getInterpreterSettings(data: MessageReceiveDataTypeMap[OP.INTERPRETER_SETTINGS]) { + this.listOfInterpreter = data.interpreterSettings; + this.defaultInterpreter = data.interpreterSettings[0].name; + this.cdr.markForCheck(); + } + + @MessageListener(OP.NOTES_INFO) + getNotes() { + this.nzModalRef.destroy(); + } + + newNoteName(path: string) { + let newCount = 1; + this.noteListService.notes.flatList.forEach(note => { + const noteName = note.path; + if (noteName.match(/^\/Untitled Note [0-9]*$/)) { + const lastCount = +noteName.substr(15); + if (newCount <= lastCount) { + newCount = lastCount + 1; + } + } + }); + return `${path ? path + '/' : ''}Untitled Note ${newCount}`; + } + + cloneNoteName() { + let copyCount = 1; + let newCloneName = ''; + const lastIndex = this.cloneNote.name.lastIndexOf(' '); + const endsWithNumber: boolean = !!this.cloneNote.name.match('^.+?\\s\\d$'); + const noteNamePrefix = endsWithNumber ? this.cloneNote.name.substr(0, lastIndex) : this.cloneNote.name; + const regexp = new RegExp(`^${noteNamePrefix}.+`); + + this.noteListService.notes.flatList.forEach(note => { + const noteName = note.path; + if (noteName.match(regexp)) { + const lastCopyCount = parseInt(noteName.substr(lastIndex).trim(), 10); + newCloneName = noteNamePrefix; + if (copyCount <= lastCopyCount) { + copyCount = lastCopyCount + 1; + } + } + }); + + if (!newCloneName) { + newCloneName = this.cloneNote.name; + } + return `${newCloneName} ${copyCount}`; + } + + createNote() { + this.cloneNote + ? this.messageService.cloneNote(this.cloneNote.id, this.noteName) + : this.messageService.newNote(this.noteName, this.defaultInterpreter); + } + + constructor( + public messageService: MessageService, + private cdr: ChangeDetectorRef, + private noteListService: NoteListService, + private nzModalRef: NzModalRef + ) { + super(messageService); + } + + ngOnInit() { + this.messageService.getInterpreterSettings(); + this.noteName = this.cloneNote ? this.cloneNoteName() : this.newNoteName(this.path); + } +} diff --git a/zeppelin-web-angular/src/app/share/note-import/note-import.component.html b/zeppelin-web-angular/src/app/share/note-import/note-import.component.html new file mode 100644 index 00000000000..861da357a90 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/note-import/note-import.component.html @@ -0,0 +1,50 @@ + + +
+ + Import As + + + + +
+ + + + +

+ +

+

Click or drag JSON file to this area to upload

+

+ JSON file size cannot exceed {{maxLimit | humanizeBytes}} +

+
+
+ +
+ + URL + + + + + + + + + +
+
+
+ diff --git a/zeppelin-web-angular/src/app/share/note-import/note-import.component.less b/zeppelin-web-angular/src/app/share/note-import/note-import.component.less new file mode 100644 index 00000000000..bb67745eec8 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/note-import/note-import.component.less @@ -0,0 +1,19 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + nz-alert { + margin-top: 12px; + } +}); diff --git a/zeppelin-web-angular/src/app/share/note-import/note-import.component.ts b/zeppelin-web-angular/src/app/share/note-import/note-import.component.ts new file mode 100644 index 00000000000..4e928c957af --- /dev/null +++ b/zeppelin-web-angular/src/app/share/note-import/note-import.component.ts @@ -0,0 +1,110 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { HttpClient } from '@angular/common/http'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core'; + +import { get } from 'lodash'; +import { NzModalRef, UploadFile } from 'ng-zorro-antd'; + +import { MessageListener, MessageListenersManager } from '@zeppelin/core'; +import { OP } from '@zeppelin/sdk'; +import { MessageService } from '@zeppelin/services/message.service'; +import { TicketService } from '@zeppelin/services/ticket.service'; + +@Component({ + selector: 'zeppelin-note-import', + templateUrl: './note-import.component.html', + styleUrls: ['./note-import.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NoteImportComponent extends MessageListenersManager implements OnInit { + noteImportName: string; + importUrl: string; + errorText: string; + importLoading = false; + maxLimit = get(this.ticketService.configuration, ['zeppelin.websocket.max.text.message.size'], null); + + @MessageListener(OP.NOTES_INFO) + getNotes() { + this.nzModalRef.destroy(); + } + + importNote() { + this.errorText = ''; + this.importLoading = true; + this.httpClient.get(this.importUrl).subscribe( + data => { + this.importLoading = false; + this.processImportJson(data); + this.cdr.markForCheck(); + }, + () => { + this.errorText = 'Unable to Fetch URL'; + this.importLoading = false; + this.cdr.markForCheck(); + }, + () => {} + ); + } + + beforeUpload = (file: UploadFile): boolean => { + this.errorText = ''; + if (file.size > this.maxLimit) { + this.errorText = 'File size limit Exceeded!'; + } else { + const reader = new FileReader(); + // tslint:disable-next-line:no-any + reader.readAsText(file as any); + reader.onloadend = () => { + this.processImportJson(reader.result); + }; + } + this.cdr.markForCheck(); + return false; + }; + + processImportJson(data) { + let result = data; + if (typeof result !== 'object') { + try { + result = JSON.parse(result); + } catch (e) { + this.errorText = 'JSON parse exception'; + return; + } + } + if (result.paragraphs && result.paragraphs.length > 0) { + if (!this.noteImportName) { + this.noteImportName = result.name; + } else { + result.name = this.noteImportName; + } + this.messageService.importNote(result); + } else { + this.errorText = 'Invalid JSON'; + } + this.cdr.markForCheck(); + } + + constructor( + private ticketService: TicketService, + public messageService: MessageService, + private cdr: ChangeDetectorRef, + private nzModalRef: NzModalRef, + private httpClient: HttpClient + ) { + super(messageService); + } + + ngOnInit() {} +} diff --git a/zeppelin-web-angular/src/app/share/note-rename/note-rename.component.html b/zeppelin-web-angular/src/app/share/note-rename/note-rename.component.html new file mode 100644 index 00000000000..f37415e04c0 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/note-rename/note-rename.component.html @@ -0,0 +1,23 @@ + + +
+ + Please enter a new name + + + + + +
diff --git a/zeppelin-web-angular/src/app/share/note-rename/note-rename.component.less b/zeppelin-web-angular/src/app/share/note-rename/note-rename.component.less new file mode 100644 index 00000000000..019b5ca53b5 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/note-rename/note-rename.component.less @@ -0,0 +1,12 @@ +/* + * 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. + */ + diff --git a/zeppelin-web-angular/src/app/share/note-rename/note-rename.component.ts b/zeppelin-web-angular/src/app/share/note-rename/note-rename.component.ts new file mode 100644 index 00000000000..3b07b8d51b9 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/note-rename/note-rename.component.ts @@ -0,0 +1,37 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; + +import { NzModalRef } from 'ng-zorro-antd'; + +import { MessageService } from '@zeppelin/services/message.service'; + +@Component({ + selector: 'zeppelin-note-rename', + templateUrl: './note-rename.component.html', + styleUrls: ['./note-rename.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class NoteRenameComponent implements OnInit { + @Input() newName: string; + @Input() id: string; + + rename() { + this.messageService.noteRename(this.id, this.newName); + this.nzModalRef.destroy(); + } + + constructor(private messageService: MessageService, private nzModalRef: NzModalRef) {} + + ngOnInit() {} +} diff --git a/zeppelin-web-angular/src/app/share/page-header/page-header.component.html b/zeppelin-web-angular/src/app/share/page-header/page-header.component.html new file mode 100644 index 00000000000..430f7e2880b --- /dev/null +++ b/zeppelin-web-angular/src/app/share/page-header/page-header.component.html @@ -0,0 +1,18 @@ + + + +

{{title}}

+

{{description}}

+ + +
diff --git a/zeppelin-web-angular/src/app/share/page-header/page-header.component.less b/zeppelin-web-angular/src/app/share/page-header/page-header.component.less new file mode 100644 index 00000000000..f0b6ac78b0e --- /dev/null +++ b/zeppelin-web-angular/src/app/share/page-header/page-header.component.less @@ -0,0 +1,17 @@ +/* + * 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. + */ + +:host { + .header-extra { + float: right; + } +} diff --git a/zeppelin-web-angular/src/app/share/page-header/page-header.component.ts b/zeppelin-web-angular/src/app/share/page-header/page-header.component.ts new file mode 100644 index 00000000000..1c03ee6298c --- /dev/null +++ b/zeppelin-web-angular/src/app/share/page-header/page-header.component.ts @@ -0,0 +1,31 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, Input, OnInit, TemplateRef } from '@angular/core'; +import { InputBoolean } from 'ng-zorro-antd'; + +@Component({ + selector: 'zeppelin-page-header', + templateUrl: './page-header.component.html', + styleUrls: ['./page-header.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PageHeaderComponent implements OnInit { + @Input() title: string; + @Input() description: string; + @Input() @InputBoolean() divider = false; + @Input() extra: TemplateRef; + + constructor() {} + + ngOnInit() {} +} diff --git a/zeppelin-web-angular/src/app/share/pipes/humanize-bytes.pipe.ts b/zeppelin-web-angular/src/app/share/pipes/humanize-bytes.pipe.ts new file mode 100644 index 00000000000..5460413af8e --- /dev/null +++ b/zeppelin-web-angular/src/app/share/pipes/humanize-bytes.pipe.ts @@ -0,0 +1,40 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'humanizeBytes' +}) +export class HumanizeBytesPipe implements PipeTransform { + transform(value: number): string { + if (value === null || value === undefined) { + return '-'; + } + const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']; + const converter = (v: number, p: number): string => { + const base = Math.pow(1024, p); + if (v < base) { + return `${(v / base).toFixed(2)} ${units[p]}`; + } else if (v < base * 1000) { + return `${(v / base).toPrecision(3)} ${units[p]}`; + } else { + return converter(v, p + 1); + } + }; + if (value < 1000) { + return value + ' B'; + } else { + return converter(value, 1); + } + } +} diff --git a/zeppelin-web-angular/src/app/share/pipes/index.ts b/zeppelin-web-angular/src/app/share/pipes/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/pipes/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/share/pipes/public-api.ts b/zeppelin-web-angular/src/app/share/pipes/public-api.ts new file mode 100644 index 00000000000..0397f58d260 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/pipes/public-api.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './humanize-bytes.pipe'; diff --git a/zeppelin-web-angular/src/app/share/public-api.ts b/zeppelin-web-angular/src/app/share/public-api.ts new file mode 100644 index 00000000000..b8c2732003e --- /dev/null +++ b/zeppelin-web-angular/src/app/share/public-api.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +export * from './pipes'; +export * from './resize-handle'; +export * from './share.module'; diff --git a/zeppelin-web-angular/src/app/share/resize-handle/index.ts b/zeppelin-web-angular/src/app/share/resize-handle/index.ts new file mode 100644 index 00000000000..49e47404422 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/resize-handle/index.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './public-api'; diff --git a/zeppelin-web-angular/src/app/share/resize-handle/public-api.ts b/zeppelin-web-angular/src/app/share/resize-handle/public-api.ts new file mode 100644 index 00000000000..3744d417562 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/resize-handle/public-api.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export * from './resize-handle.component'; diff --git a/zeppelin-web-angular/src/app/share/resize-handle/resize-handle.component.html b/zeppelin-web-angular/src/app/share/resize-handle/resize-handle.component.html new file mode 100644 index 00000000000..72092e39325 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/resize-handle/resize-handle.component.html @@ -0,0 +1,23 @@ + + + + + diff --git a/zeppelin-web-angular/src/app/share/resize-handle/resize-handle.component.less b/zeppelin-web-angular/src/app/share/resize-handle/resize-handle.component.less new file mode 100644 index 00000000000..8eb1214ddb1 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/resize-handle/resize-handle.component.less @@ -0,0 +1,23 @@ +/* + * 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. + */ + +:host { + width: 24px; + height: 24px; + position: absolute; + right: 1px; + bottom: 1px; + color: #595959; + transition: opacity ease-out .2s; + cursor: se-resize; + z-index: 9; +} diff --git a/zeppelin-web-angular/src/app/share/resize-handle/resize-handle.component.ts b/zeppelin-web-angular/src/app/share/resize-handle/resize-handle.component.ts new file mode 100644 index 00000000000..b9d43322d33 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/resize-handle/resize-handle.component.ts @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'zeppelin-resize-handle', + templateUrl: './resize-handle.component.html', + styleUrls: ['./resize-handle.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + role: 'resize-handle' + } +}) +export class ResizeHandleComponent { + constructor() {} +} diff --git a/zeppelin-web-angular/src/app/share/run-scripts/run-scripts.directive.ts b/zeppelin-web-angular/src/app/share/run-scripts/run-scripts.directive.ts new file mode 100644 index 00000000000..db6a7fc243a --- /dev/null +++ b/zeppelin-web-angular/src/app/share/run-scripts/run-scripts.directive.ts @@ -0,0 +1,80 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Directive, ElementRef, Input, NgZone, OnChanges, Renderer2, SimpleChanges } from '@angular/core'; +import { SafeHtml } from '@angular/platform-browser'; +import { take } from 'rxjs/operators'; + +const loadedExternalScripts = new Set(); + +@Directive({ + selector: '[zeppelinRunScripts]' +}) +export class RunScriptsDirective implements OnChanges { + @Input() scriptsContent: string | SafeHtml; + + constructor(private elementRef: ElementRef, private ngZone: NgZone, private renderer: Renderer2) {} + + runScripts(): void { + if (!this.scriptsContent.toString()) { + return; + } + this.ngZone.onStable.pipe(take(1)).subscribe(() => { + this.ngZone.runOutsideAngular(() => { + const scripts = this.elementRef.nativeElement.getElementsByTagName('script'); + const externalScripts = []; + const localScripts = []; + for (let i = 0; i < scripts.length; i++) { + const script = scripts[i]; + if (script.text) { + localScripts.push(script); + } else if (script.src) { + externalScripts.push(script); + } + this.renderer.removeChild(this.elementRef.nativeElement, script); + } + Promise.all(externalScripts.map(s => this.loadExternalScript(s, this.elementRef.nativeElement))).then(() => { + localScripts.forEach(s => this.loadLocalScript(s, this.elementRef.nativeElement)); + }); + }); + }); + } + + loadExternalScript(script: HTMLScriptElement, parentNode: HTMLElement): Promise { + return new Promise(resolve => { + if (loadedExternalScripts.has(script.src)) { + resolve(); + } + const scriptCopy = this.renderer.createElement('script') as HTMLScriptElement; + scriptCopy.type = script.type ? script.type : 'text/javascript'; + scriptCopy.src = script.src; + scriptCopy.onload = () => { + resolve(); + loadedExternalScripts.add(script.src); + }; + parentNode.appendChild(scriptCopy); + }); + } + + loadLocalScript(script: HTMLScriptElement, parentNode: HTMLElement): void { + const scriptCopy = this.renderer.createElement('script') as HTMLScriptElement; + scriptCopy.type = script.type ? script.type : 'text/javascript'; + scriptCopy.text = `(function() { ${script.text} })();`; + parentNode.appendChild(scriptCopy); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes.scriptsContent) { + this.runScripts(); + } + } +} diff --git a/zeppelin-web-angular/src/app/share/share.module.ts b/zeppelin-web-angular/src/app/share/share.module.ts new file mode 100644 index 00000000000..ed5d191736a --- /dev/null +++ b/zeppelin-web-angular/src/app/share/share.module.ts @@ -0,0 +1,100 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; + +import { + NzAlertModule, + NzBadgeModule, + NzButtonModule, + NzCardModule, + NzDividerModule, + NzDropDownModule, + NzFormModule, + NzGridModule, + NzIconModule, + NzInputModule, + NzMenuModule, + NzMessageModule, + NzModalModule, + NzNotificationModule, + NzPopconfirmModule, + NzProgressModule, + NzSelectModule, + NzTabsModule, + NzToolTipModule, + NzTreeModule, + NzUploadModule +} from 'ng-zorro-antd'; + +import { AboutZeppelinComponent } from '@zeppelin/share/about-zeppelin/about-zeppelin.component'; +import { CodeEditorModule } from '@zeppelin/share/code-editor'; +import { FolderRenameComponent } from '@zeppelin/share/folder-rename/folder-rename.component'; +import { HeaderComponent } from '@zeppelin/share/header/header.component'; +import { MathJaxDirective } from '@zeppelin/share/math-jax/math-jax.directive'; +import { NodeListComponent } from '@zeppelin/share/node-list/node-list.component'; +import { NoteCreateComponent } from '@zeppelin/share/note-create/note-create.component'; +import { NoteImportComponent } from '@zeppelin/share/note-import/note-import.component'; +import { NoteRenameComponent } from '@zeppelin/share/note-rename/note-rename.component'; +import { PageHeaderComponent } from '@zeppelin/share/page-header/page-header.component'; +import { HumanizeBytesPipe } from '@zeppelin/share/pipes'; +import { RunScriptsDirective } from '@zeppelin/share/run-scripts/run-scripts.directive'; +import { SpinComponent } from '@zeppelin/share/spin/spin.component'; +import { ResizeHandleComponent } from './resize-handle'; + +const MODAL_LIST = [ + AboutZeppelinComponent, + NoteImportComponent, + NoteCreateComponent, + NoteRenameComponent, + FolderRenameComponent +]; +const EXPORT_LIST = [HeaderComponent, NodeListComponent, PageHeaderComponent, SpinComponent, ResizeHandleComponent]; +const PIPES = [HumanizeBytesPipe]; + +@NgModule({ + declarations: [MODAL_LIST, EXPORT_LIST, PIPES, MathJaxDirective, RunScriptsDirective], + entryComponents: [MODAL_LIST], + exports: [EXPORT_LIST, PIPES, MathJaxDirective, RunScriptsDirective, CodeEditorModule], + imports: [ + FormsModule, + CommonModule, + NzMenuModule, + NzIconModule, + NzInputModule, + NzDropDownModule, + NzBadgeModule, + NzGridModule, + NzModalModule, + NzTreeModule, + RouterModule, + NzButtonModule, + NzNotificationModule, + NzToolTipModule, + NzDividerModule, + NzMessageModule, + NzCardModule, + NzPopconfirmModule, + NzPopconfirmModule, + NzFormModule, + NzTabsModule, + NzUploadModule, + NzSelectModule, + NzAlertModule, + NzProgressModule, + CodeEditorModule + ] +}) +export class ShareModule {} diff --git a/zeppelin-web-angular/src/app/share/spin/spin.component.html b/zeppelin-web-angular/src/app/share/spin/spin.component.html new file mode 100644 index 00000000000..81b188308b1 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/spin/spin.component.html @@ -0,0 +1,21 @@ + + +
+
+ +
+

Zeppelin

+ +
+
+
diff --git a/zeppelin-web-angular/src/app/share/spin/spin.component.less b/zeppelin-web-angular/src/app/share/spin/spin.component.less new file mode 100644 index 00000000000..019b5ca53b5 --- /dev/null +++ b/zeppelin-web-angular/src/app/share/spin/spin.component.less @@ -0,0 +1,12 @@ +/* + * 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. + */ + diff --git a/zeppelin-web-angular/src/app/share/spin/spin.component.ts b/zeppelin-web-angular/src/app/share/spin/spin.component.ts new file mode 100644 index 00000000000..34e7cedd01a --- /dev/null +++ b/zeppelin-web-angular/src/app/share/spin/spin.component.ts @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; + +@Component({ + selector: 'zeppelin-spin', + templateUrl: './spin.component.html', + styleUrls: ['./spin.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SpinComponent implements OnInit { + @Input() transparent = false; + constructor() {} + + ngOnInit() {} +} diff --git a/zeppelin-web-angular/src/app/spell/spell-result.ts b/zeppelin-web-angular/src/app/spell/spell-result.ts new file mode 100644 index 00000000000..50051d2e94a --- /dev/null +++ b/zeppelin-web-angular/src/app/spell/spell-result.ts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +export class SpellResult { + static extractMagic(allParagraphText) { + const pattern = /^\s*%(\S+)\s*/g; + try { + const match = pattern.exec(allParagraphText); + if (match) { + return `%${match[1].trim()}`; + } + } catch (error) { + // failed to parse, ignore + } + + return undefined; + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.component.html b/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.component.html new file mode 100644 index 00000000000..4b4caf1d140 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.component.html @@ -0,0 +1,35 @@ + + +
+ + + + +
+
+ + View + + + + + + + + +
+
+
diff --git a/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.component.less b/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.component.less new file mode 100644 index 00000000000..b8beb4c3cb5 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.component.less @@ -0,0 +1,15 @@ +/* + * 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. + */ + +.area-chart-setting { + margin: 10px 0; +} diff --git a/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.component.ts b/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.component.ts new file mode 100644 index 00000000000..07ffb22cc4c --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.component.ts @@ -0,0 +1,102 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + Inject, + OnInit, + ViewChild +} from '@angular/core'; + +import { G2VisualizationComponentBase, Visualization, VISUALIZATION } from '@zeppelin/visualization'; + +import { VisualizationPivotSettingComponent } from '../common/pivot-setting/pivot-setting.component'; +import { calcTickCount } from '../common/util/calc-tick-count'; +import { setChartXAxis } from '../common/util/set-x-axis'; +import { VisualizationXAxisSettingComponent } from '../common/x-axis-setting/x-axis-setting.component'; + +@Component({ + selector: 'zeppelin-area-chart-visualization', + templateUrl: './area-chart-visualization.component.html', + styleUrls: ['./area-chart-visualization.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class AreaChartVisualizationComponent extends G2VisualizationComponentBase implements OnInit, AfterViewInit { + @ViewChild('container', { static: false }) container: ElementRef; + @ViewChild(VisualizationXAxisSettingComponent, { static: false }) + xAxisSettingComponent: VisualizationXAxisSettingComponent; + @ViewChild(VisualizationPivotSettingComponent, { static: false }) + pivotSettingComponent: VisualizationPivotSettingComponent; + style: 'stream' | 'expand' | 'stack' = 'stack'; + + constructor(@Inject(VISUALIZATION) public visualization: Visualization, private cdr: ChangeDetectorRef) { + super(visualization); + } + + viewChange() { + this.config.setting.stackedAreaChart.style = this.style; + this.visualization.configChange$.next(this.config); + } + + ngOnInit() {} + + refreshSetting() { + this.style = this.config.setting.stackedAreaChart.style; + this.pivotSettingComponent.init(); + this.xAxisSettingComponent.init(); + this.cdr.markForCheck(); + } + + ngAfterViewInit(): void { + this.render(); + } + + setScale() { + const key = this.getKey(); + const tickCount = calcTickCount(this.container.nativeElement); + this.chart.scale(key, { + tickCount, + type: 'cat' + }); + } + + renderBefore() { + const key = this.getKey(); + this.setScale(); + if (this.style === 'stack') { + // area:stack + this.chart + .areaStack() + .position(`${key}*__value__`) + .color('__key__'); + } else if (this.style === 'stream') { + // area:stream + this.chart + .area() + .position(`${key}*__value__`) + .adjust(['stack', 'symmetric']) + .color('__key__'); + } else { + // area:percent + this.chart + .areaStack() + .position(`${key}*__percent__`) + .color('__key__'); + } + + setChartXAxis(this.visualization, 'stackedAreaChart', this.chart, key); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.ts b/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.ts new file mode 100644 index 00000000000..a7f1b481c69 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/area-chart/area-chart-visualization.ts @@ -0,0 +1,32 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkPortalOutlet } from '@angular/cdk/portal'; +import { ViewContainerRef } from '@angular/core'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { G2VisualizationBase, VisualizationComponentPortal } from '@zeppelin/visualization'; + +import { AreaChartVisualizationComponent } from './area-chart-visualization.component'; + +export class AreaChartVisualization extends G2VisualizationBase { + componentPortal = new VisualizationComponentPortal( + this, + AreaChartVisualizationComponent, + this.portalOutlet, + this.viewContainerRef + ); + + constructor(config: GraphConfig, private portalOutlet: CdkPortalOutlet, private viewContainerRef: ViewContainerRef) { + super(config); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.component.html b/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.component.html new file mode 100644 index 00000000000..eb798668215 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.component.html @@ -0,0 +1,34 @@ + + +
+ + + + +
+ + View + + + + + + + +
+
+
+
diff --git a/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.component.less b/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.component.less new file mode 100644 index 00000000000..cd842d1ed23 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.component.less @@ -0,0 +1,25 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + bar-chart-setting { + margin: 10px 0; + } + .field-setting-wrap { + margin-top: 10px; + } + .drag-wrap { + min-height: 23px; + } +}); diff --git a/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.component.ts b/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.component.ts new file mode 100644 index 00000000000..82ed55f0dcf --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.component.ts @@ -0,0 +1,107 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + Inject, + OnInit, + ViewChild +} from '@angular/core'; + +import { get } from 'lodash'; + +import { VisualizationMultiBarChart } from '@zeppelin/sdk'; +import { G2VisualizationComponentBase, Visualization, VISUALIZATION } from '@zeppelin/visualization'; + +import { VisualizationPivotSettingComponent } from '../common/pivot-setting/pivot-setting.component'; +import { calcTickCount } from '../common/util/calc-tick-count'; +import { setChartXAxis } from '../common/util/set-x-axis'; +import { VisualizationXAxisSettingComponent } from '../common/x-axis-setting/x-axis-setting.component'; + +@Component({ + selector: 'zeppelin-bar-chart-visualization', + templateUrl: './bar-chart-visualization.component.html', + styleUrls: ['./bar-chart-visualization.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class BarChartVisualizationComponent extends G2VisualizationComponentBase implements OnInit, AfterViewInit { + @ViewChild('container', { static: false }) container: ElementRef; + @ViewChild(VisualizationXAxisSettingComponent, { static: false }) + xAxisSettingComponent: VisualizationXAxisSettingComponent; + @ViewChild(VisualizationPivotSettingComponent, { static: false }) + pivotSettingComponent: VisualizationPivotSettingComponent; + stacked = false; + + viewChange() { + if (!this.config.setting.multiBarChart) { + this.config.setting.multiBarChart = new VisualizationMultiBarChart(); + } + this.config.setting.multiBarChart.stacked = this.stacked; + this.visualization.configChange$.next(this.config); + } + + constructor(@Inject(VISUALIZATION) public visualization: Visualization, private cdr: ChangeDetectorRef) { + super(visualization); + } + + ngOnInit() {} + + ngAfterViewInit() { + this.render(); + } + + refreshSetting() { + this.stacked = get(this.config.setting, 'multiBarChart.stacked', false); + this.pivotSettingComponent.init(); + this.xAxisSettingComponent.init(); + this.cdr.markForCheck(); + } + + setScale() { + const key = this.getKey(); + const tickCount = calcTickCount(this.container.nativeElement); + this.chart.scale(key, { + tickCount, + type: 'cat' + }); + } + + renderBefore(chart) { + const key = this.getKey(); + this.setScale(); + + if (get(this.config.setting, 'multiBarChart.stacked', false)) { + this.chart + .intervalStack() + .position(`${key}*__value__`) + .color('__key__') + .opacity(1); + } else { + this.chart + .interval() + .position(`${key}*__value__`) + .color('__key__') + .opacity(1) + .adjust([ + { + type: 'dodge', + marginRatio: 0 + } + ]); + } + setChartXAxis(this.visualization, 'multiBarChart', this.chart, key); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.ts b/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.ts new file mode 100644 index 00000000000..736e43dadd1 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/bar-chart/bar-chart-visualization.ts @@ -0,0 +1,31 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkPortalOutlet } from '@angular/cdk/portal'; +import { ViewContainerRef } from '@angular/core'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { G2VisualizationBase, VisualizationComponentPortal } from '@zeppelin/visualization'; + +import { BarChartVisualizationComponent } from './bar-chart-visualization.component'; + +export class BarChartVisualization extends G2VisualizationBase { + componentPortal = new VisualizationComponentPortal( + this, + BarChartVisualizationComponent, + this.portalOutlet, + this.viewContainerRef + ); + constructor(config: GraphConfig, private portalOutlet: CdkPortalOutlet, private viewContainerRef: ViewContainerRef) { + super(config); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/common/pivot-setting/pivot-setting.component.html b/zeppelin-web-angular/src/app/visualizations/common/pivot-setting/pivot-setting.component.html new file mode 100644 index 00000000000..2a91d7beccd --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/pivot-setting/pivot-setting.component.html @@ -0,0 +1,85 @@ + + + +
+ {{item.name}} +
+
+
+ +
+ + {{item.name}} + + +
+
+
+
+ +
+ + {{item.name}} + + +
+
+
+
+ +
+ + {{item.name}} {{item.aggr | uppercase}}  + + +
    +
  • + {{aggregate}} +
  • +
+
+
+
+
+
+
+
diff --git a/zeppelin-web-angular/src/app/visualizations/common/pivot-setting/pivot-setting.component.less b/zeppelin-web-angular/src/app/visualizations/common/pivot-setting/pivot-setting.component.less new file mode 100644 index 00000000000..87bb382eaea --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/pivot-setting/pivot-setting.component.less @@ -0,0 +1,27 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + display: block; + margin: 10px 0; + .field-setting-wrap { + margin-top: 24px; + } + .drag-wrap { + min-height: 23px; + } + nz-card { + background: #fff; + } +}); diff --git a/zeppelin-web-angular/src/app/visualizations/common/pivot-setting/pivot-setting.component.ts b/zeppelin-web-angular/src/app/visualizations/common/pivot-setting/pivot-setting.component.ts new file mode 100644 index 00000000000..12abf17c79c --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/pivot-setting/pivot-setting.component.ts @@ -0,0 +1,89 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { copyArrayItem, moveItemInArray, transferArrayItem, CdkDragDrop } from '@angular/cdk/drag-drop'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { TableData, Visualization } from '@zeppelin/visualization'; + +@Component({ + selector: 'zeppelin-visualization-pivot-setting', + templateUrl: './pivot-setting.component.html', + styleUrls: ['./pivot-setting.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class VisualizationPivotSettingComponent implements OnInit { + @Input() visualization: Visualization; + + tableData: TableData; + config: GraphConfig; + columns = []; + aggregates = ['sum', 'count', 'avg', 'min', 'max']; + + // tslint:disable-next-line + drop(event: CdkDragDrop) { + if (event.container.id === 'columns-list') { + return; + } + if (event.previousContainer === event.container) { + moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); + } else { + if ( + event.container.id !== 'value-list' && + event.container.data.findIndex(e => e.name === event.previousContainer.data[event.previousIndex].name) !== -1 + ) { + return; + } + if (event.previousContainer.id === 'columns-list') { + copyArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex); + } else { + transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex); + } + } + this.visualization.configChange$.next(this.config); + } + + // tslint:disable-next-line + removeFieldAt(data: any[], index: number): void { + data.splice(index, 1); + this.visualization.configChange$.next(this.config); + this.cdr.markForCheck(); + } + + changeAggregate(aggregates: string, index: number): void { + this.config.values[index].aggr = aggregates; + this.visualization.configChange$.next(this.config); + this.cdr.markForCheck(); + } + + noReturnPredicate() { + return false; + } + + init() { + this.tableData = this.visualization.getTransformation().getTableData() as TableData; + this.config = this.visualization.getConfig(); + this.columns = this.tableData.columns.map((name, index) => ({ + name, + index, + aggr: 'sum' + })); + this.cdr.markForCheck(); + } + + constructor(private cdr: ChangeDetectorRef) {} + + ngOnInit() { + this.init(); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.html b/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.html new file mode 100644 index 00000000000..ff03338c481 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.html @@ -0,0 +1,98 @@ + + + +
+ {{item.name}} +
+
+
+ +
+ + {{item.name}} + + +
+
+
+
+ +
+ + {{item.name}} + + +
+
+
+
+ +
+ + {{item.name}} + + +
+
+
+
+ +
+ + {{item.name}} + + +
+
+
+ +
+
diff --git a/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.less b/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.less new file mode 100644 index 00000000000..01427854d96 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.less @@ -0,0 +1,27 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + display: block; + margin: 10px 0; + .field-setting-wrap { + margin-top: 10px; + } + .drag-wrap { + min-height: 23px; + } + nz-card { + background: #fff; + } +}); diff --git a/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.ts b/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.ts new file mode 100644 index 00000000000..e154549e43e --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/scatter-setting/scatter-setting.component.ts @@ -0,0 +1,102 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkDragDrop } from '@angular/cdk/drag-drop'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; + +import { get } from 'lodash'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { TableData, Visualization } from '@zeppelin/visualization'; + +@Component({ + selector: 'zeppelin-visualization-scatter-setting', + templateUrl: './scatter-setting.component.html', + styleUrls: ['./scatter-setting.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class VisualizationScatterSettingComponent implements OnInit { + @Input() visualization: Visualization; + + tableData: TableData; + config: GraphConfig; + columns = []; + + field = { + xAxis: [], + yAxis: [], + group: [], + size: [] + }; + + // tslint:disable-next-line + drop(event: CdkDragDrop) { + this.clean(event.container.data, false); + event.container.data.push(event.previousContainer.data[event.previousIndex]); + this.cdr.markForCheck(); + this.updateConfig(); + } + + // tslint:disable-next-line + clean(data: any[], update = true): void { + while (data.length > 0) { + data.splice(0, 1); + } + if (update) { + this.updateConfig(); + } + this.cdr.markForCheck(); + } + + noReturnPredicate() { + return false; + } + + updateConfig() { + if (!this.config.setting.scatterChart) { + this.config.setting.scatterChart = {}; + } + const scatterSetting = this.config.setting.scatterChart; + scatterSetting.xAxis = this.field.xAxis[0]; + scatterSetting.yAxis = this.field.yAxis[0]; + scatterSetting.size = this.field.size[0]; + scatterSetting.group = this.field.group[0]; + this.visualization.configChange$.next(this.config); + } + + constructor(private cdr: ChangeDetectorRef) {} + + init() { + this.tableData = this.visualization.getTransformation().getTableData() as TableData; + this.config = this.visualization.getConfig(); + this.columns = this.tableData.columns.map((name, index) => ({ + name, + index, + aggr: 'sum' + })); + + const xAxis = get(this.config.setting, 'scatterChart.xAxis', this.columns[0]); + const yAxis = get(this.config.setting, 'scatterChart.yAxis', this.columns[1]); + const group = get(this.config.setting, 'scatterChart.group'); + const size = get(this.config.setting, 'scatterChart.size'); + const arrayWrapper = value => (value ? [value] : []); + this.field.xAxis = arrayWrapper(xAxis); + this.field.yAxis = arrayWrapper(yAxis); + this.field.group = arrayWrapper(group); + this.field.size = arrayWrapper(size); + this.cdr.markForCheck(); + } + + ngOnInit() { + this.init(); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/common/util/calc-tick-count.ts b/zeppelin-web-angular/src/app/visualizations/common/util/calc-tick-count.ts new file mode 100644 index 00000000000..bfa81a8df81 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/util/calc-tick-count.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +export const DEFAULT_TICK_COUNT = 16; + +export function calcTickCount(el: HTMLElement) { + if (el && el.getBoundingClientRect) { + const tickCount = Math.round(el.getBoundingClientRect().width / 60); + return Number.isNaN(tickCount) ? DEFAULT_TICK_COUNT : tickCount; + } else { + return DEFAULT_TICK_COUNT; + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/common/util/set-x-axis.ts b/zeppelin-web-angular/src/app/visualizations/common/util/set-x-axis.ts new file mode 100644 index 00000000000..e41ad7983a0 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/util/set-x-axis.ts @@ -0,0 +1,46 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as G2 from '@antv/g2'; +import { get } from 'lodash'; + +import { Visualization } from '@zeppelin/visualization'; + +export function setChartXAxis( + visualization: Visualization, + mode: 'lineChart' | 'multiBarChart' | 'stackedAreaChart', + chart: G2.Chart, + key: string +) { + const config = visualization.getConfig(); + const setting = config.setting[mode]; + chart.axis(key, { + label: { + textStyle: { + rotate: 0 + } + } + }); + switch (setting.xLabelStatus) { + case 'hide': + chart.axis(key, false); + break; + case 'rotate': + chart.axis(key, { + label: { + textStyle: { + rotate: Number.parseInt(get(setting, 'rotate.degree', '-45'), 10) + } + } + }); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/common/x-axis-setting/x-axis-setting.component.html b/zeppelin-web-angular/src/app/visualizations/common/x-axis-setting/x-axis-setting.component.html new file mode 100644 index 00000000000..cd11081ab04 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/x-axis-setting/x-axis-setting.component.html @@ -0,0 +1,38 @@ + + +
+ + xAxis + + + + + + + + + + degree + + + + + + + +
diff --git a/zeppelin-web-angular/src/app/visualizations/common/x-axis-setting/x-axis-setting.component.less b/zeppelin-web-angular/src/app/visualizations/common/x-axis-setting/x-axis-setting.component.less new file mode 100644 index 00000000000..3e7f1f963ba --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/x-axis-setting/x-axis-setting.component.less @@ -0,0 +1,18 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + display: block; + margin: 10px 0; +}); diff --git a/zeppelin-web-angular/src/app/visualizations/common/x-axis-setting/x-axis-setting.component.ts b/zeppelin-web-angular/src/app/visualizations/common/x-axis-setting/x-axis-setting.component.ts new file mode 100644 index 00000000000..0a5d5460de7 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/common/x-axis-setting/x-axis-setting.component.ts @@ -0,0 +1,78 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; + +import { get } from 'lodash'; + +import { GraphConfig, XAxisSetting, XLabelStatus } from '@zeppelin/sdk'; +import { Visualization } from '@zeppelin/visualization'; + +@Component({ + selector: 'zeppelin-visualization-x-axis-setting', + templateUrl: './x-axis-setting.component.html', + styleUrls: ['./x-axis-setting.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class VisualizationXAxisSettingComponent implements OnInit { + @Input() visualization: Visualization; + @Input() mode: 'lineChart' | 'multiBarChart' | 'stackedAreaChart'; + + setting: XAxisSetting; + config: GraphConfig; + xLabelStatus: XLabelStatus = 'default'; + degree = '-45'; + previousDegree: string; + constructor(private cdr: ChangeDetectorRef) {} + + onStatusChange() { + this.setting.xLabelStatus = this.xLabelStatus; + this.updateConfig(); + } + + onDegreeChange() { + if (this.degree === this.previousDegree) { + return; + } + const degree = Number.parseInt(this.degree, 10); + if (Number.isNaN(degree)) { + this.degree = this.previousDegree; + return; + } else { + this.degree = `${degree}`; + this.previousDegree = this.degree; + } + this.updateConfig(); + } + + updateConfig() { + this.setting.rotate.degree = this.degree; + this.setting.xLabelStatus = this.xLabelStatus; + this.visualization.configChange$.next(this.config); + } + + init() { + this.config = this.visualization.getConfig(); + this.setting = this.config.setting[this.mode]; + if (!this.setting.rotate) { + this.setting.rotate = { degree: '-45' }; + } + this.xLabelStatus = get(this.setting, ['xLabelStatus'], 'default'); + this.degree = get(this.setting, ['rotate', 'degree'], '-45'); + this.previousDegree = this.degree; + this.cdr.markForCheck(); + } + + ngOnInit() { + this.init(); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.component.html b/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.component.html new file mode 100644 index 00000000000..cb8faab7ed4 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.component.html @@ -0,0 +1,44 @@ + + +
+ + +
+ +
+ +
+ +
+ + +
+
+
diff --git a/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.component.less b/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.component.less new file mode 100644 index 00000000000..8e84bc5be30 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.component.less @@ -0,0 +1,25 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.themeMixin({ + .zoom-tips { + color: @text-color-secondary; + } + .line-setting { + margin: 10px 0; + input.format-input { + width: 160px; + } + } +}); diff --git a/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.component.ts b/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.component.ts new file mode 100644 index 00000000000..02938e55327 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.component.ts @@ -0,0 +1,137 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + Inject, + OnInit, + ViewChild +} from '@angular/core'; + +import { G2VisualizationComponentBase, Visualization, VISUALIZATION } from '@zeppelin/visualization'; + +import { VisualizationPivotSettingComponent } from '../common/pivot-setting/pivot-setting.component'; +import { calcTickCount } from '../common/util/calc-tick-count'; +import { setChartXAxis } from '../common/util/set-x-axis'; +import { VisualizationXAxisSettingComponent } from '../common/x-axis-setting/x-axis-setting.component'; + +@Component({ + selector: 'zeppelin-line-chart-visualization', + templateUrl: './line-chart-visualization.component.html', + styleUrls: ['./line-chart-visualization.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class LineChartVisualizationComponent extends G2VisualizationComponentBase implements OnInit, AfterViewInit { + @ViewChild('container', { static: false }) container: ElementRef; + @ViewChild(VisualizationXAxisSettingComponent, { static: false }) + xAxisSettingComponent: VisualizationXAxisSettingComponent; + @ViewChild(VisualizationPivotSettingComponent, { static: false }) + pivotSettingComponent: VisualizationPivotSettingComponent; + forceY = false; + lineWithFocus = false; + isDateFormat = false; + dateFormat = ''; + + settingChange(): void { + const setting = this.config.setting.lineChart; + setting.lineWithFocus = this.lineWithFocus; + setting.forceY = this.forceY; + setting.isDateFormat = this.isDateFormat; + setting.dateFormat = this.dateFormat; + this.visualization.configChange$.next(this.config); + } + + constructor(@Inject(VISUALIZATION) public visualization: Visualization, private cdr: ChangeDetectorRef) { + super(visualization); + } + + ngOnInit() {} + + refreshSetting() { + const setting = this.config.setting.lineChart; + this.forceY = setting.forceY || false; + this.lineWithFocus = setting.lineWithFocus || false; + this.isDateFormat = setting.isDateFormat || false; + this.dateFormat = setting.dateFormat || ''; + this.pivotSettingComponent.init(); + this.xAxisSettingComponent.init(); + this.cdr.markForCheck(); + } + + setScale() { + const key = this.getKey(); + const tickCount = calcTickCount(this.container.nativeElement); + this.chart.scale(key, { + tickCount, + type: 'cat' + }); + } + + renderBefore() { + const key = this.getKey(); + const setting = this.config.setting.lineChart; + this.setScale(); + this.chart + .line() + .position(`${key}*__value__`) + .color('__key__'); + setChartXAxis(this.visualization, 'lineChart', this.chart, key); + + if (setting.isDateFormat) { + if (this.visualization.transformed && this.visualization.transformed.rows) { + const invalid = this.visualization.transformed.rows.some(r => { + const isInvalidDate = Number.isNaN(new Date(r[key]).valueOf()); + if (isInvalidDate) { + console.warn(`${r[key]} is [Invalid Date]`); + } + return isInvalidDate; + }); + if (invalid) { + return; + } + this.chart.scale({ + [key]: { + type: 'time', + mask: setting.dateFormat || 'YYYY-MM-DD' + } + }); + } + } + + if (setting.forceY) { + this.chart.scale({ + __value__: { + min: 0 + } + }); + } + } + + renderAfter() { + const setting = this.config.setting.lineChart; + if (setting.lineWithFocus) { + // tslint:disable-next-line + (this.chart as any).interact('brush'); + } else { + // tslint:disable-next-line:no-any + (this.chart as any).clearInteraction(); + } + } + + ngAfterViewInit() { + this.render(); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.ts b/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.ts new file mode 100644 index 00000000000..0be29c7676b --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/line-chart/line-chart-visualization.ts @@ -0,0 +1,32 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkPortalOutlet } from '@angular/cdk/portal'; +import { ViewContainerRef } from '@angular/core'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { G2VisualizationBase, VisualizationComponentPortal } from '@zeppelin/visualization'; + +import { LineChartVisualizationComponent } from './line-chart-visualization.component'; + +export class LineChartVisualization extends G2VisualizationBase { + componentPortal = new VisualizationComponentPortal( + this, + LineChartVisualizationComponent, + this.portalOutlet, + this.viewContainerRef + ); + + constructor(config: GraphConfig, private portalOutlet: CdkPortalOutlet, private viewContainerRef: ViewContainerRef) { + super(config); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.component.html b/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.component.html new file mode 100644 index 00000000000..5ddf300130b --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.component.html @@ -0,0 +1,19 @@ + + +
+ + +
+
+
diff --git a/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.component.less b/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.component.less new file mode 100644 index 00000000000..019b5ca53b5 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.component.less @@ -0,0 +1,12 @@ +/* + * 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. + */ + diff --git a/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.component.ts b/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.component.ts new file mode 100644 index 00000000000..0edebaa9d44 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.component.ts @@ -0,0 +1,73 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + ElementRef, + Inject, + OnInit, + ViewChild +} from '@angular/core'; + +import { G2VisualizationComponentBase, Visualization, VISUALIZATION } from '@zeppelin/visualization'; + +import { VisualizationPivotSettingComponent } from '../common/pivot-setting/pivot-setting.component'; + +@Component({ + selector: 'zeppelin-pie-chart-visualization', + templateUrl: './pie-chart-visualization.component.html', + styleUrls: ['./pie-chart-visualization.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PieChartVisualizationComponent extends G2VisualizationComponentBase implements OnInit, AfterViewInit { + @ViewChild('container', { static: false }) container: ElementRef; + @ViewChild(VisualizationPivotSettingComponent, { static: false }) + pivotSettingComponent: VisualizationPivotSettingComponent; + + constructor(@Inject(VISUALIZATION) public visualization: Visualization) { + super(visualization); + } + + ngOnInit() {} + + refreshSetting() { + this.pivotSettingComponent.init(); + } + + setScale() { + // Noop + } + + renderBefore() { + this.chart.tooltip({ + showTitle: false + }); + this.chart.coord('theta', { + radius: 0.75 + }); + this.chart + .intervalStack() + .position('__value__') + .color('__key__') + .style({ + lineWidth: 1, + stroke: '#fff' + }) + .tooltip('__key__*__value__', (name, value) => ({ name, value })); + } + + ngAfterViewInit() { + this.render(); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.ts b/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.ts new file mode 100644 index 00000000000..d70572dda10 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/pie-chart/pie-chart-visualization.ts @@ -0,0 +1,32 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkPortalOutlet } from '@angular/cdk/portal'; +import { ViewContainerRef } from '@angular/core'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { G2VisualizationBase, VisualizationComponentPortal } from '@zeppelin/visualization'; + +import { PieChartVisualizationComponent } from './pie-chart-visualization.component'; + +export class PieChartVisualization extends G2VisualizationBase { + componentPortal = new VisualizationComponentPortal( + this, + PieChartVisualizationComponent, + this.portalOutlet, + this.viewContainerRef + ); + + constructor(config: GraphConfig, private portalOutlet: CdkPortalOutlet, private viewContainerRef: ViewContainerRef) { + super(config); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.html b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.html new file mode 100644 index 00000000000..ea1e3792c2c --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.html @@ -0,0 +1,19 @@ + + +
+ + +
+
+
diff --git a/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.less b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.less new file mode 100644 index 00000000000..019b5ca53b5 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.less @@ -0,0 +1,12 @@ +/* + * 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. + */ + diff --git a/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.ts b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.ts new file mode 100644 index 00000000000..f1b8ae5d8e4 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.component.ts @@ -0,0 +1,89 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + Inject, + OnInit, + ViewChild +} from '@angular/core'; + +import { get } from 'lodash'; + +import { G2VisualizationComponentBase, Visualization, VISUALIZATION } from '@zeppelin/visualization'; + +import { VisualizationScatterSettingComponent } from '../common/scatter-setting/scatter-setting.component'; +import { calcTickCount } from '../common/util/calc-tick-count'; + +@Component({ + selector: 'zeppelin-scatter-chart-visualization', + templateUrl: './scatter-chart-visualization.component.html', + styleUrls: ['./scatter-chart-visualization.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ScatterChartVisualizationComponent extends G2VisualizationComponentBase implements OnInit, AfterViewInit { + @ViewChild('container', { static: false }) container: ElementRef; + @ViewChild(VisualizationScatterSettingComponent, { static: false }) + scatterSettingComponent: VisualizationScatterSettingComponent; + + constructor(@Inject(VISUALIZATION) public visualization: Visualization, private cdr: ChangeDetectorRef) { + super(visualization); + } + + refreshSetting() { + this.scatterSettingComponent.init(); + this.cdr.markForCheck(); + } + + setScale() { + const key = this.getKey(); + const tickCount = calcTickCount(this.container.nativeElement); + this.chart.scale(key, { + tickCount, + type: 'cat' + }); + } + + renderBefore() { + const key = this.getKey(); + const size = get(this.config.setting, 'scatterChart.size.name'); + this.setScale(); + this.chart.tooltip({ + crosshairs: { + type: 'cross' + } + }); + this.chart.legend('__value__', false); + // point + const geom = this.chart + .point() + .position(`${key}*__value__`) + .color('__key__') + // .adjust('jitter') + .opacity(0.65) + .shape('circle'); + + if (size) { + geom.size('__value__'); + } + } + + ngOnInit() {} + + ngAfterViewInit() { + this.render(); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.ts b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.ts new file mode 100644 index 00000000000..0bfafab328c --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/scatter-chart/scatter-chart-visualization.ts @@ -0,0 +1,32 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkPortalOutlet } from '@angular/cdk/portal'; +import { ViewContainerRef } from '@angular/core'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { G2VisualizationBase, VisualizationComponentPortal } from '@zeppelin/visualization'; + +import { ScatterChartVisualizationComponent } from './scatter-chart-visualization.component'; + +export class ScatterChartVisualization extends G2VisualizationBase { + componentPortal = new VisualizationComponentPortal( + this, + ScatterChartVisualizationComponent, + this.portalOutlet, + this.viewContainerRef + ); + + constructor(config: GraphConfig, private portalOutlet: CdkPortalOutlet, private viewContainerRef: ViewContainerRef) { + super(config); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.html b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.html new file mode 100644 index 00000000000..db43a53f0db --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.html @@ -0,0 +1,123 @@ + + + + + + + + + + + {{col}} + + +
    + +
  • +
  • + Type +
      +
    • + {{type | titlecase}} +
    • +
    +
  • +
  • +
  • + Aggregation +
      +
    • + {{aggregation | titlecase}} +
    • +
    +
  • +
+
+ + + + + + {{data[col]}} + + +
+ +
+ + + {{aggregation}}({{col}}): {{colOptions.get(col).aggregationValue}} + + +
+
diff --git a/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.less b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.less new file mode 100644 index 00000000000..094ea9ac640 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.less @@ -0,0 +1,44 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import "theme-mixin"; + +.th-dropdown { + .search-bar.ant-menu-item-group { + padding: 5px 12px; + ::ng-deep .ant-menu-item-group-title{ + display: none; + } + } +} + +.export-dropdown { + margin-bottom: 16px; + position: absolute; + bottom: 0; + left: 0; +} + +.themeMixin({ + display: block; + position: relative; + ::ng-deep .filter-icon svg { + transition: transform 300ms; + } + + .aggregation-wrap { + text-align: right; + .aggregation-item { + margin-left: 10px; + } + } +}); diff --git a/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.ts b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.ts new file mode 100644 index 00000000000..09fa0778426 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.component.ts @@ -0,0 +1,174 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, OnInit, ViewChild } from '@angular/core'; + +import { filter, maxBy, minBy, orderBy, sumBy } from 'lodash'; +import { NzTableComponent } from 'ng-zorro-antd'; +import { utils, writeFile, WorkSheet } from 'xlsx'; + +import { TableData, Visualization, VISUALIZATION } from '@zeppelin/visualization'; + +type ColType = 'string' | 'date' | 'number'; +type AggregationType = 'count' | 'sum' | 'min' | 'max' | 'avg'; + +class FilterOption { + sort: 'desc' | 'asc' | '' = ''; + type: ColType = 'string'; + visible = true; + pinned?: string; + term = ''; + width: string | '*' = '*'; + aggregation: AggregationType | null = null; + aggregationValue: number | null = null; +} + +function typeCoercion(value: string, type: ColType): string | number | Date { + switch (type) { + case 'number': + const num = Number.parseFloat(value); + return Number.isNaN(num) ? value : num; + case 'date': + const date = new Date(value); + return Number.isNaN(date.valueOf()) ? value : date; + default: + return value; + } +} + +@Component({ + selector: 'zeppelin-visualization-table-visualization', + templateUrl: './table-visualization.component.html', + styleUrls: ['./table-visualization.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class TableVisualizationComponent implements OnInit { + tableData: TableData; + // tslint:disable-next-line:no-any + rows: any[] = []; + columns: string[] = []; + colOptions = new Map(); + types: ColType[] = ['string', 'number', 'date']; + aggregations: AggregationType[] = ['count', 'sum', 'min', 'max', 'avg']; + @ViewChild(NzTableComponent, { static: false }) nzTable: NzTableComponent; + + exportFile(type: 'csv' | 'xlsx', all = true) { + const wb = utils.book_new(); + let ws: WorkSheet; + if (all) { + ws = utils.json_to_sheet(this.rows); + } else { + ws = utils.json_to_sheet(this.nzTable.data); + } + utils.book_append_sheet(wb, ws, 'Sheet1'); + writeFile(wb, `export.${type}`); + } + + onChangeType(type: ColType, col: string) { + const opt = this.colOptions.get(col); + opt.type = type; + this.filterRows(); + this.aggregate(); + } + + onChangeAggregation(aggregation: AggregationType, col: string) { + const opt = this.colOptions.get(col); + opt.aggregation = opt.aggregation === aggregation ? null : aggregation; + this.aggregate(); + } + + onSearch(): void { + this.filterRows(); + } + + onSortChange(type: 'descend' | 'ascend' | string, key: string): void { + const opt: FilterOption = this.colOptions.get(key); + this.colOptions.delete(key); + if (type) { + opt.sort = type === 'descend' ? 'desc' : 'asc'; + } else { + opt.sort = ''; + } + this.colOptions.set(key, opt); + this.filterRows(); + } + + aggregate() { + this.colOptions.forEach((opt, key) => { + const numValue = row => { + const value = typeCoercion(row[key], opt.type); + if (typeof value === 'number') { + return value; + } + if (value instanceof Date) { + return value.valueOf(); + } + return value; + }; + const getSum = () => + sumBy(this.tableData.rows, row => { + const value = typeCoercion(row[key], 'number'); + return typeof value === 'number' ? value : 0; + }); + + switch (opt.aggregation) { + case 'sum': + opt.aggregationValue = getSum(); + break; + case 'avg': + opt.aggregationValue = getSum() / this.tableData.rows.length; + break; + case 'count': + opt.aggregationValue = this.tableData.rows.length; + break; + case 'max': + opt.aggregationValue = maxBy(this.tableData.rows, numValue)[key]; + break; + case 'min': + opt.aggregationValue = minBy(this.tableData.rows, numValue)[key]; + break; + default: + opt.aggregationValue = null; + } + }); + } + + filterRows() { + const sortKeys = []; + const sortTypes = []; + const terms = []; + this.colOptions.forEach((value, key) => { + if (value.sort) { + sortKeys.push(row => typeCoercion(row[key], value.type)); + sortTypes.push(value.sort); + } + terms.push(row => String(row[key]).search(value.term) !== -1); + }); + this.rows = filter(this.tableData.rows, row => terms.every(term => term(row))); + this.rows = orderBy(this.rows, sortKeys, sortTypes); + this.cdr.markForCheck(); + } + + constructor(@Inject(VISUALIZATION) public visualization: Visualization, private cdr: ChangeDetectorRef) {} + + ngOnInit() {} + + render() { + this.tableData = this.visualization.transformed; + this.columns = this.tableData.columns; + this.rows = [...this.tableData.rows]; + this.columns.forEach(col => { + this.colOptions.set(col, new FilterOption()); + }); + this.filterRows(); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/table/table-visualization.ts b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.ts new file mode 100644 index 00000000000..c2495b3157a --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/table/table-visualization.ts @@ -0,0 +1,60 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CdkPortalOutlet } from '@angular/cdk/portal'; +import { ViewContainerRef } from '@angular/core'; + +import { GraphConfig } from '@zeppelin/sdk'; +import { + TableTransformation, + Transformation, + Visualization, + VisualizationComponentPortal +} from '@zeppelin/visualization'; + +import { TableVisualizationComponent } from './table-visualization.component'; + +export class TableVisualization extends Visualization { + tableTransformation = new TableTransformation(this.getConfig()); + componentPortal = new VisualizationComponentPortal( + this, + TableVisualizationComponent, + this.portalOutlet, + this.viewContainerRef + ); + constructor(config: GraphConfig, private portalOutlet: CdkPortalOutlet, private viewContainerRef: ViewContainerRef) { + super(config); + } + + destroy(): void { + if (this.componentRef) { + this.componentRef.destroy(); + this.componentRef = null; + } + this.configChange$.complete(); + this.configChange$ = null; + } + + getTransformation(): Transformation { + return this.tableTransformation; + } + + refresh(): void {} + + render(data): void { + this.transformed = data; + if (!this.componentRef) { + this.componentRef = this.componentPortal.attachComponentPortal(); + } + this.componentRef.instance.render(); + } +} diff --git a/zeppelin-web-angular/src/app/visualizations/visualization.module.ts b/zeppelin-web-angular/src/app/visualizations/visualization.module.ts new file mode 100644 index 00000000000..fe2f4a18cd4 --- /dev/null +++ b/zeppelin-web-angular/src/app/visualizations/visualization.module.ts @@ -0,0 +1,79 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DragDropModule } from '@angular/cdk/drag-drop'; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { + NzButtonModule, + NzCardModule, + NzCheckboxModule, + NzDropDownModule, + NzFormModule, + NzGridModule, + NzIconModule, + NzInputModule, + NzMenuModule, + NzRadioModule, + NzTableModule, + NzTagModule +} from 'ng-zorro-antd'; + +import { AreaChartVisualizationComponent } from './area-chart/area-chart-visualization.component'; +import { BarChartVisualizationComponent } from './bar-chart/bar-chart-visualization.component'; +import { VisualizationPivotSettingComponent } from './common/pivot-setting/pivot-setting.component'; +import { VisualizationScatterSettingComponent } from './common/scatter-setting/scatter-setting.component'; +import { VisualizationXAxisSettingComponent } from './common/x-axis-setting/x-axis-setting.component'; +import { LineChartVisualizationComponent } from './line-chart/line-chart-visualization.component'; +import { PieChartVisualizationComponent } from './pie-chart/pie-chart-visualization.component'; +import { ScatterChartVisualizationComponent } from './scatter-chart/scatter-chart-visualization.component'; +import { TableVisualizationComponent } from './table/table-visualization.component'; + +const VisualizationComponents = [ + TableVisualizationComponent, + AreaChartVisualizationComponent, + BarChartVisualizationComponent, + LineChartVisualizationComponent, + PieChartVisualizationComponent, + ScatterChartVisualizationComponent +]; + +@NgModule({ + declarations: [ + ...VisualizationComponents, + VisualizationPivotSettingComponent, + VisualizationScatterSettingComponent, + VisualizationXAxisSettingComponent + ], + entryComponents: [...VisualizationComponents], + exports: [...VisualizationComponents], + imports: [ + CommonModule, + FormsModule, + DragDropModule, + NzTableModule, + NzCardModule, + NzTagModule, + NzFormModule, + NzInputModule, + NzGridModule, + NzIconModule, + NzMenuModule, + NzDropDownModule, + NzRadioModule, + NzCheckboxModule, + NzButtonModule + ] +}) +export class VisualizationModule {} diff --git a/zeppelin-web-angular/src/assets/.gitkeep b/zeppelin-web-angular/src/assets/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/zeppelin-web-angular/src/assets/fonts/patua-one.woff2 b/zeppelin-web-angular/src/assets/fonts/patua-one.woff2 new file mode 100644 index 00000000000..df2b38dc302 Binary files /dev/null and b/zeppelin-web-angular/src/assets/fonts/patua-one.woff2 differ diff --git a/zeppelin-web-angular/src/assets/helium-packages/helium-vis-example.umd.js b/zeppelin-web-angular/src/assets/helium-packages/helium-vis-example.umd.js new file mode 100644 index 00000000000..23499a03dcd --- /dev/null +++ b/zeppelin-web-angular/src/assets/helium-packages/helium-vis-example.umd.js @@ -0,0 +1,589 @@ +/* + * 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. + */ + +(function(global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + ? (module.exports = factory( + require('@zeppelin/helium'), + require('@angular/core'), + require('@zeppelin/visualization'), + require('@angular/common') + )) + : typeof define === 'function' && define.amd + ? define('helium-vis-example', [ + '@zeppelin/helium', + '@angular/core', + '@zeppelin/visualization', + '@angular/common' + ], factory) + : ((global = global || self), + (global['helium-vis-example'] = factory(global.helium, global.ng.core, global.visualization, global.ng.common))); +})(this, function(helium, core, visualization, common) { + 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. 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 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = + Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && + function(d, b) { + d.__proto__ = b; + }) || + function(d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __()); + } + + var __assign = function() { + __assign = + Object.assign || + function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === 'function') + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; + } + return t; + } + + function __decorate(decorators, target, key, desc) { + var c = arguments.length, + r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc, + d; + if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function') + r = Reflect.decorate(decorators, target, key, desc); + else + for (var i = decorators.length - 1; i >= 0; i--) + if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; + } + + function __param(paramIndex, decorator) { + return function(target, key) { + decorator(target, key, paramIndex); + }; + } + + function __metadata(metadataKey, metadataValue) { + if (typeof Reflect === 'object' && typeof Reflect.metadata === 'function') + return Reflect.metadata(metadataKey, metadataValue); + } + + function __awaiter(thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator['throw'](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done + ? resolve(result.value) + : new P(function(resolve) { + resolve(result.value); + }).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + } + + function __generator(thisArg, body) { + var _ = { + label: 0, + sent: function() { + if (t[0] & 1) throw t[1]; + return t[1]; + }, + trys: [], + ops: [] + }, + f, + y, + t, + g; + return ( + (g = { next: verb(0), throw: verb(1), return: verb(2) }), + typeof Symbol === 'function' && + (g[Symbol.iterator] = function() { + return this; + }), + g + ); + function verb(n) { + return function(v) { + return step([n, v]); + }; + } + function step(op) { + if (f) throw new TypeError('Generator is already executing.'); + while (_) + try { + if ( + ((f = 1), + y && + (t = op[0] & 2 ? y['return'] : op[0] ? y['throw'] || ((t = y['return']) && t.call(y), 0) : y.next) && + !(t = t.call(y, op[1])).done) + ) + return t; + if (((y = 0), t)) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: + case 1: + t = op; + break; + case 4: + _.label++; + return { value: op[1], done: false }; + case 5: + _.label++; + y = op[1]; + op = [0]; + continue; + case 7: + op = _.ops.pop(); + _.trys.pop(); + continue; + default: + if (!((t = _.trys), (t = t.length > 0 && t[t.length - 1])) && (op[0] === 6 || op[0] === 2)) { + _ = 0; + continue; + } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { + _.label = op[1]; + break; + } + if (op[0] === 6 && _.label < t[1]) { + _.label = t[1]; + t = op; + break; + } + if (t && _.label < t[2]) { + _.label = t[2]; + _.ops.push(op); + break; + } + if (t[2]) _.ops.pop(); + _.trys.pop(); + continue; + } + op = body.call(thisArg, _); + } catch (e) { + op = [6, e]; + y = 0; + } finally { + f = t = 0; + } + if (op[0] & 5) throw op[1]; + return { value: op[0] ? op[1] : void 0, done: true }; + } + } + + function __exportStar(m, exports) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + } + + function __values(o) { + var m = typeof Symbol === 'function' && o[Symbol.iterator], + i = 0; + if (m) return m.call(o); + return { + next: function() { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + } + + function __read(o, n) { + var m = typeof Symbol === 'function' && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), + r, + ar = [], + e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } catch (error) { + e = { error: error }; + } finally { + try { + if (r && !r.done && (m = i['return'])) m.call(i); + } finally { + if (e) throw e.error; + } + } + return ar; + } + + function __spread() { + for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); + return ar; + } + + function __spreadArrays() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; + return r; + } + + function __await(v) { + return this instanceof __await ? ((this.v = v), this) : new __await(v); + } + + function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError('Symbol.asyncIterator is not defined.'); + var g = generator.apply(thisArg, _arguments || []), + i, + q = []; + return ( + (i = {}), + verb('next'), + verb('throw'), + verb('return'), + (i[Symbol.asyncIterator] = function() { + return this; + }), + i + ); + function verb(n) { + if (g[n]) + i[n] = function(v) { + return new Promise(function(a, b) { + q.push([n, v, a, b]) > 1 || resume(n, v); + }); + }; + } + function resume(n, v) { + try { + step(g[n](v)); + } catch (e) { + settle(q[0][3], e); + } + } + function step(r) { + r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); + } + function fulfill(value) { + resume('next', value); + } + function reject(value) { + resume('throw', value); + } + function settle(f, v) { + if ((f(v), q.shift(), q.length)) resume(q[0][0], q[0][1]); + } + } + + function __asyncDelegator(o) { + var i, p; + return ( + (i = {}), + verb('next'), + verb('throw', function(e) { + throw e; + }), + verb('return'), + (i[Symbol.iterator] = function() { + return this; + }), + i + ); + function verb(n, f) { + i[n] = o[n] + ? function(v) { + return (p = !p) ? { value: __await(o[n](v)), done: n === 'return' } : f ? f(v) : v; + } + : f; + } + } + + function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError('Symbol.asyncIterator is not defined.'); + var m = o[Symbol.asyncIterator], + i; + return m + ? m.call(o) + : ((o = typeof __values === 'function' ? __values(o) : o[Symbol.iterator]()), + (i = {}), + verb('next'), + verb('throw'), + verb('return'), + (i[Symbol.asyncIterator] = function() { + return this; + }), + i); + function verb(n) { + i[n] = + o[n] && + function(v) { + return new Promise(function(resolve, reject) { + (v = o[n](v)), settle(resolve, reject, v.done, v.value); + }); + }; + } + function settle(resolve, reject, d, v) { + Promise.resolve(v).then(function(v) { + resolve({ value: v, done: d }); + }, reject); + } + } + + function __makeTemplateObject(cooked, raw) { + if (Object.defineProperty) { + Object.defineProperty(cooked, 'raw', { value: raw }); + } else { + cooked.raw = raw; + } + return cooked; + } + + function __importStar(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result.default = mod; + return result; + } + + function __importDefault(mod) { + return mod && mod.__esModule ? mod : { default: mod }; + } + + /** + * @fileoverview added by tsickle + * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + var JsonVisComponent = /** @class */ (function() { + function JsonVisComponent(visualization, cdr) { + this.visualization = visualization; + this.cdr = cdr; + } + /** + * @return {?} + */ + JsonVisComponent.prototype.ngOnInit = /** + * @return {?} + */ function() {}; + /** + * @return {?} + */ + JsonVisComponent.prototype.render = /** + * @return {?} + */ function() { + this.tableData = this.visualization.transformed; + }; + JsonVisComponent.decorators = [ + { + type: core.Component, + args: [ + { + selector: 'lib-helium-vis-example', + template: '\n
{{tableData | json}}
\n ', + changeDetection: core.ChangeDetectionStrategy.OnPush, + styles: [ + '\n pre {\n background: #fff7e7;\n padding: 10px;\n border: 1px solid #ffd278;\n color: #fa7e14;\n border-radius: 3px;\n }\n ' + ] + } + ] + } + ]; + /** @nocollapse */ + JsonVisComponent.ctorParameters = function() { + return [ + { type: visualization.Visualization, decorators: [{ type: core.Inject, args: [visualization.VISUALIZATION] }] }, + { type: core.ChangeDetectorRef } + ]; + }; + return JsonVisComponent; + })(); + if (false) { + /** @type {?} */ + JsonVisComponent.prototype.tableData; + /** @type {?} */ + JsonVisComponent.prototype.visualization; + /** + * @type {?} + * @private + */ + JsonVisComponent.prototype.cdr; + } + + /** + * @fileoverview added by tsickle + * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + var JsonVisModule = /** @class */ (function() { + function JsonVisModule() {} + JsonVisModule.decorators = [ + { + type: core.NgModule, + args: [ + { + imports: [common.CommonModule], + declarations: [JsonVisComponent], + entryComponents: [JsonVisComponent], + exports: [JsonVisComponent] + } + ] + } + ]; + return JsonVisModule; + })(); + + /** + * @fileoverview added by tsickle + * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + var JsonVisualization = /** @class */ (function(_super) { + __extends(JsonVisualization, _super); + function JsonVisualization(config, portalOutlet, viewContainerRef, componentFactoryResolver) { + var _this = _super.call(this, config) || this; + _this.portalOutlet = portalOutlet; + _this.viewContainerRef = viewContainerRef; + _this.componentFactoryResolver = componentFactoryResolver; + _this.tableTransformation = new visualization.TableTransformation(_this.getConfig()); + _this.componentPortal = new visualization.VisualizationComponentPortal( + _this, + JsonVisComponent, + _this.portalOutlet, + _this.viewContainerRef, + _this.componentFactoryResolver + ); + return _this; + } + /** + * @return {?} + */ + JsonVisualization.prototype.destroy = /** + * @return {?} + */ function() { + if (this.componentRef) { + this.componentRef.destroy(); + this.componentRef = null; + } + this.configChange$.complete(); + this.configChange$ = null; + }; + /** + * @return {?} + */ + JsonVisualization.prototype.getTransformation = /** + * @return {?} + */ function() { + return this.tableTransformation; + }; + /** + * @return {?} + */ + JsonVisualization.prototype.refresh = /** + * @return {?} + */ function() {}; + /** + * @param {?} data + * @return {?} + */ + JsonVisualization.prototype.render = /** + * @param {?} data + * @return {?} + */ function(data) { + this.transformed = data; + if (!this.componentRef) { + this.componentRef = this.componentPortal.attachComponentPortal(); + } + this.componentRef.instance.render(); + }; + return JsonVisualization; + })(visualization.Visualization); + if (false) { + /** @type {?} */ + JsonVisualization.prototype.tableTransformation; + /** @type {?} */ + JsonVisualization.prototype.componentPortal; + /** + * @type {?} + * @private + */ + JsonVisualization.prototype.portalOutlet; + /** + * @type {?} + * @private + */ + JsonVisualization.prototype.viewContainerRef; + /** + * @type {?} + * @private + */ + JsonVisualization.prototype.componentFactoryResolver; + } + + /** + * @fileoverview added by tsickle + * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + var publicApi = helium.createHeliumPackage({ + name: 'helium-vis-example', + id: 'heliumVisExample', + icon: 'appstore', + type: helium.HeliumPackageType.Visualization, + module: JsonVisModule, + component: JsonVisComponent, + visualization: JsonVisualization + }); + + return publicApi; +}); +//# sourceMappingURL=helium-vis-example.umd.js.map diff --git a/zeppelin-web-angular/src/assets/images/bg.jpg b/zeppelin-web-angular/src/assets/images/bg.jpg new file mode 100644 index 00000000000..cffbba3ff89 Binary files /dev/null and b/zeppelin-web-angular/src/assets/images/bg.jpg differ diff --git a/zeppelin-web-angular/src/assets/images/zeppelin.png b/zeppelin-web-angular/src/assets/images/zeppelin.png new file mode 100644 index 00000000000..aeb0b605654 Binary files /dev/null and b/zeppelin-web-angular/src/assets/images/zeppelin.png differ diff --git a/zeppelin-web-angular/src/assets/images/zeppelin_svg_logo.svg b/zeppelin-web-angular/src/assets/images/zeppelin_svg_logo.svg new file mode 100644 index 00000000000..9601e5dc893 --- /dev/null +++ b/zeppelin-web-angular/src/assets/images/zeppelin_svg_logo.svg @@ -0,0 +1,77 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/zeppelin-web-angular/src/assets/images/zeppelin_svg_logo_bg.svg b/zeppelin-web-angular/src/assets/images/zeppelin_svg_logo_bg.svg new file mode 100644 index 00000000000..9e0b95d9197 --- /dev/null +++ b/zeppelin-web-angular/src/assets/images/zeppelin_svg_logo_bg.svg @@ -0,0 +1,77 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/zeppelin-web-angular/src/browserslist b/zeppelin-web-angular/src/browserslist new file mode 100644 index 00000000000..37371cb04b9 --- /dev/null +++ b/zeppelin-web-angular/src/browserslist @@ -0,0 +1,11 @@ +# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers +# For additional information regarding the format and rule options, please see: +# https://github.com/browserslist/browserslist#queries +# +# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed + +> 0.5% +last 2 versions +Firefox ESR +not dead +not IE 9-11 \ No newline at end of file diff --git a/zeppelin-web-angular/src/environments/environment.prod.ts b/zeppelin-web-angular/src/environments/environment.prod.ts new file mode 100644 index 00000000000..a00527f83a1 --- /dev/null +++ b/zeppelin-web-angular/src/environments/environment.prod.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +export const environment = { + production: true +}; diff --git a/zeppelin-web-angular/src/environments/environment.ts b/zeppelin-web-angular/src/environments/environment.ts new file mode 100644 index 00000000000..7ed2ad9875b --- /dev/null +++ b/zeppelin-web-angular/src/environments/environment.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +// 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 +}; + +/* + * 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/zeppelin-web-angular/src/favicon.ico b/zeppelin-web-angular/src/favicon.ico new file mode 100644 index 00000000000..7e5049a11f6 Binary files /dev/null and b/zeppelin-web-angular/src/favicon.ico differ diff --git a/zeppelin-web-angular/src/index.html b/zeppelin-web-angular/src/index.html new file mode 100644 index 00000000000..9ad5caa094f --- /dev/null +++ b/zeppelin-web-angular/src/index.html @@ -0,0 +1,50 @@ + + + + + + + + + Zeppelin + + + + +
+
+ +
+

Zeppelin

+ +
+
+
+
+ + + + diff --git a/zeppelin-web-angular/src/karma.conf.js b/zeppelin-web-angular/src/karma.conf.js new file mode 100644 index 00000000000..f2d0ea61a85 --- /dev/null +++ b/zeppelin-web-angular/src/karma.conf.js @@ -0,0 +1,43 @@ +/* + * 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. + */ + +// 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'), + reports: ['html', 'lcovonly', 'text-summary'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }); +}; diff --git a/zeppelin-web-angular/src/main.ts b/zeppelin-web-angular/src/main.ts new file mode 100644 index 00000000000..81b410d13ed --- /dev/null +++ b/zeppelin-web-angular/src/main.ts @@ -0,0 +1,25 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { 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/zeppelin-web-angular/src/polyfills.ts b/zeppelin-web-angular/src/polyfills.ts new file mode 100644 index 00000000000..407a74e8552 --- /dev/null +++ b/zeppelin-web-angular/src/polyfills.ts @@ -0,0 +1,94 @@ +/* + * 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. + */ + +/** + * 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 + */ + +/** IE9, IE10 and IE11 requires all of the following polyfills. **/ +// import 'core-js/es6/symbol'; +// import 'core-js/es6/object'; +// import 'core-js/es6/function'; +// import 'core-js/es6/parse-int'; +// import 'core-js/es6/parse-float'; +// import 'core-js/es6/number'; +// import 'core-js/es6/math'; +// import 'core-js/es6/string'; +// import 'core-js/es6/date'; +// import 'core-js/es6/array'; +// import 'core-js/es6/regexp'; +// import 'core-js/es6/map'; +// import 'core-js/es6/weak-map'; +// import 'core-js/es6/set'; + +/** + * If the application will be indexed by Google Search, the following is required. + * Googlebot uses a renderer based on Chrome 41. + * https://developers.google.com/search/docs/guides/rendering + **/ +// import 'core-js/es6/array'; + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** IE10 and IE11 requires the following for the Reflect API. */ +// import 'core-js/es6/reflect'; + +/** + * 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 + */ + +// (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__BLACK_LISTED_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. + */ +// tslint:disable +import 'zone.js/dist/zone'; // Included with Angular CLI. + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ + +import 'core-js/es7/reflect'; diff --git a/zeppelin-web-angular/src/styles.less b/zeppelin-web-angular/src/styles.less new file mode 100644 index 00000000000..013b90e3af1 --- /dev/null +++ b/zeppelin-web-angular/src/styles.less @@ -0,0 +1,19 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import './styles/spin'; +@import './styles/base'; +@import './styles/font'; +@import './styles/global'; +@import './styles/rewrite'; +@import "node_modules/ng-zorro-antd/resizable/style/entry.less"; +@import "node_modules/ng-zorro-antd/code-editor/style/entry.less"; diff --git a/zeppelin-web-angular/src/styles/base.less b/zeppelin-web-angular/src/styles/base.less new file mode 100644 index 00000000000..333ba34de73 --- /dev/null +++ b/zeppelin-web-angular/src/styles/base.less @@ -0,0 +1,18 @@ +/* + * 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. + */ + +* { + box-sizing: border-box; + outline: none; + margin: 0; + padding: 0; +} diff --git a/zeppelin-web-angular/src/styles/font.less b/zeppelin-web-angular/src/styles/font.less new file mode 100644 index 00000000000..ead6bcffa7e --- /dev/null +++ b/zeppelin-web-angular/src/styles/font.less @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/* latin */ +@font-face { + font-family: 'Patua One'; + font-style: normal; + font-weight: 400; + src: local('Patua One'), local('PatuaOne-Regular'), url(../assets/fonts/patua-one.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/zeppelin-web-angular/src/styles/global.less b/zeppelin-web-angular/src/styles/global.less new file mode 100644 index 00000000000..42e736228c1 --- /dev/null +++ b/zeppelin-web-angular/src/styles/global.less @@ -0,0 +1,124 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import '../../node_modules/ng-zorro-antd/src/style/color/colors'; + +.mark-highlight { + color: crimson; +} + +.tips { + &.warning { + color: @volcano-6; + } + + &.error { + color: @red-6; + } +} + +.modal-footer { + padding: 10px 24px; + margin: 24px -24px -24px -24px; +} + +.transparent-button { + background: transparent; + border: none; + box-shadow: none; + + &:hover { + background: transparent; + } +} + +.padding-sm { + padding: 12px !important; +} + +.font-sm { + font-size: 12px; +} + +.opacity-05 { + opacity: 0.5; +} + +.drag-tag { + box-sizing: border-box; + color: rgba(0, 0, 0, 0.65); + font-variant: tabular-nums; + list-style: none; + font-feature-settings: 'tnum'; + display: inline-block; + height: auto; + margin: 0 8px 8px 0; + padding: 0 7px; + font-size: 12px; + line-height: 20px; + white-space: nowrap; + background: #fafafa; + border: 1px solid #d9d9d9; + border-radius: 0px; + cursor: pointer; + opacity: 1; + + &.cdk-drag-preview { + box-shadow: 0 0 6px -2px rgba(0, 0, 0, 0.2); + } + + &.cdk-drag-placeholder { + border-style: dashed; + } +} + +.interpreter-box { + margin-bottom: 12px; + line-height: 32px; + + &:last-child { + margin-bottom: 0; + } + + .refresh { + font-size: 18px; + line-height: 0; + margin-right: 12px; + } + + &.cdk-drag-placeholder { + opacity: 0; + } + + .interpreter-name { + display: inline-block; + + .main-name { + display: inline-block; + margin-right: 6px; + } + + .child-name { + font-size: 12px; + opacity: 0.7; + display: inline-block; + } + } +} + +//.view-lines { +// .view-line { +// &:first-child { +// filter: grayscale(1); +// } +// } +//} diff --git a/zeppelin-web-angular/src/styles/rewrite.less b/zeppelin-web-angular/src/styles/rewrite.less new file mode 100644 index 00000000000..43d7b61f32c --- /dev/null +++ b/zeppelin-web-angular/src/styles/rewrite.less @@ -0,0 +1,25 @@ +/* + * 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. + */ + +nz-tree { + .ant-tree { + nz-tree-node { + li { + padding: 0; + } + } + } +} + +.ant-tabs-nav .ant-tabs-tab { + font-weight: 500; +} diff --git a/zeppelin-web-angular/src/styles/spin.less b/zeppelin-web-angular/src/styles/spin.less new file mode 100644 index 00000000000..ec8c0a5a88c --- /dev/null +++ b/zeppelin-web-angular/src/styles/spin.less @@ -0,0 +1,150 @@ +/* + * 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. + */ + +.spin { + height: 100vh; + width: 100vw; + position: fixed; + z-index: 1000; + top: 0; + left: 0; + + &:after { + content: ""; + display: block; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-image: url("../assets/images/bg.jpg"); + background-size: cover; + filter: blur(4px); + background-repeat: no-repeat; + background-position: center; + } + + &.transparent { + &:after { + content: none; + } + } + + & > div { + background: rgba(255, 255, 255, 0.5); + text-align: center; + position: absolute; + z-index: 1; + top: 0; + bottom: 0; + left: 0; + right: 0; + + .logo { + width: 160px; + height: 160px; + margin: -64px auto 0; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + + &:after { + content: ""; + display: block; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + animation: opacity 2.0s infinite ease; + background-image: url(../assets/images/zeppelin_svg_logo.svg); + background-repeat: no-repeat; + background-position: center; + background-size: 75% auto; + } + } + + .spin-text { + width: 160px; + height: 160px; + top: 50%; + left: 50%; + transform: translateX(-50%); + position: absolute; + margin: -16px auto 0; + + .brand-title { + text-align: center; + font-family: 'Patua One', cursive; + color: #3071a9; + font-size: 40px; + display: block !important; + } + + .status { + margin: -6px auto 0; + width: 160px; + display: block !important; + color: #ffffff; + line-height: 24px; + height: 24px; + font-size: 12px; + position: relative; + background-color: rgba(48, 113, 169, 0.7); + + &::before { + content: ''; + position: absolute; + z-index: -1; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: #3071a9; + transform-origin: left center; + transform: scaleX(0); + transition: transform 0.2s ease-in-out; + animation: move 1.0s infinite ease; + } + } + } + } +} + +@keyframes opacity { + 0% { + opacity: 0.7; + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0.7; + } +} + + +@keyframes move { + 0% { + transform: scaleX(0); + transform-origin: left center; + } + 100% { + transform-origin: left center; + transform: scaleX(1); + } +} + + diff --git a/zeppelin-web-angular/src/styles/theme/dark/antd-dark.less b/zeppelin-web-angular/src/styles/theme/dark/antd-dark.less new file mode 100644 index 00000000000..16484d60a93 --- /dev/null +++ b/zeppelin-web-angular/src/styles/theme/dark/antd-dark.less @@ -0,0 +1,17 @@ +/* + * 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. + */ + +html.dark { + @import '../../../../node_modules/ng-zorro-antd/ng-zorro-antd.less'; + @import 'theme-dark'; + @import '../markdown'; +} diff --git a/zeppelin-web-angular/src/styles/theme/dark/theme-dark.less b/zeppelin-web-angular/src/styles/theme/dark/theme-dark.less new file mode 100644 index 00000000000..26e91867283 --- /dev/null +++ b/zeppelin-web-angular/src/styles/theme/dark/theme-dark.less @@ -0,0 +1,659 @@ +/* + * 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. + */ + +// The prefix to use on all css classes from ant. +@ant-prefix: ant; + +// An override for the html selector for theme prefixes +@html-selector: html; + +// -------- Colors ----------- +@primary-color: @blue-6; +@info-color: @blue-6; +@success-color: @green-6; +@processing-color: @blue-6; +@error-color: @red-6; +@highlight-color: @red-6; +@warning-color: @gold-6; +@normal-color: #d9d9d9; +@white: #fff; +@black: #000; + +// Color used by default to control hover and active backgrounds and for +// alert info backgrounds. +@primary-1: color(~`colorPalette('@{primary-color}', 1) `); // replace tint(@primary-color, 90%) +@primary-2: color(~`colorPalette('@{primary-color}', 2) `); // replace tint(@primary-color, 80%) +@primary-3: color(~`colorPalette('@{primary-color}', 3) `); // unused +@primary-4: color(~`colorPalette('@{primary-color}', 4) `); // unused +@primary-5: color( + ~`colorPalette('@{primary-color}', 5) ` +); // color used to control the text color in many active and hover states, replace tint(@primary-color, 20%) +@primary-6: @primary-color; // color used to control the text color of active buttons, don't use, use @primary-color +@primary-7: color(~`colorPalette('@{primary-color}', 7) `); // replace shade(@primary-color, 5%) +@primary-8: color(~`colorPalette('@{primary-color}', 8) `); // unused +@primary-9: color(~`colorPalette('@{primary-color}', 9) `); // unused +@primary-10: color(~`colorPalette('@{primary-color}', 10) `); // unused + +// Base Scaffolding Variables +// --- + +// Background color for `` +@body-background: #fff; +// Base background color for most components +@component-background: #fff; +@font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', + 'Helvetica Neue', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; +@code-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; +@text-color: fade(@black, 65%); +@text-color-secondary: fade(@black, 45%); +@text-color-warning: @gold-7; +@text-color-danger: @red-7; +@text-color-inverse: @white; +@icon-color: inherit; +@icon-color-hover: fade(@black, 75%); +@heading-color: fade(#000, 85%); +@heading-color-dark: fade(@white, 100%); +@text-color-dark: fade(@white, 85%); +@text-color-secondary-dark: fade(@white, 65%); +@font-variant-base: tabular-nums; +@font-feature-settings-base: 'tnum'; +@font-size-base: 14px; +@font-size-lg: @font-size-base + 2px; +@font-size-sm: 12px; +@heading-1-size: ceil(@font-size-base * 2.71); +@heading-2-size: ceil(@font-size-base * 2.14); +@heading-3-size: ceil(@font-size-base * 1.71); +@heading-4-size: ceil(@font-size-base * 1.42); +@line-height-base: 1.5; +@border-radius-base: 4px; +@border-radius-sm: 2px; + +// vertical paddings +@padding-lg: 24px; // containers +@padding-md: 16px; // small containers and buttons +@padding-sm: 12px; // Form controls and items +@padding-xs: 8px; // small items + +// vertical padding for all form controls +@control-padding-horizontal: @padding-sm; +@control-padding-horizontal-sm: @padding-xs; + +// The background colors for active and hover states for things like +// list items or table cells. +@item-active-bg: @primary-1; +@item-hover-bg: @primary-1; + +// ICONFONT +@iconfont-css-prefix: anticon; + +// LINK +@link-color: @primary-color; +@link-hover-color: color(~`colorPalette('@{link-color}', 5) `); +@link-active-color: color(~`colorPalette('@{link-color}', 7) `); +@link-decoration: none; +@link-hover-decoration: none; + +// Animation +@ease-base-out: cubic-bezier(0.7, 0.3, 0.1, 1); +@ease-base-in: cubic-bezier(0.9, 0, 0.3, 0.7); +@ease-out: cubic-bezier(0.215, 0.61, 0.355, 1); +@ease-in: cubic-bezier(0.55, 0.055, 0.675, 0.19); +@ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1); +@ease-out-back: cubic-bezier(0.12, 0.4, 0.29, 1.46); +@ease-in-back: cubic-bezier(0.71, -0.46, 0.88, 0.6); +@ease-in-out-back: cubic-bezier(0.71, -0.46, 0.29, 1.46); +@ease-out-circ: cubic-bezier(0.08, 0.82, 0.17, 1); +@ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.34); +@ease-in-out-circ: cubic-bezier(0.78, 0.14, 0.15, 0.86); +@ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1); +@ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06); +@ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1); + +// Border color +@border-color-base: hsv(0, 0, 85%); // base border outline a component +@border-color-split: hsv(0, 0, 91%); // split border inside a component +@border-color-inverse: @white; +@border-width-base: 1px; // width of the border for a component +@border-style-base: solid; // style of a components border + +// Outline +@outline-blur-size: 0; +@outline-width: 2px; +@outline-color: @primary-color; + +@background-color-light: hsv(0, 0, 98%); // background of header and selected item +@background-color-base: hsv(0, 0, 96%); // Default grey background color + +// Disabled states +@disabled-color: fade(#000, 25%); +@disabled-bg: @background-color-base; +@disabled-color-dark: fade(#fff, 35%); + +// Shadow +@shadow-color: rgba(0, 0, 0, 0.15); +@shadow-color-inverse: @component-background; +@box-shadow-base: @shadow-1-down; +@shadow-1-up: 0 -2px 8px @shadow-color; +@shadow-1-down: 0 2px 8px @shadow-color; +@shadow-1-left: -2px 0 8px @shadow-color; +@shadow-1-right: 2px 0 8px @shadow-color; +@shadow-2: 0 4px 12px @shadow-color; + +// Buttons +@btn-font-weight: 400; +@btn-border-radius-base: @border-radius-base; +@btn-border-radius-sm: @border-radius-base; +@btn-border-width: @border-width-base; +@btn-border-style: @border-style-base; +@btn-shadow: 0 2px 0 rgba(0, 0, 0, 0.015); +@btn-primary-shadow: 0 2px 0 rgba(0, 0, 0, 0.045); +@btn-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12); + +@btn-primary-color: #fff; +@btn-primary-bg: @primary-color; + +@btn-default-color: @text-color; +@btn-default-bg: #fff; +@btn-default-border: @border-color-base; + +@btn-danger-color: @error-color; +@btn-danger-bg: @background-color-base; +@btn-danger-border: @border-color-base; + +@btn-disable-color: @disabled-color; +@btn-disable-bg: @disabled-bg; +@btn-disable-border: @border-color-base; + +@btn-padding-base: 0 @padding-md - 1px; +@btn-font-size-lg: @font-size-lg; +@btn-font-size-sm: @font-size-base; +@btn-padding-lg: @btn-padding-base; +@btn-padding-sm: 0 @padding-xs - 1px; + +@btn-height-base: 32px; +@btn-height-lg: 40px; +@btn-height-sm: 24px; + +@btn-circle-size: @btn-height-base; +@btn-circle-size-lg: @btn-height-lg; +@btn-circle-size-sm: @btn-height-sm; + +@btn-square-size: @btn-height-base; +@btn-square-size-lg: @btn-height-lg; +@btn-square-size-sm: @btn-height-sm; + +@btn-group-border: @primary-5; + +// Checkbox +@checkbox-size: 16px; +@checkbox-color: @primary-color; +@checkbox-check-color: #fff; +@checkbox-border-width: @border-width-base; + +// Descriptions +@descriptions-bg: #fafafa; + +// Empty +@empty-font-size: @font-size-base; + +// Radio +@radio-size: 16px; +@radio-dot-color: @primary-color; + +// Radio buttons +@radio-button-bg: @btn-default-bg; +@radio-button-checked-bg: @btn-default-bg; +@radio-button-color: @btn-default-color; +@radio-button-hover-color: @primary-5; +@radio-button-active-color: @primary-7; + +// Media queries breakpoints +// Extra small screen / phone +@screen-xs: 480px; +@screen-xs-min: @screen-xs; + +// Small screen / tablet +@screen-sm: 576px; +@screen-sm-min: @screen-sm; + +// Medium screen / desktop +@screen-md: 768px; +@screen-md-min: @screen-md; + +// Large screen / wide desktop +@screen-lg: 992px; +@screen-lg-min: @screen-lg; + +// Extra large screen / full hd +@screen-xl: 1200px; +@screen-xl-min: @screen-xl; + +// Extra extra large screen / large desktop +@screen-xxl: 1600px; +@screen-xxl-min: @screen-xxl; + +// provide a maximum +@screen-xs-max: (@screen-sm-min - 1px); +@screen-sm-max: (@screen-md-min - 1px); +@screen-md-max: (@screen-lg-min - 1px); +@screen-lg-max: (@screen-xl-min - 1px); +@screen-xl-max: (@screen-xxl-min - 1px); + +// Grid system +@grid-columns: 24; +@grid-gutter-width: 0; + +// Layout +@layout-body-background: #f0f2f5; +@layout-header-background: #001529; +@layout-footer-background: @layout-body-background; +@layout-header-height: 64px; +@layout-header-padding: 0 50px; +@layout-footer-padding: 24px 50px; +@layout-sider-background: @layout-header-background; +@layout-trigger-height: 48px; +@layout-trigger-background: #002140; +@layout-trigger-color: #fff; +@layout-zero-trigger-width: 36px; +@layout-zero-trigger-height: 42px; +// Layout light theme +@layout-sider-background-light: #fff; +@layout-trigger-background-light: #fff; +@layout-trigger-color-light: @text-color; + +// z-index list, order by `z-index` +@zindex-table-fixed: auto; +@zindex-affix: 10; +@zindex-back-top: 10; +@zindex-badge: 10; +@zindex-picker-panel: 10; +@zindex-popup-close: 10; +@zindex-modal: 1000; +@zindex-modal-mask: 1000; +@zindex-message: 1010; +@zindex-notification: 1010; +@zindex-popover: 1030; +@zindex-dropdown: 1050; +@zindex-picker: 1050; +@zindex-tooltip: 1060; + +// Animation +@animation-duration-slow: 0.3s; // Modal +@animation-duration-base: 0.2s; +@animation-duration-fast: 0.1s; // Tooltip + +// Form +// --- +@label-required-color: @highlight-color; +@label-color: @heading-color; +@form-item-margin-bottom: 24px; +@form-item-trailing-colon: true; +@form-vertical-label-padding: 0 0 8px; +@form-vertical-label-margin: 0; + +// Input +// --- +@input-height-base: 32px; +@input-height-lg: 40px; +@input-height-sm: 24px; +@input-padding-horizontal: @control-padding-horizontal - 1px; +@input-padding-horizontal-base: @input-padding-horizontal; +@input-padding-horizontal-sm: @control-padding-horizontal-sm - 1px; +@input-padding-horizontal-lg: @input-padding-horizontal; +@input-padding-vertical-base: 4px; +@input-padding-vertical-sm: 1px; +@input-padding-vertical-lg: 6px; +@input-placeholder-color: hsv(0, 0, 75%); +@input-color: @text-color; +@input-border-color: @border-color-base; +@input-bg: #fff; +@input-number-handler-active-bg: #f4f4f4; +@input-number-handler-hover-bg: @primary-5; +@input-number-handler-bg: @component-background; +@input-number-handler-border-color: @border-color-base; +@input-addon-bg: @background-color-light; +@input-hover-border-color: @primary-color; +@input-disabled-bg: @disabled-bg; +@input-outline-offset: 0 0; + +// Select +// --- +@select-border-color: @border-color-base; +@select-item-selected-font-weight: 600; +@select-dropdown-bg: @component-background; +@select-item-selected-bg: @background-color-light; +@select-item-active-bg: @item-active-bg; + +// Anchor +// --- +@anchor-border-color: @border-color-split; + +// Tooltip +// --- +// Tooltip max width +@tooltip-max-width: 250px; +// Tooltip text color +@tooltip-color: #fff; +// Tooltip background color +@tooltip-bg: rgba(0, 0, 0, 0.75); +// Tooltip arrow width +@tooltip-arrow-width: 5px; +// Tooltip distance with trigger +@tooltip-distance: @tooltip-arrow-width - 1px + 4px; +// Tooltip arrow color +@tooltip-arrow-color: @tooltip-bg; + +// Popover +// --- +// Popover body background color +@popover-bg: #fff; +// Popover text color +@popover-color: @text-color; +// Popover maximum width +@popover-min-width: 177px; +// Popover arrow width +@popover-arrow-width: 6px; +// Popover arrow color +@popover-arrow-color: @popover-bg; +// Popover outer arrow width +// Popover outer arrow color +@popover-arrow-outer-color: @popover-bg; +// Popover distance with trigger +@popover-distance: @popover-arrow-width + 4px; + +// Modal +// -- +@modal-body-padding: 24px; +@modal-header-bg: @component-background; +@modal-footer-bg: transparent; +@modal-footer-border-color-split: @border-color-split; +@modal-mask-bg: fade(@black, 45%); + +// Progress +// -- +@progress-default-color: @processing-color; +@progress-remaining-color: @background-color-base; +@progress-text-color: @text-color; + +// Menu +// --- +@menu-inline-toplevel-item-height: 40px; +@menu-item-height: 40px; +@menu-collapsed-width: 80px; +@menu-bg: @component-background; +@menu-popup-bg: @component-background; +@menu-item-color: @text-color; +@menu-highlight-color: @primary-color; +@menu-item-active-bg: @item-active-bg; +@menu-item-active-border-width: 3px; +@menu-item-group-title-color: @text-color-secondary; +@menu-icon-size: @font-size-base; +@menu-icon-size-lg: @font-size-lg; + +@menu-item-vertical-margin: 4px; +@menu-item-font-size: @font-size-base; +@menu-item-boundary-margin: 8px; +@menu-icon-size: @font-size-base; +@menu-icon-size-lg: @font-size-lg; +@menu-dark-selected-item-icon-color: @white; +@menu-dark-selected-item-text-color: @white; +@dark-menu-item-hover-bg: transparent; + +// dark theme +@menu-dark-color: @text-color-secondary-dark; +@menu-dark-bg: @layout-header-background; +@menu-dark-arrow-color: #fff; +@menu-dark-submenu-bg: #000c17; +@menu-dark-highlight-color: #fff; +@menu-dark-item-active-bg: @primary-color; +@menu-dark-selected-item-icon-color: @white; +@menu-dark-selected-item-text-color: @white; +@menu-dark-item-hover-bg: transparent; + +// Spin +// --- +@spin-dot-size-sm: 14px; +@spin-dot-size: 20px; +@spin-dot-size-lg: 32px; + +// Table +// -- +@table-header-bg: @background-color-light; +@table-header-color: @heading-color; +@table-header-sort-bg: @background-color-base; +@table-body-sort-bg: rgba(0, 0, 0, 0.01); +@table-row-hover-bg: @primary-1; +@table-selected-row-bg: #fafafa; +@table-expanded-row-bg: #fbfbfb; +@table-padding-vertical: 16px; +@table-padding-horizontal: 16px; +@table-border-radius-base: @border-radius-base; +@table-footer-bg: @background-color-light; +@table-footer-color: @heading-color; + +// Tag +// -- +@tag-default-bg: @background-color-light; +@tag-default-color: @text-color; +@tag-font-size: @font-size-sm; + +// TimePicker +// --- +@time-picker-panel-column-width: 56px; +@time-picker-panel-width: @time-picker-panel-column-width * 3; +@time-picker-selected-bg: @background-color-base; + +// Carousel +// --- +@carousel-dot-width: 16px; +@carousel-dot-height: 3px; +@carousel-dot-active-width: 24px; + +// Badge +// --- +@badge-height: 20px; +@badge-dot-size: 6px; +@badge-font-size: @font-size-sm; +@badge-font-weight: normal; +@badge-status-size: 6px; +@badge-text-color: @component-background; + +// Rate +// --- +@rate-star-color: @yellow-6; +@rate-star-bg: @border-color-split; + +// Card +// --- +@card-head-color: @heading-color; +@card-head-background: transparent; +@card-head-padding: 16px; +@card-inner-head-padding: 12px; +@card-padding-base: 24px; +@card-actions-background: @background-color-light; +@card-skeleton-bg: #cfd8dc; +@card-background: @component-background; +@card-shadow: 0 2px 8px rgba(0, 0, 0, 0.09); +@card-radius: @border-radius-sm; + +// Comment +// --- +@comment-padding-base: 16px 0; +@comment-nest-indent: 44px; +@comment-author-name-color: @text-color-secondary; +@comment-author-time-color: #ccc; +@comment-action-color: @text-color-secondary; +@comment-action-hover-color: #595959; + +// Tabs +// --- +@tabs-card-head-background: @background-color-light; +@tabs-card-height: 40px; +@tabs-card-active-color: @primary-color; +@tabs-title-font-size: @font-size-base; +@tabs-title-font-size-lg: @font-size-lg; +@tabs-title-font-size-sm: @font-size-base; +@tabs-ink-bar-color: @primary-color; +@tabs-bar-margin: 0 0 16px 0; +@tabs-horizontal-margin: 0 32px 0 0; +@tabs-horizontal-padding: 12px 16px; +@tabs-horizontal-padding-lg: 16px; +@tabs-horizontal-padding-sm: 8px 16px; +@tabs-vertical-padding: 8px 24px; +@tabs-vertical-margin: 0 0 16px 0; +@tabs-scrolling-size: 32px; +@tabs-highlight-color: @primary-color; +@tabs-hover-color: @primary-5; +@tabs-active-color: @primary-7; + +// BackTop +// --- +@back-top-color: #fff; +@back-top-bg: @text-color-secondary; +@back-top-hover-bg: @text-color; + +// Avatar +// --- +@avatar-size-base: 32px; +@avatar-size-lg: 40px; +@avatar-size-sm: 24px; +@avatar-font-size-base: 18px; +@avatar-font-size-lg: 24px; +@avatar-font-size-sm: 14px; +@avatar-bg: #ccc; +@avatar-color: #fff; +@avatar-border-radius: @border-radius-base; + +// Switch +// --- +@switch-height: 22px; +@switch-sm-height: 16px; +@switch-sm-checked-margin-left: -(@switch-sm-height - 3px); +@switch-disabled-opacity: 0.4; +@switch-color: @primary-color; +@switch-shadow-color: fade(#00230b, 20%); + +// Pagination +// --- +@pagination-item-size: 32px; +@pagination-item-size-sm: 24px; +@pagination-font-family: Arial; +@pagination-font-weight-active: 500; +@pagination-item-bg-active: transparent; + +// PageHeader +// --- +@page-header-padding: 24px; +@page-header-padding-vertical: 16px; @page-header-padding-vertical: 16px; +@page-header-padding-breadcrumb: 12px; +@page-header-back-color: #000; + +// Breadcrumb +// --- +@breadcrumb-base-color: @text-color-secondary; +@breadcrumb-last-item-color: @text-color; +@breadcrumb-font-size: @font-size-base; +@breadcrumb-icon-font-size: @font-size-base; +@breadcrumb-link-color: @text-color-secondary; +@breadcrumb-link-color-hover: @primary-5; +@breadcrumb-separator-color: @text-color-secondary; +@breadcrumb-separator-margin: 0 @padding-xs; + +// Slider +// --- +@slider-margin: 14px 6px 10px; +@slider-rail-background-color: @background-color-base; +@slider-rail-background-color-hover: #e1e1e1; +@slider-track-background-color: @primary-3; +@slider-track-background-color-hover: @primary-4; +@slider-handle-color: @primary-3; +@slider-handle-color-hover: @primary-4; +@slider-handle-color-focus: tint(@primary-color, 20%); +@slider-handle-color-focus-shadow: fade(@primary-color, 20%); +@slider-handle-color-tooltip-open: @primary-color; +@slider-dot-border-color: @border-color-split; +@slider-dot-border-color-active: tint(@primary-color, 50%); +@slider-disabled-color: @disabled-color; +@slider-disabled-background-color: @component-background; + +// Tree +// --- +@tree-title-height: 24px; +@tree-child-padding: 18px; +@tree-directory-selected-color: #fff; +@tree-directory-selected-bg: @primary-color; +@tree-node-hover-bg: @item-hover-bg; +@tree-node-selected-bg: @primary-2; + +// Collapse +// --- +@collapse-header-padding: 12px 16px 12px 40px; +@collapse-header-bg: @background-color-light; +@collapse-content-padding: @padding-md; +@collapse-content-bg: @component-background; + +// Skeleton +// --- +@skeleton-color: #f2f2f2; + +// Transfer +// --- +@transfer-disabled-bg: @disabled-bg; + +// Message +// --- +@message-notice-content-padding: 10px 16px; + +// Motion +// --- +@wave-animation-width: 6px; + +// Alert +// --- +@alert-success-border-color: ~`colorPalette('@{success-color}', 3) `; +@alert-success-bg-color: ~`colorPalette('@{success-color}', 1) `; +@alert-success-icon-color: @success-color; +@alert-info-border-color: ~`colorPalette('@{info-color}', 3) `; +@alert-info-bg-color: ~`colorPalette('@{info-color}', 1) `; +@alert-info-icon-color: @info-color; +@alert-warning-border-color: ~`colorPalette('@{warning-color}', 3) `; +@alert-warning-bg-color: ~`colorPalette('@{warning-color}', 1) `; +@alert-warning-icon-color: @warning-color; +@alert-error-border-color: ~`colorPalette('@{error-color}', 3) `; +@alert-error-bg-color: ~`colorPalette('@{error-color}', 1) `; +@alert-error-icon-color: @error-color; + +// List +// --- +@list-header-background: transparent; +@list-footer-background: transparent; +@list-empty-text-padding: @padding-md; +@list-item-padding: @padding-sm 0; +@list-item-meta-margin-bottom: @padding-md; +@list-item-meta-avatar-margin-right: @padding-md; +@list-item-meta-title-margin-bottom: @padding-sm; + +// Statistic +// --- +@statistic-title-font-size: @font-size-base; +@statistic-content-font-size: 24px; +@statistic-unit-font-size: 16px; +@statistic-font-family: @font-family; + +// Drawer +// --- +@drawer-header-padding: 16px 24px; +@drawer-body-padding: 24px; + +// Typography +// --- +@typography-title-font-weight: 600; diff --git a/zeppelin-web-angular/src/styles/theme/light/antd-light.less b/zeppelin-web-angular/src/styles/theme/light/antd-light.less new file mode 100644 index 00000000000..cb114e64f28 --- /dev/null +++ b/zeppelin-web-angular/src/styles/theme/light/antd-light.less @@ -0,0 +1,15 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import '../../../../node_modules/ng-zorro-antd/ng-zorro-antd.less'; +@import 'theme-light'; +@import '../markdown'; diff --git a/zeppelin-web-angular/src/styles/theme/light/theme-light.less b/zeppelin-web-angular/src/styles/theme/light/theme-light.less new file mode 100644 index 00000000000..6f071e5f728 --- /dev/null +++ b/zeppelin-web-angular/src/styles/theme/light/theme-light.less @@ -0,0 +1,659 @@ +/* + * 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. + */ + +// The prefix to use on all css classes from ant. +@ant-prefix: ant; + +// An override for the html selector for theme prefixes +@html-selector: html; + +// -------- Colors ----------- +@primary-color: #3071a9; +@info-color: @blue-6; +@success-color: @green-6; +@processing-color: @blue-6; +@error-color: @red-6; +@highlight-color: @red-6; +@warning-color: @gold-6; +@normal-color: #d9d9d9; +@white: #fff; +@black: #000; + +// Color used by default to control hover and active backgrounds and for +// alert info backgrounds. +@primary-1: color(~`colorPalette('@{primary-color}', 1) `); // replace tint(@primary-color, 90%) +@primary-2: color(~`colorPalette('@{primary-color}', 2) `); // replace tint(@primary-color, 80%) +@primary-3: color(~`colorPalette('@{primary-color}', 3) `); // unused +@primary-4: color(~`colorPalette('@{primary-color}', 4) `); // unused +@primary-5: color( + ~`colorPalette('@{primary-color}', 5) ` +); // color used to control the text color in many active and hover states, replace tint(@primary-color, 20%) +@primary-6: @primary-color; // color used to control the text color of active buttons, don't use, use @primary-color +@primary-7: color(~`colorPalette('@{primary-color}', 7) `); // replace shade(@primary-color, 5%) +@primary-8: color(~`colorPalette('@{primary-color}', 8) `); // unused +@primary-9: color(~`colorPalette('@{primary-color}', 9) `); // unused +@primary-10: color(~`colorPalette('@{primary-color}', 10) `); // unused + +// Base Scaffolding Variables +// --- + +// Background color for `` +@body-background: #fff; +// Base background color for most components +@component-background: #fff; +@font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', + 'Helvetica Neue', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; +@code-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; +@text-color: fade(@black, 65%); +@text-color-secondary: fade(@black, 45%); +@text-color-warning: @gold-7; +@text-color-danger: @red-7; +@text-color-inverse: @white; +@icon-color: inherit; +@icon-color-hover: fade(@black, 75%); +@heading-color: fade(#000, 85%); +@heading-color-dark: fade(@white, 100%); +@text-color-dark: fade(@white, 85%); +@text-color-secondary-dark: fade(@white, 65%); +@font-variant-base: tabular-nums; +@font-feature-settings-base: 'tnum'; +@font-size-base: 14px; +@font-size-lg: @font-size-base + 2px; +@font-size-sm: 12px; +@heading-1-size: ceil(@font-size-base * 2.71); +@heading-2-size: ceil(@font-size-base * 2.14); +@heading-3-size: ceil(@font-size-base * 1.71); +@heading-4-size: ceil(@font-size-base * 1.42); +@line-height-base: 1.5; +@border-radius-base: 0px; +@border-radius-sm: 0px; + +// vertical paddings +@padding-lg: 24px; // containers +@padding-md: 16px; // small containers and buttons +@padding-sm: 12px; // Form controls and items +@padding-xs: 8px; // small items + +// vertical padding for all form controls +@control-padding-horizontal: @padding-sm; +@control-padding-horizontal-sm: @padding-xs; + +// The background colors for active and hover states for things like +// list items or table cells. +@item-active-bg: @primary-1; +@item-hover-bg: @primary-1; + +// ICONFONT +@iconfont-css-prefix: anticon; + +// LINK +@link-color: @primary-color; +@link-hover-color: color(~`colorPalette('@{link-color}', 5) `); +@link-active-color: color(~`colorPalette('@{link-color}', 7) `); +@link-decoration: none; +@link-hover-decoration: none; + +// Animation +@ease-base-out: cubic-bezier(0.7, 0.3, 0.1, 1); +@ease-base-in: cubic-bezier(0.9, 0, 0.3, 0.7); +@ease-out: cubic-bezier(0.215, 0.61, 0.355, 1); +@ease-in: cubic-bezier(0.55, 0.055, 0.675, 0.19); +@ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1); +@ease-out-back: cubic-bezier(0.12, 0.4, 0.29, 1.46); +@ease-in-back: cubic-bezier(0.71, -0.46, 0.88, 0.6); +@ease-in-out-back: cubic-bezier(0.71, -0.46, 0.29, 1.46); +@ease-out-circ: cubic-bezier(0.08, 0.82, 0.17, 1); +@ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.34); +@ease-in-out-circ: cubic-bezier(0.78, 0.14, 0.15, 0.86); +@ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1); +@ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06); +@ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1); + +// Border color +@border-color-base: hsv(0, 0, 85%); // base border outline a component +@border-color-split: hsv(0, 0, 91%); // split border inside a component +@border-color-inverse: @white; +@border-width-base: 1px; // width of the border for a component +@border-style-base: solid; // style of a components border + +// Outline +@outline-blur-size: 0; +@outline-width: 2px; +@outline-color: @primary-color; + +@background-color-light: hsv(0, 0, 98%); // background of header and selected item +@background-color-base: hsv(0, 0, 96%); // Default grey background color + +// Disabled states +@disabled-color: fade(#000, 25%); +@disabled-bg: @background-color-base; +@disabled-color-dark: fade(#fff, 35%); + +// Shadow +@shadow-color: rgba(0, 0, 0, 0.15); +@shadow-color-inverse: @component-background; +@box-shadow-base: @shadow-1-down; +@shadow-1-up: 0 -2px 8px @shadow-color; +@shadow-1-down: 0 2px 8px @shadow-color; +@shadow-1-left: -2px 0 8px @shadow-color; +@shadow-1-right: 2px 0 8px @shadow-color; +@shadow-2: 0 4px 12px @shadow-color; + +// Buttons +@btn-font-weight: 400; +@btn-border-radius-base: @border-radius-base; +@btn-border-radius-sm: @border-radius-base; +@btn-border-width: @border-width-base; +@btn-border-style: @border-style-base; +@btn-shadow: 0 2px 0 rgba(0, 0, 0, 0.015); +@btn-primary-shadow: 0 2px 0 rgba(0, 0, 0, 0.045); +@btn-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12); + +@btn-primary-color: #fff; +@btn-primary-bg: @primary-color; + +@btn-default-color: @text-color; +@btn-default-bg: #fff; +@btn-default-border: @border-color-base; + +@btn-danger-color: @error-color; +@btn-danger-bg: @background-color-base; +@btn-danger-border: @border-color-base; + +@btn-disable-color: @disabled-color; +@btn-disable-bg: @disabled-bg; +@btn-disable-border: @border-color-base; + +@btn-padding-base: 0 @padding-md - 1px; +@btn-font-size-lg: @font-size-lg; +@btn-font-size-sm: @font-size-base; +@btn-padding-lg: @btn-padding-base; +@btn-padding-sm: 0 @padding-xs - 1px; + +@btn-height-base: 32px; +@btn-height-lg: 40px; +@btn-height-sm: 24px; + +@btn-circle-size: @btn-height-base; +@btn-circle-size-lg: @btn-height-lg; +@btn-circle-size-sm: @btn-height-sm; + +@btn-square-size: @btn-height-base; +@btn-square-size-lg: @btn-height-lg; +@btn-square-size-sm: @btn-height-sm; + +@btn-group-border: @primary-5; + +// Checkbox +@checkbox-size: 16px; +@checkbox-color: @primary-color; +@checkbox-check-color: #fff; +@checkbox-border-width: @border-width-base; + +// Descriptions +@descriptions-bg: #fafafa; + +// Empty +@empty-font-size: @font-size-base; + +// Radio +@radio-size: 16px; +@radio-dot-color: @primary-color; + +// Radio buttons +@radio-button-bg: @btn-default-bg; +@radio-button-checked-bg: @btn-default-bg; +@radio-button-color: @btn-default-color; +@radio-button-hover-color: @primary-5; +@radio-button-active-color: @primary-7; + +// Media queries breakpoints +// Extra small screen / phone +@screen-xs: 480px; +@screen-xs-min: @screen-xs; + +// Small screen / tablet +@screen-sm: 576px; +@screen-sm-min: @screen-sm; + +// Medium screen / desktop +@screen-md: 768px; +@screen-md-min: @screen-md; + +// Large screen / wide desktop +@screen-lg: 992px; +@screen-lg-min: @screen-lg; + +// Extra large screen / full hd +@screen-xl: 1200px; +@screen-xl-min: @screen-xl; + +// Extra extra large screen / large desktop +@screen-xxl: 1600px; +@screen-xxl-min: @screen-xxl; + +// provide a maximum +@screen-xs-max: (@screen-sm-min - 1px); +@screen-sm-max: (@screen-md-min - 1px); +@screen-md-max: (@screen-lg-min - 1px); +@screen-lg-max: (@screen-xl-min - 1px); +@screen-xl-max: (@screen-xxl-min - 1px); + +// Grid system +@grid-columns: 24; +@grid-gutter-width: 0; + +// Layout +@layout-body-background: #f0f2f5; +@layout-header-background: #001529; +@layout-footer-background: @layout-body-background; +@layout-header-height: 64px; +@layout-header-padding: 0 50px; +@layout-footer-padding: 24px 50px; +@layout-sider-background: @layout-header-background; +@layout-trigger-height: 48px; +@layout-trigger-background: #002140; +@layout-trigger-color: #fff; +@layout-zero-trigger-width: 36px; +@layout-zero-trigger-height: 42px; +// Layout light theme +@layout-sider-background-light: #fff; +@layout-trigger-background-light: #fff; +@layout-trigger-color-light: @text-color; + +// z-index list, order by `z-index` +@zindex-table-fixed: auto; +@zindex-affix: 10; +@zindex-back-top: 10; +@zindex-badge: 10; +@zindex-picker-panel: 10; +@zindex-popup-close: 10; +@zindex-modal: 1000; +@zindex-modal-mask: 1000; +@zindex-message: 1010; +@zindex-notification: 1010; +@zindex-popover: 1030; +@zindex-dropdown: 1050; +@zindex-picker: 1050; +@zindex-tooltip: 1060; + +// Animation +@animation-duration-slow: 0.3s; // Modal +@animation-duration-base: 0.2s; +@animation-duration-fast: 0.1s; // Tooltip + +// Form +// --- +@label-required-color: @highlight-color; +@label-color: @heading-color; +@form-item-margin-bottom: 24px; +@form-item-trailing-colon: true; +@form-vertical-label-padding: 0 0 8px; +@form-vertical-label-margin: 0; + +// Input +// --- +@input-height-base: 32px; +@input-height-lg: 40px; +@input-height-sm: 24px; +@input-padding-horizontal: @control-padding-horizontal - 1px; +@input-padding-horizontal-base: @input-padding-horizontal; +@input-padding-horizontal-sm: @control-padding-horizontal-sm - 1px; +@input-padding-horizontal-lg: @input-padding-horizontal; +@input-padding-vertical-base: 4px; +@input-padding-vertical-sm: 1px; +@input-padding-vertical-lg: 6px; +@input-placeholder-color: hsv(0, 0, 75%); +@input-color: @text-color; +@input-border-color: @border-color-base; +@input-bg: #fff; +@input-number-handler-active-bg: #f4f4f4; +@input-number-handler-hover-bg: @primary-5; +@input-number-handler-bg: @component-background; +@input-number-handler-border-color: @border-color-base; +@input-addon-bg: @background-color-light; +@input-hover-border-color: @primary-color; +@input-disabled-bg: @disabled-bg; +@input-outline-offset: 0 0; + +// Select +// --- +@select-border-color: @border-color-base; +@select-item-selected-font-weight: 600; +@select-dropdown-bg: @component-background; +@select-item-selected-bg: @background-color-light; +@select-item-active-bg: @item-active-bg; + +// Anchor +// --- +@anchor-border-color: @border-color-split; + +// Tooltip +// --- +// Tooltip max width +@tooltip-max-width: 250px; +// Tooltip text color +@tooltip-color: #fff; +// Tooltip background color +@tooltip-bg: rgba(0, 0, 0, 0.75); +// Tooltip arrow width +@tooltip-arrow-width: 5px; +// Tooltip distance with trigger +@tooltip-distance: @tooltip-arrow-width - 1px + 4px; +// Tooltip arrow color +@tooltip-arrow-color: @tooltip-bg; + +// Popover +// --- +// Popover body background color +@popover-bg: #fff; +// Popover text color +@popover-color: @text-color; +// Popover maximum width +@popover-min-width: 177px; +// Popover arrow width +@popover-arrow-width: 6px; +// Popover arrow color +@popover-arrow-color: @popover-bg; +// Popover outer arrow width +// Popover outer arrow color +@popover-arrow-outer-color: @popover-bg; +// Popover distance with trigger +@popover-distance: @popover-arrow-width + 4px; + +// Modal +// -- +@modal-body-padding: 24px; +@modal-header-bg: @component-background; +@modal-footer-bg: transparent; +@modal-footer-border-color-split: @border-color-split; +@modal-mask-bg: fade(@black, 45%); + +// Progress +// -- +@progress-default-color: @processing-color; +@progress-remaining-color: @background-color-base; +@progress-text-color: @text-color; + +// Menu +// --- +@menu-inline-toplevel-item-height: 40px; +@menu-item-height: 40px; +@menu-collapsed-width: 80px; +@menu-bg: @component-background; +@menu-popup-bg: @component-background; +@menu-item-color: @text-color; +@menu-highlight-color: @primary-color; +@menu-item-active-bg: @item-active-bg; +@menu-item-active-border-width: 3px; +@menu-item-group-title-color: @text-color-secondary; +@menu-icon-size: @font-size-base; +@menu-icon-size-lg: @font-size-lg; + +@menu-item-vertical-margin: 4px; +@menu-item-font-size: @font-size-base; +@menu-item-boundary-margin: 8px; +@menu-icon-size: @font-size-base; +@menu-icon-size-lg: @font-size-lg; +@menu-dark-selected-item-icon-color: @white; +@menu-dark-selected-item-text-color: @white; +@dark-menu-item-hover-bg: transparent; + +// dark theme +@menu-dark-color: @text-color-secondary-dark; +@menu-dark-bg: @layout-header-background; +@menu-dark-arrow-color: #fff; +@menu-dark-submenu-bg: #000c17; +@menu-dark-highlight-color: #fff; +@menu-dark-item-active-bg: @primary-color; +@menu-dark-selected-item-icon-color: @white; +@menu-dark-selected-item-text-color: @white; +@menu-dark-item-hover-bg: transparent; + +// Spin +// --- +@spin-dot-size-sm: 14px; +@spin-dot-size: 20px; +@spin-dot-size-lg: 32px; + +// Table +// -- +@table-header-bg: @background-color-light; +@table-header-color: @heading-color; +@table-header-sort-bg: @background-color-base; +@table-body-sort-bg: rgba(0, 0, 0, 0.01); +@table-row-hover-bg: @primary-1; +@table-selected-row-bg: #fafafa; +@table-expanded-row-bg: #fbfbfb; +@table-padding-vertical: 16px; +@table-padding-horizontal: 16px; +@table-border-radius-base: @border-radius-base; +@table-footer-bg: @background-color-light; +@table-footer-color: @heading-color; + +// Tag +// -- +@tag-default-bg: @background-color-light; +@tag-default-color: @text-color; +@tag-font-size: @font-size-sm; + +// TimePicker +// --- +@time-picker-panel-column-width: 56px; +@time-picker-panel-width: @time-picker-panel-column-width * 3; +@time-picker-selected-bg: @background-color-base; + +// Carousel +// --- +@carousel-dot-width: 16px; +@carousel-dot-height: 3px; +@carousel-dot-active-width: 24px; + +// Badge +// --- +@badge-height: 20px; +@badge-dot-size: 6px; +@badge-font-size: @font-size-sm; +@badge-font-weight: normal; +@badge-status-size: 6px; +@badge-text-color: @component-background; + +// Rate +// --- +@rate-star-color: @yellow-6; +@rate-star-bg: @border-color-split; + +// Card +// --- +@card-head-color: @heading-color; +@card-head-background: transparent; +@card-head-padding: 16px; +@card-inner-head-padding: 12px; +@card-padding-base: 24px; +@card-actions-background: @background-color-light; +@card-skeleton-bg: #cfd8dc; +@card-background: @component-background; +@card-shadow: 0 2px 8px rgba(0, 0, 0, 0.09); +@card-radius: @border-radius-sm; + +// Comment +// --- +@comment-padding-base: 16px 0; +@comment-nest-indent: 44px; +@comment-author-name-color: @text-color-secondary; +@comment-author-time-color: #ccc; +@comment-action-color: @text-color-secondary; +@comment-action-hover-color: #595959; + +// Tabs +// --- +@tabs-card-head-background: @background-color-light; +@tabs-card-height: 40px; +@tabs-card-active-color: @primary-color; +@tabs-title-font-size: @font-size-base; +@tabs-title-font-size-lg: @font-size-lg; +@tabs-title-font-size-sm: @font-size-base; +@tabs-ink-bar-color: @primary-color; +@tabs-bar-margin: 0 0 16px 0; +@tabs-horizontal-margin: 0 32px 0 0; +@tabs-horizontal-padding: 12px 16px; +@tabs-horizontal-padding-lg: 16px; +@tabs-horizontal-padding-sm: 8px 16px; +@tabs-vertical-padding: 8px 24px; +@tabs-vertical-margin: 0 0 16px 0; +@tabs-scrolling-size: 32px; +@tabs-highlight-color: @primary-color; +@tabs-hover-color: @primary-5; +@tabs-active-color: @primary-7; + +// BackTop +// --- +@back-top-color: #fff; +@back-top-bg: @text-color-secondary; +@back-top-hover-bg: @text-color; + +// Avatar +// --- +@avatar-size-base: 32px; +@avatar-size-lg: 40px; +@avatar-size-sm: 24px; +@avatar-font-size-base: 18px; +@avatar-font-size-lg: 24px; +@avatar-font-size-sm: 14px; +@avatar-bg: #ccc; +@avatar-color: #fff; +@avatar-border-radius: @border-radius-base; + +// Switch +// --- +@switch-height: 22px; +@switch-sm-height: 16px; +@switch-sm-checked-margin-left: -(@switch-sm-height - 3px); +@switch-disabled-opacity: 0.4; +@switch-color: @primary-color; +@switch-shadow-color: fade(#00230b, 20%); + +// Pagination +// --- +@pagination-item-size: 32px; +@pagination-item-size-sm: 24px; +@pagination-font-family: Arial; +@pagination-font-weight-active: 500; +@pagination-item-bg-active: transparent; + +// PageHeader +// --- +@page-header-padding: 24px; +@page-header-padding-vertical: 16px; @page-header-padding-vertical: 16px; +@page-header-padding-breadcrumb: 12px; +@page-header-back-color: #000; + +// Breadcrumb +// --- +@breadcrumb-base-color: @text-color-secondary; +@breadcrumb-last-item-color: @text-color; +@breadcrumb-font-size: @font-size-base; +@breadcrumb-icon-font-size: @font-size-base; +@breadcrumb-link-color: @text-color-secondary; +@breadcrumb-link-color-hover: @primary-5; +@breadcrumb-separator-color: @text-color-secondary; +@breadcrumb-separator-margin: 0 @padding-xs; + +// Slider +// --- +@slider-margin: 14px 6px 10px; +@slider-rail-background-color: @background-color-base; +@slider-rail-background-color-hover: #e1e1e1; +@slider-track-background-color: @primary-3; +@slider-track-background-color-hover: @primary-4; +@slider-handle-color: @primary-3; +@slider-handle-color-hover: @primary-4; +@slider-handle-color-focus: tint(@primary-color, 20%); +@slider-handle-color-focus-shadow: fade(@primary-color, 20%); +@slider-handle-color-tooltip-open: @primary-color; +@slider-dot-border-color: @border-color-split; +@slider-dot-border-color-active: tint(@primary-color, 50%); +@slider-disabled-color: @disabled-color; +@slider-disabled-background-color: @component-background; + +// Tree +// --- +@tree-title-height: 24px; +@tree-child-padding: 18px; +@tree-directory-selected-color: #fff; +@tree-directory-selected-bg: @primary-color; +@tree-node-hover-bg: @item-hover-bg; +@tree-node-selected-bg: @primary-2; + +// Collapse +// --- +@collapse-header-padding: 12px 16px 12px 40px; +@collapse-header-bg: @background-color-light; +@collapse-content-padding: @padding-md; +@collapse-content-bg: @component-background; + +// Skeleton +// --- +@skeleton-color: #f2f2f2; + +// Transfer +// --- +@transfer-disabled-bg: @disabled-bg; + +// Message +// --- +@message-notice-content-padding: 10px 16px; + +// Motion +// --- +@wave-animation-width: 6px; + +// Alert +// --- +@alert-success-border-color: ~`colorPalette('@{success-color}', 3) `; +@alert-success-bg-color: ~`colorPalette('@{success-color}', 1) `; +@alert-success-icon-color: @success-color; +@alert-info-border-color: ~`colorPalette('@{info-color}', 3) `; +@alert-info-bg-color: ~`colorPalette('@{info-color}', 1) `; +@alert-info-icon-color: @info-color; +@alert-warning-border-color: ~`colorPalette('@{warning-color}', 3) `; +@alert-warning-bg-color: ~`colorPalette('@{warning-color}', 1) `; +@alert-warning-icon-color: @warning-color; +@alert-error-border-color: ~`colorPalette('@{error-color}', 3) `; +@alert-error-bg-color: ~`colorPalette('@{error-color}', 1) `; +@alert-error-icon-color: @error-color; + +// List +// --- +@list-header-background: transparent; +@list-footer-background: transparent; +@list-empty-text-padding: @padding-md; +@list-item-padding: @padding-sm 0; +@list-item-meta-margin-bottom: @padding-md; +@list-item-meta-avatar-margin-right: @padding-md; +@list-item-meta-title-margin-bottom: @padding-sm; + +// Statistic +// --- +@statistic-title-font-size: @font-size-base; +@statistic-content-font-size: 24px; +@statistic-unit-font-size: 16px; +@statistic-font-family: @font-family; + +// Drawer +// --- +@drawer-header-padding: 16px 24px; +@drawer-body-padding: 24px; + +// Typography +// --- +@typography-title-font-weight: 600; diff --git a/zeppelin-web-angular/src/styles/theme/markdown.less b/zeppelin-web-angular/src/styles/theme/markdown.less new file mode 100644 index 00000000000..d9f26833d6e --- /dev/null +++ b/zeppelin-web-angular/src/styles/theme/markdown.less @@ -0,0 +1,166 @@ +/* + * 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. + */ + +.markdown-body { + color: @text-color; + font-size: 14px; + line-height: 1.5; + + h1 { + color: @heading-color; + font-weight: 500; + margin: 0.6em 0 0.6em; + font-family: Avenir, @font-family; + font-size: 30px; + font-variant: tabular-nums; + line-height: 38px; + } + + h2 { + font-size: 24px; + line-height: 32px; + } + + h2, + h3, + h4, + h5, + h6 { + color: @heading-color; + font-family: Avenir, @font-family; + font-variant: tabular-nums; + margin: 0.6em 0 0.6em; + font-weight: 500; + clear: both; + } + + h3 { + font-size: 18px; + } + + h4 { + font-size: 16px; + } + + h5 { + font-size: 14px; + } + + h6 { + font-size: 12px; + } + + hr { + height: 1px; + border: 0; + background: @border-color-split; + margin: 56px 0; + clear: both; + } + + p, + pre { + margin: 1em 0; + } + + ul > li { + list-style-type: circle; + margin-left: 20px; + padding-left: 4px; + + &:empty { + display: none; + } + } + + ol > li { + list-style-type: decimal; + margin-left: 20px; + padding-left: 4px; + } + + ul > li > p, + ol > li > p { + margin: 0.2em 0; + } + + code { + margin: 0 1px; + background: #f2f4f5; + padding: .2em .4em; + border-radius: 3px; + font-size: .9em; + border: 1px solid #eee; + } + + pre { + border-radius: @border-radius-sm; + background: #f2f4f5; + font-family: "Lucida Console", Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + } + + pre code { + border: none; + background: #f2f4f5; + margin: 0; + padding: 0; + font-size: @font-size-base - 1px; + color: @text-color; + overflow: auto; + } + + strong, + b { + font-weight: 500; + } + + > table { + border-collapse: collapse; + border-spacing: 0; + empty-cells: show; + border: 1px solid @border-color-split; + width: 100%; + margin: 8px 0 16px; + } + + > table th { + white-space: nowrap; + color: #5c6b77; + font-weight: 500; + background: rgba(0, 0, 0, 0.02); + } + + & > table th, + & > table td { + border: 1px solid @border-color-split; + padding: 16px 24px; + text-align: left; + } + + blockquote { + font-size: 90%; + color: @text-color-secondary; + border-left: 4px solid @border-color-split; + padding-left: 0.8em; + margin: 1em 0; + } + + blockquote p { + margin: 0; + } + + & > br, + & > p > br { + clear: both; + } + +} diff --git a/zeppelin-web-angular/src/styles/theme/theme-mixin.less b/zeppelin-web-angular/src/styles/theme/theme-mixin.less new file mode 100644 index 00000000000..4daec305409 --- /dev/null +++ b/zeppelin-web-angular/src/styles/theme/theme-mixin.less @@ -0,0 +1,24 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@import '../../../node_modules/ng-zorro-antd/src/style/color/colors'; + +.themeMixin(@rules) { + :host-context(.light) { + @import 'theme-light'; + @rules(); + } + :host-context(.dark) { + @import 'theme-dark'; + @rules(); + } +} diff --git a/zeppelin-web-angular/src/test.ts b/zeppelin-web-angular/src/test.ts new file mode 100644 index 00000000000..f90345f8e54 --- /dev/null +++ b/zeppelin-web-angular/src/test.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import { getTestBed } from '@angular/core/testing'; +import { platformBrowserDynamicTesting, BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing'; +// tslint:disable-next-line:no-import-side-effect +import 'zone.js/dist/zone-testing'; + +// tslint:disable-next-line no-any +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/zeppelin-web-angular/src/tsconfig.app.json b/zeppelin-web-angular/src/tsconfig.app.json new file mode 100644 index 00000000000..50958688dbe --- /dev/null +++ b/zeppelin-web-angular/src/tsconfig.app.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/app", + "types": ["mathjax"] + }, + "exclude": ["test.ts", "**/*.spec.ts"] +} diff --git a/zeppelin-web-angular/src/tsconfig.spec.json b/zeppelin-web-angular/src/tsconfig.spec.json new file mode 100644 index 00000000000..70add2d529d --- /dev/null +++ b/zeppelin-web-angular/src/tsconfig.spec.json @@ -0,0 +1,9 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/spec", + "types": ["jasmine", "node"] + }, + "files": ["test.ts", "polyfills.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts"] +} diff --git a/zeppelin-web-angular/src/tslint.json b/zeppelin-web-angular/src/tslint.json new file mode 100644 index 00000000000..bb3e34a7b6e --- /dev/null +++ b/zeppelin-web-angular/src/tslint.json @@ -0,0 +1,7 @@ +{ + "extends": "../tslint.json", + "rules": { + "directive-selector": [true, "attribute", "zeppelin", "camelCase"], + "component-selector": [true, "element", "zeppelin", "kebab-case"] + } +} diff --git a/zeppelin-web-angular/tsconfig.app.json b/zeppelin-web-angular/tsconfig.app.json new file mode 100644 index 00000000000..565a11a2156 --- /dev/null +++ b/zeppelin-web-angular/tsconfig.app.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts", + "src/polyfills.ts" + ], + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "src/test.ts", + "src/**/*.spec.ts" + ] +} diff --git a/zeppelin-web-angular/tsconfig.json b/zeppelin-web-angular/tsconfig.json new file mode 100644 index 00000000000..45f06cbf7de --- /dev/null +++ b/zeppelin-web-angular/tsconfig.json @@ -0,0 +1,47 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@zeppelin/*": [ + "./src/app/*", + "./src/environments/*" + ], + "@zeppelin/helium": [ + "./dist/zeppelin-helium" + ], + "@zeppelin/helium/*": [ + "./dist/zeppelin-helium/*" + ], + "@zeppelin/visualization": [ + "dist/zeppelin-visualization" + ], + "@zeppelin/visualization/*": [ + "dist/zeppelin-visualization/*" + ], + "@zeppelin/sdk": [ + "dist/zeppelin-sdk" + ], + "@zeppelin/sdk/*": [ + "dist/zeppelin-sdk/*" + ] + }, + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "esnext", + "moduleResolution": "node", + "importHelpers": true, + "target": "es5", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2018", + "dom" + ] + } +} \ No newline at end of file diff --git a/zeppelin-web-angular/tsconfig.spec.json b/zeppelin-web-angular/tsconfig.spec.json new file mode 100644 index 00000000000..6400fde7d54 --- /dev/null +++ b/zeppelin-web-angular/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/zeppelin-web-angular/tslint.json b/zeppelin-web-angular/tslint.json new file mode 100644 index 00000000000..74aed2552ed --- /dev/null +++ b/zeppelin-web-angular/tslint.json @@ -0,0 +1,141 @@ +{ + "rulesDirectory": ["node_modules/codelyzer"], + "rules": { + "banana-in-box": true, + "templates-no-negated-async": true, + "no-life-cycle-call": false, + "prefer-output-readonly": true, + "no-conflicting-life-cycle-hooks": false, + "enforce-component-selector": false, + "use-input-property-decorator": true, + "use-output-property-decorator": true, + "use-host-property-decorator": false, + "use-view-encapsulation": false, + "no-attribute-parameter-decorator": true, + "no-output-named-after-standard-event": true, + "no-output-rename": true, + "no-output-on-prefix": true, + "no-forward-ref": false, + "use-life-cycle-interface": true, + "contextual-life-cycle": true, + "trackBy-function": false, + "use-pipe-transform-interface": true, + "component-class-suffix": true, + "directive-class-suffix": true, + "pipe-impure": true, + "angular-whitespace": [false, "check-interpolation"], + "directive-selector": [true, "attribute", ["zeppelin"], ["camelCase", "kebab-case"]], + "component-selector": [true, ["element", "attribute"], ["zeppelin"], "kebab-case"], + "callable-types": true, + "class-name": true, + "comment-format": [true, "check-space"], + "align": [true, "parameters", "statements"], + "array-type": [true, "array-simple"], + "arrow-return-shorthand": true, + "ban-types": [ + true, + ["Object", "Use {} instead."], + ["String", "Use string instead."], + ["Number", "Use number instead."], + ["Boolean", "Use boolean instead."], + ["Function", "Use specific callable interface instead."] + ], + "binary-expression-operand-order": true, + "curly": true, + "encoding": true, + "eofline": true, + "deprecation": { + "severity": "warn" + }, + "import-spacing": true, + "indent": [true, "spaces"], + "interface-name": [true, "never-prefix"], + "interface-over-type-literal": true, + "label-position": true, + "new-parens": true, + "no-angle-bracket-type-assertion": true, + "member-access": false, + "member-ordering": [ + true, + { + "order": ["static-field", "instance-field", "static-method", "instance-method"] + } + ], + "no-any": true, + "no-arg": true, + "no-bitwise": false, + "no-consecutive-blank-lines": [true], + "no-console": [true, "debug", "info", "time", "timeEnd", "trace"], + "no-duplicate-variable": true, + "no-conditional-assignment": true, + "no-construct": true, + "no-debugger": true, + "no-duplicate-imports": true, + "no-duplicate-super": true, + "no-empty": false, + "no-empty-interface": true, + "no-eval": true, + "no-floating-promises": false, + "no-for-in-array": true, + "no-import-side-effect": true, + "no-inferrable-types": [true, "ignore-params", "ignore-properties"], + "no-invalid-template-strings": true, + "no-invalid-this": true, + "no-irregular-whitespace": true, + "no-magic-numbers": false, + "no-misused-new": true, + "no-namespace": [true, "allow-declarations"], + "no-non-null-assertion": false, + "no-shadowed-variable": true, + "no-sparse-arrays": true, + "no-string-literal": true, + "no-string-throw": true, + "no-switch-case-fall-through": true, + "no-this-assignment": true, + "no-trailing-whitespace": true, + "no-parameter-reassignment": true, + "no-unnecessary-initializer": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "number-literal-format": true, + "one-line": [true, "check-open-brace", "check-catch", "check-else", "check-whitespace"], + "one-variable-per-declaration": [true, "ignore-for-loop"], + "ordered-imports": [ + true, + { + "import-sources-order": "lowercase-last", + "named-imports-order": "lowercase-first" + } + ], + "prefer-conditional-expression": false, + "prefer-const": true, + "prefer-method-signature": true, + "prefer-object-spread": true, + "prefer-template": [true, "allow-single-concat"], + "radix": true, + "trailing-comma": [ + true, + { + "multiline": "never", + "singleline": "never" + } + ], + "triple-equals": [true, "allow-null-check"], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "unified-signatures": true, + "use-isnan": true, + "variable-name": [true, "ban-keywords", "allow-leading-underscore"], + "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type"], + "no-input-rename": true + } +} diff --git a/zeppelin-web-angular/webpack.partial.js b/zeppelin-web-angular/webpack.partial.js new file mode 100644 index 00000000000..c2261441f9c --- /dev/null +++ b/zeppelin-web-angular/webpack.partial.js @@ -0,0 +1,27 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); + +module.exports = { + plugins: [ + new MonacoWebpackPlugin({ + languages: [ + 'bat', 'cpp', 'csharp', 'csp', 'css', 'dockerfile', 'go', 'handlebars', 'html', 'java', 'javascript', 'json', + 'less', 'lua', 'markdown', 'mysql', 'objective', 'perl', 'pgsql', 'php', 'powershell', 'python', 'r', 'ruby', + 'rust', 'scheme', 'scss', 'shell', 'sql', 'swift', 'typescript', 'vb', 'xml', 'yaml' + ], + features: ['!accessibilityHelp'] + }) + ] +}; +