diff --git a/.env.json b/.env.json
new file mode 100644
index 000000000..0fa6162d9
--- /dev/null
+++ b/.env.json
@@ -0,0 +1,6 @@
+{
+ "salixHost": "localhost",
+ "salixPort": "3306",
+ "salixUser": "root",
+ "salixPassword": "root"
+}
\ No newline at end of file
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 7d4a3e1da..022c3d6fa 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -1,5 +1,10 @@
-extends: google
-installedESLint: true
+extends: [eslint:recommended, google, plugin:jasmine/recommended]
+parserOptions:
+ ecmaVersion: 2017
+plugins:
+ - jasmine
+env:
+ jasmine: true
rules:
indent: [error, 4]
require-jsdoc: 0
@@ -9,3 +14,9 @@ rules:
operator-linebreak: 0
radix: 0
guard-for-in: 0
+ camelcase: 0
+ default-case: 0
+ no-eq-null: 0
+ no-console: 0
+ no-warning-comments: 0
+ no-empty: [error, allowEmptyCatch: true]
diff --git a/.gitignore b/.gitignore
index 13438391d..0f92907cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,4 @@
node_modules
-spliting.js
build
npm-debug.log
-debug.log
-datasources.development.json
+docker-compose.yml
diff --git a/.vscode/launch.json b/.vscode/launch.json
index ce047cac4..c3b70b7f0 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -2,85 +2,10 @@
"version": "0.2.0",
"configurations": [
{
- "name": "Iniciar",
- "type": "node",
- "request": "launch",
- "program": "${workspaceRoot}/app.js",
- "stopOnEntry": false,
- "args": [],
- "cwd": "${workspaceRoot}",
- "preLaunchTask": null,
- "runtimeExecutable": null,
- "runtimeArgs": [
- "--nolazy"
- ],
- "env": {
- "NODE_ENV": "development"
- },
- "console": "internalConsole",
- "sourceMaps": false,
- "outFiles": []
- },
- {
- "name": "Asociar",
"type": "node",
"request": "attach",
- "port": 5858,
- "address": "localhost",
- "restart": false,
- "sourceMaps": false,
- "outFiles": [],
- "localRoot": "${workspaceRoot}",
- "remoteRoot": null
- },
- {
- "name": "Asociar al proceso",
- "type": "node",
- "request": "attach",
- "processId": "${command.PickProcess}",
- "port": 5858,
- "sourceMaps": false,
- "outFiles": []
- },
- {
- "name": "Loopback",
- "type": "node",
- "request": "launch",
- "program": "${workspaceRoot}/services/client/server/server.js",
- "stopOnEntry": false,
- "args": [],
- "cwd": "${workspaceRoot}",
- "preLaunchTask": null,
- "runtimeExecutable": null,
- "runtimeArgs": [
- "--nolazy"
- ],
- "env": {
- "NODE_ENV": "development"
- },
- "console": "internalConsole",
- "sourceMaps": false,
- "outFiles": []
- },
- {
- "name": "gulp debug",
- "type": "node",
- "request": "launch",
- "program": "${workspaceRoot}\\@salix\\node_modules\\gulp\\bin\\gulp.js",
- "stopOnEntry": false,
- "args": [],
- "cwd": "${workspaceRoot}\\@salix",
- "preLaunchTask": null,
- "runtimeExecutable": null,
- "runtimeArgs": [
- "--nolazy"
- ],
- "env": {
- "NODE_ENV": "development"
- },
- "console": "internalConsole",
- "sourceMaps": false,
- "outFiles": []
+ "name": "Attach by Process ID",
+ "processId": "${command:PickProcess}"
}
]
}
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 000000000..098642bfb
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,13 @@
+FROM node:8.9.4
+
+COPY . /app
+COPY ../loopback /loopback
+
+WORKDIR /app
+
+RUN npm install
+RUN npm -g install pm2
+
+CMD ["pm2-docker", "./server/server.js"]
+
+EXPOSE 3000
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 000000000..617a4f8f9
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,60 @@
+#!/usr/bin/env groovy
+
+def branchName = "${env.BRANCH_NAME}";
+def branchProduction = "master"
+def branchTest = "test";
+
+env.BRANCH_NAME = branchName;
+env.TAG = "${env.BUILD_NUMBER}";
+env.salixUser="${env.salixUser}";
+env.salixPassword="${env.salixPassword}";
+env.salixHost = "${env.productionSalixHost}";
+env.salixPort = "${env.productionSalixPort}";
+
+switch (branchName){
+ case branchTest:
+ env.NODE_ENV = "test";
+ env.salixHost = "${env.testSalixHost}";
+ env.salixPort = "${env.testSalixPort}";
+ break;
+ case branchProduction:
+ env.DOCKER_HOST = "tcp://172.16.255.29:2375";
+ env.NODE_ENV = "production"
+ break;
+}
+
+node
+{
+ stage ('Print environment variables'){
+ echo "Branch ${branchName}, Build ${env.TAG}, salixHost ${env.salixHost}, NODE_ENV ${env.NODE_ENV} en docker Host ${env.DOCKER_HOST}"
+ }
+ stage ('Checkout') {
+ checkout scm
+ }
+
+ stage ('install modules'){
+ sh "npm install"
+ }
+
+ stage ('build Project'){
+ sh "gulp build"
+ }
+
+ stage ("docker")
+ {
+ stage ("install modules loopback service")
+ {
+ sh "cd ./services/loopback && npm install"
+ }
+
+ stage ("Stopping/Removing Docker")
+ {
+ sh "docker-compose down --rmi 'all'"
+ }
+
+ stage ("Generar dockers")
+ {
+ sh "docker-compose up -d --build"
+ }
+ }
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000..3d994d0a8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,17 @@
+Copyright (C) 2018 - Verdnatura Levante S.L.
+
+This package is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+On Debian systems, the complete text of the GNU General Public
+License can be found in "/usr/share/common-licenses/GPL-3".
diff --git a/README.md b/README.md
new file mode 100644
index 000000000..176f0761e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,73 @@
+# Salix
+
+This project is an Enterprise resource planning (ERP) integrated management of core business processes, in real-time and mediated by software and technology developed with the stack listed below.
+
+Salix is also the scientific name of a beautifull tree! :)
+
+## Prerequisites
+
+Required applications.
+
+* Node.js = 8.9.4
+* NGINX
+* Docker
+
+You will need to install globally the following items.
+```
+$ npm install -g karma-cli gulp webpack nodemon
+```
+
+## Getting Started // Installing
+
+Pull from repository.
+
+Run this commands on project root directory to install Node dependencies.
+```
+$ npm install
+$ gulp install
+```
+
+Launch application in developer environment.
+```
+$ gulp
+```
+
+Also you can run backend and frontend as separately gulp tasks (including NGINX).
+```
+$ gulp client
+$ gulp services
+```
+
+Manually reset fixtures.
+```
+$ gulp docker
+```
+
+## Running the unit tests
+
+For client-side unit tests run from project's root.
+```
+$ karma start
+```
+
+For server-side unit tests run from project's root.
+```
+$ npm run test
+```
+
+For end-to-end tests run from project's root.
+```
+$ gulp e2e
+```
+
+## Built With
+
+* [angularjs](https://angularjs.org/)
+* [nodejs](https://nodejs.org/)
+* [webpack](https://webpack.js.org/)
+* [loopback](https://loopback.io/)
+* [docker](https://www.docker.com/)
+* [gulp.js](https://gulpjs.com/)
+* [Karma](https://karma-runner.github.io/)
+* [Jasmine](https://jasmine.github.io/)
+* [Nightmare](http://www.nightmarejs.org/)
diff --git a/client/auth/package.json b/client/auth/package.json
deleted file mode 100644
index a9e6aac38..000000000
--- a/client/auth/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "@salix/auth",
- "version": "0.0.0",
- "description": "",
- "main": "index.js",
- "repository": {
- "type": "git",
- "url": "http://git.verdnatura.es:/salix"
- }
-}
diff --git a/client/auth/src/auth.js b/client/auth/src/auth.js
index 03062dac6..d15aa496a 100644
--- a/client/auth/src/auth.js
+++ b/client/auth/src/auth.js
@@ -1,4 +1,2 @@
-export * from './module';
-import './config';
-
-export {component as Login} from './login/login';
+import './module';
+import './login/login';
diff --git a/client/auth/src/config.js b/client/auth/src/config.js
deleted file mode 100644
index 22096d217..000000000
--- a/client/auth/src/config.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import {module} from './module';
-
-config.$inject = ['$translatePartialLoaderProvider', '$httpProvider'];
-export function config($translatePartialLoaderProvider, $httpProvider) {
- $translatePartialLoaderProvider.addPart('auth');
-
- $httpProvider.defaults.useXDomain = true;
- delete $httpProvider.defaults.headers.common['X-Requested-With'];
-}
-module.config(config);
diff --git a/client/auth/src/login/locale/en.json b/client/auth/src/login/locale/en.json
deleted file mode 100644
index 13b9103d7..000000000
--- a/client/auth/src/login/locale/en.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "User": "User",
- "Password": "Password",
- "Do not close session": "Do not close session",
- "Enter": "Enter"
-}
\ No newline at end of file
diff --git a/client/auth/src/login/locale/en.yml b/client/auth/src/login/locale/en.yml
new file mode 100644
index 000000000..c59a6dd8e
--- /dev/null
+++ b/client/auth/src/login/locale/en.yml
@@ -0,0 +1,4 @@
+User: User
+Password: Password
+Do not close session: Do not close session
+Enter: Enter
\ No newline at end of file
diff --git a/client/auth/src/login/locale/es.json b/client/auth/src/login/locale/es.json
deleted file mode 100644
index 85c5c654d..000000000
--- a/client/auth/src/login/locale/es.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "User": "Usuario",
- "Password": "Contraseña",
- "Do not close session": "No cerrar sesión",
- "Enter": "Entrar"
-}
\ No newline at end of file
diff --git a/client/auth/src/login/locale/es.yml b/client/auth/src/login/locale/es.yml
new file mode 100644
index 000000000..9c9ba5905
--- /dev/null
+++ b/client/auth/src/login/locale/es.yml
@@ -0,0 +1,4 @@
+User: Usuario
+Password: Contraseña
+Do not close session: No cerrar sesión
+Enter: Entrar
\ No newline at end of file
diff --git a/client/auth/src/login/login.html b/client/auth/src/login/login.html
old mode 100755
new mode 100644
index 8ff52f4ad..0f0bcec35
--- a/client/auth/src/login/login.html
+++ b/client/auth/src/login/login.html
@@ -3,8 +3,19 @@
-
+
-
+ popover="vn-client-search-panel"
+ ignore-keys = "['page', 'size', 'search']">
-
+
+
-
+
-
-
-
+
+
+
+
+
+
+
+
diff --git a/client/client/src/index/index.js b/client/client/src/index/index.js
index 02c58f64f..6f49f2626 100644
--- a/client/client/src/index/index.js
+++ b/client/client/src/index/index.js
@@ -1,9 +1,22 @@
-import {module} from '../module';
-import './style.css';
+import ngModule from '../module';
import './item-client';
-export const NAME = 'vnClientIndex';
-export const COMPONENT = {
- template: require('./index.html')
-};
-module.component(NAME, COMPONENT);
+export default class Controller {
+ constructor($scope) {
+ this.$scope = $scope;
+ this.clientSelected = null;
+ }
+ search(index) {
+ index.accept();
+ }
+ openSummary(client) {
+ this.clientSelected = client;
+ this.$scope.dialogSummaryClient.show();
+ }
+}
+Controller.$inject = ['$scope'];
+
+ngModule.component('vnClientIndex', {
+ template: require('./index.html'),
+ controller: Controller
+});
diff --git a/client/client/src/index/index.spec.js b/client/client/src/index/index.spec.js
new file mode 100644
index 000000000..1836029e0
--- /dev/null
+++ b/client/client/src/index/index.spec.js
@@ -0,0 +1,36 @@
+import './index.js';
+
+describe('Client', () => {
+ describe('Component vnClientIndex', () => {
+ let $componentController;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject(_$componentController_ => {
+ $componentController = _$componentController_;
+ controller = $componentController('vnClientIndex');
+ }));
+
+ it('should define and set clientSelected property as null', () => {
+ expect(controller.clientSelected).toEqual(null);
+ });
+
+ // describe('search()', () => {
+ // it(`should set model's search to the search input`, () => {
+ // controller.model.search = 'batman';
+ // let index = {
+ // filter: {},
+ // accept: () => {
+ // return 'accepted';
+ // }
+ // };
+ // controller.search(index);
+
+ // expect(index.filter.search).toBe('batman');
+ // });
+ // });
+ });
+});
diff --git a/client/client/src/index/item-client.html b/client/client/src/index/item-client.html
index 7b6c622e9..7ebb6b8f0 100644
--- a/client/client/src/index/item-client.html
+++ b/client/client/src/index/item-client.html
@@ -1,7 +1,21 @@
-
- {{itemClient.client.name}}
- Id Cliente: {{itemClient.client.id}}
- Teléfono: {{itemClient.client.phone | phone}}
- Población: {{itemClient.client.city}}
- email: {{itemClient.client.email}}
+
+
+
+ {{::$ctrl.client.name}}
+ Id {{::$ctrl.client.id}}
+ Phone {{::$ctrl.client.phone | phone}}
+ Town/City {{::$ctrl.client.city}}
+ Email {{::$ctrl.client.email}}
+
+
+
+
+
+
diff --git a/client/client/src/index/item-client.js b/client/client/src/index/item-client.js
index 0c666fd7b..5bacee25d 100644
--- a/client/client/src/index/item-client.js
+++ b/client/client/src/index/item-client.js
@@ -1,11 +1,24 @@
-import {module} from '../module';
+import ngModule from '../module';
-export const NAME = 'vnItemClient';
-export const COMPONENT = {
+class Controller {
+ onClick(event) {
+ if (event.defaultPrevented)
+ event.stopImmediatePropagation();
+ }
+
+ preview(event) {
+ event.preventDefault();
+ this.list.openSummary(this.client);
+ }
+}
+
+ngModule.component('vnItemClient', {
template: require('./item-client.html'),
- controllerAs: 'itemClient',
+ controller: Controller,
bindings: {
client: '<'
+ },
+ require: {
+ list: '^vnClientIndex'
}
-};
-module.component(NAME, COMPONENT);
+});
diff --git a/client/client/src/index/locale/es.yml b/client/client/src/index/locale/es.yml
new file mode 100644
index 000000000..c221de7f6
--- /dev/null
+++ b/client/client/src/index/locale/es.yml
@@ -0,0 +1,5 @@
+Client id: Id cliente
+Phone: Teléfono
+Town/City: Ciudad
+Email: Correo electrónico
+Create client: Crear cliente
\ No newline at end of file
diff --git a/client/client/src/index/style.scss b/client/client/src/index/style.scss
new file mode 100644
index 000000000..0f2ee429f
--- /dev/null
+++ b/client/client/src/index/style.scss
@@ -0,0 +1,3 @@
+vn-item-client {
+ display: block;
+}
\ No newline at end of file
diff --git a/client/client/src/invoices/invoices.html b/client/client/src/invoices/invoices.html
new file mode 100644
index 000000000..fcbb36b97
--- /dev/null
+++ b/client/client/src/invoices/invoices.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+ Invoices
+
+
+
+
+
+
+
+
+
+
+ {{::invoice.ref}}
+ {{::invoice.issued | date:'dd/MM/yyyy' }}
+ {{::invoice.dued | date:'dd/MM/yyyy' }}
+ {{::invoice.amount | currency:'€':2}}
+
+
+
+ No results
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/client/src/invoices/invoices.js b/client/client/src/invoices/invoices.js
new file mode 100644
index 000000000..6f1ea5df1
--- /dev/null
+++ b/client/client/src/invoices/invoices.js
@@ -0,0 +1,15 @@
+import ngModule from '../module';
+import FilterClientList from '../filter-client-list';
+
+class Controller extends FilterClientList {
+ constructor($scope, $timeout, $state, $stateParams) {
+ super($scope, $timeout, $state);
+ $scope.$stateParams = $stateParams;
+ }
+}
+Controller.$inject = ['$scope', '$timeout', '$state', '$stateParams'];
+
+ngModule.component('vnClientInvoices', {
+ template: require('./invoices.html'),
+ controller: Controller
+});
diff --git a/client/client/src/invoices/locale/es.yml b/client/client/src/invoices/locale/es.yml
new file mode 100644
index 000000000..1f03f6318
--- /dev/null
+++ b/client/client/src/invoices/locale/es.yml
@@ -0,0 +1,5 @@
+Invoices: Facturas
+Reference: Referencia
+Issue date: Fecha de emisión
+Due date: Vencimiento
+Amount: Total
\ No newline at end of file
diff --git a/client/client/src/locale/en.json b/client/client/src/locale/en.json
deleted file mode 100644
index 9e26dfeeb..000000000
--- a/client/client/src/locale/en.json
+++ /dev/null
@@ -1 +0,0 @@
-{}
\ No newline at end of file
diff --git a/client/client/src/locale/en.yml b/client/client/src/locale/en.yml
new file mode 100644
index 000000000..3dec4a7ed
--- /dev/null
+++ b/client/client/src/locale/en.yml
@@ -0,0 +1,2 @@
+Client: Client
+Clients: Clients
\ No newline at end of file
diff --git a/client/client/src/locale/es.json b/client/client/src/locale/es.json
deleted file mode 100644
index 9e26dfeeb..000000000
--- a/client/client/src/locale/es.json
+++ /dev/null
@@ -1 +0,0 @@
-{}
\ No newline at end of file
diff --git a/client/client/src/locale/es.yml b/client/client/src/locale/es.yml
new file mode 100644
index 000000000..bb2984d9b
--- /dev/null
+++ b/client/client/src/locale/es.yml
@@ -0,0 +1,23 @@
+Active: Activo
+Client: Cliente
+Clients: Clientes
+Basic data: Datos básicos
+Fiscal data: Datos Fiscales
+Addresses: Consignatarios
+Web access: Acceso web
+Notes: Notas
+Has to invoice: Factura
+Invoice by mail: Factura impresa
+Country: País
+Street: Domicilio fiscal
+City: Municipio
+Postcode: Código postal
+Province: Provincia
+Save: Guardar
+Pay method : Forma de pago
+Address: Consignatario
+Credit : Crédito
+Secured credit: Crédito asegurado
+Verified data: Datos comprobados
+Mandate: Mandato
+Amount: Importe
\ No newline at end of file
diff --git a/client/client/src/mandate/locale/es.yml b/client/client/src/mandate/locale/es.yml
new file mode 100644
index 000000000..545707023
--- /dev/null
+++ b/client/client/src/mandate/locale/es.yml
@@ -0,0 +1,3 @@
+Company: Empresa
+Register date: Fecha alta
+End date: Fecha baja
\ No newline at end of file
diff --git a/client/client/src/mandate/mandate.html b/client/client/src/mandate/mandate.html
new file mode 100644
index 000000000..ef706ece6
--- /dev/null
+++ b/client/client/src/mandate/mandate.html
@@ -0,0 +1,30 @@
+
+
+
+
+ Mandate
+
+
+
+
+
+
+
+
+
+ {{::mandate.id}}
+ {{::mandate.company.code}}
+ {{::mandate.mandateType.name}}
+ {{::mandate.created | date:'dd/MM/yyyy HH:mm' }}
+ {{::mandate.finished | date:'dd/MM/yyyy HH:mm' || '-'}}
+
+
+ No results
+
+
+
+
+
\ No newline at end of file
diff --git a/client/client/src/mandate/mandate.js b/client/client/src/mandate/mandate.js
new file mode 100644
index 000000000..f21f83d28
--- /dev/null
+++ b/client/client/src/mandate/mandate.js
@@ -0,0 +1,7 @@
+import ngModule from '../module';
+import FilterClientList from '../filter-client-list';
+
+ngModule.component('vnClientMandate', {
+ template: require('./mandate.html'),
+ controller: FilterClientList
+});
diff --git a/client/client/src/module.js b/client/client/src/module.js
index 85de3c756..aabcb4d82 100644
--- a/client/client/src/module.js
+++ b/client/client/src/module.js
@@ -1,5 +1,5 @@
import {ng} from 'vendor';
-import * as core from 'core';
+import 'core';
-export const NAME = 'client';
-export const module = ng.module(NAME, []);
+const ngModule = ng.module('client', ['vnCore']);
+export default ngModule;
diff --git a/client/client/src/new-note/index.html b/client/client/src/new-note/index.html
deleted file mode 100644
index 2e05ec244..000000000
--- a/client/client/src/new-note/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/client/client/src/new-note/index.js b/client/client/src/new-note/index.js
deleted file mode 100644
index e4001c688..000000000
--- a/client/client/src/new-note/index.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import template from './index.html';
-import {module} from '../module';
-
-class Controller {
- constructor($element, $state) {
- this.element = $element[0];
- this.$state = $state;
- this.note = {
- client: $state.params.id,
- text: null
- };
- }
- onSubmit() {
- this.element.querySelector('vn-watcher').$ctrl.submit().then(
- () => this.$state.go('clientCard.notes')
- );
- }
-}
-Controller.$inject = ['$element', '$state'];
-
-export const NAME = 'vnNewNote';
-export const COMPONENT = {
- template: template,
- controllerAs: 'newNote',
- controller: Controller
-};
-module.component(NAME, COMPONENT);
diff --git a/client/client/src/note-create/locale/es.yml b/client/client/src/note-create/locale/es.yml
new file mode 100644
index 000000000..bfe773f48
--- /dev/null
+++ b/client/client/src/note-create/locale/es.yml
@@ -0,0 +1,2 @@
+New note: Nueva nota
+Note: Nota
\ No newline at end of file
diff --git a/client/client/src/note-create/note-create.html b/client/client/src/note-create/note-create.html
new file mode 100644
index 000000000..6ad907794
--- /dev/null
+++ b/client/client/src/note-create/note-create.html
@@ -0,0 +1,25 @@
+
+
+
\ No newline at end of file
diff --git a/client/client/src/note-create/note-create.js b/client/client/src/note-create/note-create.js
new file mode 100644
index 000000000..3f5c68ce2
--- /dev/null
+++ b/client/client/src/note-create/note-create.js
@@ -0,0 +1,16 @@
+import ngModule from '../module';
+
+export default class Controller {
+ constructor($state) {
+ this.note = {
+ clientFk: parseInt($state.params.id),
+ text: null
+ };
+ }
+}
+Controller.$inject = ['$state'];
+
+ngModule.component('vnNoteCreate', {
+ template: require('./note-create.html'),
+ controller: Controller
+});
diff --git a/client/client/src/note-create/note-create.spec.js b/client/client/src/note-create/note-create.spec.js
new file mode 100644
index 000000000..1414835fd
--- /dev/null
+++ b/client/client/src/note-create/note-create.spec.js
@@ -0,0 +1,25 @@
+import './note-create.js';
+
+describe('Client', () => {
+ describe('Component vnNoteCreate', () => {
+ let $componentController;
+ let $state;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$state_) => {
+ $componentController = _$componentController_;
+ $state = _$state_;
+ $state.params.id = '1234';
+ controller = $componentController('vnNoteCreate', {$state: $state});
+ }));
+
+ it('should define clientFk using $state.params.id', () => {
+ expect(controller.note.clientFk).toBe(1234);
+ expect(controller.note.client).toBe(undefined);
+ });
+ });
+});
diff --git a/client/client/src/notes/index.html b/client/client/src/notes/index.html
deleted file mode 100644
index c276409fd..000000000
--- a/client/client/src/notes/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- Notas
-
-
- {{n.creationTime | date:'dd/MM/yyyy HH:mm'}}
- {{n.employeeFk}}
- {{n.text}}
-
-
-
-
-
-
\ No newline at end of file
diff --git a/client/client/src/notes/index.js b/client/client/src/notes/index.js
deleted file mode 100644
index 459470167..000000000
--- a/client/client/src/notes/index.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import './style.css';
-import template from './index.html';
-import {module} from '../module';
-
-export const NAME = 'vnClientNotes';
-export const COMPONENT = {
- template: template,
- controllerAs: 'observation',
- bindings: {
- client: '<'
- },
- controller: function($http, $state) {
- this.$onChanges = function(changes) {
- if (this.client) {
- this.getObservation(this.client.id);
- }
- };
-
- this.getObservation = function(clientId) {
- let json = JSON.stringify({where: {clientFk: this.client.id}, order: 'creationTime DESC'});
- $http.get(`/client/api/clientObservations?filter=${json}`).then(
- json => {
- this.observations = json.data;
- }
- );
- };
-
- this.newObservation = () => {
- $state.go("clientCard.newNote", {id: this.client.id});
- };
- }
-};
-COMPONENT.controller.$inject = ['$http', '$state'];
-module.component(NAME, COMPONENT);
diff --git a/client/client/src/notes/notes.html b/client/client/src/notes/notes.html
new file mode 100644
index 000000000..213a4fecb
--- /dev/null
+++ b/client/client/src/notes/notes.html
@@ -0,0 +1,24 @@
+
+
+ Notes
+
+
+ {{::n.worker.firstName}} {{::n.worker.name}}
+ {{::n.created | date:'dd/MM/yyyy HH:mm'}}
+
+
+ {{::n.text}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/client/src/notes/notes.js b/client/client/src/notes/notes.js
new file mode 100644
index 000000000..7e0ec424a
--- /dev/null
+++ b/client/client/src/notes/notes.js
@@ -0,0 +1,37 @@
+import ngModule from '../module';
+import './style.css';
+
+export default class Controller {
+ constructor($http, $state) {
+ this.$http = $http;
+ this.$state = $state;
+ }
+
+ $onChanges() {
+ if (this.client) {
+ this.getObservation(this.client.id);
+ }
+ }
+
+ getObservation(clientId) {
+ let json = JSON.stringify({where: {clientFk: this.client.id}, order: 'created DESC'});
+ this.$http.get(`/client/api/clientObservations?filter=${json}`).then(
+ json => {
+ this.observations = json.data;
+ }
+ );
+ }
+
+ newObservation() {
+ this.$state.go("clientCard.notes.create", {id: this.client.id});
+ }
+}
+Controller.$inject = ['$http', '$state'];
+
+ngModule.component('vnClientNotes', {
+ template: require('./notes.html'),
+ controller: Controller,
+ bindings: {
+ client: '<'
+ }
+});
diff --git a/client/client/src/notes/notes.spec.js b/client/client/src/notes/notes.spec.js
new file mode 100644
index 000000000..1ec7744de
--- /dev/null
+++ b/client/client/src/notes/notes.spec.js
@@ -0,0 +1,58 @@
+import './notes.js';
+
+describe('Client', () => {
+ describe('Component vnClientNotes', () => {
+ let $componentController;
+ let $state;
+ let $httpBackend;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
+ $componentController = _$componentController_;
+ $state = _$state_;
+ $httpBackend = _$httpBackend_;
+ $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ controller = $componentController('vnClientNotes', {$state: $state});
+ }));
+
+ describe('$onChanges()', () => {
+ it(`should call getObservation() with the client id`, () => {
+ controller.client = {
+ id: 1234
+ };
+ spyOn(controller, 'getObservation').and.returnValue();
+ controller.$onChanges();
+
+ expect(controller.getObservation).toHaveBeenCalledWith(1234);
+ });
+ });
+
+ describe('$getObservation()', () => {
+ it(`should request to GET the client notes`, () => {
+ controller.client = {id: '1234'};
+ let jsonString = JSON.stringify({where: {clientFk: '1234'}, order: 'created DESC'});
+ let json = {data: 'some data'};
+ $httpBackend.when('GET', `/client/api/clientObservations?filter=${jsonString}`).respond(json);
+ $httpBackend.expectGET(`/client/api/clientObservations?filter=${jsonString}`, {Accept: 'application/json, text/plain, */*'});
+ controller.getObservation();
+ $httpBackend.flush();
+
+ expect(controller.observations).toEqual(json);
+ });
+ });
+
+ describe('$newObservation()', () => {
+ it(`should redirect the user to the newObservation view`, () => {
+ controller.client = {id: '1234'};
+ spyOn(controller.$state, 'go');
+ controller.newObservation();
+
+ expect(controller.$state.go).toHaveBeenCalledWith('clientCard.notes.create', Object({id: '1234'}));
+ });
+ });
+ });
+});
diff --git a/client/client/src/notes/style.css b/client/client/src/notes/style.css
index b5e17c7a7..e69de29bb 100644
--- a/client/client/src/notes/style.css
+++ b/client/client/src/notes/style.css
@@ -1,3 +0,0 @@
-.notes-date{
- font-family: raleway-bold;
-}
\ No newline at end of file
diff --git a/client/client/src/recovery-create/locale/es.yml b/client/client/src/recovery-create/locale/es.yml
new file mode 100644
index 000000000..64e15cd43
--- /dev/null
+++ b/client/client/src/recovery-create/locale/es.yml
@@ -0,0 +1,2 @@
+Add recovery: Añadir recobro
+Period: Periodo
\ No newline at end of file
diff --git a/client/client/src/recovery-create/recovery-create.html b/client/client/src/recovery-create/recovery-create.html
new file mode 100644
index 000000000..a9ea4933d
--- /dev/null
+++ b/client/client/src/recovery-create/recovery-create.html
@@ -0,0 +1,42 @@
+
+
+
+
diff --git a/client/client/src/recovery-create/recovery-create.js b/client/client/src/recovery-create/recovery-create.js
new file mode 100644
index 000000000..67e4421a2
--- /dev/null
+++ b/client/client/src/recovery-create/recovery-create.js
@@ -0,0 +1,25 @@
+import ngModule from '../module';
+
+class ClientRecoveryCreate {
+ constructor($scope, $state, $filter) {
+ this.$ = $scope;
+ this.$state = $state;
+ this.recovery = {
+ started: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm')
+ };
+ }
+ onSubmit() {
+ this.recovery.clientFk = this.$state.params.id;
+ this.$.watcher.submit().then(
+ () => {
+ this.$state.go('clientCard.recovery.list');
+ }
+ );
+ }
+}
+ClientRecoveryCreate.$inject = ['$scope', '$state', '$filter'];
+
+ngModule.component('vnClientRecoveryCreate', {
+ template: require('./recovery-create.html'),
+ controller: ClientRecoveryCreate
+});
diff --git a/client/client/src/recovery-create/recovery-create.spec.js b/client/client/src/recovery-create/recovery-create.spec.js
new file mode 100644
index 000000000..eede3a8f9
--- /dev/null
+++ b/client/client/src/recovery-create/recovery-create.spec.js
@@ -0,0 +1,39 @@
+import './recovery-create.js';
+
+describe('Client', () => {
+ describe('Component vnClientRecoveryCreate', () => {
+ let $componentController;
+ let $scope;
+ let $state;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $state = _$state_;
+ $scope.watcher = {
+ submit: () => {
+ return {
+ then: callback => {
+ callback();
+ }
+ };
+ }
+ };
+ controller = $componentController('vnClientRecoveryCreate', {$scope: $scope});
+ }));
+
+ describe('onSubmit()', () => {
+ it('should call the function go() on $state to go to the recovery list', () => {
+ spyOn($state, 'go');
+ controller.onSubmit();
+
+ expect(controller.$state.go).toHaveBeenCalledWith('clientCard.recovery.list');
+ });
+ });
+ });
+});
diff --git a/client/client/src/recovery-list/locale/es.yml b/client/client/src/recovery-list/locale/es.yml
new file mode 100644
index 000000000..3ad385a5c
--- /dev/null
+++ b/client/client/src/recovery-list/locale/es.yml
@@ -0,0 +1,6 @@
+Since: Desde
+Employee: Empleado
+No results: Sin resultados
+To: Hasta
+Recovery: Recobros
+Finish that recovery period: Terminar el recobro
\ No newline at end of file
diff --git a/client/client/src/recovery-list/recovery-list.html b/client/client/src/recovery-list/recovery-list.html
new file mode 100644
index 000000000..b8d083e99
--- /dev/null
+++ b/client/client/src/recovery-list/recovery-list.html
@@ -0,0 +1,37 @@
+
+
+
+
+ Recovery
+
+
+
+
+
+
+
+
+
+ lock
+
+ {{recovery.started | date:'dd/MM/yyyy' }}
+ {{recovery.finished | date:'dd/MM/yyyy' }}
+ {{recovery.amount | currency:'€':0}}
+ {{recovery.period}}
+
+
+ No results
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/client/src/recovery-list/recovery-list.js b/client/client/src/recovery-list/recovery-list.js
new file mode 100644
index 000000000..5996f2d50
--- /dev/null
+++ b/client/client/src/recovery-list/recovery-list.js
@@ -0,0 +1,24 @@
+import ngModule from '../module';
+import FilterClientList from '../filter-client-list';
+
+class ClientRecoveryList extends FilterClientList {
+ constructor($scope, $timeout, $state, $http) {
+ super($scope, $timeout, $state);
+ this.$http = $http;
+ }
+ setFinished(recovery) {
+ if (!recovery.finished) {
+ let params = {finished: Date.now()};
+ this.$http.patch(`/client/api/Recoveries/${recovery.id}`, params).then(
+ () => this.$.index.accept()
+ );
+ }
+ }
+}
+
+ClientRecoveryList.$inject = ['$scope', '$timeout', '$state', '$http'];
+
+ngModule.component('vnClientRecoveryList', {
+ template: require('./recovery-list.html'),
+ controller: ClientRecoveryList
+});
diff --git a/client/client/src/search-panel/index.html b/client/client/src/search-panel/index.html
deleted file mode 100644
index 60385efc5..000000000
--- a/client/client/src/search-panel/index.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
diff --git a/client/client/src/search-panel/index.js b/client/client/src/search-panel/index.js
deleted file mode 100644
index bf8af3c03..000000000
--- a/client/client/src/search-panel/index.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import {module} from '../module';
-
-export const NAME = 'vnClientSearchPanel';
-export const COMPONENT = {
- template: require('./index.html'),
- controller: function($scope, $window) {
- this.filter = {id: null, fi: null, name: null, socialName: null, city: null, postcode: null, email: null, phone: null};
- this.formVisibility = true;
- this.onSearch = () => {
- this.setStorageValue();
- this.onSubmit(this.filter);
- };
- this.getKeyPressed = function(event) {
- if (event.which === 27)
- this.formVisibility = false;
- };
- this.$onChanges = () => {
- var value = JSON.parse($window.sessionStorage.getItem('filter'));
- if (value !== undefined)
- this.filter = value;
- };
- this.setStorageValue = () => {
- $window.sessionStorage.setItem('filter', JSON.stringify(this.filter));
- };
- }
-};
-
-module.component(NAME, COMPONENT);
diff --git a/client/client/src/search-panel/locale/es.yml b/client/client/src/search-panel/locale/es.yml
new file mode 100644
index 000000000..590d0e6d8
--- /dev/null
+++ b/client/client/src/search-panel/locale/es.yml
@@ -0,0 +1,8 @@
+Client id: Id cliente
+Tax number: NIF/CIF
+Name: Nombre
+Social name: Razon social
+Town/City: Ciudad
+Postcode: Código postal
+Email: Correo electrónico
+Phone: Teléfono
\ No newline at end of file
diff --git a/client/client/src/search-panel/search-panel.html b/client/client/src/search-panel/search-panel.html
new file mode 100644
index 000000000..2cb6a5aeb
--- /dev/null
+++ b/client/client/src/search-panel/search-panel.html
@@ -0,0 +1,25 @@
+
+
+
diff --git a/client/client/src/search-panel/search-panel.js b/client/client/src/search-panel/search-panel.js
new file mode 100644
index 000000000..74c4647ba
--- /dev/null
+++ b/client/client/src/search-panel/search-panel.js
@@ -0,0 +1,18 @@
+import ngModule from '../module';
+
+export default class Controller {
+ constructor() {
+ // onSubmit() is defined by @vnSearchbar
+ this.onSubmit = () => {};
+ }
+
+ onSearch() {
+ this.onSubmit(this.filter);
+ }
+}
+Controller.$inject = [];
+
+ngModule.component('vnClientSearchPanel', {
+ template: require('./search-panel.html'),
+ controller: Controller
+});
diff --git a/client/client/src/summary/client-summary.html b/client/client/src/summary/client-summary.html
new file mode 100644
index 000000000..e506ae23e
--- /dev/null
+++ b/client/client/src/summary/client-summary.html
@@ -0,0 +1,155 @@
+
+
+
+
+ {{$ctrl.summary.name}} - {{$ctrl.summary.id}} - {{$ctrl.summary.salesPerson.name}}
+
+
+
+ Basic data
+ Comercial Name {{$ctrl.summary.name}}
+ Contact {{$ctrl.summary.contact}}
+ Phone {{$ctrl.summary.phone}}
+ Mobile {{$ctrl.summary.mobile}}
+ Email {{$ctrl.summary.email}}
+ Salesperson {{$ctrl.summary.salesPerson.name}}
+ Channel {{$ctrl.summary.contactChannel.name}}
+
+
+ Fiscal data
+ Social name {{$ctrl.summary.socialName}}
+ NIF / CIF {{$ctrl.summary.fi}}
+ Street {{$ctrl.summary.street}}
+ City {{$ctrl.summary.city}}
+ Postcode {{$ctrl.summary.postcode}}
+ Province {{$ctrl.summary.province.name}}
+ Country {{$ctrl.summary.country.country}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Pay method
+ Pay method {{$ctrl.summary.payMethod.name}}
+ IBAN {{$ctrl.summary.iban}}
+ Due day {{$ctrl.summary.dueDay}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default address
+ {{$ctrl.address.nickname}}
+ {{$ctrl.address.street}}
+ {{$ctrl.address.city}}
+
+
+ Web access
+ User {{$ctrl.summary.account.name}}
+
+
+
+
+
+
+ Recovery
+
+ Since {{$ctrl.recovery.started}}
+ To {{$ctrl.recovery.finished}}
+ Amount {{$ctrl.recovery.amount | currency:'€':2}}
+ Period {{$ctrl.recovery.period}}
+
+
+
+
+
+
+ Total greuge
+ Total {{$ctrl.greuge.sumAmount | currency:'€':2}}
+
+
+
+ Credit
+
+ Credit
+ {{$ctrl.summary.credit | currency:'€':2}}
+
+
+ Secured credit
+ -
+ {{$ctrl.summary.creditInsurance | currency:'€':2}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/client/src/summary/client-summary.js b/client/client/src/summary/client-summary.js
new file mode 100644
index 000000000..a3e7c7bae
--- /dev/null
+++ b/client/client/src/summary/client-summary.js
@@ -0,0 +1,100 @@
+import ngModule from '../module';
+
+class ClientSummary {
+
+ constructor($http) {
+ this.$http = $http;
+ }
+
+ set client(value) {
+ if (!value)
+ return;
+
+ let filter = {
+ include: [
+ {
+ relation: 'account',
+ scope: {
+ fields: ['name', 'active']
+ }
+ },
+ {
+ relation: 'salesPerson',
+ scope: {
+ fields: ['name']
+ }
+ },
+ {
+ relation: 'country',
+ scope: {
+ fields: ['country']
+ }
+ },
+ {
+ relation: 'province',
+ scope: {
+ fields: ['name']
+ }
+ },
+ {
+ relation: 'contactChannel',
+ scope: {
+ fields: ['name']
+ }
+ },
+ {
+ relation: 'payMethod',
+ scope: {
+ fields: ['name']
+ }
+ },
+ {
+ relation: 'addresses',
+ scope: {
+ where: {isDefaultAddress: true},
+ fields: ['nickname', 'street', 'city', 'postalCode']
+ }
+ }
+ ]
+ };
+
+ let clientSummary = `/client/api/Clients/${value.id}?filter=${JSON.stringify(filter)}`;
+
+ this.$http.get(encodeURIComponent(clientSummary)).then(res => {
+ if (res.data) {
+ this.summary = res.data;
+ this.address = res.data.addresses[0];
+ }
+ });
+
+ let greugeSum = `/client/api/Greuges/${value.id}/sumAmount`;
+
+ this.$http.get(encodeURIComponent(greugeSum)).then(res => {
+ if (res.data)
+ this.greuge = res.data;
+ });
+
+ let recoveryFilter = {
+ where: {
+ and: [{clientFk: value.id}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}]
+ },
+ limit: 1
+ };
+
+ let recovery = `/client/api/Recoveries?filter=${JSON.stringify(recoveryFilter)}`;
+
+ this.$http.get(encodeURIComponent(recovery)).then(res => {
+ if (res.data)
+ this.recovery = res.data[0];
+ });
+ }
+}
+ClientSummary.$inject = ['$http'];
+
+ngModule.component('vnClientSummary', {
+ template: require('./client-summary.html'),
+ controller: ClientSummary,
+ bindings: {
+ client: '<'
+ }
+});
diff --git a/client/client/src/summary/locale/es.yml b/client/client/src/summary/locale/es.yml
new file mode 100644
index 000000000..27ebf6e37
--- /dev/null
+++ b/client/client/src/summary/locale/es.yml
@@ -0,0 +1,2 @@
+Default address: Consignatario pred.
+Total greuge: Greuge total
\ No newline at end of file
diff --git a/client/client/src/web-access/index.html b/client/client/src/web-access/index.html
deleted file mode 100644
index 50cf431cd..000000000
--- a/client/client/src/web-access/index.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/client/client/src/web-access/index.js b/client/client/src/web-access/index.js
deleted file mode 100644
index d7f444af4..000000000
--- a/client/client/src/web-access/index.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import {module} from '../module';
-
-class Controller {
- constructor($scope, $http, vnAppLogger) {
- this.$scope = $scope;
- this.$http = $http;
- this.vnAppLogger = vnAppLogger;
- }
- $onChanges() {
- if(this.client)
- this.account = this.client.account;
- }
- onPassOpen() {
- this.newPassword = '';
- this.repeatPassword = '';
- this.$scope.$apply();
- }
- onPassChange(response) {
- if(response == 'ACCEPT')
- try {
- if(!this.newPassword)
- throw new Error(`Passwords can't be empty`);
- if(this.newPassword != this.repeatPassword)
- throw new Error(`Passwords don't match`);
-
- let account = {
- password: this.newPassword
- };
-
- this.$http.put(`/client/api/Accounts/${this.client.id}`, account);
- }
- catch(e) {
- this.vnAppLogger.showError(e.message);
- return false;
- }
-
- return true;
- }
-}
-Controller.$inject = ['$scope', '$http', 'vnAppLogger'];
-
-module.component('vnClientWebAccess', {
- template: require('./index.html'),
- bindings: {
- client: '<'
- },
- controller: Controller
-});
diff --git a/client/client/src/web-access/locale/es.json b/client/client/src/web-access/locale/es.json
deleted file mode 100644
index 9ca721958..000000000
--- a/client/client/src/web-access/locale/es.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "Web access": "Acceso web",
- "New password": "Nueva contraseña",
- "Repeat password": "Repetir contraseña",
- "Change password": "Cambiar contraseña"
-}
\ No newline at end of file
diff --git a/client/client/src/web-access/locale/es.yml b/client/client/src/web-access/locale/es.yml
new file mode 100644
index 000000000..2d1905c16
--- /dev/null
+++ b/client/client/src/web-access/locale/es.yml
@@ -0,0 +1,5 @@
+User: Usuario
+Enable web access: Habilitar acceso web
+New password: Nueva contraseña
+Repeat password: Repetir contraseña
+Change password: Cambiar contraseña
\ No newline at end of file
diff --git a/client/client/src/web-access/web-access.html b/client/client/src/web-access/web-access.html
new file mode 100644
index 000000000..47e05759a
--- /dev/null
+++ b/client/client/src/web-access/web-access.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/client/src/web-access/web-access.js b/client/client/src/web-access/web-access.js
new file mode 100644
index 000000000..5545b96f8
--- /dev/null
+++ b/client/client/src/web-access/web-access.js
@@ -0,0 +1,70 @@
+import ngModule from '../module';
+
+export default class Controller {
+ constructor($scope, $http, vnApp) {
+ this.$ = $scope;
+ this.$http = $http;
+ this.vnApp = vnApp;
+ this.canChangePassword = false;
+ this.canEnableCheckBox = true;
+ }
+
+ $onChanges() {
+ if (this.client) {
+ this.account = this.client.account;
+ this.isCustomer();
+ this.checkConditions();
+ }
+ }
+
+ isCustomer() {
+ if (this.client.id) {
+ this.$http.get(`/client/api/Clients/${this.client.id}/hasCustomerRole`).then(res => {
+ this.canChangePassword = res.data && res.data.isCustomer;
+ });
+ }
+ }
+
+ checkConditions() {
+ if (this.client.id) {
+ this.$http.get(`/client/api/Clients/${this.client.id}/isValidClient`).then(res => {
+ this.canEnableCheckBox = res.data;
+ });
+ }
+ }
+
+ onPassOpen() {
+ this.newPassword = '';
+ this.repeatPassword = '';
+ this.$.$apply();
+ }
+
+ onPassChange(response) {
+ if (response == 'ACCEPT')
+ try {
+ if (!this.newPassword)
+ throw new Error(`Passwords can't be empty`);
+ if (this.newPassword != this.repeatPassword)
+ throw new Error(`Passwords don't match`);
+ let account = {
+ password: this.newPassword
+ };
+
+ this.$http.patch(`/client/api/Accounts/${this.client.id}`, account);
+ } catch (e) {
+ this.vnApp.showError(e.message);
+ return false;
+ }
+
+ return true;
+ }
+}
+Controller.$inject = ['$scope', '$http', 'vnApp'];
+
+ngModule.component('vnClientWebAccess', {
+ template: require('./web-access.html'),
+ controller: Controller,
+ bindings: {
+ client: '<'
+ }
+});
diff --git a/client/client/src/web-access/web-access.spec.js b/client/client/src/web-access/web-access.spec.js
new file mode 100644
index 000000000..a700f4c8b
--- /dev/null
+++ b/client/client/src/web-access/web-access.spec.js
@@ -0,0 +1,93 @@
+import './web-access.js';
+
+describe('Component VnClientWebAccess', () => {
+ let $componentController;
+ let $httpBackend;
+ let $scope;
+ let vnApp;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _vnApp_) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $httpBackend = _$httpBackend_;
+ $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ vnApp = _vnApp_;
+ spyOn(vnApp, 'showError');
+ controller = $componentController('vnClientWebAccess', {$scope: $scope});
+ }));
+
+ describe('$onChanges()', () => {
+ it(`should pass client's account data to account then call isCustomer function`, () => {
+ spyOn(controller, 'isCustomer');
+ controller.client = {client: 'Bruce Wayne', account: 'Wayne Industries'};
+ controller.account = {};
+ controller.$onChanges();
+
+ expect(controller.account).toBe('Wayne Industries');
+ expect(controller.isCustomer).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('isCustomer()', () => {
+ it(`should perform a query if client is defined with an ID`, () => {
+ controller.client = {id: '1234'};
+ controller.isCustomer();
+
+ $httpBackend.when('GET', `/client/api/Clients/${controller.client.id}/hasCustomerRole`).respond('ok');
+ $httpBackend.expectGET(`/client/api/Clients/${controller.client.id}/hasCustomerRole`);
+ $httpBackend.flush();
+ });
+ });
+
+ describe('onPassOpen()', () => {
+ it('should set passwords to empty values', () => {
+ controller.newPassword = 'm24x8';
+ controller.repeatPassword = 'm24x8';
+ controller.onPassOpen();
+
+ expect(controller.newPassword).toBe('');
+ expect(controller.repeatPassword).toBe('');
+ });
+ });
+
+ describe('onPassChange()', () => {
+ it('should request to update the password', () => {
+ controller.client = {id: '1234'};
+ controller.newPassword = 'm24x8';
+ controller.repeatPassword = 'm24x8';
+ controller.canChangePassword = true;
+ $httpBackend.when('PATCH', '/client/api/Accounts/1234').respond('done');
+ $httpBackend.expectPATCH('/client/api/Accounts/1234', {password: 'm24x8'});
+ controller.onPassChange('ACCEPT');
+ $httpBackend.flush();
+ });
+
+ describe(`when password is empty`, () => {
+ it(`should throw Passwords can't be empty error`, () => {
+ controller.client = {id: '1234'};
+ controller.newPassword = '';
+ controller.canChangePassword = true;
+ controller.onPassChange('ACCEPT');
+
+ expect(vnApp.showError).toHaveBeenCalledWith(`Passwords can't be empty`);
+ });
+ });
+
+ describe(`when passwords don't match`, () => {
+ it(`should throw Passwords don't match error`, () => {
+ controller.client = {id: '1234'};
+ controller.newPassword = 'm24x8';
+ controller.canChangePassword = true;
+ controller.repeatPassword = 'notMatchingPassword';
+ controller.onPassChange('ACCEPT');
+
+ expect(vnApp.showError).toHaveBeenCalledWith(`Passwords don't match`);
+ });
+ });
+ });
+});
diff --git a/client/core/package.json b/client/core/package.json
deleted file mode 100644
index 626726422..000000000
--- a/client/core/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "@salix/core",
- "version": "0.0.0",
- "description": "",
- "main": "index.js",
- "repository": {
- "type": "git",
- "url": "http://git.verdnatura.es:/salix"
- }
-}
diff --git a/client/core/src/autocomplete/index.html b/client/core/src/autocomplete/index.html
deleted file mode 100644
index 4d25b25c1..000000000
--- a/client/core/src/autocomplete/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
diff --git a/client/core/src/autocomplete/index.js b/client/core/src/autocomplete/index.js
deleted file mode 100644
index 9cb309650..000000000
--- a/client/core/src/autocomplete/index.js
+++ /dev/null
@@ -1,356 +0,0 @@
-import {module} from '../module';
-import Component from '../lib/component';
-import './style.scss';
-
-/**
- * Combobox like component with search and partial data loading features.
- */
-export default class Autocomplete extends Component {
- constructor($element, $scope, $http, vnPopover) {
- super($element);
- this.input = $element[0].querySelector('input');
- this.item = null;
- this.data = null;
- this.popover = null;
- this.popoverData = null;
- this.timeoutId = null;
- this.lastSearch = null;
- this.lastRequest = null;
- this.currentRequest = null;
- this.moreData = false;
- this.activeOption = -1;
- this.maxRows = 10;
- this.requestDelay = 350;
- this.locked = false;
- this.$http = $http;
- this.$scope = $scope;
- this.vnPopover = vnPopover;
-
- componentHandler.upgradeElement($element[0].firstChild);
- this.requestItem();
- }
- set field(value) {
- this.locked = true;
- this.setValue(value);
- this.locked = false;
- }
- get field() {
- return this.value;
- }
- mdlUpdate() {
- let mdlField = this.element.firstChild.MaterialTextfield;
- if (mdlField)
- mdlField.updateClasses_();
- }
- loadData(textFilter) {
- textFilter = textFilter ? textFilter : '';
-
- if (this.lastSearch === textFilter) {
- this.popoverDataReady();
- return;
- }
-
- this.lastSearch = textFilter;
-
- let lastRequest = this.lastRequest;
- let requestWillSame = lastRequest !== null
- && !this.moreData
- && textFilter.substr(0, lastRequest.length) === lastRequest;
-
- if (requestWillSame)
- this.localFilter(textFilter);
- else
- this.requestData(textFilter, false);
- }
- getRequestFields() {
- let fields = {};
- fields[this.valueField] = true;
- fields[this.showField] = true;
- return fields;
- }
- requestData(textFilter, append) {
- let where = {};
- let skip = 0;
-
- if (textFilter)
- where[this.showField] = {regexp: textFilter};
- if (append && this.data)
- skip = this.data.length;
-
- let filter = {
- fields: this.getRequestFields(),
- where: where,
- order: `${this.showField} ASC`,
- skip: skip,
- limit: this.maxRows
- };
-
- this.lastRequest = textFilter ? textFilter : '';
- let json = JSON.stringify(filter);
-
- if (this.currentRequest)
- this.currentRequest.resolve();
-
- this.currentRequest = this.$http.get(`${this.url}?filter=${json}`);
- this.currentRequest.then(
- json => this.onRequest(json.data, append),
- json => this.onRequest([])
- );
- }
- onRequest(data, append) {
- this.currentRequest = null;
- this.moreData = data.length >= this.maxRows;
-
- if (!append || !this.data)
- this.data = data;
- else
- this.data = this.data.concat(data);
-
- this.setPopoverData(this.data);
- }
- localFilter(textFilter) {
- let regex = new RegExp(textFilter, 'i');
- let data = this.data.filter(item => {
- return regex.test(item[this.showField]);
- });
- this.setPopoverData(data);
- }
- setPopoverData(data) {
- this.popoverData = data;
- this.popoverDataReady();
- }
- popoverDataReady() {
- if (this.hasFocus)
- this.showPopover();
- }
- showPopover() {
- if (!this.data) return;
-
- let fragment = this.document.createDocumentFragment();
- let data = this.popoverData;
-
- for (let i = 0; i < data.length; i++) {
- let li = this.document.createElement('li');
- li.appendChild(this.document.createTextNode(data[i][this.showField]));
- fragment.appendChild(li);
- }
-
- if (this.moreData) {
- let li = this.document.createElement('li');
- li.appendChild(this.document.createTextNode('Load more'));
- li.className = 'load-more';
- fragment.appendChild(li);
- }
-
- if (this.popover) {
- this.popover.innerHTML = '';
- this.popover.appendChild(fragment);
- } else {
- let popover = this.document.createElement('ul');
- popover.addEventListener('click',
- e => this.onPopoverClick(e));
- popover.addEventListener('mousedown',
- e => this.onPopoverMousedown(e));
- popover.className = 'vn-autocomplete';
- popover.appendChild(fragment);
- this.vnPopover.show(popover, this.input);
- this.popover = popover;
- }
- }
- hidePopover() {
- if (!this.popover) return;
- this.activeOption = -1;
- this.vnPopover.hide();
- this.popover = null;
- }
- selectPopoverOption(index) {
- if (!this.popover || index === -1) return;
- if (index < this.popoverData.length) {
- this.selectOptionByDataIndex(this.popoverData, index);
- this.hidePopover();
- } else
- this.requestData(this.lastRequest, true);
- }
- onPopoverClick(event) {
- let childs = this.popover.childNodes;
- for (let i = 0; i < childs.length; i++)
- if (childs[i] === event.target) {
- this.selectPopoverOption(i);
- break;
- }
- }
- onPopoverMousedown(event) {
- // Prevents input from loosing focus
- event.preventDefault();
- }
- onClick(event) {
- if (!this.popover)
- this.showPopover();
- }
- onFocus() {
- this.hasFocus = true;
- this.input.select();
-
- if (this.data)
- this.showPopover();
- else
- this.loadData();
- }
- onBlur() {
- this.hasFocus = false;
- this.restoreShowValue();
- this.hidePopover();
- }
- onKeydown(event) {
- switch (event.keyCode) {
- case 13: // Enter
- this.selectPopoverOption(this.activeOption);
- break;
- case 27: // Escape
- this.restoreShowValue();
- this.input.select();
- break;
- case 38: // Arrow up
- this.activateOption(this.activeOption - 1);
- break;
- case 40: // Arrow down
- this.activateOption(this.activeOption + 1);
- break;
- default:
- return;
- }
-
- event.preventDefault();
- }
- onKeyup(event) {
- if (!this.isKeycodePrintable(event.keyCode)) return;
- if (this.timeoutId) clearTimeout(this.timeoutId);
- this.timeoutId = setTimeout(() => this.onTimeout(), this.requestDelay);
- }
- onTimeout() {
- this.loadData(this.input.value);
- this.timeoutId = null;
- }
- isKeycodePrintable(keyCode) {
- return keyCode === 32 // Spacebar
- || keyCode === 8 // Backspace
- || (keyCode > 47 && keyCode < 58) // Numbers
- || (keyCode > 64 && keyCode < 91) // Letters
- || (keyCode > 95 && keyCode < 112) // Numpad
- || (keyCode > 185 && keyCode < 193) // ;=,-./`
- || (keyCode > 218 && keyCode < 223); // [\]'
- }
- restoreShowValue() {
- this.putItem(this.item);
- }
- requestItem() {
- if (!this.value) return;
-
- let where = {};
- where[this.valueField] = this.value;
-
- let filter = {
- fields: this.getRequestFields(),
- where: where
- };
-
- let json = JSON.stringify(filter);
-
- this.$http.get(`${this.url}?filter=${json}`).then(
- json => this.onItemRequest(json.data),
- json => this.onItemRequest(null)
- );
- }
- onItemRequest(data) {
- if (data && data.length > 0)
- this.showItem(data[0]);
- else
- this.showItem(null);
- }
- activateOption(index) {
- if (!this.popover)
- this.showPopover();
-
- let popover = this.popover;
- let childs = popover.childNodes;
- let len = this.popoverData.length;
-
- if (this.activeOption >= 0)
- childs[this.activeOption].className = '';
-
- if (index >= len)
- index = 0;
- else if (index < 0)
- index = len - 1;
-
- if (index >= 0) {
- let opt = childs[index];
- let top = popover.scrollTop;
- let height = popover.clientHeight;
-
- if (opt.offsetTop + opt.offsetHeight > top + height)
- top = opt.offsetTop + opt.offsetHeight - height;
- else if (opt.offsetTop < top)
- top = opt.offsetTop;
-
- opt.className = 'active';
- popover.scrollTop = top;
- }
-
- this.activeOption = index;
- }
- setValue(value) {
- this.value = value;
-
- if (value) {
- let data = this.data;
-
- if (data)
- for (let i = 0; i < data.length; i++)
- if (data[i][this.valueField] == value) {
- this.putItem(data[i]);
- return;
- }
-
- this.requestItem();
- } else
- this.putItem(null);
- }
- selectOptionByIndex(index) {
- this.selectOptionByDataIndex(this.data, index);
- }
- selectOptionByDataIndex(data, index) {
- if (data && index >= 0 && index < data.length)
- this.putItem(data[index]);
- else
- this.putItem(null);
- }
- putItem(item) {
- this.showItem(item);
- let value = item ? item[this.valueField] : undefined;
-
- if (!this.locked) {
- this.value = value;
- setTimeout(
- () => this.$scope.$apply());
- }
- }
- showItem(item) {
- this.input.value = item ? item[this.showField] : '';
- this.item = item;
- this.mdlUpdate();
- }
-}
-Autocomplete.$inject = ['$element', '$scope', '$http', 'vnPopover'];
-
-module.component('vnAutocomplete', {
- template: require('./index.html'),
- bindings: {
- url: '@',
- showField: '@',
- valueField: '@',
- field: '=',
- label: '@'
- },
- controller: Autocomplete
-});
diff --git a/client/core/src/autocomplete/style.scss b/client/core/src/autocomplete/style.scss
deleted file mode 100644
index 1ddff61ec..000000000
--- a/client/core/src/autocomplete/style.scss
+++ /dev/null
@@ -1,25 +0,0 @@
-ul.vn-autocomplete {
- list-style-type: none;
- padding: 1em;
- margin: 0;
- padding: 0;
- overflow: auto;
- max-height: 300px;
-
- li {
- display: block;
- padding: .8em;
- margin: 0;
- cursor: pointer;
-
- &.active,
- &:hover {
- background-color: rgba(1,1,1,.1);
- }
- &.load-more {
- color: #ffa410;
- font-weight: bold;
- padding: .4em .8em;
- }
- }
-}
\ No newline at end of file
diff --git a/client/core/src/button/button.js b/client/core/src/button/button.js
deleted file mode 100644
index 727633999..000000000
--- a/client/core/src/button/button.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as util from '../lib/util';
-
-const _NAME = 'button';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME];
-export function directive(resolve) {
- return {
- restrict: 'E',
- template: function(_, attr) {
- return resolve.getTemplate(_NAME, attr);
- }
- };
-}
-
-_module.directive(NAME, directive);
diff --git a/client/core/src/button/button.mdl.js b/client/core/src/button/button.mdl.js
deleted file mode 100644
index aa3989284..000000000
--- a/client/core/src/button/button.mdl.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import {module as _module} from '../module';
-import * as util from '../lib/util';
-import * as constant from '../lib/constants';
-import template from './button.mdl.html';
-
-const _NAME = 'button';
-export const NAME = util.getFactoryName(_NAME + constant.MATERIAL_DESIGN_FRAMEWORK);
-
-export function factory() {
- return {
- template: template,
- default: {
- label: 'Submit',
- className: 'mdl-button mdl-js-button mdl-button--raised mdl-button--colored',
- enabled: 'true',
- typeName: 'button'
- }
- }
-}
-
-_module.factory(NAME, factory);
diff --git a/client/core/src/card/card.js b/client/core/src/card/card.js
deleted file mode 100644
index 50aad3a2b..000000000
--- a/client/core/src/card/card.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as util from '../lib/util';
-require('./style.css');
-
-const _NAME = 'card';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME];
-export function directive(resolve) {
- return {
- restrict: 'E',
- transclude: true,
- template: function(_, attr) {
- return resolve.getTemplate(_NAME, attr);
- }
- };
-}
-
-_module.directive(NAME, directive);
-
diff --git a/client/core/src/card/card.mdl.html b/client/core/src/card/card.mdl.html
deleted file mode 100644
index f9edc7feb..000000000
--- a/client/core/src/card/card.mdl.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/client/core/src/card/card.mdl.js b/client/core/src/card/card.mdl.js
deleted file mode 100644
index a8e8954d6..000000000
--- a/client/core/src/card/card.mdl.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import {module as _module} from '../module';
-import * as util from '../lib/util';
-import * as constant from '../lib/constants';
-import template from './card.mdl.html';
-
-const _NAME = 'card';
-
-export const NAME = util.getFactoryName(_NAME + constant.MATERIAL_DESIGN_FRAMEWORK);
-
-export function factory() {
- return {
- template: template
- }
-}
-
-_module.factory(NAME, factory);
diff --git a/client/core/src/check/check.js b/client/core/src/check/check.js
deleted file mode 100644
index 5976a6625..000000000
--- a/client/core/src/check/check.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as normalizerFactory from '../lib/inputAttrsNormalizer';
-import * as util from '../lib/util';
-
-const _NAME = 'check';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME, normalizerFactory.NAME];
-export function directive(resolve, normalizer) {
- return {
- restrict: 'E',
- template: function(_, attrs) {
- normalizer.normalize(attrs);
- return resolve.getTemplate(_NAME, attrs);
- },
- link: function(scope, element, attrs) {
- scope.$watch(attrs.model, () => {
- let mdlField = element[0].firstChild.MaterialCheckbox;
- if (mdlField)
- mdlField.updateClasses_();
- });
- componentHandler.upgradeElement(element[0].firstChild);
- }
- };
-}
-
-_module.directive(NAME, directive);
diff --git a/client/core/src/check/check.mdl.html b/client/core/src/check/check.mdl.html
deleted file mode 100644
index 9e206cf8f..000000000
--- a/client/core/src/check/check.mdl.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/client/core/src/check/check.mdl.js b/client/core/src/check/check.mdl.js
deleted file mode 100644
index 757efaa08..000000000
--- a/client/core/src/check/check.mdl.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import {module as _module} from '../module';
-import * as util from '../lib/util';
-import * as constant from '../lib/constants';
-import template from './check.mdl.html';
-
-const _NAME = 'check';
-const DEFAULT_CLASS = 'mdl-checkbox__input';
-
-export const NAME = util.getFactoryName(_NAME + constant.MATERIAL_DESIGN_FRAMEWORK);
-
-export function factory() {
- return {
- template: template,
- default: {
- enabled: 'true',
- className: DEFAULT_CLASS
- }
- };
-}
-
-_module.factory(NAME, factory);
diff --git a/client/core/src/combo/combo.js b/client/core/src/combo/combo.js
deleted file mode 100644
index 12663ea2a..000000000
--- a/client/core/src/combo/combo.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as normalizerFactory from '../lib/inputAttrsNormalizer';
-import * as util from '../lib/util';
-
-const _NAME = 'combo';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME, normalizerFactory.NAME];
-export function directive(resolve, normalizer) {
- return {
- restrict: 'E',
- transclude: true,
- template: function(_, attrs) {
- normalizer.normalize(attrs);
- return resolve.getTemplate(_NAME, attrs);
- },
- link: function(scope, element, attrs) {
- scope.$watch(attrs.model, () => {
- let mdlField = element[0].firstChild.MaterialTextfield;
- if (mdlField)
- mdlField.updateClasses_();
- });
- componentHandler.upgradeElement(element[0].firstChild);
- }
- };
-}
-_module.directive(NAME, directive);
diff --git a/client/core/src/combo/combo.mdl.js b/client/core/src/combo/combo.mdl.js
deleted file mode 100644
index 86f7121d9..000000000
--- a/client/core/src/combo/combo.mdl.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import {module} from '../module';
-import template from './combo.mdl.html';
-
-export const NAME = 'vnComboMdlFactory';
-export function factory() {
- return {
- template: template,
- default: {
- label: 'Label',
- enabled: 'enabled'
- }
- }
-}
-module.factory(NAME, factory);
diff --git a/client/core/src/components.js b/client/core/src/components.js
deleted file mode 100644
index 7a258fd3b..000000000
--- a/client/core/src/components.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import './mdl-override.css';
-import './styles/fonts/mdi-override.css';
-
-import './textfield/index';
-import './watcher/index';
-import './paging/index';
-import './icon/index';
-import './autocomplete/index';
-import './popover/index';
-import './dialog/index';
-import './confirm/index';
-import './title/index';
-import './subtitle/index';
-import './spinner/index';
-
-export {NAME as BUTTON, directive as ButtonDirective} from './button/button';
-export {NAME as BUTTON_MDL, factory as buttonMdl} from './button/button.mdl';
-export {NAME as CHECK, directive as CheckDirective} from './check/check';
-export {NAME as CHECK_MDL, factory as checknMdl} from './check/check.mdl';
-export {NAME as RADIO, directive as RadioDirective} from './radio/radio';
-export {NAME as RADIO_MDL, factory as radionMdl} from './radio/radio.mdl';
-export {NAME as TEXTAREA, directive as TextareaDirective} from './textarea/textarea';
-export {NAME as TEXTAREA_MDL, factory as textareaMdl} from './textarea/textarea.mdl';
-export {NAME as LABEL, directive as LabelDirective} from './label/label';
-export {NAME as LABEL_MDL, factory as labelMdl} from './label/label.mdl';
-export {NAME as ICON_BUTTON, directive as IconButtonDirective} from './icon-button/icon-button';
-export {NAME as ICON_BUTTON_MDL, factory as iconButtonMdl} from './icon-button/icon-button.mdl';
-export {NAME as PASSWORD, directive as PasswordDirective} from './password/password';
-export {NAME as PASSWORD_MDL, factory as passwordMdl} from './password/password.mdl';
-export {NAME as SUBMIT, directive as SubmitDirective} from './submit/submit';
-export {NAME as SUBMIT_MDL, factory as submitMdl} from './submit/submit.mdl';
-export {NAME as SNACKBAR, directive as SnackbarDirective} from './snackbar/snackbar';
-export {NAME as SNACKBAR_MDL, factory as snackbarMdl} from './snackbar/snackbar.mdl';
-export {NAME as COMBO, directive as ComboDirective} from './combo/combo';
-export {NAME as COMBO_MDL, factory as comboMdl} from './combo/combo.mdl';
-export {NAME as DATE_PICKER, directive as DatePickerDirective} from './date-picker/date-picker';
-export {NAME as DATE_PICKER_MDL, factory as datePickerMdl} from './date-picker/date-picker.mdl';
-export {NAME as CARD, directive as CardDirective} from './card/card';
-export {NAME as CARD_MDL, factory as cardMdl} from './card/card.mdl';
-export {NAME as SWITCH, directive as SwitchDirective} from './switch/switch';
-export {NAME as SWITCH_MDL, factory as switchdMdl} from './switch/switch.mdl';
-export {NAME as FLOATBUTTON, directive as FloatButtonDirective} from './floatbutton/floatbutton';
-export {NAME as FLOATBUTTON_MDL, factory as floatButtondMdl} from './floatbutton/floatbutton.mdl';
diff --git a/client/core/src/components/autocomplete/autocomplete.html b/client/core/src/components/autocomplete/autocomplete.html
new file mode 100755
index 000000000..0ee10c5ae
--- /dev/null
+++ b/client/core/src/components/autocomplete/autocomplete.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/core/src/components/autocomplete/autocomplete.js b/client/core/src/components/autocomplete/autocomplete.js
new file mode 100755
index 000000000..5c216d21d
--- /dev/null
+++ b/client/core/src/components/autocomplete/autocomplete.js
@@ -0,0 +1,255 @@
+import ngModule from '../../module';
+import Component from '../../lib/component';
+import './style.scss';
+
+/**
+ * Input with option selector.
+ *
+ * @property {String} valueField The data field name that should be shown
+ * @property {String} showFiled The data field name that should be used as value
+ * @property {Array} data Static data for the autocomplete
+ * @property {Object} intialData A initial data to avoid the server request used to get the selection
+ * @property {Boolean} multiple Wether to allow multiple selection
+ */
+export default class Autocomplete extends Component {
+ constructor($element, $scope, $http, $transclude) {
+ super($element, $scope);
+ this.$http = $http;
+ this.$transclude = $transclude;
+
+ this._field = undefined;
+ this._selection = null;
+ this.valueField = 'id';
+ this.showField = 'name';
+ this._multiField = [];
+ this.readonly = true;
+ this.form = null;
+ this.input = this.element.querySelector('.mdl-textfield__input');
+
+ componentHandler.upgradeElement(
+ this.element.querySelector('.mdl-textfield'));
+ }
+
+ /**
+ * @type {any} The autocomplete value.
+ */
+ get field() {
+ return this._field;
+ }
+
+ set field(value) {
+ if (angular.equals(value, this._field))
+ return;
+
+ this._field = value;
+ this.refreshSelection();
+
+ if (this.onChange)
+ this.onChange(value);
+ }
+
+ /**
+ * @type {Object} The selected data object, you can use this property
+ * to prevent requests to display the initial value.
+ */
+ get selection() {
+ return this._selection;
+ }
+
+ set selection(value) {
+ this._selection = value;
+ this.refreshDisplayed();
+ }
+
+ selectionIsValid(selection) {
+ return selection
+ && selection[this.valueField] == this._field
+ && selection[this.showField] != null;
+ }
+
+ refreshSelection() {
+ if (this.selectionIsValid(this._selection))
+ return;
+
+ let value = this._field;
+
+ if (value && this.valueField && this.showField) {
+ if (this.selectionIsValid(this.initialData)) {
+ this.selection = this.initialData;
+ return;
+ }
+
+ let data = this.data;
+
+ if (!data && this.$.dropDown)
+ data = this.$.dropDown.$.model.data;
+
+ if (data)
+ for (let i = 0; i < data.length; i++)
+ if (data[i][this.valueField] === value) {
+ this.selection = data[i];
+ return;
+ }
+
+ if (this.url) {
+ this.requestSelection(value);
+ return;
+ }
+ } else
+ this.selection = null;
+ }
+
+ requestSelection(value) {
+ let where = {};
+
+ if (this.multiple)
+ where[this.valueField] = {inq: this.field};
+ else
+ where[this.valueField] = value;
+
+ let filter = {
+ fields: this.getFields(),
+ where: where
+ };
+
+ let json = encodeURIComponent(JSON.stringify(filter));
+ this.$http.get(`${this.url}?filter=${json}`).then(
+ json => this.onSelectionRequest(json.data),
+ () => this.onSelectionRequest(null)
+ );
+ }
+
+ onSelectionRequest(data) {
+ if (data && data.length > 0) {
+ if (this.multiple)
+ this.selection = data;
+ else
+ this.selection = data[0];
+ } else
+ this.selection = null;
+ }
+
+ refreshDisplayed() {
+ let display = '';
+
+ if (this._selection && this.showField) {
+ if (this.multiple && Array.isArray(this._selection)) {
+ for (var item of this._selection) {
+ if (display.length > 0) display += ', ';
+ display += item[this.showField];
+ }
+ } else {
+ display = this._selection[this.showField];
+ }
+ }
+
+ this.input.value = display;
+ this.mdlUpdate();
+ }
+
+ getFields() {
+ let fields = [];
+ fields.push(this.valueField);
+ fields.push(this.showField);
+
+ if (this.selectFields)
+ for (let field of this.selectFields)
+ fields.push(field);
+
+ return fields;
+ }
+
+ mdlUpdate() {
+ let field = this.element.querySelector('.mdl-textfield');
+ let mdlField = field.MaterialTextfield;
+ if (mdlField) mdlField.updateClasses_();
+ }
+
+ setValue(value) {
+ this.field = value;
+ if (this.form) this.form.$setDirty();
+ }
+
+ onDropDownSelect(value) {
+ this.setValue(value);
+ this.field = value;
+ }
+
+ onClearClick(event) {
+ event.preventDefault();
+ this.setValue(null);
+ }
+
+ onKeyDown(event) {
+ if (event.defaultPrevented) return;
+
+ switch (event.keyCode) {
+ case 38: // Up
+ case 40: // Down
+ case 13: // Enter
+ this.showDropDown();
+ break;
+ default:
+ if (event.key.length == 1)
+ this.showDropDown(event.key);
+ else
+ return;
+ }
+
+ event.preventDefault();
+ }
+
+ onMouseDown(event) {
+ event.preventDefault();
+ this.showDropDown();
+ }
+
+ showDropDown(search) {
+ Object.assign(this.$.dropDown.$.model, {
+ url: this.url,
+ staticData: this.data
+ });
+
+ Object.assign(this.$.dropDown, {
+ valueField: this.valueField,
+ showField: this.showField,
+ selectFields: this.getFields(),
+ where: this.where,
+ order: this.order,
+ parent: this.input,
+ multiple: this.multiple,
+ limit: this.limit,
+ $transclude: this.$transclude
+ });
+ this.$.dropDown.show(search);
+ }
+}
+Autocomplete.$inject = ['$element', '$scope', '$http', '$transclude'];
+
+ngModule.component('vnAutocomplete', {
+ template: require('./autocomplete.html'),
+ controller: Autocomplete,
+ bindings: {
+ url: '@?',
+ data: '',
+ showField: '@?',
+ valueField: '@?',
+ selectFields: '',
+ where: '@?',
+ order: '@?',
+ label: '@',
+ initialData: '',
+ field: '=?',
+ limit: '',
+ showFilter: '',
+ selection: '',
+ multiple: '',
+ onChange: '&?'
+ },
+ transclude: {
+ tplItem: '?tplItem'
+ },
+ require: {
+ form: '?^form'
+ }
+});
diff --git a/client/core/src/components/autocomplete/autocomplete.spec.js b/client/core/src/components/autocomplete/autocomplete.spec.js
new file mode 100644
index 000000000..602112b68
--- /dev/null
+++ b/client/core/src/components/autocomplete/autocomplete.spec.js
@@ -0,0 +1,74 @@
+import './autocomplete.js';
+import template from './autocomplete.html';
+
+describe('Component vnAutocomplete', () => {
+ let $element;
+ let $scope;
+ let $httpBackend;
+ let controller;
+
+ let data = {id: 1, name: 'Bruce Wayne'};
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => {
+ $scope = $rootScope.$new();
+ $element = angular.element(`
${template}
`);
+ $httpBackend = _$httpBackend_;
+ $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ controller = _$componentController_('vnAutocomplete', {$element, $scope, $httpBackend, $transclude: null});
+ }));
+
+ describe('field() setter/getter', () => {
+ it(`should set field controllers property`, () => {
+ controller.field = data.id;
+
+ expect(controller.field).toEqual(data.id);
+ });
+
+ it(`should set selection finding an existing item in the initialData property`, () => {
+ controller.valueField = 'id';
+ controller.showField = 'name';
+ controller.initialData = data;
+ controller.field = data.id;
+
+ expect(controller.selection).toEqual(data);
+ });
+
+ it(`should set selection finding an existing item in the data property`, () => {
+ controller.valueField = 'id';
+ controller.showField = 'name';
+ controller.data = [data];
+ controller.field = data.id;
+
+ expect(controller.selection).toEqual(data);
+ });
+
+ it(`should set selection to null when can't find an existing item in the data property`, () => {
+ controller.valueField = 'id';
+ controller.showField = 'name';
+ controller.field = data.id;
+
+ expect(controller.selection).toEqual(null);
+ });
+
+ it(`should perform a query if the item id isn't present in the data property`, () => {
+ controller.valueField = 'id';
+ controller.showField = 'name';
+ controller.url = 'localhost';
+ controller.field = data.id;
+
+ let filter = {
+ fields: ['id', 'name'],
+ where: {id: data.id}
+ };
+ let json = encodeURIComponent(JSON.stringify(filter));
+
+ $httpBackend.expectGET(`localhost?filter=${json}`);
+ controller.field = data.id;
+ $httpBackend.flush();
+ });
+ });
+});
diff --git a/client/core/src/components/autocomplete/style.scss b/client/core/src/components/autocomplete/style.scss
new file mode 100755
index 000000000..2dda27653
--- /dev/null
+++ b/client/core/src/components/autocomplete/style.scss
@@ -0,0 +1,62 @@
+
+vn-autocomplete > div > .mdl-textfield {
+ position: relative;
+ width: 100%;
+
+ & > input {
+ cursor: pointer;
+ height: 26px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+ & > .icons {
+ display: none;
+ position: absolute;
+ right: 0;
+ top: 1.3em;
+ height: 1em;
+ color: #888;
+ border-radius: .2em;
+ background-color: rgba(255, 255, 255, .8);
+
+ & > vn-icon {
+ cursor: pointer;
+ font-size: 18px;
+
+ &:hover {
+ color: #333;
+ }
+ }
+ }
+ &:hover > .icons,
+ & > input:focus + .icons {
+ display: block;
+ }
+}
+
+ul.vn-autocomplete {
+ list-style-type: none;
+ padding: 1em;
+ margin: 0;
+ padding: 0;
+ overflow: auto;
+ max-height: 300px;
+
+ li {
+ display: block;
+ padding: .8em;
+ margin: 0;
+ cursor: pointer;
+
+ &.active,
+ &:hover {
+ background-color: rgba(1, 1, 1, .1);
+ }
+ &.load-more {
+ color: #ffa410;
+ font-family: vn-font-bold;
+ padding: .4em .8em;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/core/src/button/button.mdl.html b/client/core/src/components/button/button.html
similarity index 100%
rename from client/core/src/button/button.mdl.html
rename to client/core/src/components/button/button.html
diff --git a/client/core/src/components/button/button.js b/client/core/src/components/button/button.js
new file mode 100644
index 000000000..6247bb77b
--- /dev/null
+++ b/client/core/src/components/button/button.js
@@ -0,0 +1,17 @@
+import ngModule from '../../module';
+import template from './button.html';
+
+directive.$inject = ['vnTemplate'];
+export default function directive(vnTemplate) {
+ return {
+ restrict: 'E',
+ template: (_, $attrs) =>
+ vnTemplate.get(template, $attrs, {
+ label: 'Submit',
+ className: 'mdl-button mdl-js-button mdl-button--raised mdl-button--colored',
+ enabled: 'true',
+ typeName: 'button'
+ })
+ };
+}
+ngModule.directive('vnButton', directive);
diff --git a/client/core/src/components/card/card.html b/client/core/src/components/card/card.html
new file mode 100644
index 000000000..e608d6fa9
--- /dev/null
+++ b/client/core/src/components/card/card.html
@@ -0,0 +1 @@
+
diff --git a/client/core/src/components/card/card.js b/client/core/src/components/card/card.js
new file mode 100644
index 000000000..12df8da7d
--- /dev/null
+++ b/client/core/src/components/card/card.js
@@ -0,0 +1,15 @@
+import ngModule from '../../module';
+require('./style.scss');
+
+directive.$inject = ['vnTemplate'];
+export default function directive(vnTemplate) {
+ return {
+ restrict: 'E',
+ transclude: true,
+ template: require('./card.html'),
+ link: function(_, $element) {
+ $element.addClass('demo-card-wide mdl-shadow--2dp bg-panel');
+ }
+ };
+}
+ngModule.directive('vnCard', directive);
diff --git a/client/core/src/card/style.css b/client/core/src/components/card/style.scss
similarity index 100%
rename from client/core/src/card/style.css
rename to client/core/src/components/card/style.scss
diff --git a/client/core/src/components/check/check.html b/client/core/src/components/check/check.html
new file mode 100644
index 000000000..b261a53a7
--- /dev/null
+++ b/client/core/src/components/check/check.html
@@ -0,0 +1,4 @@
+
diff --git a/client/core/src/components/check/check.js b/client/core/src/components/check/check.js
new file mode 100644
index 000000000..5b1a276d6
--- /dev/null
+++ b/client/core/src/components/check/check.js
@@ -0,0 +1,50 @@
+import ngModule from '../../module';
+import Input from '../../lib/input';
+import './style.scss';
+
+export default class Controller extends Input {
+ constructor($element, $scope) {
+ super($element, $scope);
+ componentHandler.upgradeElement(this.element.firstChild);
+ this.mdlElement = this.element.firstChild.MaterialCheckbox;
+ this.input.addEventListener('change', () => this.onChange());
+ }
+ set field(value) {
+ this.input.checked = value == true;
+ this.mdlUpdate();
+ }
+ get field() {
+ return this.input.checked == true;
+ }
+ $onInit() {
+ if (this.model) {
+ this.model.$render = () => {
+ this.input.checked = this.model.$viewValue || false;
+ this.mdlUpdate();
+ };
+ this.$element.on('blur keyup change', () => {
+ this.$.$evalAsync(() => {
+ this.model.$setViewValue(this.input.checked);
+ });
+ });
+ }
+ }
+ onChange() {
+ this.$.$applyAsync();
+ }
+}
+Controller.$inject = ['$element', '$scope', '$injector'];
+
+ngModule.component('vnCheck', {
+ template: require('./check.html'),
+ controller: Controller,
+ require: {
+ model: '?ngModel'
+ },
+ bindings: {
+ field: '=?',
+ label: '@?',
+ disabled: '',
+ rule: '@?'
+ }
+});
diff --git a/client/core/src/components/check/style.scss b/client/core/src/components/check/style.scss
new file mode 100644
index 000000000..1088ad05e
--- /dev/null
+++ b/client/core/src/components/check/style.scss
@@ -0,0 +1,3 @@
+vn-check {
+ float: left;
+}
\ No newline at end of file
diff --git a/client/core/src/components/column-header/column-header.html b/client/core/src/components/column-header/column-header.html
new file mode 100644
index 000000000..df0a4caee
--- /dev/null
+++ b/client/core/src/components/column-header/column-header.html
@@ -0,0 +1,23 @@
+
+
+
+ {{::$ctrl.text}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/core/src/components/column-header/column-header.js b/client/core/src/components/column-header/column-header.js
new file mode 100644
index 000000000..dc32e7e49
--- /dev/null
+++ b/client/core/src/components/column-header/column-header.js
@@ -0,0 +1,56 @@
+import ngModule from '../../module';
+
+export default class ColumnHeader {
+ constructor($attrs) {
+ this.order = undefined;
+ this.mouseIsOver = false;
+ this.orderLocked = ($attrs.orderLocked !== undefined);
+ }
+ onClick(event, order) {
+ if (!this.orderLocked) {
+ if (order) {
+ this.order = order;
+ } else if (this.order === 'ASC') {
+ this.order = 'DESC';
+ } else {
+ this.order = 'ASC';
+ }
+ this.gridHeader.selectColum(this);
+ }
+ if (event)
+ event.preventDefault();
+ }
+ showArrow(type) {
+ if (this.orderLocked)
+ return false;
+
+ let showArrow = (this.gridHeader && this.gridHeader.currentColumn && this.gridHeader.currentColumn.field === this.field && this.order === type);
+ let showOther = (this.gridHeader && this.gridHeader.currentColumn && this.gridHeader.currentColumn.field === this.field && this.order !== type);
+ if (type === 'DESC' && this.mouseIsOver && !showOther) {
+ showArrow = true;
+ }
+ return showArrow;
+ }
+ $onInit() {
+ if (this.defaultOrder && !this.orderLocked) {
+ this.order = this.defaultOrder;
+ this.onClick();
+ }
+ }
+}
+ColumnHeader.$inject = ['$attrs'];
+
+ngModule.component('vnColumnHeader', {
+ template: require('./column-header.html'),
+ bindings: {
+ field: '@?',
+ text: '@?',
+ className: '@?',
+ defaultOrder: '@?'
+ },
+ require: {
+ gridHeader: '^^vnGridHeader'
+ },
+ controller: ColumnHeader,
+ transclude: true
+});
diff --git a/client/core/src/components/column-header/column-header.spec.js b/client/core/src/components/column-header/column-header.spec.js
new file mode 100644
index 000000000..2291094b3
--- /dev/null
+++ b/client/core/src/components/column-header/column-header.spec.js
@@ -0,0 +1,94 @@
+import './column-header.js';
+
+describe('Component vnColumnHeader', () => {
+ let $componentController;
+ let controller;
+ let $event;
+ let $attrs;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject(_$componentController_ => {
+ $componentController = _$componentController_;
+ $event = {
+ preventDefault: () => {}
+ };
+ $attrs = {};
+ controller = $componentController('vnColumnHeader', {$attrs});
+ }));
+
+ describe('onClick()', () => {
+ it(`should change the ordenation to DESC (descendant) if it was ASC (ascendant)`, () => {
+ controller.gridHeader = {selectColum: () => {}};
+ controller.order = 'ASC';
+ controller.onClick($event);
+
+ expect(controller.order).toEqual('DESC');
+ });
+
+ it(`should change the ordenation to ASC (ascendant) if it wasnt ASC`, () => {
+ controller.gridHeader = {selectColum: () => {}};
+ controller.order = 'DESC or any other value that might occur';
+ controller.onClick($event);
+
+ expect(controller.order).toEqual('ASC');
+ });
+
+ it(`should call the selectColum() function after changing a value`, () => {
+ controller.gridHeader = {selectColum: () => {}};
+ controller.order = 'Change me!';
+ spyOn(controller.gridHeader, 'selectColum');
+ controller.onClick($event);
+
+ expect(controller.gridHeader.selectColum).toHaveBeenCalledWith(controller);
+ });
+ });
+
+ describe('showArrow()', () => {
+ it(`should return true when the type is DESC and MouseIsOver`, () => {
+ controller.gridHeader = {selectColum: () => {}};
+ controller.mouseIsOver = true;
+ let result = controller.showArrow('DESC');
+
+ expect(result).toEqual(true);
+ });
+
+ it(`should return true if many conditions are true`, () => {
+ controller.gridHeader = {currentColumn: {field: 'fields should be identical'}};
+ controller.field = 'fields should be identical';
+ controller.order = 'ASC';
+ let result = controller.showArrow('ASC');
+
+ expect(result).toEqual(true);
+ });
+
+ it(`should return false without type being DESC or any other values being true`, () => {
+ controller.gridHeader = {currentColumn: {field: 'fields should be identical'}};
+ controller.field = 'I am the controllers field';
+ controller.order = 'ASC';
+ let result = controller.showArrow('ASC');
+
+ expect(result).toEqual(false);
+ });
+ });
+
+ describe('onInit()', () => {
+ it(`should never call onClick()`, () => {
+ spyOn(controller, 'onClick');
+ controller.$onInit();
+
+ expect(controller.onClick).not.toHaveBeenCalledWith();
+ });
+
+ it(`should define controllers order as per defaultOrder then call onClick()`, () => {
+ controller.defaultOrder = 'ASC';
+ spyOn(controller, 'onClick');
+ controller.$onInit();
+
+ expect(controller.order).toEqual('ASC');
+ expect(controller.onClick).toHaveBeenCalledWith();
+ });
+ });
+});
diff --git a/client/core/src/combo/combo.mdl.html b/client/core/src/components/combo/combo.html
similarity index 53%
rename from client/core/src/combo/combo.mdl.html
rename to client/core/src/components/combo/combo.html
index 74f8c77ea..7b434fa62 100644
--- a/client/core/src/combo/combo.mdl.html
+++ b/client/core/src/components/combo/combo.html
@@ -1,5 +1,11 @@
-
diff --git a/client/core/src/components/combo/combo.js b/client/core/src/components/combo/combo.js
new file mode 100644
index 000000000..94c493379
--- /dev/null
+++ b/client/core/src/components/combo/combo.js
@@ -0,0 +1,25 @@
+import ngModule from '../../module';
+import template from './combo.html';
+
+directive.$inject = ['vnTemplate'];
+export function directive(vnTemplate) {
+ return {
+ restrict: 'E',
+ transclude: true,
+ template: (_, $attrs) =>
+ vnTemplate.getNormalized(template, $attrs, {
+ label: 'Label',
+ enabled: 'enabled',
+ class: 'mdl-textfield__input'
+ }),
+ link: function(scope, element, attrs) {
+ scope.$watch(attrs.model, () => {
+ let mdlField = element[0].firstChild.MaterialTextfield;
+ if (mdlField)
+ mdlField.updateClasses_();
+ });
+ componentHandler.upgradeElement(element[0].firstChild);
+ }
+ };
+}
+ngModule.directive('vnCombo', directive);
diff --git a/client/core/src/components/confirm/confirm.html b/client/core/src/components/confirm/confirm.html
new file mode 100644
index 000000000..3cdbb4a34
--- /dev/null
+++ b/client/core/src/components/confirm/confirm.html
@@ -0,0 +1,10 @@
+
+
+ {{::$ctrl.question}}
+ {{::$ctrl.message}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/core/src/components/confirm/confirm.js b/client/core/src/components/confirm/confirm.js
new file mode 100644
index 000000000..1431cf28a
--- /dev/null
+++ b/client/core/src/components/confirm/confirm.js
@@ -0,0 +1,24 @@
+import ngModule from '../../module';
+import Dialog from '../dialog/dialog';
+import template from './confirm.html';
+
+export default class Confirm extends Dialog {
+ constructor($element, $scope, $compile) {
+ super($element);
+ let cTemplate = $compile(template)($scope)[0];
+ this.body = cTemplate.querySelector('tpl-body');
+ this.buttons = cTemplate.querySelector('tpl-buttons');
+ }
+}
+Confirm.$inject = ['$element', '$scope', '$compile'];
+
+ngModule.component('vnConfirm', {
+ template: require('../dialog/dialog.html'),
+ bindings: {
+ onOpen: '&?',
+ onResponse: '&',
+ question: '@',
+ message: '@?'
+ },
+ controller: Confirm
+});
diff --git a/client/core/src/components/date-picker/date-picker.html b/client/core/src/components/date-picker/date-picker.html
new file mode 100644
index 000000000..299d9df4b
--- /dev/null
+++ b/client/core/src/components/date-picker/date-picker.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+ query_builder
+
+
+ clear
+
+
+
+
\ No newline at end of file
diff --git a/client/core/src/components/date-picker/date-picker.js b/client/core/src/components/date-picker/date-picker.js
new file mode 100644
index 000000000..db5e59d6f
--- /dev/null
+++ b/client/core/src/components/date-picker/date-picker.js
@@ -0,0 +1,252 @@
+import ngModule from '../../module';
+import Component from '../../lib/component';
+import Flatpickr from 'vendor/src/flatpickr';
+import './style.scss';
+
+// equivalences to format date between flatpicker and angularjs
+export const formatEquivalence = {
+ d: 'dd', // Day of the month, 2 digits with leading zeros (01 to 31)
+ j: 'd', // Day of the month without leading zeros (1 to 31)
+ m: 'MM', // Month in year, padded (01-12)
+ n: 'M', // Month in year (1-12)
+ y: 'yy', // A two digit representation of a year (00-99)
+ Y: 'yyyy', // A full numeric representation of a year, 4 digits (1999 or 2003)
+ H: 'HH', // Hour in AM/PM, padded (01-12)
+ h: 'H', // Hour in AM/PM, (1-12)
+ i: 'mm', // Minutes (00 to 59)
+ s: 'ss' // Seconds (00 to 59)
+};
+
+class DatePicker extends Component {
+ constructor($element, $translate, $filter, $timeout, $attrs) {
+ super($element);
+ this.input = $element[0].querySelector('input');
+ this.$translate = $translate;
+ this.$filter = $filter;
+ this.$timeout = $timeout;
+ this.$attrs = $attrs;
+
+ this.enabled = true;
+ this._modelView = null;
+ this._model = undefined;
+ this._optionsChecked = false;
+ this._waitingInit = 0;
+ this.hasFocus = false;
+ this.hasMouseIn = false;
+ componentHandler.upgradeElement($element[0].firstChild);
+ }
+
+ get model() {
+ return this._model;
+ }
+ set model(value) {
+ if (this._optionsChecked) {
+ this._waitingInit = 0;
+ this._model = value;
+ if (value && !this.modelView) {
+ let options = this._getOptions();
+ let initialDateFormat;
+ if (options && options.dateFormat) {
+ initialDateFormat = options.dateFormat;
+ } else {
+ initialDateFormat = this.$translate.use() === 'es' ? 'd-m-Y' : 'Y-m-d';
+ if (options.enableTime) {
+ initialDateFormat += ' H:i:s';
+ }
+ }
+
+ let format = this._formatFlat2Angular(initialDateFormat);
+ this._modelView = this.$filter('date')(new Date(this._model), format);
+ this.mdlUpdate();
+ }
+ } else if (this._waitingInit < 4) {
+ this._waitingInit++;
+ this.$timeout(() => {
+ this.model = value;
+ }, 250);
+ } else {
+ this.model = null;
+ this.modelView = '';
+ this._waitingInit = 0;
+ }
+ }
+ get modelView() {
+ return this._modelView;
+ }
+ set modelView(value) {
+ this._modelView = value;
+ this.input.value = value;
+ this._setModel(value);
+ this.mdlUpdate();
+ }
+
+ onClear() {
+ this.modelView = null;
+ }
+ onClick() {
+ if (this.vp) {
+ this.vp.open();
+ }
+ }
+ mdlUpdate() {
+ this.$timeout(() => {
+ let mdlField = this.element.firstChild.MaterialTextfield;
+ if (mdlField)
+ mdlField.updateClasses_();
+ }, 500);
+ }
+
+ _formatFlat2Angular(string) { // change string Flatpickr format to angular format (d-m-Y -> dd-MM-yyyy)
+ let aux = string.split(/[ZT.,/ :-]/);
+ let parts = [];
+ aux.forEach(
+ val => {
+ parts.push(formatEquivalence[val]);
+ }
+ );
+ if (string.indexOf(' ') !== -1 || string.indexOf('T') !== -1) { // datetime format
+ let dates = parts.slice(0, 3).join('-');
+ let hours = parts.slice(3, parts.length).join(':');
+ return `${dates} ${hours}`.trim();
+ } else if (string.indexOf(':') !== -1) { // only time format
+ return parts.join(':');
+ } // only date format
+ return parts.join('-');
+ }
+
+ _string2BackFormat(value) {
+ let formats = this.iniOptions.dateFormat.split(/[ZT.,/ :-]/);
+ let aux = value.split(/[ZT.,/ :-]/);
+ let date = {};
+ formats.forEach(
+ (k, i) => {
+ if (k.toLowerCase() === 'y') {
+ date.year = aux[i];
+ } else if (k === 'm' || k === 'n') {
+ date.month = aux[i];
+ } else if (k === 'd' || k === 'j') {
+ date.day = aux[i];
+ } else if (k.toLowerCase() === 'h') {
+ date.hour = aux[i];
+ } else if (k === 'i') {
+ date.minutes = aux[i];
+ } else if (k === 's') {
+ date.seccons = aux[i];
+ }
+ }
+ );
+
+ let dateStr = '';
+ let hourStr = '';
+
+ if (date.year && date.month && date.day) {
+ dateStr = `${date.year}-${date.month}-${date.day}`;
+ }
+ if (date.hour) {
+ hourStr = date.hour;
+ if (date.minutes) {
+ hourStr += ':' + date.minutes;
+ } else {
+ hourStr += ':00';
+ }
+ if (date.seccons) {
+ hourStr += ':' + date.seccons;
+ } else {
+ hourStr += ':00';
+ }
+ }
+ return `${dateStr} ${hourStr}`.trim();
+ }
+
+ _setModel(value) {
+ let model;
+ let options = this._getOptions();
+ if (!value) {
+ model = undefined;
+ } else if (!options || (options.dateFormat && options.dateFormat.startsWith('Y-m-d'))) {
+ model = value;
+ } else {
+ model = this._string2BackFormat(value);
+ }
+
+ if (this.model !== model) {
+ this.model = model;
+ }
+ }
+
+ _getOptions() {
+ if (this.iniOptions && this._optionsChecked) {
+ return this.iniOptions;
+ } else if (!this.iniOptions) {
+ this.iniOptions = {};
+ }
+
+ if (!this.iniOptions.locale)
+ this.iniOptions.locale = this.$translate.use();
+
+ if (!this.iniOptions.dateFormat)
+ this.iniOptions.dateFormat = this.iniOptions.locale === 'es' ? 'd-m-Y' : 'Y-m-d';
+ else if (this.iniOptions.dateFormat) {
+ let format = this.iniOptions.dateFormat.split(/[ZT.,/ :-]/);
+ if (format.length <= 1) {
+ throw new Error(`Error: Invalid string format ${format}`);
+ }
+ format.forEach(
+ val => {
+ if (!formatEquivalence[val]) {
+ throw new Error(`Error in dateFormat ${this.iniOptions.dateFormat}: is not like Flatpickr Formatting Token https://chmln.github.io/flatpickr/formatting/`);
+ }
+ }
+ );
+ }
+
+ if (this.$attrs.hasOwnProperty('today')) {
+ this.iniOptions.defaultDate = new Date();
+ }
+
+ this._optionsChecked = true;
+ return this.iniOptions;
+ }
+
+ initPicker() {
+ this.iniOptions = this._getOptions();
+ this.isTimePicker = (this.iniOptions && this.iniOptions.enableTime && this.iniOptions.noCalendar);
+ this.vp = new Flatpickr(this.input, this.iniOptions);
+ if (this.iniOptions.defaultDate) {
+ this.modelView = this.vp.formatDate(this.iniOptions.defaultDate, this.iniOptions.dateFormat);
+ }
+ }
+ destroyPicker() {
+ if (this.vp)
+ this.vp.destroy();
+ this.vp = undefined;
+ }
+
+ $onChanges(objChange) {
+ if (objChange.iniOptions && objChange.iniOptions.currentValue) {
+ this.iniOptions = Object.assign(this.iniOptions, objChange.iniOptions.currentValue);
+ }
+ }
+
+ $onInit() {
+ this.initPicker();
+ }
+
+ $onDestroy() {
+ this.destroyPicker();
+ }
+}
+DatePicker.$inject = ['$element', '$translate', '$filter', '$timeout', '$attrs'];
+
+ngModule.component('vnDatePicker', {
+ template: require('./date-picker.html'),
+ bindings: {
+ model: '=',
+ label: '@?',
+ name: '@?',
+ enabled: '',
+ rule: '',
+ iniOptions: ''
+ },
+ controller: DatePicker
+});
diff --git a/client/core/src/components/date-picker/date-picker.spec.js b/client/core/src/components/date-picker/date-picker.spec.js
new file mode 100644
index 000000000..2be0c1eb4
--- /dev/null
+++ b/client/core/src/components/date-picker/date-picker.spec.js
@@ -0,0 +1,47 @@
+import './date-picker.js';
+
+describe('Component vnDatePicker', () => {
+ let $componentController;
+ let $filter;
+ let $timeout;
+ let $element;
+ let $attrs;
+ let $translate;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$filter_, _$timeout_, _$translate_) => {
+ $componentController = _$componentController_;
+ $filter = _$filter_;
+ $timeout = _$timeout_;
+ $element = angular.element(`
`);
+ $translate = _$translate_;
+ $attrs = {};
+ controller = $componentController('vnDatePicker', {$element, $translate, $filter, $timeout, $attrs});
+ }));
+
+ describe('_formatFlat2Angular()', () => {
+ it(`should format date from Y-m-d to yyyy-MM-dd`, () => {
+ let formatedDate = controller._formatFlat2Angular(`Y-m-d`);
+
+ expect(formatedDate).toBe('yyyy-MM-dd');
+ });
+
+ it(`should format date from d-m-Y to dd-MM-yyyy`, () => {
+ let formatedDate = controller._formatFlat2Angular(`d-m-Y`);
+
+ expect(formatedDate).toBe('dd-MM-yyyy');
+ });
+
+ it(`should split the given string into parts`, () => {
+ controller.iniOptions = {dateFormat: 'd/m/Y'};
+ controller._optionsChecked = true;
+ controller.model = '2017-12-23';
+
+ expect(controller.modelView).toBe('23-12-2017');
+ });
+ });
+});
diff --git a/client/core/src/components/date-picker/style.scss b/client/core/src/components/date-picker/style.scss
new file mode 100644
index 000000000..99f1cbc1b
--- /dev/null
+++ b/client/core/src/components/date-picker/style.scss
@@ -0,0 +1,15 @@
+vn-date-picker {
+ .mdl-chip__action {
+ position: absolute;
+ width: auto;
+ top: 0px;
+ right: -6px;
+ margin: 22px 0px;
+ background-color: white;
+ }
+ .material-icons {
+ font-size: 18px;
+ float: right;
+ margin-right: 5px;
+ }
+}
\ No newline at end of file
diff --git a/client/core/src/components/dialog/dialog.html b/client/core/src/components/dialog/dialog.html
new file mode 100644
index 000000000..1ce4eea58
--- /dev/null
+++ b/client/core/src/components/dialog/dialog.html
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/client/core/src/components/dialog/dialog.js b/client/core/src/components/dialog/dialog.js
new file mode 100644
index 000000000..401a13e11
--- /dev/null
+++ b/client/core/src/components/dialog/dialog.js
@@ -0,0 +1,120 @@
+import ngModule from '../../module';
+import Component from '../../lib/component';
+import './style.scss';
+
+/**
+ * Dialog component.
+ *
+ * @property {HTMLElement} body The dialog HTML body
+ * @property {HTMLElement} buttons The dialog HTML buttons
+ */
+export default class Dialog extends Component {
+ constructor($element, $transclude) {
+ super($element);
+ this.shown = false;
+ this.$element.addClass('vn-dialog');
+ this.element.addEventListener('mousedown',
+ e => this.onBackgroundMouseDown(e));
+
+ if ($transclude) {
+ $transclude(tClone => {
+ this.body = tClone[0];
+ }, null, 'body');
+ $transclude(tClone => {
+ this.buttons = tClone[0];
+ }, null, 'buttons');
+ }
+ }
+ set body(value) {
+ this.element.querySelector('.body').appendChild(value);
+ }
+ set buttons(value) {
+ this.element.querySelector('.buttons').appendChild(value);
+ }
+ /**
+ * Displays the dialog to the user.
+ */
+ show() {
+ if (this.shown) return;
+ this.shown = true;
+ this.keyDownHandler = e => this.onkeyDown(e);
+ this.document.addEventListener('keydown', this.keyDownHandler);
+ this.element.style.display = 'flex';
+ this.transitionTimeout = setTimeout(() => this.$element.addClass('shown'), 30);
+
+ if (this.onOpen)
+ this.onOpen();
+
+ let firstFocusable = this.element.querySelector('input, textarea');
+ if (firstFocusable) firstFocusable.focus();
+ }
+ /**
+ * Hides the dialog calling the response handler.
+ */
+ hide() {
+ this.fireResponse();
+ this.realHide();
+ }
+ /**
+ * Calls the response handler.
+ *
+ * @param {String} response The response code
+ * @return {Boolean} %true if response was canceled, %false otherwise
+ */
+ fireResponse(response) {
+ let cancel = false;
+ if (this.onResponse)
+ cancel = this.onResponse({response: response});
+ return cancel;
+ }
+ realHide() {
+ if (!this.shown) return;
+ this.element.style.display = 'none';
+ this.document.removeEventListener('keydown', this.keyDownHandler);
+ this.lastEvent = null;
+ this.shown = false;
+ this.transitionTimeout =
+ setTimeout(() => this.$element.removeClass('shown'), 30);
+ }
+ onButtonClick(event) {
+ let buttons = this.element.querySelector('.buttons');
+ let tplButtons = buttons.querySelector('tpl-buttons');
+ let node = event.target;
+ while (node.parentNode != tplButtons) {
+ if (node == buttons) return;
+ node = node.parentNode;
+ }
+
+ let response = node.getAttribute('response');
+ let cancel = this.fireResponse(response);
+ if (cancel !== false) this.realHide();
+ }
+ onDialogMouseDown(event) {
+ this.lastEvent = event;
+ }
+ onBackgroundMouseDown(event) {
+ if (event != this.lastEvent)
+ this.hide();
+ }
+ onkeyDown(event) {
+ if (event.keyCode == 27) // Esc
+ this.hide();
+ }
+ $onDestroy() {
+ clearTimeout(this.transitionTimeout);
+ }
+}
+Dialog.$inject = ['$element', '$transclude'];
+
+ngModule.component('vnDialog', {
+ template: require('./dialog.html'),
+ transclude: {
+ body: 'tplBody',
+ buttons: '?tplButtons'
+ },
+ bindings: {
+ onOpen: '&?',
+ onResponse: '&?'
+ },
+ controller: Dialog
+});
diff --git a/client/core/src/components/dialog/dialog.spec.js b/client/core/src/components/dialog/dialog.spec.js
new file mode 100644
index 000000000..8cb1ad4a9
--- /dev/null
+++ b/client/core/src/components/dialog/dialog.spec.js
@@ -0,0 +1,53 @@
+describe('Component vnDialog', () => {
+ let $componentController;
+ let $element;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject(_$componentController_ => {
+ $componentController = _$componentController_;
+ $element = angular.element('
');
+ controller = $componentController('vnDialog', {$element: $element, $transclude: null});
+ }));
+
+ describe('show()', () => {
+ it(`should handle escape keypress event, define element.style.display to not none and call onOpen function`, () => {
+ window.innerHeight = 600;
+ window.innerWidth = 800;
+ controller.dialog = {style: {display: 'none'}};
+ controller.onOpen = () => {};
+ spyOn(controller, 'onOpen');
+ controller.show();
+
+ expect(controller.element.style.display).not.toEqual('none');
+ expect(controller.onOpen).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('hide()', () => {
+ it(`should call onResponse()`, () => {
+ controller.onResponse = () => {};
+ spyOn(controller, 'onResponse');
+ controller.hide();
+
+ expect(controller.onResponse).toHaveBeenCalled();
+ });
+ });
+
+ describe('fireResponse()', () => {
+ it(`should call onResponse()`, () => {
+ let responseRes;
+ controller.onResponse = response => {
+ responseRes = response;
+ return false;
+ };
+ let responseRet = controller.fireResponse('answer');
+
+ expect(responseRes).toEqual({response: 'answer'});
+ expect(responseRet).toEqual(false);
+ });
+ });
+});
diff --git a/client/core/src/components/dialog/style.scss b/client/core/src/components/dialog/style.scss
new file mode 100644
index 000000000..de13f0f7c
--- /dev/null
+++ b/client/core/src/components/dialog/style.scss
@@ -0,0 +1,73 @@
+.vn-dialog {
+ display: none;
+ justify-content: center;
+ align-items: center;
+ z-index: 11;
+ position: fixed;
+ left: 0;
+ top: 0;
+ height: 100%;
+ width: 100%;
+ background-color: rgba(1, 1, 1, .6);
+ opacity: 0;
+ transition: opacity 300ms ease-in-out;
+
+ &.shown {
+ opacity: 1;
+ }
+ & > div {
+ position: relative;
+ box-shadow: 0 0 .4em rgba(1,1,1,.4);
+ background-color: white;
+ border-radius: .2em;
+ overflow: auto;
+ padding: 2em;
+ box-sizing: border-box;
+
+ tpl-body {
+ display: block;
+ width: 20em;
+ }
+ button,
+ input[type="button"],
+ input[type="submit"],
+ input[type="reset"] {
+ text-transform: uppercase;
+ background-color: transparent;
+ border: none;
+ cursor: pointer;
+ transition: background-color 250ms;
+ border-radius: .1em;
+
+ &:hover {
+ background-color: rgba(1,1,1,.1);
+ }
+ }
+ & > button.close {
+ position: absolute;
+ top: 0;
+ right: 0;
+ padding: .3em;
+
+ & > vn-icon {
+ display: block;
+ color: #666;
+ }
+ }
+ & > form > .buttons {
+ margin-top: 1.5em;
+ text-align: right;
+
+ button,
+ input[type="button"],
+ input[type="submit"],
+ input[type="reset"] {
+ color: #ffa410;
+ font-family: vn-font-bold;
+ padding: .7em;
+ margin: -0.7em;
+ margin-left: .7em;
+ }
+ }
+ }
+}
diff --git a/client/core/src/components/drop-down/drop-down.html b/client/core/src/components/drop-down/drop-down.html
new file mode 100755
index 000000000..560ef77fa
--- /dev/null
+++ b/client/core/src/components/drop-down/drop-down.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{$ctrl.statusText}}
+
+
+
+
diff --git a/client/core/src/components/drop-down/drop-down.js b/client/core/src/components/drop-down/drop-down.js
new file mode 100755
index 000000000..482297618
--- /dev/null
+++ b/client/core/src/components/drop-down/drop-down.js
@@ -0,0 +1,375 @@
+import ngModule from '../../module';
+import Component from '../../lib/component';
+import './style.scss';
+import './model';
+
+export default class DropDown extends Component {
+ constructor($element, $scope, $transclude, $timeout, $http) {
+ super($element, $scope);
+ this.$transclude = $transclude;
+ this.$timeout = $timeout;
+
+ this.valueField = 'id';
+ this.showField = 'name';
+ this._search = undefined;
+ this._activeOption = -1;
+ this.showLoadMore = true;
+ this.showFilter = true;
+
+ this.docKeyDownHandler = e => this.onDocKeyDown(e);
+ }
+
+ $postLink() {
+ this.input = this.element.querySelector('.search');
+ this.ul = this.element.querySelector('ul');
+ this.list = this.element.querySelector('.list');
+ this.list.addEventListener('scroll', e => this.onScroll(e));
+ }
+
+ get shown() {
+ return this.$.popover.shown;
+ }
+
+ set shown(value) {
+ this.$.popover.shown = value;
+ }
+
+ get search() {
+ return this._search;
+ }
+
+ set search(value) {
+ value = value == '' || value == null ? null : value;
+ if (value === this._search) return;
+
+ this._search = value;
+ this.$.model.clear();
+
+ this.$timeout.cancel(this.searchTimeout);
+ this.searchTimeout = this.$timeout(() => {
+ this.refreshModel();
+ this.searchTimeout = null;
+ }, 350);
+
+ this.buildList();
+ }
+
+ get statusText() {
+ let model = this.$.model;
+ let data = model.data;
+ let statusText = null;
+
+ if (model.isLoading || this.searchTimeout)
+ statusText = 'Loading...';
+ else if (data == null)
+ statusText = 'No data';
+ else if (model.moreRows)
+ statusText = 'Load More';
+ else if (data.length === 0)
+ statusText = 'No results found';
+
+ return statusText;
+ }
+
+ get model() {
+ return this.$.model;
+ }
+
+ get activeOption() {
+ return this._activeOption;
+ }
+
+ /**
+ * Shows the drop-down. If a parent is specified it is shown in a visible
+ * relative position to it.
+ *
+ * @param {String} search The initial search term or %null
+ */
+ show(search) {
+ this.search = search;
+ this._activeOption = -1;
+ this.buildList();
+ this.$.popover.parent = this.parent;
+ this.$.popover.show();
+ }
+
+ /**
+ * Hides the drop-down.
+ */
+ hide() {
+ this.$.popover.hide();
+ }
+
+ /**
+ * Activates a option and scrolls the drop-down to that option.
+ *
+ * @param {Number} option The option index
+ */
+ moveToOption(option) {
+ this.activateOption(option);
+
+ let list = this.list;
+ let li = this.activeLi;
+ if (!li) return;
+
+ let liRect = li.getBoundingClientRect();
+ let listRect = list.getBoundingClientRect();
+
+ if (liRect.bottom > listRect.bottom)
+ list.scrollTop += liRect.bottom - listRect.bottom;
+ else if (liRect.top < listRect.top)
+ list.scrollTop -= listRect.top - liRect.top;
+ }
+
+ /**
+ * Activates a option.
+ *
+ * @param {Number} option The option index
+ */
+ activateOption(option) {
+ this._activeOption = option;
+
+ if (this.activeLi)
+ this.activeLi.className = '';
+
+ let data = this.$.model.data;
+
+ if (option >= 0 && data && option < data.length) {
+ this.activeLi = this.ul.children[option];
+ this.activeLi.className = 'active';
+ }
+ }
+
+ /**
+ * Selects an option.
+ *
+ * @param {Number} option The option index
+ */
+ selectOption(option) {
+ if (option != -1) {
+ let data = this.$.model.data;
+ let item = data ? data[option] : null;
+ let value = item ? item[this.valueField] : null;
+
+ if (this.multiple) {
+ if (!Array.isArray(this.selection)) {
+ this.selection = [];
+ this.field = [];
+ }
+
+ this.selection.push(item);
+ this.field.push(value);
+ } else {
+ this.selection = item;
+ this.field = value;
+ }
+
+ if (this.onSelect)
+ this.onSelect({value: value});
+ }
+
+ if (!this.multiple)
+ this.$.popover.hide();
+ }
+
+ refreshModel() {
+ this.$.model.filter = {
+ fields: this.selectFields,
+ where: this.getWhere(this._search),
+ order: this.getOrder(),
+ limit: this.limit || 8
+ };
+ this.$.model.refresh(this._search);
+ }
+
+ getWhere(search) {
+ if (search == '' || search == null)
+ return undefined;
+
+ if (this.where) {
+ let jsonFilter = this.where.replace(/search/g, search);
+ return this.$.$eval(jsonFilter);
+ }
+
+ let where = {};
+ where[this.showField] = {regexp: search};
+ return where;
+ }
+
+ getOrder() {
+ if (this.order)
+ return this.order;
+ else if (this.showField)
+ return `${this.showField} ASC`;
+
+ return undefined;
+ }
+
+ onOpen() {
+ this.document.addEventListener('keydown', this.docKeyDownHandler);
+ this.list.scrollTop = 0;
+ this.input.focus();
+ }
+
+ onClose() {
+ this.document.removeEventListener('keydown', this.docKeyDownHandler);
+ }
+
+ onClearClick() {
+ this.search = null;
+ }
+
+ onScroll() {
+ let list = this.list;
+ let shouldLoad =
+ list.scrollTop + list.clientHeight >= (list.scrollHeight - 40)
+ && !this.$.model.isLoading;
+
+ if (shouldLoad)
+ this.$.model.loadMore();
+ }
+
+ onLoadMoreClick(event) {
+ event.preventDefault();
+ this.$.model.loadMore();
+ }
+
+ onContainerClick(event) {
+ if (event.defaultPrevented) return;
+ let index = getPosition(this.ul, event);
+ if (index != -1) this.selectOption(index);
+ }
+
+ onModelDataChange() {
+ this.buildList();
+ }
+
+ onDocKeyDown(event) {
+ if (event.defaultPrevented) return;
+
+ let data = this.$.model.data;
+ let option = this.activeOption;
+ let nOpts = data ? data.length - 1 : 0;
+
+ switch (event.keyCode) {
+ case 13: // Enter
+ this.selectOption(option);
+ break;
+ case 38: // Up
+ this.moveToOption(option <= 0 ? nOpts : option - 1);
+ break;
+ case 40: // Down
+ this.moveToOption(option >= nOpts ? 0 : option + 1);
+ break;
+ case 35: // End
+ this.moveToOption(nOpts);
+ break;
+ case 36: // Start
+ this.moveToOption(0);
+ break;
+ default:
+ return;
+ }
+
+ event.preventDefault();
+ this.$.$applyAsync();
+ }
+
+ buildList() {
+ this.destroyList();
+
+ let hasTemplate = this.$transclude &&
+ this.$transclude.isSlotFilled('tplItem');
+ let fragment = this.document.createDocumentFragment();
+ let data = this.$.model.data;
+
+ if (data) {
+ for (let i = 0; i < data.length; i++) {
+ let li = this.document.createElement('li');
+ fragment.appendChild(li);
+
+ if (this.multiple) {
+ let check = this.document.createElement('input');
+ check.type = 'checkbox';
+ li.appendChild(check);
+
+ if (this.field && this.field.indexOf(data[i][this.valueField]) != -1)
+ check.checked = true;
+ }
+
+ if (hasTemplate) {
+ this.$transclude((clone, scope) => {
+ Object.assign(scope, data[i]);
+ li.appendChild(clone[0]);
+ this.scopes[i] = scope;
+ }, null, 'tplItem');
+ } else {
+ let text = this.document.createTextNode(data[i][this.showField]);
+ li.appendChild(text);
+ }
+ }
+ }
+
+ this.ul.appendChild(fragment);
+ this.activateOption(this._activeOption);
+ this.$.$applyAsync(() => this.$.popover.relocate());
+ }
+
+ destroyList() {
+ this.ul.innerHTML = '';
+
+ if (this.scopes)
+ for (let scope of this.scopes)
+ scope.$destroy();
+
+ this.scopes = [];
+ }
+
+ $onDestroy() {
+ this.destroyList();
+ }
+}
+DropDown.$inject = ['$element', '$scope', '$transclude', '$timeout', '$http'];
+
+/**
+ * Gets the position of an event element relative to a parent.
+ *
+ * @param {HTMLElement} parent The parent element
+ * @param {Event} event The event object
+ * @return {Number} The element index
+ */
+function getPosition(parent, event) {
+ let target = event.target;
+ let children = parent.children;
+
+ if (target === parent)
+ return -1;
+
+ while (target.parentNode !== parent)
+ target = target.parentNode;
+
+ for (let i = 0; i < children.length; i++)
+ if (children[i] === target)
+ return i;
+
+ return -1;
+}
+
+ngModule.component('vnDropDown', {
+ template: require('./drop-down.html'),
+ controller: DropDown,
+ bindings: {
+ field: '=?',
+ data: '',
+ selection: '=?',
+ search: '',
+ limit: '',
+ showFilter: '',
+ parent: '',
+ multiple: '',
+ onSelect: '&?'
+ },
+ transclude: {
+ tplItem: '?tplItem'
+ }
+});
diff --git a/client/core/src/components/drop-down/drop-down.spec.js b/client/core/src/components/drop-down/drop-down.spec.js
new file mode 100644
index 000000000..0b46f9ade
--- /dev/null
+++ b/client/core/src/components/drop-down/drop-down.spec.js
@@ -0,0 +1,56 @@
+import './drop-down.js';
+import template from './drop-down.html';
+
+describe('Component vnDropDown', () => {
+ let $componentController;
+ let $timeout;
+ let $element;
+ let $scope;
+ let $httpBackend;
+ let $transitions;
+ let $q;
+ let $filter;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$timeout_, _$httpBackend_, _$q_, _$filter_, _$transitions_) => {
+ $componentController = _$componentController_;
+ $element = angular.element(`
${template}
`);
+ $timeout = _$timeout_;
+ $transitions = _$transitions_;
+ $q = _$q_;
+ $filter = _$filter_;
+ $scope = $rootScope.$new();
+ $httpBackend = _$httpBackend_;
+ $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+
+ let popoverTemplate = require('../popover/popover.html');
+ let $popover = angular.element(`
${popoverTemplate}
`);
+ $scope.popover = $componentController('vnPopover', {$element: $popover, $scope, $timeout, $transitions});
+ $scope.popover.$postLink();
+
+ $scope.model = $componentController('vnModel', {$httpBackend, $q, $filter});
+ controller = $componentController('vnDropDown', {$element, $scope, $transclude: null, $timeout, $httpBackend, $translate: null});
+ controller.$postLink();
+ controller.parent = angular.element('
')[0];
+ }));
+
+ describe('show() method', () => {
+ it(`should define controllers _show using the value received as argument`, () => {
+ controller.show();
+
+ expect(controller.shown).toEqual(true);
+ });
+ });
+
+ describe('hide() method', () => {
+ it(`should define controllers _show using the value received as argument`, () => {
+ controller.hide();
+
+ expect(controller.shown).toEqual(false);
+ });
+ });
+});
diff --git a/client/core/src/components/drop-down/model.js b/client/core/src/components/drop-down/model.js
new file mode 100644
index 000000000..12888563c
--- /dev/null
+++ b/client/core/src/components/drop-down/model.js
@@ -0,0 +1,107 @@
+import ngModule from '../../module';
+
+export default class Model {
+ constructor($http, $q, $filter) {
+ this.$http = $http;
+ this.$q = $q;
+ this.$filter = $filter;
+ this.filter = null;
+ this.clear();
+ }
+
+ get isLoading() {
+ return this.canceler != null;
+ }
+
+ loadMore() {
+ if (this.moreRows) {
+ let filter = Object.assign({}, this.myFilter);
+ filter.skip += filter.limit;
+ this.sendRequest(filter, true);
+ }
+ }
+
+ clear() {
+ this.cancelRequest();
+ this.data = null;
+ this.moreRows = false;
+ this.dataChanged();
+ }
+
+ refresh(search) {
+ if (this.url) {
+ let filter = Object.assign({}, this.filter);
+
+ if (filter.limit)
+ filter.skip = 0;
+
+ this.clear();
+ this.sendRequest(filter);
+ } else if (this.staticData) {
+ if (search)
+ this.data = this.$filter('filter')(this.staticData, search);
+ else
+ this.data = this.staticData;
+ this.dataChanged();
+ }
+ }
+
+ cancelRequest() {
+ if (this.canceler) {
+ this.canceler.resolve();
+ this.canceler = null;
+ this.request = null;
+ }
+ }
+
+ sendRequest(filter, append) {
+ this.cancelRequest();
+ this.canceler = this.$q.defer();
+ let options = {timeout: this.canceler.promise};
+ let json = encodeURIComponent(JSON.stringify(filter));
+ this.request = this.$http.get(`${this.url}?filter=${json}`, options).then(
+ json => this.onRemoteDone(json, filter, append),
+ json => this.onRemoteError(json)
+ );
+ }
+
+ onRemoteDone(json, filter, append) {
+ let data = json.data;
+
+ if (append)
+ this.data = this.data.concat(data);
+ else
+ this.data = data;
+
+ this.myFilter = filter;
+ this.moreRows = filter.limit && data.length == filter.limit;
+ this.onRequestEnd();
+ this.dataChanged();
+ }
+
+ onRemoteError(json) {
+ this.onRequestEnd();
+ }
+
+ onRequestEnd() {
+ this.request = null;
+ this.canceler = null;
+ }
+
+ dataChanged() {
+ if (this.onDataChange)
+ this.onDataChange();
+ }
+}
+Model.$inject = ['$http', '$q', '$filter'];
+
+ngModule.component('vnModel', {
+ controller: Model,
+ bindings: {
+ url: '@?',
+ staticData: '',
+ data: '=?',
+ limit: '',
+ onDataChange: '&?'
+ }
+});
diff --git a/client/core/src/components/drop-down/style.scss b/client/core/src/components/drop-down/style.scss
new file mode 100755
index 000000000..94521aff8
--- /dev/null
+++ b/client/core/src/components/drop-down/style.scss
@@ -0,0 +1,72 @@
+vn-drop-down {
+ .dropdown {
+ display: flex;
+ flex-direction: column;
+
+ & > .filter {
+ position: relative;
+
+ & > .search {
+ display: block;
+ width: 100%;
+ box-sizing: border-box;
+ border: none;
+ border-bottom: 1px solid #ccc;
+ font-size: inherit;
+ padding: .6em;
+ }
+ & > vn-icon[icon=clear] {
+ display: none;
+ cursor: pointer;
+ position: absolute;
+ right: .5em;
+ top: .6em;
+ height: 1em;
+ color: #888;
+ border-radius: 50%;
+ background-color: rgba(255, 255, 255, .8);
+ font-size: 18px;
+
+ &:hover {
+ color: #333;
+ }
+ }
+ &:hover > vn-icon[icon=clear] {
+ display: block;
+ }
+ }
+ & > .list {
+ max-height: 12.8em;
+ overflow: auto;
+
+ ul {
+ padding: 0;
+ margin: 0;
+ list-style-type: none;
+ }
+ li, .status {
+ padding: .6em;
+ cursor: pointer;
+ white-space: nowrap;
+ transition: background-color 250ms ease-out;
+ display: flex;
+
+ & > input[type=checkbox] {
+ margin: 0;
+ margin-right: .6em;
+ }
+ &:hover {
+ background-color: rgba(0, 0, 0, .1);
+ }
+ &.active {
+ background-color: #3D3A3B;
+ color: white;
+ }
+ }
+ .status {
+ color: #ffab40;
+ font-weight: bold;
+ }
+ }
+ }
+}
diff --git a/client/core/src/floatbutton/floatbutton.mdl.html b/client/core/src/components/float-button/float-button.html
similarity index 100%
rename from client/core/src/floatbutton/floatbutton.mdl.html
rename to client/core/src/components/float-button/float-button.html
diff --git a/client/core/src/components/float-button/float-button.js b/client/core/src/components/float-button/float-button.js
new file mode 100644
index 000000000..d655a721b
--- /dev/null
+++ b/client/core/src/components/float-button/float-button.js
@@ -0,0 +1,14 @@
+import ngModule from '../../module';
+import template from './float-button.html';
+
+directive.$inject = ['vnTemplate'];
+export function directive(vnTemplate) {
+ return {
+ restrict: 'E',
+ template: (_, $attrs) =>
+ vnTemplate.get(template, $attrs, {
+ className: 'mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored'
+ })
+ };
+}
+ngModule.directive('vnFloatButton', directive);
diff --git a/client/core/src/components/grid-header/grid-header.html b/client/core/src/components/grid-header/grid-header.html
new file mode 100644
index 000000000..02c0e4101
--- /dev/null
+++ b/client/core/src/components/grid-header/grid-header.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/core/src/components/grid-header/grid-header.js b/client/core/src/components/grid-header/grid-header.js
new file mode 100644
index 000000000..41d96602d
--- /dev/null
+++ b/client/core/src/components/grid-header/grid-header.js
@@ -0,0 +1,27 @@
+import ngModule from '../../module';
+import './style.scss';
+
+export default class GridHeader {
+ constructor() {
+ this.currentColumn = undefined;
+ }
+
+ selectColum(col) {
+ if (this.currentColumn && this.currentColumn.field != col.field)
+ this.currentColumn.order = undefined;
+
+ this.currentColumn = col;
+ if (this.onOrder)
+ this.onOrder(this.currentColumn);
+ }
+
+}
+
+ngModule.component('vnGridHeader', {
+ template: require('./grid-header.html'),
+ transclude: true,
+ bindings: {
+ onOrder: '&?'
+ },
+ controller: GridHeader
+});
diff --git a/client/core/src/components/grid-header/grid-header.spec.js b/client/core/src/components/grid-header/grid-header.spec.js
new file mode 100644
index 000000000..03294a348
--- /dev/null
+++ b/client/core/src/components/grid-header/grid-header.spec.js
@@ -0,0 +1,43 @@
+import './grid-header.js';
+
+describe('Component vnGridHeader', () => {
+ let $componentController;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject(_$componentController_ => {
+ $componentController = _$componentController_;
+ controller = $componentController('vnGridHeader', {});
+ }));
+
+ describe('selectColum()', () => {
+ it(`should set controller currentColumn to equal the argument received`, () => {
+ let col = {columnStuff: 'some stuff'};
+ controller.selectColum(col);
+
+ expect(controller.currentColumn).toEqual(col);
+ });
+
+ it(`should set controller currentColumn.order to undefined then set currentColumn to equal the argument received`, () => {
+ controller.currentColumn = {field: 'some field', order: 'ordered'};
+ let col = {columnStuff: 'some stuff'};
+ controller.selectColum(col);
+
+ expect(controller.currentColumn.order).not.toBeDefined();
+ expect(controller.currentColumn).toEqual(col);
+ });
+
+ it(`should set controller currentColumn.order to undefined then call onOrder passing currentColumn as argument`, () => {
+ controller.onOrder = () => {};
+ spyOn(controller, 'onOrder');
+ let col = {columnStuff: 'some stuff'};
+ controller.selectColum(col);
+
+ expect(controller.currentColumn).toEqual(col);
+ expect(controller.onOrder).toHaveBeenCalledWith(col);
+ });
+ });
+});
diff --git a/client/core/src/components/grid-header/style.scss b/client/core/src/components/grid-header/style.scss
new file mode 100644
index 000000000..8f3475b35
--- /dev/null
+++ b/client/core/src/components/grid-header/style.scss
@@ -0,0 +1,30 @@
+vn-grid-header {
+ border-bottom: 3px solid #9D9D9D;
+ font-weight: bold;
+ .orderly{
+ text-align: center;
+ white-space: nowrap;
+ justify-content: center;
+ vn-none{
+ min-width: 17px;
+ }
+ }
+ vn-icon{
+ margin: 0;
+ padding: 0;
+ i {
+ padding: 0;
+ margin: -2px -17px 0 0;
+ opacity: 0.2;
+ cursor: pointer;
+ }
+ &.active {
+ i {
+ opacity: 1;
+ }
+ }
+ }
+ [min-none]{
+ min-width: 60px;
+ }
+}
\ No newline at end of file
diff --git a/client/core/src/components/icon-button/icon-button.html b/client/core/src/components/icon-button/icon-button.html
new file mode 100644
index 000000000..fdd022710
--- /dev/null
+++ b/client/core/src/components/icon-button/icon-button.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/client/core/src/components/icon-button/icon-button.js b/client/core/src/components/icon-button/icon-button.js
new file mode 100644
index 000000000..c257b9da9
--- /dev/null
+++ b/client/core/src/components/icon-button/icon-button.js
@@ -0,0 +1,12 @@
+import ngModule from '../../module';
+
+ngModule.component('vnIconButton', {
+ template: require('./icon-button.html'),
+ bindings: {
+ icon: '@',
+ className: '@?',
+ enabled: '',
+ label: '@?'
+ }
+});
+
diff --git a/client/core/src/components/icon-menu/icon-menu.html b/client/core/src/components/icon-menu/icon-menu.html
new file mode 100644
index 000000000..c2d5ffeff
--- /dev/null
+++ b/client/core/src/components/icon-menu/icon-menu.html
@@ -0,0 +1,27 @@
+
\ No newline at end of file
diff --git a/client/core/src/components/icon-menu/icon-menu.js b/client/core/src/components/icon-menu/icon-menu.js
new file mode 100644
index 000000000..fc0e57432
--- /dev/null
+++ b/client/core/src/components/icon-menu/icon-menu.js
@@ -0,0 +1,131 @@
+import ngModule from '../../module';
+import './style.scss';
+
+export default class IconMenu {
+ constructor($element, $http, $timeout) {
+ this.$element = $element;
+ this.$http = $http;
+ this.$timeout = $timeout;
+ this._showDropDown = false;
+ this.finding = false;
+ this.findMore = false;
+ this.element = $element[0];
+ }
+
+ get showDropDown() {
+ return this._showDropDown;
+ }
+
+ set showDropDown(value) {
+ this._showDropDown = value;
+ }
+
+ findItems(search) {
+ if (!this.url)
+ return this.items ? this.items : [];
+
+ if (search && !this.finding) {
+ let filter = {where: {name: {regexp: search}}};
+ let json = JSON.stringify(filter);
+ this.finding = true;
+ this.$http.get(`${this.url}?filter=${json}`).then(
+ json => {
+ this.items = json.data;
+ this.finding = false;
+ },
+ () => {
+ this.finding = false;
+ }
+ );
+ } else if (!search && !this.finding) {
+ this.maxRow = 10;
+ this.items = [];
+ this.getItems();
+ }
+ }
+
+ getItems() {
+ let filter = {};
+
+ if (this.maxRow) {
+ if (this.items) {
+ filter.skip = this.items.length;
+ }
+ filter.limit = this.maxRow;
+ filter.order = 'name ASC';
+ }
+
+ let json = JSON.stringify(filter);
+
+ this.$http.get(`${this.url}?filter=${json}`).then(
+ json => {
+ if (json.data.length)
+ json.data.forEach(
+ el => {
+ this.items.push(el);
+ }
+ );
+ else
+ this.maxRow = false;
+ }
+ );
+ }
+
+ $onInit() {
+ if (!this.items && this.url) {
+ this.items = [];
+ this.getItems();
+ }
+
+ this.findMore = this.url && this.maxRow;
+
+ this.mouseFocus = false;
+ this.focused = false;
+
+ this.$element.bind('mouseover', e => {
+ this.$timeout(() => {
+ this.mouseFocus = true;
+ this.showDropDown = this.focused;
+ });
+ });
+
+ this.$element.bind('mouseout', () => {
+ this.$timeout(() => {
+ this.mouseFocus = false;
+ this.showDropDown = this.focused;
+ });
+ });
+ this.$element.bind('focusin', e => {
+ this.$timeout(() => {
+ this.focused = true;
+ this.showDropDown = true;
+ });
+ });
+ this.$element.bind('focusout', e => {
+ this.$timeout(() => {
+ this.focused = false;
+ this.showDropDown = this.mouseFocus;
+ });
+ });
+ }
+
+ $onDestroy() {
+ this.$element.unbind('mouseover');
+ this.$element.unbind('mouseout');
+ this.$element.unbind('focusin');
+ this.$element.unbind('focusout');
+ }
+}
+IconMenu.$inject = ['$element', '$http', '$timeout'];
+
+ngModule.component('vnIconMenu', {
+ template: require('./icon-menu.html'),
+ bindings: {
+ url: '@?',
+ items: '',
+ icon: '@',
+ maxRow: '@?',
+ selected: '='
+ },
+ controller: IconMenu
+});
diff --git a/client/core/src/components/icon-menu/icon-menu.spec.js b/client/core/src/components/icon-menu/icon-menu.spec.js
new file mode 100644
index 000000000..11be1ff62
--- /dev/null
+++ b/client/core/src/components/icon-menu/icon-menu.spec.js
@@ -0,0 +1,85 @@
+import './icon-menu.js';
+
+describe('Component vnIconMenu', () => {
+ let $componentController;
+ let $element;
+ let $httpBackend;
+ let $timeout;
+ let $scope;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => {
+ $componentController = _$componentController_;
+ $httpBackend = _$httpBackend_;
+ $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ $timeout = _$timeout_;
+ $scope = $rootScope.$new();
+ $element = angular.element('
');
+ controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
+ }));
+
+ describe('component vnIconMenu', () => {
+ describe('findItem()', () => {
+ it(`should return items empty array if the controller does not provide a url and have no items defined`, () => {
+ controller.url = undefined;
+ controller.items = undefined;
+ let result = controller.findItems('some search value');
+
+ expect(result).toEqual([]);
+ });
+
+ it(`should return items array if the controller does not provide a url`, () => {
+ controller.url = undefined;
+ controller.items = ['Batman', 'Bruce Wayne'];
+ controller.findItems('some search value');
+
+ expect(controller.items.length).toEqual(2);
+ });
+
+ it(`should perform a search and store the result in controller items`, () => {
+ let search = 'The Joker';
+ let json = JSON.stringify({where: {name: {regexp: search}}});
+ $httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
+ $httpBackend.expectGET(`${controller.url}?filter=${json}`);
+ controller.findItems(search);
+ $httpBackend.flush();
+
+ expect(controller.items[0]).toEqual({id: 3, name: 'The Joker'});
+ });
+
+ it(`should call getItems function if there's no search value`, () => {
+ spyOn(controller, 'getItems');
+ controller.findItems();
+
+ expect(controller.getItems).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('getItems()', () => {
+ it(`should perform a query and then push elements found into controller.items`, () => {
+ controller.items = [];
+ $httpBackend.whenGET(`${controller.url}?filter={}`).respond([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
+ $httpBackend.expectGET(`${controller.url}?filter={}`);
+ controller.getItems();
+ $httpBackend.flush();
+
+ expect(controller.items).toEqual([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
+ });
+
+ it(`should perform a query and then set controller.maxRow to false if there are no items in the controller`, () => {
+ controller.items = [];
+ controller.maxRow = true;
+ $httpBackend.whenGET(`${controller.url}?filter={"skip":0,"limit":true,"order":"name ASC"}`).respond(controller.items);
+ $httpBackend.expectGET(`${controller.url}?filter={"skip":0,"limit":true,"order":"name ASC"}`);
+ controller.getItems();
+ $httpBackend.flush();
+
+ expect(controller.maxRow).toBeFalsy();
+ });
+ });
+ });
+});
diff --git a/client/core/src/components/icon-menu/style.scss b/client/core/src/components/icon-menu/style.scss
new file mode 100644
index 000000000..2d3919f4d
--- /dev/null
+++ b/client/core/src/components/icon-menu/style.scss
@@ -0,0 +1,12 @@
+vn-icon-menu{
+ position: relative;
+ .icon-menu__button {
+ padding: 0 10px;
+ }
+ vn-icon{
+ float: left;
+ }
+ vn-icon.icon-menu__arrow_down{
+ margin:2px 0 0 5px;
+ }
+}
\ No newline at end of file
diff --git a/client/core/src/components/icon/icon.js b/client/core/src/components/icon/icon.js
new file mode 100644
index 000000000..01087b0c7
--- /dev/null
+++ b/client/core/src/components/icon/icon.js
@@ -0,0 +1,34 @@
+import ngModule from '../../module';
+import './style.scss';
+
+class Icon {
+ constructor($attrs) {
+ this.$attrs = $attrs;
+ this._icon = null;
+ }
+ set icon(value) {
+ this._icon = value;
+ this.drawIcon();
+ }
+ get icon() {
+ return this._icon;
+ }
+ drawIcon() {
+ if (this.icon.startsWith('icon-')) {
+ this.iconClass = this.icon;
+ this.iconContent = '';
+ } else {
+ this.iconClass = 'material-icons';
+ this.iconContent = this.icon;
+ }
+ }
+}
+Icon.$inject = ['$attrs'];
+
+ngModule.component('vnIcon', {
+ template: '
{{::$ctrl.iconContent}}',
+ controller: Icon,
+ bindings: {
+ icon: '@'
+ }
+});
diff --git a/client/core/src/components/icon/style.scss b/client/core/src/components/icon/style.scss
new file mode 100644
index 000000000..e9764adec
--- /dev/null
+++ b/client/core/src/components/icon/style.scss
@@ -0,0 +1,10 @@
+vn-icon {
+ display: inline-block;
+ font-size: 18pt;
+
+ & > i,
+ & > i.material-icons {
+ display: block;
+ font-size: inherit;
+ }
+}
diff --git a/client/core/src/components/index.js b/client/core/src/components/index.js
new file mode 100644
index 000000000..774971572
--- /dev/null
+++ b/client/core/src/components/index.js
@@ -0,0 +1,30 @@
+import './textfield/textfield';
+import './watcher/watcher';
+import './paging/paging';
+import './icon/icon';
+import './dialog/dialog';
+import './confirm/confirm';
+import './title/title';
+import './subtitle/subtitle';
+import './spinner/spinner';
+import './snackbar/snackbar';
+import './tooltip/tooltip';
+import './icon-menu/icon-menu';
+import './popover/popover';
+import './autocomplete/autocomplete';
+import './drop-down/drop-down';
+import './menu/menu';
+import './column-header/column-header';
+import './grid-header/grid-header';
+import './multi-check/multi-check';
+import './date-picker/date-picker';
+import './button/button';
+import './check/check';
+import './radio/radio';
+import './textarea/textarea';
+import './icon-button/icon-button';
+import './submit/submit';
+import './combo/combo';
+import './card/card';
+import './switch/switch';
+import './float-button/float-button';
diff --git a/client/core/src/components/menu/menu.js b/client/core/src/components/menu/menu.js
new file mode 100755
index 000000000..ce32502d9
--- /dev/null
+++ b/client/core/src/components/menu/menu.js
@@ -0,0 +1,24 @@
+import ngModule from '../../module';
+import Popover from '../popover/popover';
+
+export default class Menu extends Popover {
+ $postLink() {
+ super.$postLink();
+ this.element.addEventListener('click',
+ () => this.onClick());
+ }
+
+ onClick() {
+ this.hide();
+ }
+}
+
+ngModule.component('vnMenu', {
+ template: require('../popover/popover.html'),
+ controller: Menu,
+ transclude: true,
+ bindings: {
+ onOpen: '&?',
+ onClose: '&?'
+ }
+});
diff --git a/client/core/src/components/multi-check/multi-check.html b/client/core/src/components/multi-check/multi-check.html
new file mode 100644
index 000000000..36f7f3ec7
--- /dev/null
+++ b/client/core/src/components/multi-check/multi-check.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/core/src/components/multi-check/multi-check.js b/client/core/src/components/multi-check/multi-check.js
new file mode 100644
index 000000000..21f60ec63
--- /dev/null
+++ b/client/core/src/components/multi-check/multi-check.js
@@ -0,0 +1,106 @@
+import ngModule from '../../module';
+import './multi-check.scss';
+
+/**
+ * Draw checkbox with a drop-down and multi options
+ * @param {SmallInt} checkAll Primary input-check state: 0 -> uncheck, 1 -> checked, 2 -> indeterminate checked
+ * @param {Array} options List of options shown in drop-down
+ * @param {Array} models Elements to check / unCheck
+ * @param {String} className Optional css class name
+ */
+export default class MultiCheck {
+ constructor($timeout) {
+ this.$timeout = $timeout;
+ this._checkAll = 0;
+ this._models = [];
+ this._type = {};
+ this.showDropDown = false;
+ }
+
+ get type() {
+ return this._type;
+ }
+
+ set type(value) {
+ if (value && value.id) {
+ this._type = value;
+ switch (value.id) {
+ case 'all':
+ this.checkAll = 1;
+ break;
+ case 'any':
+ this.checkAll = 0;
+ break;
+ default:
+ this.checkAll = 2;
+ break;
+ }
+ }
+ this._type = {};
+ this.showDropDown = false;
+ }
+
+ get models() {
+ return this._models;
+ }
+
+ set models(value) {
+ this._models = value;
+ }
+
+ get checkAll() {
+ return this._checkAll;
+ }
+
+ set checkAll(value) {
+ this._checkAll = value;
+ this.switchChecks();
+ }
+
+ switchChecks() {
+ if (this.models)
+ this.models.forEach(
+ el => {
+ let checked;
+ if (this.type.id && this.type.id !== 'all' && this.type.id !== 'any') {
+ if (this.type.id.length > 3 && this.type.id.substr(0, 3) === 'no-') {
+ let label = this.type.id.replace('no-', '');
+ checked = Boolean(el[label]) === false;
+ } else if (this.type.id.length > 6 && this.type.id.substr(0, 6) === 'equal-') {
+ let label = this.type.id.replace('equal-', '');
+ checked = (el[label] && el[label] === this.type.name);
+ } else {
+ checked = Boolean(el[this.type.id]) === true;
+ }
+ } else {
+ checked = this.checkAll === 1;
+ }
+ el.checked = checked;
+ }
+ );
+ }
+
+ $onChanges() {
+ this.type = {};
+ this.checkAll = 0;
+ }
+
+ onBlur() {
+ this.$timeout(() => {
+ this.showDropDown = false;
+ }, 200);
+ }
+}
+MultiCheck.$inject = ['$timeout'];
+
+ngModule.component('vnMultiCheck', {
+ template: require('./multi-check.html'),
+ controller: MultiCheck,
+ bindings: {
+ checkAll: '=',
+ options: '<',
+ models: '<',
+ className: '@?'
+ }
+});
+
diff --git a/client/core/src/components/multi-check/multi-check.scss b/client/core/src/components/multi-check/multi-check.scss
new file mode 100644
index 000000000..c253bbde6
--- /dev/null
+++ b/client/core/src/components/multi-check/multi-check.scss
@@ -0,0 +1,24 @@
+.multi-check {
+ vn-icon{
+ cursor: pointer;
+ }
+ .primaryCheckbox {
+ vn-icon{
+ font-size: 22px;
+ margin-left: -4px;
+ i{
+ color: rgba(0,0,0,.54);
+ }
+ }
+ &.color {
+ i{
+ color: rgb(255,152,0);
+ }
+ }
+ }
+ .arrow_down{
+ i{
+ padding-top: 8px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/core/src/components/multi-check/multi-check.spec.js b/client/core/src/components/multi-check/multi-check.spec.js
new file mode 100644
index 000000000..a221e3cc7
--- /dev/null
+++ b/client/core/src/components/multi-check/multi-check.spec.js
@@ -0,0 +1,163 @@
+import './multi-check.js';
+
+describe('Component vnMultiCheck', () => {
+ let $componentController;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject(_$componentController_ => {
+ $componentController = _$componentController_;
+ controller = $componentController('vnMultiCheck', {});
+ }));
+
+ describe('models()', () => {
+ it(`should set controller _models property with the argument received`, () => {
+ let argument = 'I am the model';
+ controller.models = argument;
+
+ expect(controller._models).toEqual(argument);
+ });
+ });
+
+ describe('checkAll()', () => {
+ it(`should set controller _checkAll property with the argument received then call switchChecks()`, () => {
+ let argument = 'I am the model';
+ spyOn(controller, 'switchChecks');
+ controller.checkAll = argument;
+
+ expect(controller._checkAll).toEqual(argument);
+ expect(controller.switchChecks).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('switchChecks()', () => {
+ it(`should set checked property inside each existing elemenet when id begings with no-`, () => {
+ controller.type = {id: 'no-name'};
+ controller.models = [
+ {name: 'name'},
+ {name: null}
+ ];
+
+ expect(controller._models[0].checked).not.toBeDefined();
+ expect(controller._models[1].checked).not.toBeDefined();
+ controller._checkAll = 1;
+ controller.switchChecks();
+
+ expect(controller._models[0].checked).toBeTruthy();
+ expect(controller._models[1].checked).toBeTruthy();
+ });
+
+ it(`should set checked property inside each existing elemenet when id begings with equal-`, () => {
+ controller.type = {id: 'equal-name', name: 'name'};
+ controller.models = [
+ {name: null},
+ {name: 'name'}
+ ];
+
+ expect(controller._models[0].checked).not.toBeDefined();
+ expect(controller._models[1].checked).not.toBeDefined();
+ controller._checkAll = 1;
+ controller.switchChecks();
+
+ expect(controller._models[0].checked).toBeTruthy();
+ expect(controller._models[1].checked).toBeTruthy();
+ });
+
+ it(`should set checked property inside each existing elemenet when begings with anything but any, all, no- or equal-`, () => {
+ controller.type = {id: 'name'};
+ controller.models = [
+ {name: null},
+ {name: 'name'}
+ ];
+
+ expect(controller._models[0].checked).not.toBeDefined();
+ expect(controller._models[1].checked).not.toBeDefined();
+ controller._checkAll = 1;
+ controller.switchChecks();
+
+ expect(controller._models[0].checked).toBeTruthy();
+ expect(controller._models[1].checked).toBeTruthy();
+ });
+
+ describe('when id is any', () => {
+ it('should set element checked property based on controller._checkAll', () => {
+ controller.type = {id: 'any'};
+ controller.models = [
+ {name: 'name'}
+ ];
+
+ expect(controller._models[0].checked).not.toBeDefined();
+ controller._checkAll = 1;
+ controller.switchChecks();
+
+ expect(controller._models[0].checked).toBeTruthy();
+ controller._checkAll = 0;
+ controller.switchChecks();
+
+ expect(controller._models[0].checked).toBeFalsy();
+ controller._checkAll = 2;
+ controller.switchChecks();
+
+ expect(controller._models[0].checked).toBeFalsy();
+ });
+ });
+
+ describe('when id is all', () => {
+ it('should set element checked property based on controller._checkAll property', () => {
+ controller.type = {id: 'all'};
+ controller.models = [
+ {name: 'name'}
+ ];
+
+ expect(controller._models[0].checked).not.toBeDefined();
+ controller._checkAll = 1;
+ controller.switchChecks();
+
+ expect(controller._models[0].checked).toBeTruthy();
+ controller._checkAll = 0;
+ controller.switchChecks();
+
+ expect(controller._models[0].checked).toBeFalsy();
+ controller._checkAll = 2;
+ controller.switchChecks();
+
+ expect(controller._models[0].checked).toBeFalsy();
+ });
+ });
+ });
+
+ describe('$onChanges()', () => {
+ it('should set controller.type to empty object and checkAll to zero', () => {
+ controller.type = {id: 'all'};
+ controller._checkAll = 1;
+ controller.$onChanges();
+
+ expect(controller.type).toEqual({});
+ expect(controller._checkAll).toEqual(0);
+ });
+ });
+
+ describe('type setter', () => {
+ it('should set controller.type to empty object and checkAll based on controller.type.id', () => {
+ let value = {id: 'all'};
+ controller._checkAll = 0;
+ controller.type = value;
+
+ expect(controller.type).toEqual({});
+ expect(controller._checkAll).toEqual(1);
+ value = {id: 'any'};
+ controller.type = value;
+
+ expect(controller.type).toEqual({});
+ expect(controller._checkAll).toEqual(0);
+ value = {id: 'any other id name'};
+ controller.type = value;
+
+ expect(controller.type).toEqual({});
+ expect(controller._checkAll).toEqual(2);
+ });
+ });
+});
diff --git a/client/core/src/paging/index.html b/client/core/src/components/paging/paging.html
similarity index 76%
rename from client/core/src/paging/index.html
rename to client/core/src/components/paging/paging.html
index 6e2f56fd3..6e71f321d 100644
--- a/client/core/src/paging/index.html
+++ b/client/core/src/components/paging/paging.html
@@ -1,6 +1,7 @@
this.onModelUpdated());
+ }
+
+ $onChanges(changes) {
+ if (!this.index) return;
+ this.numPerPage = this.index.filter.size;
+ this.currentPage = this.index.filter.page;
+ if (changes.total)
+ this.numItems = changes.total.currentValue;
+ }
+
+ onModelUpdated() {
+ let index = this.index;
+ let filter = index.filter;
+
+ if (filter.page >= this.numPages && index.model.length >= this.numPerPage)
+ this.numItems = filter.page * filter.size + 1;
+ }
+
+ onPageChange(page) {
+ this.index.filter.page = page;
+ if (typeof this.pageChange === 'undefined') {
+ this.index.accept();
+ } else {
+ this.pageChange();
+ }
+ }
+ $doCheck() {
+ if (this.index && this.index.filter && this.index.filter.page && this.index.filter.page != this.currentPage) {
+ this.currentPage = this.index.filter.page;
+ }
+ }
+}
+Paging.$inject = ['$http', '$scope'];
+
+ngModule.component('vnPaging', {
+ template: require('./paging.html'),
+ bindings: {
+ index: '<',
+ pageChange: '&?',
+ total: '<'
+ },
+ controller: Paging
+});
diff --git a/client/core/src/components/paging/paging.spec.js b/client/core/src/components/paging/paging.spec.js
new file mode 100644
index 000000000..ab36635d5
--- /dev/null
+++ b/client/core/src/components/paging/paging.spec.js
@@ -0,0 +1,69 @@
+import './paging.js';
+
+describe('Component vnPaging', () => {
+ let $componentController;
+ let $scope;
+ let $httpBackend;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $httpBackend = _$httpBackend_;
+ controller = $componentController('vnPaging', {$scope, $httpBackend});
+ }));
+
+ describe('$onChanges()', () => {
+ it(`should define numberPage and currentPage based on index.filter properties`, () => {
+ controller.index = {filter: {size: 'something', page: 'something else'}};
+ controller.$onChanges({index: 'simpleChange', currentValue: 'current value', previousValue: 'previous value'});
+
+ expect(controller.numPerPage).toBe(controller.index.filter.size);
+ expect(controller.currentPage).toEqual(controller.index.filter.page);
+ });
+
+ it(`should define numItems based on changes.total.currentValue`, () => {
+ controller.index = {filter: {size: 'something', page: 'something else'}};
+ controller.$onChanges({total: {currentValue: 'current value'}});
+
+ expect(controller.numItems).toEqual('current value');
+ });
+ });
+
+ describe('onModelUpdated()', () => {
+ it(`should define controllers numItems as the result of page times size plus one`, () => {
+ controller.numPerPage = 2;
+ controller.index = {
+ filter: {size: 10, page: 10},
+ model: ['one mother..', 'another model..', 'last model..']
+ };
+ controller.onModelUpdated();
+
+ expect(controller.numItems).toBe(101);
+ });
+ });
+
+ describe('onPageChange()', () => {
+ it(`should call accept() since pageChange property is undefined`, () => {
+ controller.index = {accept: () => {}, filter: {page: 0}};
+ spyOn(controller.index, 'accept');
+ controller.onPageChange(100);
+
+ expect(controller.index.accept).toHaveBeenCalledWith();
+ });
+
+ it(`should call pageChange() since pageChange property isn't undefined`, () => {
+ controller.index = {accept: () => {}, filter: {page: 0}};
+ controller.pageChange = true;
+ spyOn(controller, 'pageChange');
+ controller.onPageChange(100);
+
+ expect(controller.pageChange).toHaveBeenCalledWith();
+ });
+ });
+});
+
diff --git a/client/core/src/paging/style.scss b/client/core/src/components/paging/style.scss
similarity index 100%
rename from client/core/src/paging/style.scss
rename to client/core/src/components/paging/style.scss
diff --git a/client/core/src/components/popover/popover.html b/client/core/src/components/popover/popover.html
new file mode 100644
index 000000000..3e3e6ca59
--- /dev/null
+++ b/client/core/src/components/popover/popover.html
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/client/core/src/components/popover/popover.js b/client/core/src/components/popover/popover.js
new file mode 100644
index 000000000..4e2326c77
--- /dev/null
+++ b/client/core/src/components/popover/popover.js
@@ -0,0 +1,223 @@
+import ngModule from '../../module';
+import Component from '../../lib/component';
+import './style.scss';
+
+/**
+ * A simple popover.
+ */
+export default class Popover extends Component {
+ constructor($element, $scope, $timeout, $transitions) {
+ super($element, $scope);
+ this.$timeout = $timeout;
+ this.$transitions = $transitions;
+ this._shown = false;
+ }
+
+ $postLink() {
+ this.$element.addClass('vn-popover');
+
+ this.docKeyDownHandler = e => this.onDocKeyDown(e);
+ this.docFocusInHandler = e => this.onDocFocusIn(e);
+
+ this.element.addEventListener('mousedown',
+ e => this.onBackgroundMouseDown(e));
+ this.element.addEventListener('focusin',
+ e => this.onFocusIn(e));
+
+ this.popover = this.element.querySelector('.popover');
+ this.popover.addEventListener('mousedown',
+ e => this.onMouseDown(e));
+
+ this.arrow = this.element.querySelector('.arrow');
+ this.content = this.element.querySelector('.content');
+ }
+
+ set child(value) {
+ this.content.appendChild(value);
+ }
+
+ get child() {
+ return this.content.firstChild;
+ }
+
+ get shown() {
+ return this._shown;
+ }
+
+ set shown(value) {
+ if (value)
+ this.show();
+ else
+ this.hide();
+ }
+
+ /**
+ * Shows the popover. If a parent is specified it is shown in a visible
+ * relative position to it.
+ */
+ show() {
+ if (this._shown) return;
+
+ this._shown = true;
+ this.element.style.display = 'block';
+ this.$timeout.cancel(this.showTimeout);
+ this.showTimeout = this.$timeout(() => {
+ this.$element.addClass('shown');
+ this.showTimeout = null;
+ }, 30);
+
+ this.document.addEventListener('keydown', this.docKeyDownHandler);
+ this.document.addEventListener('focusin', this.docFocusInHandler);
+
+ this.deregisterCallback = this.$transitions.onStart({}, () => this.hide());
+ this.relocate();
+
+ if (this.onOpen)
+ this.onOpen();
+ }
+
+ /**
+ * Hides the popover.
+ */
+ hide() {
+ if (!this._shown) return;
+
+ this._shown = false;
+ this.$element.removeClass('shown');
+ this.$timeout.cancel(this.showTimeout);
+ this.showTimeout = this.$timeout(() => {
+ this.element.style.display = 'none';
+ this.showTimeout = null;
+ }, 250);
+
+ this.document.removeEventListener('keydown', this.docKeyDownHandler);
+ this.document.removeEventListener('focusin', this.docFocusInHandler);
+
+ if (this.deregisterCallback)
+ this.deregisterCallback();
+
+ if (this.parent)
+ this.parent.focus();
+
+ if (this.onClose)
+ this.onClose();
+ }
+
+ /**
+ * Repositions the popover to a correct location relative to the parent.
+ */
+ relocate() {
+ if (!(this.parent && this._shown)) return;
+
+ let style = this.popover.style;
+ style.width = '';
+ style.height = '';
+
+ let arrowStyle = this.arrow.style;
+ arrowStyle.top = '';
+ arrowStyle.bottom = '';
+
+ let parentRect = this.parent.getBoundingClientRect();
+ let popoverRect = this.popover.getBoundingClientRect();
+ let arrowRect = this.arrow.getBoundingClientRect();
+
+ let arrowHeight = Math.sqrt(Math.pow(arrowRect.height, 2) * 2) / 2;
+
+ let top = parentRect.top + parentRect.height + arrowHeight;
+ let left = parentRect.left;
+ let height = popoverRect.height;
+ let width = Math.max(popoverRect.width, parentRect.width);
+
+ let margin = 10;
+ let showTop = top + height + margin > window.innerHeight;
+
+ if (showTop)
+ top = Math.max(parentRect.top - height - arrowHeight, margin);
+ if (left + width + margin > window.innerWidth)
+ left = window.innerWidth - width - margin;
+
+ if (showTop)
+ arrowStyle.bottom = `0`;
+ else
+ arrowStyle.top = `0`;
+
+ arrowStyle.left = `${(parentRect.left - left) + parentRect.width / 2}px`;
+
+ style.top = `${top}px`;
+ style.left = `${left}px`;
+ style.width = `${width}px`;
+
+ if (height + margin * 2 + arrowHeight > window.innerHeight)
+ style.height = `${window.innerHeight - margin * 2 - arrowHeight}px`;
+ }
+
+ onDocKeyDown(event) {
+ if (event.defaultPrevented) return;
+
+ if (event.keyCode == 27) { // Esc
+ event.preventDefault();
+ this.hide();
+ }
+ }
+
+ onMouseDown(event) {
+ this.lastMouseEvent = event;
+ }
+
+ onBackgroundMouseDown(event) {
+ if (event != this.lastMouseEvent)
+ this.hide();
+ }
+
+ onFocusIn(event) {
+ this.lastFocusEvent = event;
+ }
+
+ onDocFocusIn(event) {
+ if (event !== this.lastFocusEvent)
+ this.hide();
+ }
+}
+Popover.$inject = ['$element', '$scope', '$timeout', '$transitions'];
+
+ngModule.component('vnPopover', {
+ template: require('./popover.html'),
+ controller: Popover,
+ transclude: true,
+ bindings: {
+ onOpen: '&?',
+ onClose: '&?'
+ }
+});
+
+class PopoverService {
+ constructor($document, $compile, $transitions, $rootScope) {
+ this.$compile = $compile;
+ this.$rootScope = $rootScope;
+ this.$document = $document;
+ this.stack = [];
+ }
+ show(child, parent, $scope) {
+ let element = this.$compile('')($scope || this.$rootScope)[0];
+ let popover = element.$ctrl;
+ popover.parent = parent;
+ popover.child = child;
+ popover.show();
+ popover.onClose = () => {
+ this.$document[0].body.removeChild(element);
+ if ($scope) $scope.$destroy();
+ };
+ this.$document[0].body.appendChild(element);
+ return popover;
+ }
+
+ showComponent(componentTag, $scope, parent) {
+ let $newScope = $scope.$new();
+ let childElement = this.$compile(`<${componentTag}/>`)($newScope)[0];
+ this.show(childElement, parent, $newScope);
+ return childElement;
+ }
+}
+PopoverService.$inject = ['$document', '$compile', '$transitions', '$rootScope'];
+
+ngModule.service('vnPopover', PopoverService);
diff --git a/client/core/src/components/popover/style.scss b/client/core/src/components/popover/style.scss
new file mode 100644
index 000000000..458a47df9
--- /dev/null
+++ b/client/core/src/components/popover/style.scss
@@ -0,0 +1,43 @@
+.vn-popover {
+ display: none;
+ z-index: 10;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+
+ opacity: 0;
+ transform: translateY(-.6em);
+ transition-property: opacity, transform;
+ transition-duration: 200ms;
+ transition-timing-function: ease-in-out;
+
+ &.shown {
+ transform: translateY(0);
+ opacity: 1;
+ }
+ & > .popover {
+ position: absolute;
+ display: flex;
+ box-shadow: 0 .1em .4em rgba(1, 1, 1, .4);
+
+ & > .arrow {
+ width: 1em;
+ height: 1em;
+ margin: -.5em;
+ background-color: white;
+ box-shadow: 0 .1em .4em rgba(1, 1, 1, .4);
+ position: absolute;
+ transform: rotate(45deg);
+ z-index: 0;
+ }
+ & > .content {
+ width: 100%;
+ border-radius: .1em;
+ overflow: auto;
+ background-color: white;
+ z-index: 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/core/src/components/radio/radio.html b/client/core/src/components/radio/radio.html
new file mode 100644
index 000000000..887a97c04
--- /dev/null
+++ b/client/core/src/components/radio/radio.html
@@ -0,0 +1,7 @@
+
+*[text]*
diff --git a/client/core/src/components/radio/radio.js b/client/core/src/components/radio/radio.js
new file mode 100644
index 000000000..70dbc059d
--- /dev/null
+++ b/client/core/src/components/radio/radio.js
@@ -0,0 +1,15 @@
+import ngModule from '../../module';
+import template from './radio.html';
+
+directive.$inject = ['vnTemplate'];
+export default function directive(vnTemplate) {
+ return {
+ restrict: 'E',
+ template: (_, $attrs) =>
+ vnTemplate.get(template, $attrs, {
+ enabled: 'true',
+ className: 'mdl-radio mdl-js-radio mdl-js-ripple-effect'
+ })
+ };
+}
+ngModule.directive('vnRadio', directive);
diff --git a/client/core/src/components/snackbar/snackbar.html b/client/core/src/components/snackbar/snackbar.html
new file mode 100644
index 000000000..60eff1e46
--- /dev/null
+++ b/client/core/src/components/snackbar/snackbar.html
@@ -0,0 +1,4 @@
+
diff --git a/client/core/src/components/snackbar/snackbar.js b/client/core/src/components/snackbar/snackbar.js
new file mode 100644
index 000000000..387442f83
--- /dev/null
+++ b/client/core/src/components/snackbar/snackbar.js
@@ -0,0 +1,99 @@
+import ngModule from '../../module';
+import Component from '../../lib/component';
+import './style.scss';
+
+/**
+ * A simple component to show non-obstructive notifications to the user.
+ */
+export default class Controller extends Component {
+ constructor($element, $translate) {
+ super($element);
+ this.$translate = $translate;
+ this.shown = false;
+ this.snackbar = $element[0].firstChild;
+ this.$snackbar = angular.element(this.snackbar);
+ this.button = $element[0].querySelector('button');
+ this.textNode = this.snackbar.querySelector('.text');
+ }
+
+ /**
+ * Shows a notification.
+ *
+ * @param {Object} data The message data
+ */
+ show(data) {
+ this.clearTimeouts();
+ this.shown = true;
+ this.textNode.textContent = data.message;
+ this.actionHandler = data.actionHandler;
+
+ this.button.textContent =
+ data.actionText || this.$translate.instant('Hide');
+
+ this.timeoutId = setTimeout(() =>
+ this.hide(), data.timeout || 6000);
+
+ this.transitionTimeout = setTimeout(() =>
+ this.$snackbar.addClass('shown'), 30);
+ }
+
+ /**
+ * Shows an error.
+ *
+ * @param {Object} data The message data
+ */
+ showError(data) {
+ this.$snackbar.addClass('error');
+ this.show(data);
+ }
+
+ /**
+ * Hides the snackbar.
+ */
+ hide() {
+ if (!this.shown) return;
+ clearTimeout(this.timeoutId);
+ this.shown = false;
+ this.hideTimeout = setTimeout(() => this.onTransitionEnd(), 250);
+
+ this.transitionTimeout =
+ setTimeout(() => this.$snackbar.removeClass('shown'), 30);
+ }
+
+ onTransitionEnd() {
+ this.$snackbar.removeClass('error');
+ this.textNode.textContent = '';
+ this.button.textContent = '';
+ this.actionHandler = null;
+ }
+
+ onSnackbarClick(event) {
+ this.event = event;
+ }
+
+ onButtonClick() {
+ if (this.actionHandler)
+ this.actionHandler();
+ else
+ this.hide();
+ }
+
+ clearTimeouts() {
+ clearTimeout(this.timeoutId);
+ clearTimeout(this.hideTimeout);
+ clearTimeout(this.transitionTimeout);
+ this.timeoutId = null;
+ this.hideTimeout = null;
+ this.transitionTimeout = null;
+ }
+
+ $onDestroy() {
+ this.clearTimeouts();
+ }
+}
+Controller.$inject = ['$element', '$translate'];
+
+ngModule.component('vnSnackbar', {
+ template: require('./snackbar.html'),
+ controller: Controller
+});
diff --git a/client/core/src/components/snackbar/style.scss b/client/core/src/components/snackbar/style.scss
new file mode 100644
index 000000000..513280243
--- /dev/null
+++ b/client/core/src/components/snackbar/style.scss
@@ -0,0 +1,48 @@
+vn-snackbar > div {
+ box-sizing: border-box;
+ background-color: #333;
+ color: white;
+ position: fixed;
+ bottom: 0;
+ left: 50%;
+ width: 20em;
+ margin-left: -10em;
+ padding: 1em;
+ border-top-left-radius: .2em;
+ border-top-right-radius: .2em;
+ transform: translateY(10em);
+ transition: transform 300ms ease-in-out;
+ z-index: 100;
+ box-shadow: 0 0 .4em rgba(1,1,1,.4);
+
+ &.shown {
+ transform: translateY(0);
+ }
+ &.notice {
+ background-color: #1e88e5;
+
+ & > button {
+ color: rgba(1, 1, 1, 0.6);
+ }
+ }
+ &.error {
+ background-color: #c62828;
+
+ & > button {
+ color: rgba(1, 1, 1, 0.6);
+ }
+ }
+ & > button {
+ cursor: pointer;
+ float: right;
+ text-transform: uppercase;
+ border: none;
+ background-color: transparent;
+ font-weight: bold;
+ color: #ffab40;
+ padding: 1em;
+ margin: -1em;
+ padding-left: 1.5em;
+ margin-left: 0;
+ }
+}
\ No newline at end of file
diff --git a/client/core/src/spinner/index.html b/client/core/src/components/spinner/spinner.html
similarity index 100%
rename from client/core/src/spinner/index.html
rename to client/core/src/components/spinner/spinner.html
diff --git a/client/core/src/spinner/index.js b/client/core/src/components/spinner/spinner.js
similarity index 81%
rename from client/core/src/spinner/index.js
rename to client/core/src/components/spinner/spinner.js
index 14419a4b7..ca87323d5 100644
--- a/client/core/src/spinner/index.js
+++ b/client/core/src/components/spinner/spinner.js
@@ -1,5 +1,5 @@
-import {module} from '../module';
-import Component from '../lib/component';
+import ngModule from '../../module';
+import Component from '../../lib/component';
import './style.css';
/**
@@ -14,8 +14,8 @@ export default class Spinner extends Component {
}
/**
* Enables/disables the spinner.
- *
- * @param {Boolean} %true to enable, %false to disable
+ *
+ * @param {Boolean} value %true to enable, %false to disable
*/
set enable(value) {
if (value)
@@ -25,7 +25,7 @@ export default class Spinner extends Component {
}
/**
* Returns the current spinner state.
- *
+ *
* @return {Boolean} %true if it's enabled, %false otherwise
*/
get enable() {
@@ -49,10 +49,10 @@ export default class Spinner extends Component {
Spinner.$inject = ['$element', '$scope'];
export const component = {
- template: require('./index.html'),
+ template: require('./spinner.html'),
bindings: {
enable: '='
},
controller: Spinner
};
-module.component('vnSpinner', component);
+ngModule.component('vnSpinner', component);
diff --git a/client/core/src/components/spinner/spinner.spec.js b/client/core/src/components/spinner/spinner.spec.js
new file mode 100644
index 000000000..d5bad0746
--- /dev/null
+++ b/client/core/src/components/spinner/spinner.spec.js
@@ -0,0 +1,63 @@
+import './spinner.js';
+
+describe('Component vnSpinner', () => {
+ let $componentController;
+ let $scope;
+ let $element;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $element = angular.element('');
+ controller = $componentController('vnSpinner', {$scope, $element});
+ }));
+
+ describe('enable()', () => {
+ it(`should call start() based on a boolean value passed as argument`, () => {
+ spyOn(controller, 'start');
+ spyOn(controller, 'stop');
+ controller.enable = true;
+
+ expect(controller.start).toHaveBeenCalledWith();
+ expect(controller.stop).not.toHaveBeenCalledWith();
+ });
+
+ it(`should call stop() based on a boolean value passed as argument`, () => {
+ spyOn(controller, 'start');
+ spyOn(controller, 'stop');
+ controller.enable = false;
+
+ expect(controller.start).not.toHaveBeenCalledWith();
+ expect(controller.stop).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('start()', () => {
+ it(`should call start() on the controller.materialSpinner then set controllers._enable to be truthy`, () => {
+ controller.spinner = {MaterialSpinner: {start: () => {}}};
+ spyOn(controller.spinner.MaterialSpinner, 'start');
+ controller._enable = false;
+ controller.start();
+
+ expect(controller.spinner.MaterialSpinner.start).toHaveBeenCalledWith();
+ expect(controller._enable).toBeTruthy();
+ });
+ });
+
+ describe('stop()', () => {
+ it(`should call stop() on the controller.materialSpinner then set controllers._enable to be truthy`, () => {
+ controller.spinner = {MaterialSpinner: {stop: () => {}}};
+ spyOn(controller.spinner.MaterialSpinner, 'stop');
+ controller._enable = true;
+ controller.stop();
+
+ expect(controller.spinner.MaterialSpinner.stop).toHaveBeenCalledWith();
+ expect(controller._enable).toBeFalsy();
+ });
+ });
+});
diff --git a/client/core/src/spinner/style.css b/client/core/src/components/spinner/style.css
similarity index 100%
rename from client/core/src/spinner/style.css
rename to client/core/src/components/spinner/style.css
diff --git a/client/core/src/components/submit/submit.html b/client/core/src/components/submit/submit.html
new file mode 100644
index 000000000..378920de0
--- /dev/null
+++ b/client/core/src/components/submit/submit.html
@@ -0,0 +1,7 @@
+
+
diff --git a/client/core/src/components/submit/submit.js b/client/core/src/components/submit/submit.js
new file mode 100644
index 000000000..6eb67dea8
--- /dev/null
+++ b/client/core/src/components/submit/submit.js
@@ -0,0 +1,16 @@
+import ngModule from '../../module';
+import template from './submit.html';
+
+directive.$inject = ['vnTemplate'];
+export default function directive(vnTemplate) {
+ return {
+ restrict: 'E',
+ template: (_, $attrs) =>
+ vnTemplate.get(template, $attrs, {
+ label: 'Submit',
+ className: 'mdl-button mdl-js-button mdl-button--raised mdl-button--colored',
+ enabled: 'true'
+ })
+ };
+}
+ngModule.directive('vnSubmit', directive);
diff --git a/client/core/src/subtitle/index.html b/client/core/src/components/subtitle/subtitle.html
similarity index 100%
rename from client/core/src/subtitle/index.html
rename to client/core/src/components/subtitle/subtitle.html
diff --git a/client/core/src/components/subtitle/subtitle.js b/client/core/src/components/subtitle/subtitle.js
new file mode 100644
index 000000000..577bdf83f
--- /dev/null
+++ b/client/core/src/components/subtitle/subtitle.js
@@ -0,0 +1,6 @@
+import ngModule from '../../module';
+
+ngModule.component('vnSubtitle', {
+ template: require('./subtitle.html'),
+ transclude: true
+});
diff --git a/client/core/src/switch/switch.mdl.html b/client/core/src/components/switch/switch.html
similarity index 100%
rename from client/core/src/switch/switch.mdl.html
rename to client/core/src/components/switch/switch.html
diff --git a/client/core/src/components/switch/switch.js b/client/core/src/components/switch/switch.js
new file mode 100644
index 000000000..c86d6f665
--- /dev/null
+++ b/client/core/src/components/switch/switch.js
@@ -0,0 +1,26 @@
+import ngModule from '../../module';
+
+directive.$inject = ['vnTemplate'];
+export default function directive(vnTemplate) {
+ return {
+ restrict: 'E',
+ template: (_, $attrs) =>
+ vnTemplate.getNormalized(template, $attrs, {
+ className: 'mdl-switch__input',
+ label: ''
+ }),
+ link: function(scope, element, attrs) {
+ scope.$watch(attrs.model, () => {
+ let mdlField = element[0].firstChild.MaterialSwitch;
+ if (mdlField)
+ mdlField.updateClasses_();
+ });
+ componentHandler.upgradeElement(element[0].firstChild);
+ }
+ };
+}
+ngModule.directive('vnSwitch', directive);
+
+export function factory() {
+}
+ngModule.factory('vnSwitchMdlFactory', factory);
diff --git a/client/core/src/components/textarea/style.scss b/client/core/src/components/textarea/style.scss
new file mode 100644
index 000000000..91b29b3cf
--- /dev/null
+++ b/client/core/src/components/textarea/style.scss
@@ -0,0 +1,6 @@
+vn-textarea {
+ & > .mdl-textfield {
+ width: initial;
+ display: block;
+ }
+}
\ No newline at end of file
diff --git a/client/core/src/components/textarea/textarea.html b/client/core/src/components/textarea/textarea.html
new file mode 100644
index 000000000..04102cd5e
--- /dev/null
+++ b/client/core/src/components/textarea/textarea.html
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/client/core/src/components/textarea/textarea.js b/client/core/src/components/textarea/textarea.js
new file mode 100644
index 000000000..122259ff3
--- /dev/null
+++ b/client/core/src/components/textarea/textarea.js
@@ -0,0 +1,24 @@
+import ngModule from '../../module';
+import template from './textarea.html';
+import './style.scss';
+
+directive.$inject = ['vnTemplate'];
+export function directive(vnTemplate) {
+ return {
+ restrict: 'E',
+ template: (_, $attrs) =>
+ vnTemplate.getNormalized(template, $attrs, {
+ label: '',
+ rows: 3
+ }),
+ link: function(scope, element, attrs) {
+ scope.$watch(attrs.model, () => {
+ let mdlField = element[0].firstChild.MaterialTextfield;
+ if (mdlField)
+ mdlField.updateClasses_();
+ });
+ componentHandler.upgradeElement(element[0].firstChild);
+ }
+ };
+}
+ngModule.directive('vnTextarea', directive);
diff --git a/client/core/src/components/textfield/style.scss b/client/core/src/components/textfield/style.scss
new file mode 100644
index 000000000..181ad8d8b
--- /dev/null
+++ b/client/core/src/components/textfield/style.scss
@@ -0,0 +1,45 @@
+vn-textfield {
+ .mdl-chip__action {
+ position: absolute;
+ width: auto;
+ top: 0px;
+ right: -6px;
+ margin: 21px 0px;
+ background: white;
+ opacity: 1;
+ z-index: 1;
+ color: #aaa;
+ }
+ .mdl-textfield {
+ width: 100%;
+ }
+ .mdl-textfield__error {
+ visibility: visible;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ width: 100%;
+ }
+ .mdl-textfield.invalid {
+ .mdl-textfield__input {
+ border-color: #d50000;
+ box-shadow: none;
+ }
+ .mdl-textfield__label::after {
+ background-color: #d50000;
+ }
+ }
+ .mdl-textfield--floating-label.invalid .mdl-textfield__label {
+ color: #d50000;
+ font-size: 12px;
+ top: 4px;
+ }
+ .material-icons {
+ font-size: 18px;
+ float: right;
+ margin-right: 5px;
+ }
+ .material-icons:hover {
+ color: rgba(0,0,0, .87);
+ }
+}
\ No newline at end of file
diff --git a/client/core/src/components/textfield/textfield.html b/client/core/src/components/textfield/textfield.html
new file mode 100644
index 000000000..43599186b
--- /dev/null
+++ b/client/core/src/components/textfield/textfield.html
@@ -0,0 +1,29 @@
+
+
+
+
+ info_outline
+
+
+ clear
+
+
+
+
diff --git a/client/core/src/components/textfield/textfield.js b/client/core/src/components/textfield/textfield.js
new file mode 100644
index 000000000..feb5b98a9
--- /dev/null
+++ b/client/core/src/components/textfield/textfield.js
@@ -0,0 +1,54 @@
+import ngModule from '../../module';
+import Input from '../../lib/input';
+import './style.scss';
+
+export default class Textfield extends Input {
+ constructor($element, $scope, $attrs, vnTemplate) {
+ super($element, $scope);
+ vnTemplate.normalizeInputAttrs($attrs);
+ this._value = null;
+ this.type = $attrs.type || 'text';
+ this.showActions = false;
+ this.hasInfo = Boolean($attrs.info);
+ this.info = $attrs.info || null;
+ this.hasFocus = false;
+ this.hasMouseIn = false;
+ componentHandler.upgradeElement($element[0].firstChild);
+ }
+ get value() {
+ return this._value;
+ }
+ set value(value) {
+ this._value = (value === undefined || value === '') ? null : value;
+ this.input.value = this._value;
+ this.hasValue = Boolean(this._value);
+ this.mdlUpdate();
+ }
+ set tabIndex(value) {
+ this.input.tabIndex = value;
+ }
+ clear() {
+ this.value = null;
+ this.input.focus();
+ }
+ mdlUpdate() {
+ let mdlElement = this.element.firstChild.MaterialTextfield;
+ if (mdlElement) mdlElement.updateClasses_();
+ }
+}
+Textfield.$inject = ['$element', '$scope', '$attrs', 'vnTemplate'];
+
+ngModule.component('vnTextfield', {
+ template: require('./textfield.html'),
+ controller: Textfield,
+ bindings: {
+ value: '=model',
+ label: '@?',
+ name: '@?',
+ disabled: '',
+ readonly: '',
+ rule: '@?',
+ type: '@?',
+ tabIndex: '@?'
+ }
+});
diff --git a/client/core/src/components/textfield/textfield.spec.js b/client/core/src/components/textfield/textfield.spec.js
new file mode 100644
index 000000000..9eea12b0c
--- /dev/null
+++ b/client/core/src/components/textfield/textfield.spec.js
@@ -0,0 +1,47 @@
+import './textfield.js';
+
+describe('Component vnTextfield', () => {
+ let $componentController;
+ let $scope;
+ let $attrs;
+ let $timeout;
+ let $element;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $attrs = {};
+ $timeout = _$timeout_;
+ $element = angular.element('');
+ controller = $componentController('vnTextfield', {$scope, $element, $attrs, $timeout});
+ }));
+
+ describe('value() setter', () => {
+ it(`should set _value, input.value and hasValue properties to null, '' and false then call mdlUpdate()`, () => {
+ spyOn(controller, 'mdlUpdate');
+ let testValue = '';
+ controller.value = testValue;
+
+ expect(controller._value).toEqual(null);
+ expect(controller.input.value).toEqual(testValue);
+ expect(controller.hasValue).toEqual(Boolean(testValue));
+ expect(controller.mdlUpdate).toHaveBeenCalledWith();
+ });
+
+ it(`should set _value, input.value and hasValue propertiest to test, test and true then call mdlUpdate()`, () => {
+ spyOn(controller, 'mdlUpdate');
+ let testValue = 'test';
+ controller.value = testValue;
+
+ expect(controller._value).toEqual(testValue);
+ expect(controller.input.value).toEqual(testValue);
+ expect(controller.hasValue).toEqual(Boolean(testValue));
+ expect(controller.mdlUpdate).toHaveBeenCalledWith();
+ });
+ });
+});
diff --git a/client/core/src/components/title/title.html b/client/core/src/components/title/title.html
new file mode 100644
index 000000000..773b40040
--- /dev/null
+++ b/client/core/src/components/title/title.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/client/core/src/components/title/title.js b/client/core/src/components/title/title.js
new file mode 100644
index 000000000..15e0b7c84
--- /dev/null
+++ b/client/core/src/components/title/title.js
@@ -0,0 +1,6 @@
+import ngModule from '../../module';
+
+ngModule.component('vnTitle', {
+ template: require('./title.html'),
+ transclude: true
+});
diff --git a/client/core/src/components/tooltip/style.css b/client/core/src/components/tooltip/style.css
new file mode 100644
index 000000000..0a5ca7e23
--- /dev/null
+++ b/client/core/src/components/tooltip/style.css
@@ -0,0 +1,60 @@
+.tooltip {
+ display: none;
+ position: fixed;
+ background-color: #fff;
+ padding: 20px;
+ color: #424242;
+ z-index: 999;
+ border: 1px solid #A7A7A7;
+ text-align: justify;
+}
+
+.tooltip-show {
+ display: inherit;
+}
+
+.tooltip-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+}
+
+.tooltip-text{
+ max-width: 320px;
+}
+
+.tooltip-down .tooltip-arrow {
+ top: -15px;
+ left: 50%;
+ margin-left: -10px;
+ border-left: 10px solid transparent;
+ border-right: 10px solid transparent;
+ border-bottom: 15px solid #A7A7A7;
+}
+
+.tooltip-up .tooltip-arrow {
+ bottom: -15px;
+ left: 50%;
+ margin-left: -10px;
+ border-left: 10px solid transparent;
+ border-right: 10px solid transparent;
+ border-top: 15px solid #A7A7A7;
+}
+
+.tooltip-right .tooltip-arrow {
+ left: -15px;
+ top: 50%;
+ margin-top: -10px;
+ border-top: 10px solid transparent;
+ border-bottom: 10px solid transparent;
+ border-right: 15px solid #A7A7A7;
+}
+
+.tooltip-left .tooltip-arrow {
+ right: -15px;
+ top: 50%;
+ margin-top: -10px;
+ border-top: 10px solid transparent;
+ border-bottom: 10px solid transparent;
+ border-left: 15px solid #A7A7A7;
+}
diff --git a/client/core/src/components/tooltip/tooltip.js b/client/core/src/components/tooltip/tooltip.js
new file mode 100644
index 000000000..052e30267
--- /dev/null
+++ b/client/core/src/components/tooltip/tooltip.js
@@ -0,0 +1,159 @@
+import ngModule from '../../module';
+import './style.css';
+
+tooltip.$inject = ['$document', '$compile', '$interpolate', '$sce', '$templateCache', '$http', '$q'];
+function tooltip($document, $compile, $interpolate, $sce, $templateCache, $http, $q) {
+ var promise;
+
+ function _getTemplate(tooltipTemplateUrl) {
+ var template = $templateCache.get(tooltipTemplateUrl);
+ if (typeof template === 'undefined') {
+ template = $http.get(tooltipTemplateUrl).then(function onGetTemplateSuccess(response) {
+ if (promise) {
+ promise.resolve(response.data);
+ }
+ promise = undefined;
+ return response.data;
+ });
+ $templateCache.put(tooltipTemplateUrl, template);
+ }
+ return template;
+ }
+
+ function getTemplate(tooltipTemplateUrl) {
+ var _promise = $q.defer();
+ var template = _getTemplate(tooltipTemplateUrl);
+ if (template) {
+ _promise.resolve(template);
+ } else {
+ promise = _promise;
+ }
+ return _promise.promise;
+ }
+
+ return {
+ restrict: 'A',
+ priority: -1,
+ link: function($scope, element, attrs) {
+ let tipHtml = '';
+ let tip;
+ let tipClassName = 'tooltip';
+ let tipActiveClassName = 'tooltip-show';
+ let scope = $scope.$new();
+
+ scope.tipClass = [tipClassName];
+ scope.text = attrs.vnTooltip || '';
+
+ if (attrs.tooltipHtml) {
+ scope.isHtmlContent = true;
+ scope.htmlContent = $sce.trustAsHtml(attrs.tooltipHtml);
+ _compileTip();
+ } else if (attrs.tooltipTemplate) {
+ getTemplate(attrs.tooltipTemplate).then(template => {
+ scope.isHtmlContent = true;
+ scope.htmlContent = $sce.trustAsHtml($interpolate(template)(scope));
+ _compileTip();
+ });
+ } else {
+ scope.isHtmlContent = false;
+ scope.htmlContent = null;
+ _compileTip();
+ }
+
+ if (attrs.tooltipPosition) {
+ scope.tipClass.push('tooltip-' + attrs.tooltipPosition);
+ } else {
+ scope.tipClass.push('tooltip-down');
+ }
+
+ function _compileTip() {
+ tip = $compile(tipHtml)(scope);
+ $document.find('body').append(tip);
+ _bindEvents();
+ }
+
+ function _bindEvents() {
+ element.bind('mouseover', function(e) {
+ _showTooltip(e);
+ });
+
+ element.on('mouseout', function() {
+ _hideTooltip();
+ });
+
+ tip.on('mouseover', function(e) {
+ _showTooltip(e);
+ });
+
+ tip.on('mouseout', function() {
+ _hideTooltip();
+ });
+
+ element.on('$destroy', function() {
+ tip.remove();
+ scope.$destroy();
+ });
+ }
+
+ function _calculatePosition(e) {
+ let pos = element[0].getBoundingClientRect();
+ let tipPos = tip[0].getBoundingClientRect();
+ let offset = {top: 0, left: 0};
+ let tipWidth = tipPos.width || tipPos.right - tipPos.left;
+ let tipHeight = tipPos.height || tipPos.bottom - tipPos.top;
+ let elWidth = pos.width || pos.right - pos.left;
+ let elHeight = pos.height || pos.bottom - pos.top;
+ let tipOffset = 10;
+
+ if (tip.hasClass('tooltip-right')) {
+ offset.top = pos.top - (tipHeight / 2) + (elHeight / 2);
+ offset.left = pos.right + tipOffset;
+ } else if (tip.hasClass('tooltip-left')) {
+ offset.top = pos.top - (tipHeight / 2) + (elHeight / 2);
+ offset.left = pos.left - tipWidth - tipOffset;
+ } else if (tip.hasClass('tooltip-down')) {
+ offset.top = pos.top + elHeight + tipOffset;
+ offset.left = pos.left - (tipWidth / 2) + (elWidth / 2);
+ } else {
+ offset.top = pos.top - tipHeight - tipOffset;
+ offset.left = pos.left - (tipWidth / 2) + (elWidth / 2);
+ }
+ // outsides
+ if (offset.left + tipPos.width > window.innerWidth) { // right outside
+ let diffLeft = (offset.left + tipPos.width) - window.innerWidth;
+ offset.left -= diffLeft + 10;
+
+ let arrow = tip[0].querySelector('.tooltip-arrow');
+ if (arrow) {
+ angular.element(arrow).css('margin-left', diffLeft + 'px');
+ }
+ } else if (offset.left < 10) { // left outside
+ offset.left = 10;
+ let arrow = tip[0].querySelector('.tooltip-arrow');
+ if (arrow) {
+ angular.element(arrow).css('margin-left', '10px');
+ }
+ }
+ if (offset.top > window.innerHeight) { // down outside
+ offset.top = pos.top - tipHeight - tipOffset;
+ } else if (offset.top < 10) { // top outside
+ offset.top = pos.top + elHeight + tipOffset;
+ }
+
+ tip.css('top', offset.top + 'px');
+ tip.css('left', offset.left + 'px');
+ }
+
+ function _showTooltip(e) {
+ tip.addClass(tipActiveClassName);
+ _calculatePosition(e);
+ }
+
+ function _hideTooltip() {
+ tip.removeClass(tipActiveClassName);
+ }
+ }
+ };
+}
+
+ngModule.directive('vnTooltip', tooltip);
diff --git a/client/core/src/components/watcher/locale/es.yml b/client/core/src/components/watcher/locale/es.yml
new file mode 100644
index 000000000..5d25752b4
--- /dev/null
+++ b/client/core/src/components/watcher/locale/es.yml
@@ -0,0 +1,4 @@
+Are you sure exit without saving?: ¿Seguro que quieres salir sin guardar?
+Unsaved changes will be lost: Los cambios que no hayas guardado se perderán
+No changes to save: No hay cambios que guardar
+Some fields are invalid: Algunos campos no son válidos
\ No newline at end of file
diff --git a/client/core/src/watcher/index.html b/client/core/src/components/watcher/watcher.html
similarity index 100%
rename from client/core/src/watcher/index.html
rename to client/core/src/components/watcher/watcher.html
diff --git a/client/core/src/components/watcher/watcher.js b/client/core/src/components/watcher/watcher.js
new file mode 100644
index 000000000..7b5317ca4
--- /dev/null
+++ b/client/core/src/components/watcher/watcher.js
@@ -0,0 +1,235 @@
+import ngModule from '../../module';
+import Component from '../../lib/component';
+import getModifiedData from '../../lib/modified';
+import copyObject from '../../lib/copy';
+import isEqual from '../../lib/equals';
+import isFullEmpty from '../../lib/full-empty';
+
+/**
+ * Component that checks for changes on a specific model property and
+ * asks the user to save or discard it when the state changes.
+ * Also it can save the data to the server when the @url and @idField
+ * properties are provided.
+ */
+export default class Watcher extends Component {
+ constructor($element, $scope, $state, $transitions, $http, vnApp, $translate, $attrs) {
+ super($element);
+ this.$scope = $scope;
+ this.$state = $state;
+ this.$http = $http;
+ this.$translate = $translate;
+ this.$attrs = $attrs;
+ this.vnApp = vnApp;
+
+ this.state = null;
+ this.deregisterCallback = $transitions.onStart({},
+ transition => this.callback(transition));
+ this.updateOriginalData();
+ }
+
+ $onInit() {
+ if (this.get && this.url) {
+ this.fetchData();
+ } else if (this.get && !this.url) {
+ throw new Error('Error: Parameter url ommitted');
+ }
+ }
+
+ $onChanges(changes) {
+ if (this.data) {
+ this.updateOriginalData();
+ }
+ }
+
+ $onDestroy() {
+ this.deregisterCallback();
+ }
+
+ fetchData() {
+ let id = this.data[this.idField];
+ // return new Promise((resolve, reject) => {
+ this.$http.get(`${this.url}/${id}`).then(
+ json => {
+ this.data = copyObject(json.data);
+ this.updateOriginalData();
+ }
+ // json => reject(json)
+ );
+ // });
+ }
+
+ /**
+ * Submits the data and goes back in the history.
+ *
+ * @return {Promise} The request promise
+ */
+ submitBack() {
+ return this.submit().then(
+ () => this.window.history.back()
+ );
+ }
+
+ /**
+ * Submits the data and goes another state.
+ *
+ * @param {String} state The state name
+ * @param {Object} params The request params
+ * @return {Promise} The request promise
+ */
+ submitGo(state, params) {
+ return this.submit().then(
+ () => this.$state.go(state, params || {})
+ );
+ }
+
+ /**
+ * Submits the data to the server.
+ *
+ * @return {Promise} The http request promise
+ */
+ submit() {
+ if (this.form) {
+ this.form.$setSubmitted();
+
+ if (!this.form.$valid)
+ return new Promise(
+ (resolve, reject) => this.invalidForm(reject)
+ );
+ }
+ if (!this.dataChanged()) {
+ return new Promise(
+ (resolve, reject) => this.noChanges(reject)
+ );
+ }
+ let isPost = (this.$attrs.save && this.$attrs.save.toLowerCase() === 'post');
+ let changedData = isPost
+ ? this.copyInNewObject(this.data)
+ : getModifiedData(this.data, this.orgData);
+
+ if (this.requiredField && !changedData[this.requiredField]) {
+ let required = this.data[this.requiredField] || this.orgData[this.requiredField];
+ if (required === undefined) {
+ return new Promise(
+ (resolve, reject) => this.invalidForm(reject)
+ );
+ }
+ changedData[this.requiredField] = required;
+ }
+
+ if (this.save && this.save.accept) {
+ this.save.model = changedData; // this.copyInNewObject(changedData);
+ return new Promise((resolve, reject) => {
+ this.save.accept().then(
+ json => this.writeData({data: json}, resolve),
+ json => reject(json)
+ );
+ });
+ }
+
+ // XXX: Alternative when mgCrud is not used
+
+ let id = this.idField ? this.orgData[this.idField] : null;
+
+ if (id) {
+ return new Promise((resolve, reject) => {
+ this.$http.patch(`${this.url}/${id}`, changedData).then(
+ json => this.writeData(json, resolve),
+ json => reject(json)
+ );
+ });
+ }
+
+ return new Promise((resolve, reject) => {
+ this.$http.post(this.url, changedData).then(
+ json => this.writeData(json, resolve),
+ json => reject(json)
+ );
+ });
+ }
+
+ writeData(json, resolve) {
+ Object.assign(this.data, json.data);
+ this.updateOriginalData();
+ resolve(json);
+ }
+
+ noChanges(resolve) {
+ this.vnApp.showMessage(
+ this.$translate.instant('No changes to save')
+ );
+ resolve();
+ }
+
+ invalidForm(resolve) {
+ this.vnApp.showMessage(
+ this.$translate.instant('Some fields are invalid')
+ );
+ resolve();
+ }
+
+ updateOriginalData() {
+ this.orgData = this.copyInNewObject(this.data);
+ if (this.form && this.form.$dirty)
+ this.form.$setPristine();
+ }
+
+ copyInNewObject(data) {
+ let newCopy = {};
+ if (data && typeof data === 'object') {
+ Object.keys(data).forEach(
+ val => {
+ if (!isFullEmpty(data[val])) {
+ if (typeof data[val] === 'object') {
+ newCopy[val] = this.copyInNewObject(data[val]);
+ } else {
+ newCopy[val] = data[val];
+ }
+ }
+ }
+ );
+ }
+ return newCopy;
+ }
+
+ callback(transition) {
+ let dataChanged = this.dataChanged();
+ if (!this.state && dataChanged) {
+ this.state = transition.to().name;
+ this.$scope.confirm.show();
+ return false;
+ }
+
+ return true;
+ }
+
+ dataChanged() {
+ if (this.form && this.form.$dirty) return true;
+ let newData = this.copyInNewObject(this.data);
+ return !isEqual(newData, this.orgData);
+ }
+
+ onConfirmResponse(response) {
+ if (response === 'ACCEPT') {
+ if (this.data)
+ Object.assign(this.data, this.orgData);
+ this.$state.go(this.state);
+ } else {
+ this.state = null;
+ }
+ }
+}
+Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnApp', '$translate', '$attrs'];
+
+ngModule.component('vnWatcher', {
+ template: require('./watcher.html'),
+ bindings: {
+ url: '@?',
+ idField: '@?',
+ requiredField: '@?',
+ data: '<',
+ form: '<',
+ save: '<',
+ get: '=?'
+ },
+ controller: Watcher
+});
diff --git a/client/core/src/components/watcher/watcher.spec.js b/client/core/src/components/watcher/watcher.spec.js
new file mode 100644
index 000000000..88305c819
--- /dev/null
+++ b/client/core/src/components/watcher/watcher.spec.js
@@ -0,0 +1,297 @@
+import './watcher.js';
+import getModifiedData from '../../lib/modified';
+
+describe('Component vnWatcher', () => {
+ let $componentController;
+ let $scope;
+ let $element;
+ let $state;
+ let $transitions;
+ let $httpBackend;
+ let vnApp;
+ let $translate;
+ let controller;
+ let $attrs;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_, _$transitions_, _$httpBackend_, _vnApp_, _$translate_) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $element = angular.element('');
+ $state = _$state_;
+ vnApp = _vnApp_;
+ $transitions = _$transitions_;
+ $httpBackend = _$httpBackend_;
+ $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ $translate = _$translate_;
+ $attrs = {
+ save: "patch"
+ };
+ controller = $componentController('vnWatcher', {$scope, $element, $state, vnApp, $transitions, $httpBackend, $translate, $attrs});
+ }));
+
+ describe('$onInit()', () => {
+ it(`should call fetchData() if controllers get and url properties are defined`, () => {
+ controller.get = () => {};
+ controller.url = 'test.com';
+ spyOn(controller, 'fetchData');
+ controller.$onInit();
+
+ expect(controller.fetchData).toHaveBeenCalledWith();
+ });
+
+ it(`should throw an error if $onInit is called without url defined`, () => {
+ controller.get = () => {};
+
+ expect(function() {
+ controller.$onInit();
+ }).toThrow(new Error('Error: Parameter url ommitted'));
+ });
+ });
+
+ describe('$onChanges()', () => {
+ it(`should call updateOriginalData() if controllers data is defined`, () => {
+ controller.data = [];
+ spyOn(controller, 'updateOriginalData');
+ controller.$onChanges();
+
+ expect(controller.updateOriginalData).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('$onDestroy()', () => {
+ it(`should call deregisterCallback()`, () => {
+ spyOn(controller, 'deregisterCallback');
+ controller.$onDestroy();
+
+ expect(controller.deregisterCallback).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('fetchData()', () => {
+ it(`should perform a query then store the received data into controller.data and call updateOriginalData()`, () => {
+ spyOn(controller, 'updateOriginalData');
+ let json = {data: 'some data'};
+ controller.data = [1];
+ controller.idField = 0;
+ controller.url = 'test.com';
+ $httpBackend.whenGET('test.com/1').respond(json);
+ $httpBackend.expectGET('test.com/1');
+ controller.fetchData();
+ $httpBackend.flush();
+
+ expect(controller.data).toEqual({data: 'some data'});
+ expect(controller.updateOriginalData).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('submitBack()', () => {
+ it(`should call controller.window.history.back() function after calling controllers submit() function`, done => {
+ spyOn(controller, 'submit').and.returnValue(Promise.resolve());
+ spyOn(controller.window.history, 'back');
+ controller.submitBack()
+ .then(() => {
+ expect(controller.submit).toHaveBeenCalledWith();
+ expect(controller.window.history.back).toHaveBeenCalledWith();
+ done();
+ });
+ });
+ });
+
+ describe('submitGo()', () => {
+ it(`should call controller.$state.go() function after calling controllers submit() function`, done => {
+ spyOn(controller, 'submit').and.returnValue(Promise.resolve());
+ spyOn(controller.$state, 'go');
+ let state = 'the.State';
+ controller.submitGo(state)
+ .then(() => {
+ expect(controller.submit).toHaveBeenCalledWith();
+ expect(controller.$state.go).toHaveBeenCalledWith(state, {});
+ done();
+ });
+ });
+ });
+
+ describe('submit()', () => {
+ describe('when controller.form', () => {
+ it(`should call controller.form.setSubminted if controller.form is defined`, () => {
+ controller.form = {$setSubmitted: () => {}};
+ spyOn(controller.form, '$setSubmitted');
+ controller.submit();
+
+ expect(controller.form.$setSubmitted).toHaveBeenCalledWith();
+ });
+
+ it(`should call controller.invalidForm if controller.form.$valid is not defined`, () => {
+ controller.form = {$setSubmitted: () => {}};
+ spyOn(controller, 'invalidForm');
+ controller.submit();
+
+ expect(controller.invalidForm).toHaveBeenCalledWith(jasmine.any(Function));
+ });
+ });
+
+ describe('when !controller.dataChanged()', () => {
+ it(`should call controller.noChanges()`, () => {
+ spyOn(controller, 'noChanges');
+ controller.submit();
+
+ expect(controller.noChanges).toHaveBeenCalledWith(jasmine.any(Function));
+ });
+ });
+
+ describe('when controller.save()', () => {
+ it(`should set controller.save.model property`, () => {
+ controller.save = {accept: () => {}};
+ controller.data = {originalInfo: 'original data', info: 'new data'};
+ controller.orgData = {originalInfo: 'original data'};
+ controller.submit();
+
+ expect(controller.save.model).toEqual({info: 'new data'});
+ });
+
+ it(`should call controller.save.accept() then controller.writeData`, done => {
+ controller.save = {accept: () => {}};
+ controller.data = {originalInfo: 'original data', info: 'new data'};
+ controller.orgData = {originalInfo: 'original data'};
+ spyOn(controller.save, 'accept').and.returnValue(Promise.resolve());
+ spyOn(controller, 'writeData').and.callThrough();
+ controller.submit()
+ .then(() => {
+ expect(controller.save.accept).toHaveBeenCalledWith();
+ expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
+ done();
+ });
+ });
+ });
+
+ describe('when id is defined', () => {
+ it(`should perform a query then call controller.writeData()`, () => {
+ controller.dataChanged = () => {
+ return true;
+ };
+ controller.data = {id: 2};
+ controller.orgData = {id: 1};
+ let changedData = getModifiedData(controller.data, controller.orgData);
+ controller.idField = 'id';
+ controller.url = 'test.com';
+ let json = {data: 'some data'};
+ spyOn(controller, 'writeData').and.callThrough();
+ $httpBackend.whenPATCH(`${controller.url}/1`, changedData).respond(json);
+ $httpBackend.expectPATCH(`${controller.url}/1`);
+ controller.submit()
+ .then(() => {
+ expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
+ done();
+ });
+ $httpBackend.flush();
+ });
+ });
+
+ it(`should perform a POST query then call controller.writeData()`, () => {
+ controller.dataChanged = () => {
+ return true;
+ };
+ controller.data = {id: 2};
+ controller.orgData = {id: 1};
+ controller.url = 'test.com';
+ let json = {data: 'some data'};
+ spyOn(controller, 'writeData').and.callThrough();
+ $httpBackend.whenPOST(`${controller.url}`, controller.data).respond(json);
+ $httpBackend.expectPOST(`${controller.url}`, controller.data);
+ controller.submit()
+ .then(() => {
+ expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
+ done();
+ });
+ $httpBackend.flush();
+ });
+ });
+
+ describe('writeData()', () => {
+ it(`should call Object.asssign() function over controllers.data with json.data, then call updateOriginalData function and finally call resolve() function`, () => {
+ spyOn(controller, 'updateOriginalData');
+ controller.data = {};
+ let json = {data: 'some data'};
+ let resolve = jasmine.createSpy('resolve');
+ controller.writeData(json, resolve);
+
+ expect(controller.updateOriginalData).toHaveBeenCalledWith();
+ expect(resolve).toHaveBeenCalledWith(json);
+ });
+ });
+
+ describe('copyInNewObject()', () => {
+ it(`should return newCopy object if data was an object`, () => {
+ let data = {id: 1, Heroname: 'Batman', name: 'Bruce Wayne'};
+ let result = controller.copyInNewObject(data);
+
+ expect(result).toEqual(data);
+ });
+ });
+
+ describe('callback()', () => {
+ describe(`when dataChanged() returns true and there's no state in the controller`, () => {
+ it(`should define controller.state, call controller.$scope.confirm.show() and return false`, () => {
+ $scope.confirm = {show: jasmine.createSpy('show')};
+ controller.dataChanged = () => {
+ return true;
+ };
+ controller.state = undefined;
+ let transition = {to: () => {
+ return {name: 'Batman'};
+ }};
+ let result = controller.callback(transition);
+
+ expect(controller.state).toEqual('Batman');
+ expect(controller.$scope.confirm.show).toHaveBeenCalledWith();
+ expect(result).toBeFalsy();
+ });
+ });
+
+ describe(`when dataChanged() returns false and/or there's a state in the controller`, () => {
+ it(`should return true`, () => {
+ $scope.confirm = {show: jasmine.createSpy('show')};
+ controller.dataChanged = () => {
+ return false;
+ };
+ controller.state = 'the state';
+ let transition = {to: () => {
+ return {name: 'Batman'};
+ }};
+ let result = controller.callback(transition);
+
+ expect(result).toBeTruthy();
+ });
+ });
+ });
+
+ describe(`onConfirmResponse()`, () => {
+ describe(`when response is ACCEPT`, () => {
+ it(`should call Object.assing on controlle.data with controller.orgData then call go() on state`, () => {
+ let response = 'ACCEPT';
+ controller.data = {};
+ controller.orgData = {name: 'Batman'};
+ controller.$state = {go: jasmine.createSpy('go')};
+ controller.state = 'Batman';
+ controller.onConfirmResponse(response);
+
+ expect(controller.data).toEqual(controller.orgData);
+ expect(controller.$state.go).toHaveBeenCalledWith(controller.state);
+ });
+ });
+
+ describe(`when response is not ACCEPT`, () => {
+ it(`should set controller.state to null`, () => {
+ let response = 'anything but ACCEPT';
+ controller.state = 'Batman';
+ controller.onConfirmResponse(response);
+
+ expect(controller.state).toBeFalsy();
+ });
+ });
+ });
+});
diff --git a/client/core/src/config.js b/client/core/src/config.js
deleted file mode 100644
index 5b627b054..000000000
--- a/client/core/src/config.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import {module} from './module';
-
-config.$inject = ['$translateProvider', '$translatePartialLoaderProvider'];
-export function config($translateProvider, $translatePartialLoaderProvider) {
- $translatePartialLoaderProvider.addPart('core');
-
- let conf = {urlTemplate: '/static/locale/{part}/{lang}.json'};
- let langs = ['en', 'es'];
- let localLangs = {
- 'en_US': 'en',
- 'en_UK': 'en',
- 'es_ES': 'es',
- 'es_AR': 'es'
- };
- $translateProvider
- .useSanitizeValueStrategy('escape')
- .useLoader('$translatePartialLoader', conf)
- .registerAvailableLanguageKeys(langs, localLangs)
- .determinePreferredLanguage();
-}
-module.config(config);
diff --git a/client/core/src/confirm/index.html b/client/core/src/confirm/index.html
deleted file mode 100644
index 1b8decb22..000000000
--- a/client/core/src/confirm/index.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/client/core/src/confirm/index.js b/client/core/src/confirm/index.js
deleted file mode 100644
index 4f63e8a55..000000000
--- a/client/core/src/confirm/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import {module} from '../module';
-import Dialog from '../dialog/index';
-import './style.css';
-
-export default class Confirm extends Dialog {
- constructor($element) {
- super($element);
- }
-}
-Dialog.$inject = ['$element'];
-
-module.component('vnConfirm', {
- template: require('./index.html'),
- bindings: {
- onResponse: '&',
- question: '@',
- message: '@'
- },
- controller: Confirm
-});
diff --git a/client/core/src/confirm/style.css b/client/core/src/confirm/style.css
deleted file mode 100644
index dc8f595c9..000000000
--- a/client/core/src/confirm/style.css
+++ /dev/null
@@ -1,5 +0,0 @@
-
-vn-dialog .dialog-title {
- color:#424242;
- font-family: raleway-bold;
-}
diff --git a/client/core/src/core.js b/client/core/src/core.js
index bb9eb7f56..d3601a8e1 100644
--- a/client/core/src/core.js
+++ b/client/core/src/core.js
@@ -1,6 +1,7 @@
-export * from './config';
+import './styles';
+
export * from './module';
-export * from './directives/index';
-export * from './filters/index';
-export * from './lib/index';
+export * from './directives';
+export * from './filters';
+export * from './lib';
export * from './components';
diff --git a/client/core/src/date-picker/date-picker.js b/client/core/src/date-picker/date-picker.js
deleted file mode 100644
index 8b02d1236..000000000
--- a/client/core/src/date-picker/date-picker.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as normalizerFactory from '../lib/inputAttrsNormalizer';
-import * as util from '../lib/util';
-
-const _NAME = 'datePicker';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME, normalizerFactory.NAME];
-export function directive(resolve, normalizer) {
- return {
- restrict: 'E',
- template: function(_, attrs) {
- normalizer.normalize(attrs);
- return resolve.getTemplate(_NAME, attrs);
- },
- link: function(scope, element, attrs) {
- scope.$watch(attrs.model, () => {
- let mdlField = element[0].firstChild.MaterialTextfield;
- if (mdlField)
- mdlField.updateClasses_();
- });
- componentHandler.upgradeElement(element[0].firstChild);
- }
- };
-}
-_module.directive(NAME, directive);
diff --git a/client/core/src/date-picker/date-picker.mdl.html b/client/core/src/date-picker/date-picker.mdl.html
deleted file mode 100644
index 292b43c09..000000000
--- a/client/core/src/date-picker/date-picker.mdl.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/client/core/src/date-picker/date-picker.mdl.js b/client/core/src/date-picker/date-picker.mdl.js
deleted file mode 100644
index 6939367fa..000000000
--- a/client/core/src/date-picker/date-picker.mdl.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import {module} from '../module';
-import template from './date-picker.mdl.html';
-
-export const NAME = 'vnDatePickerMdlFactory';
-export function factory() {
- return {
- template: template,
- default: {
- label: 'Label',
- enabled: 'enabled'
- }
- }
-}
-module.factory(NAME, factory);
diff --git a/client/core/src/dialog/index.html b/client/core/src/dialog/index.html
deleted file mode 100644
index f491e0249..000000000
--- a/client/core/src/dialog/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
\ No newline at end of file
diff --git a/client/core/src/dialog/index.js b/client/core/src/dialog/index.js
deleted file mode 100644
index 431c41df6..000000000
--- a/client/core/src/dialog/index.js
+++ /dev/null
@@ -1,111 +0,0 @@
-import {module} from '../module';
-import Component from '../lib/component';
-import './style.scss';
-
-/**
- * Dialog component.
- */
-export default class Dialog extends Component {
- /**
- * Contructor.
- */
- constructor($element) {
- super($element);
- $element.addClass('vn-dialog');
- this.dialog = $element[0].firstChild;
- this.element.addEventListener('mousedown',
- event => this.onBackgroundMouseDown(event));
- }
- /**
- * Displays the dialog to the user.
- */
- show() {
- let style = this.dialog.style;
- let screenMargin = 20;
-
- let window = this.window;
- let innerWidth = window.innerWidth;
- let innerHeight = window.innerHeight;
- let width = this.dialog.offsetWidth;
- let height = this.dialog.offsetHeight;
-
- if(width + screenMargin > innerWidth) {
- width = innerWidth - dblMargin;
- style.width = width +'px';
- }
- if(height + screenMargin > innerHeight) {
- height = innerHeight - dblMargin;
- style.height = height +'px';
- }
-
- this.keypressHandler =
- event => this.onKeypress(event);
- this.document.addEventListener('keypress',
- this.keypressHandler);
- this.element.style.display = 'block';
-
- if(this.onOpen)
- this.onOpen();
- }
- /**
- * Hides the dialog calling the response handler.
- */
- hide() {
- this.fireResponse();
- this.realHide();
- }
- /**
- * Calls the response handler.
- */
- fireResponse(response) {
- let cancel = false;
- if(this.onResponse)
- cancel = this.onResponse({response: response});
- return cancel;
- }
- realHide() {
- this.element.style.display = 'none';
- this.document.removeEventListener('keypress',
- this.keypressHandler);
- this.lastEvent = null;
- }
- onButtonClick(event) {
- let buttonBar = this.element.querySelector('.button-bar');
- let buttons = buttonBar.querySelector('buttons');
- let node = event.target;
-
- while(node.parentNode != buttons) {
- if(node == buttonBar) return;
- node = node.parentNode;
- }
-
- let response = node.getAttribute('response');
- let cancel = this.fireResponse(response);
- if(cancel !== false) this.realHide();
- }
- onDialogMouseDown(event) {
- this.lastEvent = event;
- }
- onBackgroundMouseDown(event) {
- if (event != this.lastEvent)
- this.hide();
- }
- onKeypress(event) {
- if(event.keyCode == 27) // Esc
- this.hide();
- }
-}
-Dialog.$inject = ['$element'];
-
-module.component('vnDialog', {
- template: require('./index.html'),
- transclude: {
- dbody: 'dbody',
- buttons: 'buttons'
- },
- bindings: {
- onOpen: '&',
- onResponse: '&'
- },
- controller: Dialog
-});
diff --git a/client/core/src/dialog/style.scss b/client/core/src/dialog/style.scss
deleted file mode 100644
index dba0096c8..000000000
--- a/client/core/src/dialog/style.scss
+++ /dev/null
@@ -1,48 +0,0 @@
-.vn-dialog {
- display: none;
- z-index: 100;
- position: fixed;
- left: 0;
- top: 0;
- height: 100%;
- width: 100%;
- background-color: rgba(1,1,1,.4);
-
- & > div {
- position: relative;
- box-shadow: 0 0 .4em rgba(1,1,1,.4);
- background-color: white;
- border-radius: .2em;
- overflow: auto;
- top: 50%;
- left: 50%;
- padding: 2em;
- box-sizing: border-box;
-
- width: 28em;
- margin-top: -10em;
- margin-left: -14em;
- }
-
- .button-bar {
- margin-top: 1.5em;
- text-align: right;
- }
-
- button {
- background: none;
- border: none;
- text-transform: uppercase;
- font-size: 1.1em;
- color: #ffa410;
- font-weight: bold;
- cursor: pointer;
- padding: .5em;
- margin: -0.5em;
- margin-left: .5em;
-
- &:hover {
- background-color: rgba(1,1,1,.1);
- }
- }
-}
diff --git a/client/core/src/directives/acl.js b/client/core/src/directives/acl.js
new file mode 100644
index 000000000..c32b02830
--- /dev/null
+++ b/client/core/src/directives/acl.js
@@ -0,0 +1,103 @@
+import ngModule from '../module';
+
+function vnAcl(aclService, $timeout) {
+ let acls = [];
+
+ function getMaterialType(className) {
+ let type = '';
+ if (className) {
+ type = className.replace('mdl-', '').replace('__input', '');
+ type = type.charAt(0).toUpperCase() + type.slice(1);
+ }
+ return type;
+ }
+ function updateMaterial(input) {
+ if (input && input.className) {
+ let find = input.className.match(/mdl-[\w]+input/g);
+ if (find && find.length && find[0]) {
+ let type = getMaterialType(find[0]);
+ if (type && input.parentNode[`Material${type}`] && input.parentNode[`Material${type}`].updateClasses_) {
+ input.parentNode[`Material${type}`].updateClasses_();
+ }
+ }
+ }
+ }
+ function getDynamicConditions($attrs) {
+ let atributes = $attrs.$attr;
+ let conditions = {};
+
+ Object.keys(atributes).forEach(atribute => {
+ if (atribute.startsWith('aclConditionalTo')) {
+ let role = atributes[atribute].split('-').slice(-1)[0];
+ conditions[atribute] = {
+ role: role
+ };
+ }
+ });
+ return conditions;
+ }
+
+ function permissionElement($element, action) {
+ if (!aclService.aclPermission(acls)) {
+ if (action === 'disabled') {
+ let input = $element[0];
+ let selector = 'input, textarea, button, submit';
+
+ if (!input.matches(selector))
+ input = input.querySelector(selector);
+
+ if (input) {
+ $timeout(() => {
+ input.setAttribute("disabled", "true");
+ updateMaterial(input);
+ });
+ $element[0].querySelectorAll('i, vn-drop-down').forEach(element => {
+ element.parentNode.removeChild(element);
+ });
+ }
+ } else {
+ $element.remove();
+ }
+ }
+ }
+
+ function updateAcls(role, toAdd) {
+ let position = acls.indexOf(role);
+
+ if (!toAdd && position > -1) {
+ acls.splice(position, 1);
+ } // todo: add acl and enabled element if previusly was disabled
+ }
+
+ return {
+ restrict: 'A',
+ priority: -1,
+ link: function($scope, $element, $attrs) {
+ acls = $attrs.vnAcl.split(',').map(element => element.trim().toLowerCase());
+ let action = $attrs.vnAclAction || 'disabled';
+ let conditions = getDynamicConditions($attrs);
+ permissionElement($element, action);
+
+ if (Object.keys(conditions).length) {
+ let watchConditions = $scope.$watch(() => {
+ Object.keys(conditions).forEach(attrName => {
+ let hasPermission = $scope.$eval($attrs[attrName]);
+ if (!hasPermission) {
+ updateAcls(conditions[attrName].role, hasPermission);
+ permissionElement($element, action);
+ delete conditions[attrName];
+ }
+ });
+
+ if (Object.keys(conditions).length === 0) {
+ // unWacth
+ watchConditions();
+ }
+ });
+ }
+ }
+ };
+}
+vnAcl.$inject = ['aclService', '$timeout'];
+
+ngModule.directive('vnAcl', vnAcl);
diff --git a/client/core/src/directives/dialog.js b/client/core/src/directives/dialog.js
index 740c83f03..7e51a8e9e 100644
--- a/client/core/src/directives/dialog.js
+++ b/client/core/src/directives/dialog.js
@@ -1,23 +1,25 @@
-import {module} from '../module';
-import Dialog from '../dialog/index';
+import ngModule from '../module';
+import Dialog from '../components/dialog/dialog';
import {kebabToCamel} from '../lib/string';
/**
* Registers a click handler on the element that opens the dialog id
* specified as value.
+ *
+ * @return {Object} The directive
*/
-directive.$inject = ['$document'];
-export function directive($document) {
+export function directive() {
return {
restrict: 'A',
link: function($scope, $element, $attrs) {
$element.on('click', function(event) {
- let dialog = $scope[kebabToCamel($attrs['vnDialog'])];
- if(dialog instanceof Dialog)
+ let dialogKey = kebabToCamel($attrs.vnDialog);
+ let dialog = $scope[dialogKey];
+ if (dialog instanceof Dialog)
dialog.show();
event.preventDefault();
});
}
- }
+ };
}
-module.directive('vnDialog', directive);
+ngModule.directive('vnDialog', directive);
diff --git a/client/core/src/directives/focus.js b/client/core/src/directives/focus.js
index 60d47fbd9..26376a260 100644
--- a/client/core/src/directives/focus.js
+++ b/client/core/src/directives/focus.js
@@ -1,7 +1,9 @@
-import {module} from '../module';
+import ngModule from '../module';
/**
- * Sets the focus and selects the text on the input.
+ * Sets the focus and selects the text on the input.
+ *
+ * @return {Object} The directive
*/
export function directive() {
return {
@@ -11,20 +13,20 @@ export function directive() {
let input = $element[0];
let selector = 'input, textarea, button, submit';
- if(!input.matches(selector))
+ if (!input.matches(selector))
input = input.querySelector(selector);
- if(!input) {
+ if (!input) {
console.warn(`vnFocus: Can't find a focusable element`);
return;
}
input.focus();
- if(input.select)
+ if (input.select)
input.select();
});
}
};
}
-module.directive('vnFocus', directive);
+ngModule.directive('vnFocus', directive);
diff --git a/client/core/src/directives/id.js b/client/core/src/directives/id.js
index b142eadee..193d84781 100644
--- a/client/core/src/directives/id.js
+++ b/client/core/src/directives/id.js
@@ -1,24 +1,27 @@
-import {module} from '../module';
+import ngModule from '../module';
import {kebabToCamel} from '../lib/string';
/**
- * Registers the element controller into its scope as a
- * property whose name is the directive value.
+ * Registers the element controller into the scope as a property whose name is
+ * the directive value transformed to lowerCamelCase.
+ *
+ * @return {Object} The directive
*/
export function directive() {
return {
restrict: 'A',
link: function($scope, $element, $attrs) {
let id = kebabToCamel($attrs.vnId);
- let controller = $element[0].$ctrl;
+ let controller = $element[0].$ctrl ?
+ $element[0].$ctrl : $element.controller($element[0].tagName.toLowerCase());
- if(!id)
+ if (!id)
throw new Error(`vnId: Attribute can't be null`);
- if(!controller)
+ if (!controller)
throw new Error(`vnId: Can't find controller for element '${id}'`);
$scope[id] = controller;
}
};
-};
-module.directive('vnId', directive);
+}
+ngModule.directive('vnId', directive);
diff --git a/client/core/src/directives/index.js b/client/core/src/directives/index.js
index fb240eefc..23392e5e0 100644
--- a/client/core/src/directives/index.js
+++ b/client/core/src/directives/index.js
@@ -1,4 +1,9 @@
import './id';
import './focus';
import './dialog';
-import './validation';
\ No newline at end of file
+import './popover';
+import './validation';
+import './acl';
+import './on-error-src';
+import './zoom-image';
+import './visible-by';
diff --git a/client/core/src/directives/on-error-src.js b/client/core/src/directives/on-error-src.js
new file mode 100644
index 000000000..1462063d6
--- /dev/null
+++ b/client/core/src/directives/on-error-src.js
@@ -0,0 +1,16 @@
+import ngModule from '../module';
+
+function onErrorSrc() {
+ return {
+ restrict: 'A',
+ link: (scope, element, attrs) => {
+ let imgError = '/static/images/no-image200x200.png';
+ element.bind('error', function() {
+ if (attrs.src != imgError) {
+ attrs.$set('src', imgError);
+ }
+ });
+ }
+ };
+}
+ngModule.directive('onErrorSrc', onErrorSrc);
diff --git a/client/core/src/directives/popover.js b/client/core/src/directives/popover.js
new file mode 100644
index 000000000..437d93783
--- /dev/null
+++ b/client/core/src/directives/popover.js
@@ -0,0 +1,26 @@
+import ngModule from '../module';
+import Popover from '../components/popover/popover';
+import {kebabToCamel} from '../lib/string';
+
+/**
+ * Directive used to open a popover.
+ *
+ * @return {Object} The directive
+ */
+export function directive() {
+ return {
+ restrict: 'A',
+ link: function($scope, $element, $attrs) {
+ $element.on('click', function(event) {
+ let popoverKey = kebabToCamel($attrs.vnPopover);
+ let popover = $scope[popoverKey];
+ if (popover instanceof Popover) {
+ popover.parent = $element[0];
+ popover.show();
+ }
+ event.preventDefault();
+ });
+ }
+ };
+}
+ngModule.directive('vnPopover', directive);
diff --git a/client/core/src/directives/specs/acl.spec.js b/client/core/src/directives/specs/acl.spec.js
new file mode 100644
index 000000000..a8c1afc42
--- /dev/null
+++ b/client/core/src/directives/specs/acl.spec.js
@@ -0,0 +1,55 @@
+describe('Directive acl', () => {
+ let scope;
+ let element;
+ let compile;
+ let $timeout;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ compile = (hasPermissions, _element) => {
+ inject(($compile, $rootScope, aclService, _$timeout_, _$httpBackend_) => {
+ _$httpBackend_.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ spyOn(aclService, 'aclPermission').and.returnValue(hasPermissions);
+ scope = $rootScope.$new();
+ $timeout = _$timeout_;
+ element = angular.element(_element);
+ $compile(element)(scope);
+ scope.$digest();
+ });
+ };
+
+ it('should not disable the input element as the user has permision', () => {
+ let html = ``;
+ compile(true, html);
+ let input = element.find('input');
+
+ expect(input).toBeDefined();
+ expect(input.attr('disabled')).toBeFalsy();
+ });
+
+ it('should delete the element as the user does not have permission and there is no action', () => {
+ let html = ``;
+ compile(false, html);
+
+ expect(element.children().length).toEqual(0);
+ });
+
+ it('should disable the element as the action is to disable it but the user has no permission but present', () => {
+ let html = ``;
+ compile(false, html);
+ let input = element.find('input');
+ $timeout.flush();
+
+ expect(input).toBeDefined();
+ expect(input.attr('disabled')).toBeTruthy();
+ });
+
+ it('should delete any element with the tag i and vn-drop-down', () => {
+ let html = ``;
+ compile(false, html);
+
+ expect(element.find('i').length).toBe(0);
+ });
+});
diff --git a/client/core/src/directives/specs/dialog.spec.js b/client/core/src/directives/specs/dialog.spec.js
new file mode 100644
index 000000000..12616fc19
--- /dev/null
+++ b/client/core/src/directives/specs/dialog.spec.js
@@ -0,0 +1,38 @@
+describe('Directive dialog', () => {
+ let $scope;
+ let $element;
+ let element;
+ let compile;
+ let $componentController;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ compile = _element => {
+ inject(($compile, $rootScope) => {
+ $scope = $rootScope.$new();
+ $scope.myDialog = controller;
+ element = angular.element(_element);
+ $compile(element)($scope);
+ $scope.$digest();
+ });
+ };
+
+ beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
+ $componentController = _$componentController_;
+ _$httpBackend_.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ $element = angular.element('');
+ controller = $componentController('vnDialog', {$element: $element, $transclude: null});
+ }));
+
+ it('should call show() function if dialog is a instance of vnDialog', () => {
+ let html = ``;
+ spyOn(controller, 'show');
+ compile(html);
+ element[0].click();
+
+ expect(controller.show).toHaveBeenCalledWith();
+ });
+});
diff --git a/client/core/src/directives/specs/focus.spec.js b/client/core/src/directives/specs/focus.spec.js
new file mode 100644
index 000000000..6b13c98a3
--- /dev/null
+++ b/client/core/src/directives/specs/focus.spec.js
@@ -0,0 +1,54 @@
+describe('Directive focus', () => {
+ let $scope;
+ let $element;
+ let compile;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ compile = (_element, _childElement) => {
+ inject(($compile, $rootScope, _$httpBackend_) => {
+ $scope = $rootScope.$new();
+ _$httpBackend_.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ $element = angular.element(_element);
+ if (_childElement) {
+ $element[0].firstChild.focus = jasmine.createSpy(focus);
+ }
+ $element[0].focus = jasmine.createSpy('focus');
+ $element[0].select = jasmine.createSpy('select');
+ $compile($element)($scope);
+ $scope.$digest();
+ });
+ };
+
+ it('should call the querySelector function upon the input to redefine it with the expected selector then call focus', () => {
+ let html = ``;
+ let childHtml = '';
+ compile(html, childHtml);
+
+ expect($element[0].firstChild.focus).toHaveBeenCalled();
+ });
+
+ it('should print a warning message on console', () => {
+ let html = ``;
+ console.warn = jasmine.createSpy('warn');
+ compile(html);
+
+ expect(console.warn).toHaveBeenCalledWith(`vnFocus: Can't find a focusable element`);
+ });
+
+ it('should call focus function on the element', () => {
+ let html = ``;
+ compile(html);
+
+ expect($element[0].focus).toHaveBeenCalledWith();
+ });
+
+ it('should call select function on the element', () => {
+ let html = ``;
+ compile(html);
+
+ expect($element[0].select).toHaveBeenCalledWith();
+ });
+});
diff --git a/client/core/src/directives/specs/id.spec.js b/client/core/src/directives/specs/id.spec.js
new file mode 100644
index 000000000..5c6fb0baa
--- /dev/null
+++ b/client/core/src/directives/specs/id.spec.js
@@ -0,0 +1,44 @@
+describe('Directive vnId', () => {
+ let $scope;
+ let $element;
+ let compile;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ compile = _element => {
+ inject(($compile, $rootScope, _$httpBackend_) => {
+ $scope = $rootScope.$new();
+ _$httpBackend_.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ $element = angular.element(_element);
+ $compile($element)($scope);
+ $scope.$digest();
+ });
+ };
+
+ it(`should throw an error when there's no id defined`, () => {
+ let html = ``;
+
+ expect(() => {
+ compile(html);
+ }).toThrow(new Error(`vnId: Attribute can't be null`));
+ });
+
+ it(`should throw an error when these's no controller defined in $element[0]`, () => {
+ let html = ``;
+
+ expect(() => {
+ compile(html);
+ }).toThrow(new Error(`vnId: Can't find controller for element '1'`));
+ });
+
+ it(`should set the controller into the $scope as there are no errors being thrown`, () => {
+ let html = ``;
+
+ expect($scope['1']).not.toBeDefined();
+ compile(html);
+
+ expect($scope['1']).toBeDefined();
+ });
+});
diff --git a/client/core/src/directives/specs/validation.spec.js b/client/core/src/directives/specs/validation.spec.js
new file mode 100644
index 000000000..26208e34b
--- /dev/null
+++ b/client/core/src/directives/specs/validation.spec.js
@@ -0,0 +1,187 @@
+describe('Directive validation', () => {
+ let scope;
+ let element;
+ let compile;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ compile = (_element, validations, value) => {
+ inject(($compile, $rootScope, aclService, _$timeout_, $window, _$httpBackend_) => {
+ $window.validations = validations;
+ _$httpBackend_.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
+ scope = $rootScope.$new();
+ scope.user = {name: value};
+ element = angular.element(_element);
+ $compile(element)(scope);
+ scope.$digest();
+ });
+ };
+
+ it(`should throw an error if the vnValidation doesn't have the right syntax`, () => {
+ let html = ``;
+
+ expect(() => {
+ compile(html, {});
+ }).toThrow(new Error(`vnValidation: Attribute must have this syntax: [entity].[field]`));
+ });
+
+ it('should throw an error if the window.validations aint defined', () => {
+ let html = ``;
+
+ expect(() => {
+ compile(html, {});
+ }).toThrow(new Error(`vnValidation: Entity 'User' doesn't exist`));
+ });
+
+ describe('Validator presence()', () => {
+ it('should not validate the user name as it is an empty string', () => {
+ let html = ``;
+ let validations = {User: {validations: {name: [{validation: 'presence'}]}}};
+ compile(html, validations, 'Spiderman');
+ scope.user.name = '';
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-invalid');
+ expect(element[0].classList).not.toContain('ng-valid');
+ });
+ });
+
+ describe('Validator absence()', () => {
+ it('should not validate the entity as it should be an empty string', () => {
+ let html = ``;
+ let validations = {User: {validations: {name: [{validation: 'absence'}]}}};
+ compile(html, validations, 'Spiderman');
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-invalid');
+ expect(element[0].classList).not.toContain('ng-valid');
+ });
+
+ it('should validate the entity as it is an empty string', () => {
+ let html = ``;
+ let validations = {User: {validations: {name: [{validation: 'absence'}]}}};
+ compile(html, validations, '');
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-valid');
+ expect(element[0].classList).not.toContain('ng-invalid');
+ });
+ });
+
+ describe('Validator length()', () => {
+ it('should not validate the user name as it should have min length of 15', () => {
+ let html = ``;
+ let validations = {User: {validations: {name: [{validation: 'length', min: 10, max: 50, is: 15}]}}};
+ compile(html, validations, 'fifteen!');
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-invalid');
+ expect(element[0].classList).not.toContain('ng-valid');
+ });
+
+ it('should validate the user name as it has length of 15', () => {
+ let html = ``;
+ let validations = {User: {validations: {name: [{validation: 'length', min: 10, max: 50, is: 15}]}}};
+ compile(html, validations, 'fifteen length!');
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-valid');
+ expect(element[0].classList).not.toContain('ng-invalid');
+ });
+
+ it('should not validate the user name as it should have min length of 10', () => {
+ let html = ``;
+ let validations = {User: {validations: {name: [{validation: 'length', min: 10}]}}};
+ compile(html, validations, 'shortname');
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-invalid');
+ expect(element[0].classList).not.toContain('ng-valid');
+ });
+
+ it('should validate the user name as its length is greater then the minimum', () => {
+ let html = ``;
+ let validations = {User: {validations: {name: [{validation: 'length', min: 10}]}}};
+ compile(html, validations, 'verylongname');
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-valid');
+ expect(element[0].classList).not.toContain('ng-invalid');
+ });
+
+ it('should not validate the user name as its length is greater then the maximum', () => {
+ let html = ``;
+ let validations = {User: {validations: {name: [{validation: 'length', max: 10}]}}};
+ compile(html, validations, 'toolongname');
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-invalid');
+ expect(element[0].classList).not.toContain('ng-valid');
+ });
+ });
+
+ describe('Validator numericality()', () => {
+ it('should not validate the phone number as it should a integer', () => {
+ let html = ``;
+ let validations = {User: {validations: {phone: [{validation: 'numericality', is: 'what is this?'}]}}};
+ compile(html, validations, 'spiderman');
+ scope.user.phone = 'this is not a phone number!';
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-invalid');
+ expect(element[0].classList).not.toContain('ng-valid');
+ });
+
+ it('should validate the phone number as it an integer', () => {
+ let html = ``;
+ let validations = {User: {validations: {phone: [{validation: 'numericality', is: 'what is this?'}]}}};
+ compile(html, validations, 'spiderman');
+ scope.user.phone = '555555555';
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-valid');
+ expect(element[0].classList).not.toContain('ng-invalid');
+ });
+ });
+
+ describe('Validator inclusion()', () => {
+ it('should not validate the phone number as it is not an integer', () => {
+ let html = ``;
+ let validations = {User: {validations: {phone: [{validation: 'inclusion'}]}}};
+ compile(html, validations, 'spiderman');
+ scope.user.phone = 'this is not a phone number!';
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-invalid');
+ expect(element[0].classList).not.toContain('ng-valid');
+ });
+ });
+
+ describe('Validator exclusion()', () => {
+ it('should validate the phone number as it is an integer', () => {
+ let html = ``;
+ let validations = {User: {validations: {phone: [{validation: 'exclusion'}]}}};
+ compile(html, validations, 'spiderman');
+ scope.user.phone = '555555555';
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-valid');
+ expect(element[0].classList).not.toContain('ng-invalid');
+ });
+ });
+
+ describe('Validator format()', () => {
+ it('should not validate the email number as it doesnt contain @', () => {
+ let html = ``;
+ let validations = {User: {validations: {email: [{validation: 'format', with: '@'}]}}};
+ compile(html, validations, 'spiderman');
+ scope.user.email = 'userverdnatura.es';
+ scope.$digest();
+
+ expect(element[0].classList).toContain('ng-invalid');
+ expect(element[0].classList).not.toContain('ng-valid');
+ });
+ });
+});
diff --git a/client/core/src/directives/specs/zoom-image.spec.js b/client/core/src/directives/specs/zoom-image.spec.js
new file mode 100644
index 000000000..1891f738a
--- /dev/null
+++ b/client/core/src/directives/specs/zoom-image.spec.js
@@ -0,0 +1,71 @@
+describe('Directive zoomImage', () => {
+ let compile;
+ let scope;
+ let srcDefault = 'http://default.img.jpg/';
+ let srcZoom = 'http://zoom.img.jpg/';
+ let findContainer;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject(($compile, $rootScope) => {
+ compile = $compile;
+ scope = $rootScope.$new();
+ }));
+
+ afterEach(() => {
+ if (findContainer) {
+ findContainer.parentNode.removeChild(findContainer);
+ findContainer = undefined;
+ }
+ });
+
+ function getCompiledImage(imgHtml) {
+ let element = angular.element(imgHtml);
+ var compiledElement = compile(element)(scope);
+ scope.$digest();
+ return compiledElement;
+ }
+
+ it('should create zoom container when click into image', () => {
+ let image = getCompiledImage(``);
+ image[0].click();
+
+ findContainer = document.querySelector('.vn-zoom-image');
+
+ expect(findContainer).not.toBeNull();
+ });
+
+ it('should detroy zoom container when click outside zoomed image', () => {
+ let image = getCompiledImage(``);
+ image[0].click();
+
+ findContainer = document.querySelector('.vn-zoom-image');
+ findContainer.click();
+
+ findContainer = document.querySelector('.vn-zoom-image');
+
+ expect(findContainer).toBeNull();
+ });
+
+ it('should create new image, into zoom container, with src as original image src', () => {
+ let image = getCompiledImage(``);
+ image[0].click();
+ findContainer = document.querySelector('.vn-zoom-image');
+
+ let zoomedImg = findContainer.querySelector('img');
+
+ expect(zoomedImg.src).toEqual(srcDefault);
+ });
+
+ it('should create new image, into zoom container, with src likes zoomImage value', () => {
+ let image = getCompiledImage(``);
+ image[0].click();
+ findContainer = document.querySelector('.vn-zoom-image');
+
+ let zoomedImg = findContainer.querySelector('img');
+
+ expect(zoomedImg.src).toEqual(srcZoom);
+ });
+});
diff --git a/client/core/src/directives/validation.js b/client/core/src/directives/validation.js
index 0b0939318..76a94da3b 100644
--- a/client/core/src/directives/validation.js
+++ b/client/core/src/directives/validation.js
@@ -1,4 +1,4 @@
-import {module} from '../module';
+import ngModule from '../module';
import {validateAll} from '../lib/validator';
import {firstUpper} from '../lib/string';
@@ -6,7 +6,7 @@ directive.$inject = ['$interpolate', '$compile', '$window'];
export function directive(interpolate, compile, $window) {
return {
restrict: 'A',
- require: ['ngModel', '^^form'],
+ require: ['ngModel', '^^?form'],
link: link
};
@@ -29,17 +29,17 @@ export function directive(interpolate, compile, $window) {
throw new Error(`vnValidation: Entity '${entityName}' doesn't exist`);
let validations = entity.validations[fieldName];
-
if (!validations || validations.length == 0)
return;
- let input = ctrl[0];
+ let ngModel = ctrl[0];
let form = ctrl[1];
let errorSpan = angular.element('');
let errorMsg;
let errorShown = false;
- input.$validators.entity = function(value) {
+ ngModel.$options.$$options.allowInvalid = true;
+ ngModel.$validators.entity = value => {
try {
validateAll(value, validations);
return true;
@@ -50,9 +50,9 @@ export function directive(interpolate, compile, $window) {
}
};
- scope.$watch(function() {
- return (form.$submitted || input.$dirty) && input.$invalid;
- }, function(value) {
+ scope.$watch(() => {
+ return (form.$submitted || ngModel.$dirty) && ngModel.$invalid;
+ }, value => {
let parent = element.parent();
if (value) {
@@ -76,5 +76,5 @@ export function directive(interpolate, compile, $window) {
}
}
}
-module.directive('vnValidation', directive);
+ngModule.directive('vnValidation', directive);
diff --git a/client/core/src/directives/visible-by.js b/client/core/src/directives/visible-by.js
new file mode 100644
index 000000000..e05079fb5
--- /dev/null
+++ b/client/core/src/directives/visible-by.js
@@ -0,0 +1,17 @@
+import ngModule from '../module';
+
+function vnVisibleBy(aclService) {
+ return {
+ restrict: 'A',
+ priority: -1,
+ link: function($scope, $element, $attrs) {
+ let acls = $attrs.vnVisibleBy.split(',');
+ if (!aclService.aclPermission(acls)) {
+ $element[0].style.visibility = 'hidden';
+ }
+ }
+ };
+}
+vnVisibleBy.$inject = ['aclService'];
+
+ngModule.directive('vnVisibleBy', vnVisibleBy);
diff --git a/client/core/src/directives/zoom-image.js b/client/core/src/directives/zoom-image.js
new file mode 100644
index 000000000..db7de27be
--- /dev/null
+++ b/client/core/src/directives/zoom-image.js
@@ -0,0 +1,60 @@
+import ngModule from '../module';
+
+export function directive($timeout) {
+ let container;
+ let keyDownHandler;
+
+ function createContainers(src) {
+ destroyContainers();
+
+ container = document.createElement('div');
+ container.className = 'vn-zoom-image';
+ container.addEventListener('click', destroyContainers);
+
+ let wrapper = document.createElement('div');
+ container.appendChild(wrapper);
+
+ let background = document.createElement('img');
+ background.src = src;
+ wrapper.appendChild(background);
+
+ document.body.appendChild(container);
+ keyDownHandler = e => onKeyDown(e);
+ document.addEventListener('keydown', keyDownHandler);
+ }
+
+ function onKeyDown(event) {
+ if (event.keyCode === 27) {
+ destroyContainers();
+ }
+ }
+
+ function destroyContainers() {
+ if (!container) return;
+
+ container.removeEventListener('click', destroyContainers);
+ container.parentNode.removeChild(container);
+ container = undefined;
+
+ document.removeEventListener('keydown', keyDownHandler);
+ keyDownHandler = undefined;
+ }
+
+ return {
+ restrict: 'A',
+ link: function($scope, $element, $attrs) {
+ $element.on('click', function(event) {
+ event.preventDefault();
+
+ let src = $attrs.zoomImage || $attrs.src;
+ if (src) {
+ createContainers(src);
+ } else
+ throw new Error('No image source detected');
+ });
+ }
+ };
+}
+directive.$inject = ['$timeout'];
+
+ngModule.directive('zoomImage', directive);
diff --git a/client/core/src/filters/index.js b/client/core/src/filters/index.js
index de0560b2f..885f3cd66 100644
--- a/client/core/src/filters/index.js
+++ b/client/core/src/filters/index.js
@@ -1 +1,2 @@
import './phone';
+import './ucwords';
diff --git a/client/core/src/filters/phone.js b/client/core/src/filters/phone.js
index 3146e24c1..40701f9e2 100644
--- a/client/core/src/filters/phone.js
+++ b/client/core/src/filters/phone.js
@@ -1,4 +1,4 @@
-import {module} from '../module';
+import ngModule from '../module';
/**
* Formats a phone number putting a space every three digits.
@@ -17,4 +17,4 @@ export default function phone() {
return out;
};
}
-module.filter('phone', phone);
+ngModule.filter('phone', phone);
diff --git a/client/core/src/filters/ucwords.js b/client/core/src/filters/ucwords.js
new file mode 100644
index 000000000..5939d343d
--- /dev/null
+++ b/client/core/src/filters/ucwords.js
@@ -0,0 +1,20 @@
+import ngModule from '../module';
+
+/**
+ * Uppercase the first character of each word in a string
+ *
+ * @return {String} The formated string
+ */
+export default function ucwords() {
+ return function(input) {
+ input = input || '';
+ let out = '';
+ let aux = input.split(' ');
+ for (let i = 0; i < aux.length; i++) {
+ out += (aux[i]) ? aux[i].charAt(0).toUpperCase() + aux[i].substr(1).toLowerCase() : '';
+ out += ' ';
+ }
+ return out.trim();
+ };
+}
+ngModule.filter('ucwords', ucwords);
diff --git a/client/core/src/floatbutton/floatbutton.js b/client/core/src/floatbutton/floatbutton.js
deleted file mode 100644
index 56cbbcb40..000000000
--- a/client/core/src/floatbutton/floatbutton.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as util from '../lib/util';
-
-const _NAME = 'floatButton';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME];
-export function directive(resolve) {
- return {
- restrict: 'E',
- template: function(_, attr) {
- return resolve.getTemplate(_NAME, attr);
- }
- };
-}
-
-_module.directive(NAME, directive);
-
diff --git a/client/core/src/floatbutton/floatbutton.mdl.js b/client/core/src/floatbutton/floatbutton.mdl.js
deleted file mode 100644
index 68b585d24..000000000
--- a/client/core/src/floatbutton/floatbutton.mdl.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import {module as _module} from '../module';
-import * as util from '../lib/util';
-import * as constant from '../lib/constants';
-import template from './floatbutton.mdl.html';
-
-const _NAME = 'floatButton';
-const DEFAULT_CLASS = 'mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored';
-
-export const NAME = util.getFactoryName(_NAME + constant.MATERIAL_DESIGN_FRAMEWORK);
-
-export function factory() {
- return {
- template: template,
- default: {
- className: DEFAULT_CLASS
- }
- };
-}
-
-_module.factory(NAME, factory);
diff --git a/client/core/src/icon-button/icon-button.js b/client/core/src/icon-button/icon-button.js
deleted file mode 100644
index 62ce9a2a4..000000000
--- a/client/core/src/icon-button/icon-button.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as util from '../lib/util';
-
-const _NAME = 'iconButton';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME];
-export function directive(resolve) {
- return {
- restrict: 'E',
- template: function(_, attr) {
- return resolve.getTemplate(_NAME, attr);
- }
- };
-}
-_module.directive(NAME, directive);
diff --git a/client/core/src/icon-button/icon-button.mdl.html b/client/core/src/icon-button/icon-button.mdl.html
deleted file mode 100644
index 3b8763a59..000000000
--- a/client/core/src/icon-button/icon-button.mdl.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
\ No newline at end of file
diff --git a/client/core/src/icon-button/icon-button.mdl.js b/client/core/src/icon-button/icon-button.mdl.js
deleted file mode 100644
index 14c9fa2a3..000000000
--- a/client/core/src/icon-button/icon-button.mdl.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import {module} from '../module';
-import template from './icon-button.mdl.html';
-
-export const NAME = 'vnIconButtonMdlFactory';
-export function factory() {
- return {
- template: template,
- default: {
- enabled: 'enabled',
- icon: '',
- label: ''
- }
- };
-}
-module.factory(NAME, factory);
diff --git a/client/core/src/icon/index.js b/client/core/src/icon/index.js
deleted file mode 100644
index 7e36fab97..000000000
--- a/client/core/src/icon/index.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import {module} from '../module';
-import './index.mdl';
-import './style.css';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-
-const _NAME = 'icon';
-export const NAME = 'vnIcon';
-
-export function directive(resolver) {
- return {
- restrict: 'E',
- template: function(_, attrs) {
- return resolver.getTemplate(_NAME, attrs);
- }
- };
-}
-directive.$inject = [resolveFactory.NAME];
-
-module.directive(NAME, directive);
diff --git a/client/core/src/icon/index.mdl.html b/client/core/src/icon/index.mdl.html
deleted file mode 100644
index f4b1888dd..000000000
--- a/client/core/src/icon/index.mdl.html
+++ /dev/null
@@ -1 +0,0 @@
-*[icon]*
diff --git a/client/core/src/icon/index.mdl.js b/client/core/src/icon/index.mdl.js
deleted file mode 100644
index 3084fdd12..000000000
--- a/client/core/src/icon/index.mdl.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import {module} from '../module';
-import template from './index.mdl.html';
-
-export const NAME = 'vnIconMdlFactory';
-export function factory() {
- return {
- template: template,
- default: {}
- }
-}
-
-module.factory(NAME, factory);
diff --git a/client/core/src/icon/style.css b/client/core/src/icon/style.css
deleted file mode 100644
index fc4dacc93..000000000
--- a/client/core/src/icon/style.css
+++ /dev/null
@@ -1,7 +0,0 @@
-vn-icon {
- display: inline;
- font-size: 18pt;
-}
-vn-icon > i {
- font-size: inherit !important;
-}
\ No newline at end of file
diff --git a/client/core/src/label/label.js b/client/core/src/label/label.js
deleted file mode 100644
index 8d6d1b4f4..000000000
--- a/client/core/src/label/label.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as util from '../lib/util';
-
-const _NAME = 'label';
-export const NAME = util.getName(_NAME);
-
-directive.$inject =[resolveFactory.NAME];
-export function directive (resolve){
- return{
- restrict:'E',
- template: function(_,attr){
- return resolve.getTemplate(_NAME, attr);
- }
- }
-}
-
-_module.directive(NAME,directive);
diff --git a/client/core/src/label/label.mdl.html b/client/core/src/label/label.mdl.html
deleted file mode 100644
index 9f95f13b3..000000000
--- a/client/core/src/label/label.mdl.html
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/client/core/src/label/label.mdl.js b/client/core/src/label/label.mdl.js
deleted file mode 100644
index 0f66320d7..000000000
--- a/client/core/src/label/label.mdl.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import {module as _module} from '../module';
-import * as util from '../lib/util';
-import * as constant from '../lib/constants';
-import template from './label.mdl.html';
-
-const _NAME = 'label';
-const DEFAULT_TEXT = 'label';
-
-export const NAME = util.getFactoryName(_NAME + constant.MATERIAL_DESIGN_FRAMEWORK);
-
-export function factory() {
- return {
- template: template,
- default: {
- text: DEFAULT_TEXT
- }
- };
-}
-
-_module.factory(NAME, factory);
diff --git a/client/core/src/lib/acl-service.js b/client/core/src/lib/acl-service.js
new file mode 100644
index 000000000..ae4c865bf
--- /dev/null
+++ b/client/core/src/lib/acl-service.js
@@ -0,0 +1,43 @@
+import ngModule from '../module';
+
+var acl = window.salix ? window.salix.acl : {};
+ngModule.constant('aclConstant', acl);
+
+aclService.$inject = ['aclConstant'];
+function aclService(aclConstant) {
+ if (aclConstant.roles) {
+ this.roles = {};
+ Object.keys(aclConstant.roles).forEach(role => {
+ this.roles[role.toLowerCase()] = aclConstant.roles[role];
+ });
+ } else {
+ this.roles = undefined;
+ }
+
+ this.routeHasPermission = function(route) {
+ let hasPermission;
+ if (!this.roles)
+ hasPermission = false;
+ else if (!route.acl)
+ hasPermission = true;
+ else if (!this.roles || !Object.keys(this.roles).length)
+ hasPermission = false;
+ else
+ hasPermission = this.aclPermission(route.acl);
+ return hasPermission;
+ };
+ this.aclPermission = function(aclCollection) {
+ let hasPermission = false;
+ let total = aclCollection.length;
+ for (let i = 0; i < total; i++) {
+ let role = aclCollection[i].trim().toLowerCase();
+ if (this.roles[role]) {
+ hasPermission = true;
+ break;
+ }
+ }
+ return hasPermission;
+ };
+}
+
+ngModule.service('aclService', aclService);
diff --git a/client/core/src/lib/app.js b/client/core/src/lib/app.js
new file mode 100644
index 000000000..5a41d209c
--- /dev/null
+++ b/client/core/src/lib/app.js
@@ -0,0 +1,35 @@
+import ngModule from '../module';
+
+/**
+ * The main application class.
+ *
+ * @property {String} name The application name.
+ * @property {Snackbar} snackbar The main object to show messages.
+ */
+export default class App {
+ constructor($rootScope) {
+ this.loaderStatus = 0;
+ this.$rootScope = $rootScope;
+ }
+ showMessage(message) {
+ if (this.snackbar)
+ this.snackbar.show({message: message});
+ }
+ showError(message) {
+ if (this.snackbar)
+ this.snackbar.showError({message: `Error: ${message}`});
+ }
+ pushLoader() {
+ this.loaderStatus++;
+ if (this.loaderStatus === 1)
+ this.$rootScope.loading = true;
+ }
+ popLoader() {
+ this.loaderStatus--;
+ if (this.loaderStatus === 0)
+ this.$rootScope.loading = false;
+ }
+}
+App.$inject = ['$rootScope'];
+
+ngModule.service('vnApp', App);
diff --git a/client/core/src/lib/component.js b/client/core/src/lib/component.js
index 2d8d689cc..36380a5ed 100644
--- a/client/core/src/lib/component.js
+++ b/client/core/src/lib/component.js
@@ -18,10 +18,13 @@ export default class Component {
* Contructor.
*
* @param {HTMLElement} $element The main component element
+ * @param {$rootScope.Scope} $scope The element scope
*/
- constructor($element) {
+ constructor($element, $scope) {
this.element = $element[0];
this.element.$ctrl = this;
+ this.$element = $element;
+ this.$ = $scope;
}
}
-Component.$inject = ['$element'];
+Component.$inject = ['$element', '$scope'];
diff --git a/client/core/src/lib/constants.js b/client/core/src/lib/constants.js
deleted file mode 100644
index 5cd04dedc..000000000
--- a/client/core/src/lib/constants.js
+++ /dev/null
@@ -1,10 +0,0 @@
-
-// Proyect prefix name
-export const PREFIX ='vn';
-
-// CSS frameworks
-export const MATERIAL_DESIGN_FRAMEWORK = 'Mdl';
-export const BOOTSTRAP_FRAMEWORK = 'Bt';
-
-// Module dependencies
-export const EMPTY_DEPENDECIES = [];
diff --git a/client/core/src/lib/copy.js b/client/core/src/lib/copy.js
index f0948de33..2a9dde35c 100644
--- a/client/core/src/lib/copy.js
+++ b/client/core/src/lib/copy.js
@@ -1,7 +1,3 @@
-import {module} from '../module';
const copyObject = angular.copy;
export default copyObject;
-
-export const NAME = 'copyObject';
-module.value(NAME, copyObject);
diff --git a/client/core/src/lib/crud.js b/client/core/src/lib/crud.js
index 5bddebfb8..c2f6f0de4 100644
--- a/client/core/src/lib/crud.js
+++ b/client/core/src/lib/crud.js
@@ -1,12 +1,20 @@
-import {module} from '../module';
+import ngModule from '../module';
index.$inject = ['mgIndex'];
function index(mgIndex) {
return Object.assign({}, mgIndex, {
- init: 'index.filter={page: 1, size: 4}'
+ init: 'index.filter={page: 1, size: 5}'
});
}
-module.factory('vnIndex', index);
+ngModule.factory('vnIndex', index);
+
+nonAuto.$inject = ['mgIndex'];
+function nonAuto(mgIndex) {
+ return Object.assign({}, mgIndex, {
+ auto: false
+ });
+}
+ngModule.factory('vnIndexNonAuto', nonAuto);
successFactoryCreate.$inject = ['mgSuccessFactoryCreate'];
function successFactoryCreate(create) {
@@ -14,7 +22,7 @@ function successFactoryCreate(create) {
back: undefined
});
}
-module.factory('vnSuccessFactoryCreate', successFactoryCreate);
+ngModule.factory('vnSuccessFactoryCreate', successFactoryCreate);
put.$inject = ['mgPut'];
function put(mgPut) {
@@ -22,7 +30,15 @@ function put(mgPut) {
success: 'vnSuccessFactoryCreate'
});
}
-module.factory('vnPut', put);
+ngModule.factory('vnPut', put);
+
+patch.$inject = ['mgPatch'];
+function patch(mgPatch) {
+ return Object.assign({}, mgPatch, {
+ success: 'vnSuccessFactoryCreate'
+ });
+}
+ngModule.factory('vnPatch', patch);
post.$inject = ['mgCreate'];
function post(mgCreate) {
@@ -31,4 +47,4 @@ function post(mgCreate) {
success: 'vnSuccessFactoryCreate'
});
}
-module.factory('vnPost', post);
+ngModule.factory('vnPost', post);
diff --git a/client/core/src/lib/equals.js b/client/core/src/lib/equals.js
index 40b36cca0..5c8e6c651 100644
--- a/client/core/src/lib/equals.js
+++ b/client/core/src/lib/equals.js
@@ -1,7 +1,3 @@
-import {module} from '../module';
const isEqual = angular.equals;
export default isEqual;
-
-export const NAME = 'equalsObject';
-module.value(NAME, isEqual);
diff --git a/client/core/src/lib/filter-list.js b/client/core/src/lib/filter-list.js
new file mode 100644
index 000000000..1c63414d7
--- /dev/null
+++ b/client/core/src/lib/filter-list.js
@@ -0,0 +1,42 @@
+/**
+ * Generic class to list models.
+ */
+export default class FilterList {
+ constructor($scope, $timeout, $state) {
+ this.$ = $scope;
+ this.$timeout = $timeout;
+ this.$state = $state;
+
+ this.waitingMgCrud = 0;
+ this.modelId = $state.params.id;
+ }
+ onOrder(field, order) {
+ this.filter(`${field} ${order}`);
+ }
+ filter(order) {
+ if (this.$.index && this.modelId && this.modelName) {
+ this.waitingMgCrud = 0;
+ this.$.index.filter = {
+ page: 1,
+ size: 10
+ };
+
+ this.$.index.filter[this.modelName] = this.modelId;
+
+ if (order) {
+ this.$.index.filter.order = order;
+ }
+
+ this.$.index.accept();
+ } else if (!this.modelId || !this.modelName) {
+ throw new Error('Error: model not found');
+ } else if (this.waitingMgCrud > 3) {
+ throw new Error('Error: Magic Crud is not loaded');
+ } else {
+ this.waitingMgCrud++;
+ this.$timeout(() => {
+ this.filter(order);
+ }, 250);
+ }
+ }
+}
diff --git a/client/core/src/lib/full-empty.js b/client/core/src/lib/full-empty.js
new file mode 100644
index 000000000..65a0e1e1d
--- /dev/null
+++ b/client/core/src/lib/full-empty.js
@@ -0,0 +1,7 @@
+
+function isFullEmpty(item) {
+ return (item === null || item === undefined) ||
+ (typeof item === 'object' && !Object.keys(item).length);
+}
+
+export default isFullEmpty;
diff --git a/client/core/src/lib/getTemplate.js b/client/core/src/lib/getTemplate.js
deleted file mode 100644
index 58e891c7d..000000000
--- a/client/core/src/lib/getTemplate.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import {kebabToCamel} from './string';
-
-getTemplate.$inject = ['$element', '$attrs', 'vnResolveDefaultComponent'];
-export default function getTemplate($element, $attrs, resolve) {
- let templateName = kebabToCamel($element[0].tagName.toLowerCase().substr(3));
- return resolve.getTemplate(templateName, $attrs);
-}
diff --git a/client/core/src/lib/index.js b/client/core/src/lib/index.js
index 806c6cfde..9df4b6911 100644
--- a/client/core/src/lib/index.js
+++ b/client/core/src/lib/index.js
@@ -1,12 +1,14 @@
-import './moduleLoader';
+import './module-loader';
import './crud';
+import './app';
+import './interceptor';
+import './acl-service';
+import './storage-services';
+import './filter-list';
import './template';
-import './getTemplate';
-
-export * from './util';
-export {default as splitingRegister} from './splitingRegister';
-export {NAME as RESOLVEDEFAULTCOMPONENT, ResolveDefaultComponent} from './resolveDefaultComponents';
-export {NAME as INTERPOLATE, Interpolate} from './interpolate';
-export {NAME as COPY_OBJECT} from './copy';
-export {NAME as EQUALS_OBJECT} from './equals';
-export {NAME as GET_DATA_MODIFIED, factory as Modified} from './modified';
+import './spliting-register';
+import './interpolate';
+import './copy';
+import './equals';
+import './modified';
+import './key-codes';
diff --git a/client/core/src/lib/input.js b/client/core/src/lib/input.js
new file mode 100644
index 000000000..9e428e675
--- /dev/null
+++ b/client/core/src/lib/input.js
@@ -0,0 +1,29 @@
+import Component from './component';
+
+/**
+ * Component that host an input.
+ */
+export default class Input extends Component {
+ constructor($element, $scope) {
+ super($element, $scope);
+ this.input = this.element.querySelector('input');
+ }
+ set disabled(value) {
+ this.input.disabled = value == true;
+ this.mdlUpdate();
+ }
+ get disabled() {
+ return this.input.disabled;
+ }
+ select() {
+ this.input.select();
+ }
+ focus() {
+ this.input.focus();
+ }
+ mdlUpdate() {
+ if (this.mdlElement)
+ this.mdlElement.updateClasses_();
+ }
+}
+Input.$inject = ['$element', '$scope'];
diff --git a/client/core/src/lib/inputAttrsNormalizer.js b/client/core/src/lib/inputAttrsNormalizer.js
deleted file mode 100644
index 355d268b9..000000000
--- a/client/core/src/lib/inputAttrsNormalizer.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import {module} from '../module';
-
-export const NAME = 'vnInputAttrsNormalizer';
-export class InputAttrsNormalizer {
- normalize(attrs) {
- if (attrs.field) {
- let split = attrs.field.split('.');
- let len = split.length;
-
- if (len == 0)
- throw new Error(`Attribute 'field' can not be empty`);
- if (len > 3)
- throw new Error(`Attribute 'field' must have this syntax: [ctrl].[entity].[field]`);
-
- let i = len - 1;
- let field = split[i--];
- let entity = i >= 0 ? split[i--] : 'model';
- let ctrl = i >= 0 ? split[i--] : '$ctrl';
-
- if (attrs.model === undefined)
- attrs.model = `${ctrl}.${entity}.${field}`;
- if (attrs.rule === undefined && len >= 2)
- attrs.rule = `${entity}.${field}`;
- if (attrs.label === undefined && len >= 2)
- attrs.label = `${entity}.${field}`;
- if (attrs.name === undefined)
- attrs.name = field;
- }
-
- if (attrs.focus !== undefined)
- attrs.focus = 'vn-focus';
- }
-}
-module.service(NAME, InputAttrsNormalizer);
diff --git a/client/core/src/lib/interceptor.js b/client/core/src/lib/interceptor.js
new file mode 100644
index 000000000..d6a2b4b59
--- /dev/null
+++ b/client/core/src/lib/interceptor.js
@@ -0,0 +1,52 @@
+import ngModule from '../module';
+
+interceptor.$inject = ['$q', '$window', 'vnApp', '$translate', '$cookies'];
+function interceptor($q, $window, vnApp, $translate, $cookies) {
+ return {
+ request: function(config) {
+ vnApp.pushLoader();
+ let token = $cookies.get('vnToken');
+
+ if (token)
+ config.headers.Authorization = token;
+
+ return config;
+ },
+ requestError: function(rejection) {
+ return $q.reject(rejection);
+ },
+ response: function(response) {
+ switch (response.config.method) {
+ case 'PUT':
+ case 'POST':
+ case 'PATCH':
+ vnApp.showMessage($translate.instant('Data saved!'));
+ }
+ vnApp.popLoader();
+ return response;
+ },
+ responseError: function(rejection) {
+ vnApp.popLoader();
+ let data = rejection.data;
+ let error;
+
+ if (data && data.error instanceof Object)
+ error = data.error.message;
+ else if (rejection.status === -1)
+ error = $translate.instant(`Can't contact with server`);
+ else
+ error = `${rejection.status}: ${rejection.statusText}`;
+
+ if (rejection.status === 401) {
+ let location = $window.location;
+ let continueUrl = location.pathname + location.search + location.hash;
+ continueUrl = encodeURIComponent(continueUrl);
+ $window.location = `/auth/?apiKey=${vnApp.name}&continue=${continueUrl}`;
+ }
+
+ vnApp.showError(error);
+ return $q.reject(rejection);
+ }
+ };
+}
+ngModule.factory('vnInterceptor', interceptor);
diff --git a/client/core/src/lib/interpolate.js b/client/core/src/lib/interpolate.js
index d961a6a41..6321ce813 100644
--- a/client/core/src/lib/interpolate.js
+++ b/client/core/src/lib/interpolate.js
@@ -1,10 +1,5 @@
-import {module} from '../module';
+import ngModule from '../module';
import {ng} from 'vendor';
-import * as util from './util';
-
-export const NAME = util.getProviderName('interpolate');
-
-function minErr() {}
function stringify(value) {
if (value === null) { // null || undefined
@@ -37,11 +32,11 @@ $interpolateMinErr.interr = function(text, err) {
};
function $get($parse, $exceptionHandler, $sce) {
- var startSymbolLength = this._startSymbol.length,
- endSymbolLength = this._endSymbol.length,
- escapedStartRegexp = new RegExp(this._startSymbol.replace(/./g, escape), 'g'),
- escapedEndRegexp = new RegExp(this._endSymbol.replace(/./g, escape), 'g'),
- self = this;
+ let startSymbolLength = this._startSymbol.length;
+ let endSymbolLength = this._endSymbol.length;
+ let escapedStartRegexp = new RegExp(this._startSymbol.replace(/./g, escape), 'g');
+ let escapedEndRegexp = new RegExp(this._endSymbol.replace(/./g, escape), 'g');
+ let self = this;
function escape(ch) {
return '\\\\\\' + ch;
@@ -76,22 +71,21 @@ function $get($parse, $exceptionHandler, $sce) {
}
allOrNothing = Boolean(allOrNothing);
- var startIndex,
- endIndex,
- index = 0,
- expressions = [],
- parseFns = [],
- textLength = text.length,
- exp,
- concat = [],
- expressionPositions = [];
+ let startIndex;
+ let endIndex;
+ let index = 0;
+ let expressions = [];
+ let parseFns = [];
+ let textLength = text.length;
+ let exp;
+ let concat = [];
+ let expressionPositions = [];
while (index < textLength) {
if (((startIndex = text.indexOf(self._startSymbol, index)) !== -1) &&
((endIndex = text.indexOf(self._endSymbol, startIndex + startSymbolLength)) !== -1)) {
- if (index !== startIndex) {
- concat.push(unescapeText(text.substring(index, startIndex)));
- }
+ if (index !== startIndex)
+ concat.push(unescapeText(text.substring(index, startIndex)));
exp = text.substring(startIndex + startSymbolLength, endIndex);
expressions.push(exp);
parseFns.push($parse(exp, parseStringifyInterceptor));
@@ -100,9 +94,8 @@ function $get($parse, $exceptionHandler, $sce) {
concat.push('');
} else {
// we did not find an interpolation, so we have to add the remainder to the separators array
- if (index !== textLength) {
- concat.push(unescapeText(text.substring(index)));
- }
+ if (index !== textLength)
+ concat.push(unescapeText(text.substring(index)));
break;
}
}
@@ -111,40 +104,40 @@ function $get($parse, $exceptionHandler, $sce) {
$interpolateMinErr.throwNoconcat(text);
}
+ var getValue = function(value) {
+ return trustedContext ?
+ $sce.getTrusted(trustedContext, value) :
+ $sce.valueOf(value);
+ };
+
if (!mustHaveExpression || expressions.length) {
var compute = function(values) {
for (var i = 0, ii = expressions.length; i < ii; i++) {
- if (allOrNothing && isUndefined(values[i])) return;
- concat[expressionPositions[i]] = values[i];
- }
+ if (allOrNothing && isUndefined(values[i])) return;
+ concat[expressionPositions[i]] = values[i];
+ }
return concat.join('');
};
- var getValue = function(value) {
- return trustedContext ?
- $sce.getTrusted(trustedContext, value) :
- $sce.valueOf(value);
- };
-
return angular.extend(function interpolationFn(context) {
var i = 0;
var ii = expressions.length;
var values = new Array(ii);
try {
- for (; i < ii; i++) {
- values[i] = parseFns[i](context);
- }
-
- return compute(values);
- } catch (err) {
- $exceptionHandler($interpolateMinErr.interr(text, err));
+ for (; i < ii; i++) {
+ values[i] = parseFns[i](context);
}
+
+ return compute(values);
+ } catch (err) {
+ $exceptionHandler($interpolateMinErr.interr(text, err));
+ }
}, {
- // all of these properties are undocumented for now
- exp: text, // just for compatibility with regular watchers created via $watch
- expressions: expressions
- });
+ // all of these properties are undocumented for now
+ exp: text, // just for compatibility with regular watchers created via $watch
+ expressions: expressions
+ });
}
function parseStringifyInterceptor(value) {
@@ -170,33 +163,27 @@ function $get($parse, $exceptionHandler, $sce) {
$get.$inject = ['$parse', '$exceptionHandler', '$sce'];
-export class Interpolate
-{
+export class Interpolate {
constructor() {
this._startSymbol = '*[';
this._endSymbol = ']*';
}
-
set startSymbol(value) {
if (value) {
this._startSymbol = value;
return this;
- } else {
- return this._startSymbol;
}
+ return this._startSymbol;
}
-
set endSymbol(value) {
if (value) {
this._endSymbol = value;
return this;
- } else {
- return this._endSymbol;
}
+ return this._endSymbol;
}
-
}
Interpolate.prototype.$get = $get;
var interpolate = new Interpolate();
-module.provider(NAME, () => interpolate);
+ngModule.provider('vnInterpolate', () => interpolate);
diff --git a/client/core/src/lib/key-codes.js b/client/core/src/lib/key-codes.js
new file mode 100644
index 000000000..8c84b6b4d
--- /dev/null
+++ b/client/core/src/lib/key-codes.js
@@ -0,0 +1,13 @@
+
+export default function validKey(key) {
+ let keycode = key.keyCode || key;
+
+ let valid =
+ (keycode > 47 && keycode < 58) || // number keys
+ (keycode > 64 && keycode < 91) || // letter keys
+ (keycode > 95 && keycode < 112) || // numpad keys
+ (keycode > 185 && keycode < 193) || // ;=,-./` (in order)
+ (keycode > 218 && keycode < 223); // [\]' (in order)
+
+ return valid;
+}
diff --git a/client/core/src/lib/modified.js b/client/core/src/lib/modified.js
index 9ce1d9429..f142126fb 100644
--- a/client/core/src/lib/modified.js
+++ b/client/core/src/lib/modified.js
@@ -1,24 +1,22 @@
-import {module} from '../module';
import isEqual from './equals';
export default function getModifiedData(object, objectOld) {
var newObject = {};
+ if (objectOld === null) {
+ return object;
+ }
for (var k in object) {
var val = object[k];
- var valOld = objectOld[k];
+ var valOld = objectOld[k] === undefined ? null : objectOld[k];
if (!isEqual(val, valOld)) {
if (val instanceof Object) {
newObject[k] = getModifiedData(val, valOld);
- }
- else {
+ } else {
newObject[k] = val;
}
}
}
- return newObject;
+ return Object.keys(newObject).length ? newObject : undefined;
}
-
-export const NAME = 'getDataModified';
-module.value(NAME, getModifiedData);
diff --git a/client/core/src/lib/module-loader.js b/client/core/src/lib/module-loader.js
new file mode 100644
index 000000000..57cca1753
--- /dev/null
+++ b/client/core/src/lib/module-loader.js
@@ -0,0 +1,96 @@
+import ngModule from '../module';
+import splitingRegister from './spliting-register';
+
+factory.$inject = ['$http', '$window', '$ocLazyLoad', '$translatePartialLoader', '$translate'];
+export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $translate) {
+ class ModuleLoader {
+ constructor() {
+ this._loaded = {};
+ }
+ load(moduleName, validations) {
+ let loaded = this._loaded;
+
+ if (loaded[moduleName] === true)
+ return Promise.resolve(true);
+ if (loaded[moduleName] instanceof Promise)
+ return loaded[moduleName];
+ if (loaded[moduleName] === false)
+ return Promise.reject(
+ new Error(`Module dependency loop detected: ${moduleName}`));
+
+ loaded[moduleName] = false;
+
+ let deps = splitingRegister.getDependencies(moduleName);
+ let depPromises = [];
+
+ if (deps)
+ for (let dep of deps)
+ depPromises.push(this.load(dep, validations));
+
+ loaded[moduleName] = new Promise((resolve, reject) => {
+ Promise.all(depPromises)
+ .then(() => {
+ let promises = [];
+
+ $translatePartialLoader.addPart(moduleName);
+ promises.push(new Promise(resolve => {
+ $translate.refresh().then(
+ () => resolve(),
+ () => resolve()
+ );
+ }));
+
+ if (validations)
+ promises.push(new Promise(resolve => {
+ $http.get(`/${moduleName}/validations`).then(
+ json => this.onValidationsReady(json, resolve),
+ () => resolve()
+ );
+ }));
+
+ promises.push(new Promise(resolve => {
+ splitingRegister.modules[moduleName](resolve);
+ }));
+
+ Promise.all(promises)
+ .then(() => {
+ loaded[moduleName] = true;
+ resolve($ocLazyLoad.load({name: moduleName}));
+ })
+ .catch(reject);
+ })
+ .catch(reject);
+ });
+
+ return loaded[moduleName];
+ }
+ onValidationsReady(json, resolve) {
+ let entities = json.data;
+ for (let entity in entities) {
+ let fields = entities[entity].validations;
+ for (let field in fields) {
+ let validations = fields[field];
+ for (let validation of validations)
+ this.parseValidation(validation);
+ }
+ }
+
+ Object.assign($window.validations, json.data);
+ resolve();
+ }
+ parseValidation(val) {
+ switch (val.validation) {
+ case 'custom':
+ // TODO: Replace eval
+ val.bindedFunction = eval(`(${val.bindedFunction})`);
+ break;
+ case 'format':
+ val.with = new RegExp(val.with);
+ break;
+ }
+ }
+ }
+
+ return new ModuleLoader();
+}
+ngModule.factory('vnModuleLoader', factory);
diff --git a/client/core/src/lib/moduleLoader.js b/client/core/src/lib/moduleLoader.js
deleted file mode 100644
index 62fe2c3fd..000000000
--- a/client/core/src/lib/moduleLoader.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import {module} from '../module';
-import splitingRegister from './splitingRegister';
-
-factory.$inject = ['$translatePartialLoader', '$http', '$window', '$ocLazyLoad', '$q', '$translate'];
-export function factory($translatePartialLoader, $http, $window, $ocLazyLoad, $q, $translate) {
- class ModuleLoader {
- constructor() {
- this._loadedModules = {};
- }
- load(moduleName) {
- if(this._loadedModules[moduleName])
- return;
-
- this._loadedModules[moduleName] = true;
-
- let deps = splitingRegister.getDependencies(moduleName);
- let modules = splitingRegister.modules;
- let promises = [];
-
- for(let dep of deps) {
- this._loadedModules[dep] = true;
- promises.push(modules[dep]());
- promises.push(new Promise(resolve => {
- $http.get(`/${dep}/validations`).then(
- json => this.onValidationsReady(json, resolve)
- );
- }));
-
- $translatePartialLoader.addPart(dep);
- // FIXME: https://github.com/angular-translate/angular-translate/pull/1674
- //promises.push($translate.refresh());
- setTimeout (() => $translate.refresh(), 500);
- }
-
- let ocDeps = deps.map(item => { return { name: item } });
-
- return new Promise (resolve => {
- Promise.all(promises).then(
- () => resolve($ocLazyLoad.load(ocDeps))
- )
- });
- }
- parseValidation(val) {
- switch(val.validation) {
- case 'custom':
- // TODO: Reemplazar eval
- val.customValidator = eval(`(${val.customValidator})`);
- break;
- case 'format':
- val.with = new RegExp(val.with);
- break;
- }
- }
- onValidationsReady(json, resolve) {
- let entities = json.data;
- for(let entity in entities) {
- let fields = entities[entity].validations;
- for(let field in fields) {
- let validations = fields[field];
- for(let validation of validations)
- this.parseValidation(validation);
- }
- }
-
- Object.assign($window.validations, json.data);
- resolve();
- }
- }
-
- return new ModuleLoader();
-};
-module.factory('vnModuleLoader', factory);
diff --git a/client/core/src/lib/resolveDefaultComponents.js b/client/core/src/lib/resolveDefaultComponents.js
deleted file mode 100644
index 312bf8ca2..000000000
--- a/client/core/src/lib/resolveDefaultComponents.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import {module} from '../module';
-import * as util from './util';
-import constant from './constants';
-import Interpolate from './interpolate';
-
-export const NAME = util.getProviderName('ResolveDefaultComponent');
-
-function $get($injector, vnInterpolate) {
- return {
- getTemplate: function(name, attrs) {
- this._frameworkName = 'Mdl';
- let _name = util.getFactoryName(name + this._frameworkName);
- let defaultfactory = $injector.has(_name) ? $injector.get(_name) : undefined;
-
- if (!defaultfactory) {
- throw new Error("factory is not defined");
- }
-
- let defaultValues = defaultfactory.default;
- let template = defaultfactory.template;
- let scope = Object.assign({}, defaultValues || {}, attrs || {});
- return template && vnInterpolate(template)(scope);
- }
- };
-}
-$get.$inject = ['$injector', 'vnInterpolate'];
-
-export class ResolveDefaultComponent {
- constructor() {
- this._frameworkName = 'Mdl';
- }
- set frameworkName(value) {
- this._frameworkName = value;
- }
-}
-
-ResolveDefaultComponent.prototype.$get = $get;
-var resolve = new ResolveDefaultComponent();
-module.provider(NAME, () => resolve);
diff --git a/client/core/src/lib/specs/acl-service.spec.js b/client/core/src/lib/specs/acl-service.spec.js
new file mode 100644
index 000000000..45a820acc
--- /dev/null
+++ b/client/core/src/lib/specs/acl-service.spec.js
@@ -0,0 +1,50 @@
+describe('Service acl', () => {
+ let aclService;
+
+ beforeEach(() => {
+ angular.mock.module('vnCore');
+ });
+
+ beforeEach(angular.mock.module($provide => {
+ $provide.value('aclConstant', {});
+ }));
+
+ beforeEach(inject((_aclService_, $httpBackend) => {
+ aclService = _aclService_;
+ }));
+
+ it("should return false as the service doesn't have roles", () => {
+ expect(aclService.routeHasPermission('http://www.verdnatura.es')).toBeFalsy();
+ });
+
+ it("should return true as the service has roles but the route has no acl", () => {
+ aclService.roles = {customer: true};
+
+ expect(aclService.routeHasPermission('http://www.verdnatura.es')).toBeTruthy();
+ });
+
+ it("should return false as the service roles have no length", () => {
+ aclService.roles = {};
+ let route = {url: 'http://www.verdnatura.es', acl: []};
+
+ expect(aclService.routeHasPermission(route)).toBeFalsy();
+ });
+
+ it("should call the service aclPermission() function and return false as the service has roles and the rote has acl without length", () => {
+ aclService.roles = {customer: true, employee: true};
+ let route = {url: 'http://www.verdnatura.es', acl: []};
+ spyOn(aclService, 'aclPermission').and.callThrough();
+
+ expect(aclService.routeHasPermission(route)).toBeFalsy();
+ expect(aclService.aclPermission).toHaveBeenCalledWith(route.acl);
+ });
+
+ it("should call the service aclPermission() function to return true as the service has roles matching with the ones in acl", () => {
+ aclService.roles = {customer: true, employee: true};
+ let route = {url: 'http://www.verdnatura.es', acl: ['customer']};
+ spyOn(aclService, 'aclPermission').and.callThrough();
+
+ expect(aclService.routeHasPermission(route)).toBeTruthy();
+ expect(aclService.aclPermission).toHaveBeenCalledWith(route.acl);
+ });
+});
diff --git a/client/core/src/lib/spliting-register.js b/client/core/src/lib/spliting-register.js
new file mode 100644
index 000000000..d6af3de64
--- /dev/null
+++ b/client/core/src/lib/spliting-register.js
@@ -0,0 +1,12 @@
+
+class SplitingRegister {
+ constructor() {
+ this.graph = null;
+ this.modules = {};
+ }
+ getDependencies(moduleName) {
+ return this.graph[moduleName];
+ }
+}
+
+export default new SplitingRegister();
diff --git a/client/core/src/lib/splitingRegister.js b/client/core/src/lib/splitingRegister.js
deleted file mode 100644
index 28daae062..000000000
--- a/client/core/src/lib/splitingRegister.js
+++ /dev/null
@@ -1,29 +0,0 @@
-
-class SplitingRegister {
- constructor() {
- this._graph = null;
- this._modules = {};
- }
- get modules() {
- return this._modules;
- }
- getDependencies(dependency) {
- var array = [];
- array.push(dependency);
- var first = this._graph[dependency];
-
- while (first && first.length > 0) {
- dependency = first.shift();
- array = array.concat(this.getDependencies(dependency));
- }
- return array;
- }
- registerGraph(graph) {
- this._graph = graph;
- }
- register(moduleName, loader) {
- this._modules[moduleName] = loader;
- }
-}
-
-export default new SplitingRegister();
diff --git a/client/core/src/lib/storage-services.js b/client/core/src/lib/storage-services.js
new file mode 100644
index 000000000..bb766215e
--- /dev/null
+++ b/client/core/src/lib/storage-services.js
@@ -0,0 +1,66 @@
+import ngModule from '../module';
+
+class VnStorage {
+ constructor() {
+ this._type = '';
+ this.prefix = 'vn';
+ }
+ set type(value) {
+ this._type = value;
+ this.checkSupport();
+ }
+ get type() {
+ return this._type;
+ }
+ get webStorage() {
+ return window[this.type];
+ }
+ checkSupport() {
+ try {
+ let supported = (this.type in window && window[this.type] !== null);
+ if (supported) {
+ let key = '__' + Math.round(Math.random() * 1e7);
+ let webStorage = window[this.type];
+ webStorage.setItem(key, '');
+ webStorage.removeItem(key);
+ }
+ } catch (e) {
+ console.error('VnStorage.notification.error', e.message);
+ return false;
+ }
+ }
+ get(param) {
+ let toRead = this.webStorage.getItem(`${this.prefix}.${param}`);
+ if (toRead && toRead.startsWith('jsonObject:')) {
+ toRead = JSON.parse(toRead.replace('jsonObject:', ''));
+ }
+ return toRead;
+ }
+ set(param, data) {
+ let toStorage = typeof data === 'object' ? `jsonObject:${JSON.stringify(data)}` : data;
+ this.webStorage.setItem(`${this.prefix}.${param}`, toStorage);
+ }
+ remove(param) {
+ this.webStorage.removeItem(`${this.prefix}.${param}`);
+ }
+ clear() {
+ this.webStorage.clear();
+ }
+}
+
+class SessionStorage extends VnStorage {
+ constructor() {
+ super();
+ this.type = 'sessionStorage';
+ }
+}
+
+class LocalStorage extends VnStorage {
+ constructor() {
+ super();
+ this.type = 'localStorage';
+ }
+}
+
+ngModule.service('sessionStorage', SessionStorage);
+ngModule.service('localStorage', LocalStorage);
diff --git a/client/core/src/lib/string.js b/client/core/src/lib/string.js
index e48bd082b..920640a95 100644
--- a/client/core/src/lib/string.js
+++ b/client/core/src/lib/string.js
@@ -1,12 +1,12 @@
/**
* Transforms a kebab-case string to camelCase. A kebab-case string
* is a string with hyphen character as word separator.
- *
+ *
* @param {String} str The hyphenized string
* @return {String} The camelized string
*/
export function kebabToCamel(str) {
- var camelCased = str.replace (/-([a-z])/, function(g) {
+ var camelCased = str.replace(/-([a-z])/g, function(g) {
return g[1].toUpperCase();
});
return camelCased;
@@ -14,7 +14,7 @@ export function kebabToCamel(str) {
/**
* Transforms the first letter of a string to uppercase.
- *
+ *
* @param {String} str The input string
* @return {String} The transformed string
*/
diff --git a/client/core/src/lib/template.js b/client/core/src/lib/template.js
index 59edd21cb..b8aa1b30e 100644
--- a/client/core/src/lib/template.js
+++ b/client/core/src/lib/template.js
@@ -1,8 +1,46 @@
-import {kebabToCamel} from './string';
+import ngModule from '../module';
-template.$inject = ['$element', '$attrs', 'vnInputAttrsNormalizer', 'vnResolveDefaultComponent'];
-export default function template($element, $attrs, normalizer, resolve) {
- normalizer.normalize($attrs);
- let templateName = kebabToCamel($element[0].tagName.toLowerCase().substr(3));
- return resolve.getTemplate(templateName, $attrs);
+export default class Template {
+ constructor(vnInterpolate) {
+ this.vnInterpolate = vnInterpolate;
+ }
+ get(template, $attrs, defaults) {
+ let scope = Object.assign({}, defaults, $attrs);
+ return template && this.vnInterpolate(template)(scope);
+ }
+ getNormalized(template, $attrs, defaults) {
+ this.normalizeInputAttrs($attrs);
+ return this.get(template, $attrs, defaults);
+ }
+ normalizeInputAttrs($attrs) {
+ if ($attrs.field) {
+ let split = $attrs.field.split('.');
+ let len = split.length;
+
+ if (len == 0)
+ throw new Error(`Attribute 'field' can not be empty`);
+ if (len > 3)
+ throw new Error(`Attribute 'field' must have this syntax: [ctrl].[entity].[field]`);
+
+ let i = len - 1;
+ let field = split[i--];
+ let entity = i >= 0 ? split[i--] : 'model';
+ let ctrl = i >= 0 ? split[i--] : '$ctrl';
+
+ if ($attrs.model === undefined)
+ $attrs.model = `${ctrl}.${entity}.${field}`;
+ if ($attrs.rule === undefined && len >= 2)
+ $attrs.rule = `${entity}.${field}`;
+ if ($attrs.label === undefined && len >= 2)
+ $attrs.label = `${entity}.${field}`;
+ if ($attrs.name === undefined)
+ $attrs.name = field;
+ }
+
+ if ($attrs.focus !== undefined)
+ $attrs.focus = 'vn-focus';
+ }
}
+Template.$inject = ['vnInterpolate'];
+
+ngModule.service('vnTemplate', Template);
diff --git a/client/core/src/lib/util.js b/client/core/src/lib/util.js
deleted file mode 100644
index b0da3807c..000000000
--- a/client/core/src/lib/util.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import * as constant from './constants';
-
-const FACTORY = 'Factory';
-const SERVICE = 'Service';
-
-export function getName(name) {
- return constant.PREFIX + toUpperCamelCase(name);
-}
-
-export function toUpperCamelCase(stringToConvert) {
- return stringToConvert.substr(0, 1).toUpperCase() + stringToConvert.substr(1);
-}
-
-export function getFactoryName(name) {
- return getName(name) + FACTORY;
-}
-
-export function getServiceName(name) {
- return getName(name) + SERVICE;
-}
-
-export function getModuleName(name) {
- return constant.PREFIX + name;
-}
-
-export function getProviderNameFromConfig(name) {
- return getName(name) + 'Provider';
-}
-
-export function getProviderName(name) {
- return getName(name);
-}
-
-export function getTemplateName(componentName, frameworkName) {
- return componentName + '.' + frameworkName + '.html';
-}
-
-export function getVendorDependencies(vendors) {
- let dependencies = [];
- Object.keys(vendors).forEach(vendor => {
- let name = vendors[vendor].name;
- if (name) {
- dependencies.push(name);
- }
- });
- return dependencies;
-}
diff --git a/client/core/src/lib/validator.js b/client/core/src/lib/validator.js
index b27fdf8d8..e1a3dd1ed 100644
--- a/client/core/src/lib/validator.js
+++ b/client/core/src/lib/validator.js
@@ -1,60 +1,54 @@
import {validator} from 'vendor';
export const validators = {
- presence: function(value, conf) {
- if (validator.isEmpty(value))
+ presence: value => {
+ if (validator.isEmpty(value ? String(value) : ''))
throw new Error(`Value can't be empty`);
},
- absence: function(value, conf) {
+ absence: value => {
if (!validator.isEmpty(value))
throw new Error(`Value should be empty`);
},
- length: function(value, conf) {
+ length: (value, conf) => {
let options = {
min: conf.min || conf.is,
max: conf.max || conf.is
};
-
- if (!validator.isLength(value, options)) {
- if (conf.is)
+ let val = value ? String(value) : '';
+ if (!validator.isLength(val, options)) {
+ if (conf.is) {
throw new Error(`Value should be ${conf.is} characters long`);
- else
+ } else if (conf.min && conf.max) {
throw new Error(`Value should have a length between ${conf.min} and ${conf.max}`);
+ } else if (conf.min) {
+ throw new Error(`Value should have at least ${conf.min} characters`);
+ } else {
+ throw new Error(`Value should have at most ${conf.max} characters`);
+ }
}
},
- numericality: function(value, conf) {
+ numericality: (value, conf) => {
if (conf.int) {
if (!validator.isInt(value))
throw new Error(`Value should be integer`);
} else if (!validator.isNumeric(value))
throw new Error(`Value should be a number`);
},
- inclusion: function(value, conf) {
+ inclusion: (value, conf) => {
if (!validator.isIn(value, conf.in))
throw new Error(`Invalid value`);
},
- exclusion: function(value, conf) {
+ exclusion: (value, conf) => {
if (validator.isIn(value, conf.in))
throw new Error(`Invalid value`);
},
- format: function(value, conf) {
+ format: (value, conf) => {
if (!validator.matches(value, conf.with))
throw new Error(`Invalid value`);
},
- custom: function(value, conf) {
- let valid = true;
- function err(kind) {
- valid = false;
- }
-
- let inst = {attr: value};
- conf.customValidator.call(inst, err);
-
- if (!valid)
+ custom: (value, conf) => {
+ if (!conf.bindedFunction(value))
throw new Error(`Invalid value`);
- },
- uniqueness: function() {
- // TODO: Implement me
}
};
@@ -78,8 +72,12 @@ export function validateAll(value, validations) {
export function validate(value, conf) {
let validator = validators[conf.validation];
try {
- checkNull(value, conf);
- if (validator) validator(value, conf);
+ let isEmpty = value == null || value === '';
+
+ if (isEmpty)
+ checkNull(value, conf);
+ if (validator && (!isEmpty || conf.validation == 'presence'))
+ validator(value, conf);
} catch (e) {
let message = conf.message ? conf.message : e.message;
throw new Error(message);
@@ -87,15 +85,14 @@ export function validate(value, conf) {
}
/**
- * Checks if value satisfies a not null validation.
+ * Checks if value satisfies a blank or not null validation.
*
* @param {*} value The value
* @param {Object} conf The validation configuration
*/
export function checkNull(value, conf) {
- if (typeof value === 'undefined') {
- if (!conf.allowBlank)
- throw new Error(`Value can't be blank`);
- } else if (value === null && !conf.allowNull)
+ if (conf.allowBlank === false && value === '')
+ throw new Error(`Value can't be blank`);
+ else if (conf.allowNull === false && value == null)
throw new Error(`Value can't be null`);
}
diff --git a/client/core/src/locale/en.json b/client/core/src/locale/en.json
deleted file mode 100644
index f2c3b62b9..000000000
--- a/client/core/src/locale/en.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "Accept": "Accept",
- "Cancel": "Cancel"
-}
\ No newline at end of file
diff --git a/client/core/src/locale/en.yml b/client/core/src/locale/en.yml
new file mode 100644
index 000000000..a89a8ca8d
--- /dev/null
+++ b/client/core/src/locale/en.yml
@@ -0,0 +1,10 @@
+Accept: Accept
+Cancel: Cancel
+Close: Close
+Clear: Clear
+Save: Save
+Add: Add
+Search: Search
+Show More: Show More
+No more results: No more results
+Hide: Hide
\ No newline at end of file
diff --git a/client/core/src/locale/es.json b/client/core/src/locale/es.json
deleted file mode 100644
index cd2b7eea1..000000000
--- a/client/core/src/locale/es.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "Accept": "Aceptar",
- "Cancel": "Cancelar"
-}
\ No newline at end of file
diff --git a/client/core/src/locale/es.yml b/client/core/src/locale/es.yml
new file mode 100644
index 000000000..2b6386570
--- /dev/null
+++ b/client/core/src/locale/es.yml
@@ -0,0 +1,10 @@
+Accept: Aceptar
+Cancel: Cancelar
+Close: Cerrar
+Clear: Borrar
+Save: Guardar
+Add: Añadir
+Search: Buscar
+Show More: Ver más
+No more results: No hay más resultados
+Hide: Ocultar
\ No newline at end of file
diff --git a/client/core/src/mdl-override.css b/client/core/src/mdl-override.css
deleted file mode 100644
index b29cc68d9..000000000
--- a/client/core/src/mdl-override.css
+++ /dev/null
@@ -1,55 +0,0 @@
-.mdl-textfield {
- width: 100%;
-}
-/* TODO: No utilizar !important */
-.mdl-button {
- font-weight: bolder;
- color: #ffa410;
-}
-.mdl-button--colored {
- color: white !important;
-}
-.mdl-button--colored,
-.mdl-button--colored:focus,
-.mdl-button--colored:active {
- background-color: #ffa410 !important;
-}
-.mdl-button--colored:hover,
-.mdl-button--raised:hover {
- background-color: #ffa410 !important;
-}
-.mdl-button--fab{
- color: white !important;
- background-color: #ff9400 !important;
-}
-
-.mdl-dialog__actions--full-width>*{
- text-align: center;
-}
-
-.mdl-dialog{
- width: 400px;
- font-family: raleway-regular;
- line-height:60px;
- text-align: center;
-}
-
-.mdl-textfield__error {
- visibility: visible;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- width: 100%;
-}
-.mdl-textfield.invalid .mdl-textfield__input {
- border-color: #d50000;
- box-shadow: none;
-}
-.mdl-textfield.invalid .mdl-textfield__label::after {
- background-color: #d50000;
-}
-.mdl-textfield--floating-label.invalid .mdl-textfield__label {
- color: #d50000;
- font-size: 12px;
- top: 4px;
-}
diff --git a/client/core/src/module.js b/client/core/src/module.js
index d366003db..81fb84f00 100644
--- a/client/core/src/module.js
+++ b/client/core/src/module.js
@@ -1,6 +1,43 @@
import * as vendors from 'vendor';
-import {getModuleName, getVendorDependencies} from './lib/util';
-const DEPENDENCIES = getVendorDependencies(vendors);
-export const NAME = getModuleName('core');
-export const module = vendors.ng.module(NAME, DEPENDENCIES);
+let deps = [];
+Object.keys(vendors).forEach(vendor => {
+ let name = vendors[vendor].name;
+ if (name)
+ deps.push(name);
+});
+
+const ngModule = vendors.ng.module('vnCore', deps);
+export default ngModule;
+
+config.$inject = ['$translateProvider', '$translatePartialLoaderProvider'];
+export function config($translateProvider, $translatePartialLoaderProvider) {
+ $translatePartialLoaderProvider.addPart('core');
+
+ let conf = {urlTemplate: '/static/locale/{part}/{lang}.json'};
+
+ let fallbackLang = 'es';
+ let langs = ['en', 'es'];
+ let langAliases = {
+ en_US: 'en',
+ en_UK: 'en',
+ es_ES: 'es',
+ es_AR: 'es'
+ };
+
+ $translateProvider
+ .useSanitizeValueStrategy('escape')
+ .useLoader('$translatePartialLoader', conf)
+ .registerAvailableLanguageKeys(langs, langAliases)
+ // FIXME: Circular dependency due to vnInterceptor
+ // .fallbackLanguage(fallbackLang)
+ .determinePreferredLanguage(() => {
+ let locale = $translateProvider.resolveClientLocale();
+ if (langs.indexOf(locale) !== -1)
+ return locale;
+ if (langAliases[locale])
+ return langAliases[locale];
+ return fallbackLang;
+ });
+}
+ngModule.config(config);
diff --git a/client/core/src/paging/index.js b/client/core/src/paging/index.js
deleted file mode 100644
index c20405613..000000000
--- a/client/core/src/paging/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import {module} from '../module';
-import './style.scss';
-
-export default class Paging {
- get numPages() {
- return Math.ceil(this.numItems / this.numPerPage);
- }
- constructor($http, $scope) {
- this.$http = $http;
- this.$scope = $scope;
- this.where = this.filter;
- this.numPerPage = null;
- this.numItems = 0;
- $scope.$watch('$ctrl.index.model.length', () => this.onModelUpdated());
- }
- $onChanges() {
- if(!this.index) return;
- this.numPerPage = this.index.filter.size;
- }
- onModelUpdated() {
- let index = this.index;
- let filter = index.filter;
-
- if(filter.page >= this.numPages
- && index.model.length >= this.numPerPage)
- this.numItems = filter.page * filter.size + 1;
- }
- onPageChange(page) {
- this.index.filter.page = page;
- this.index.accept();
- }
-}
-Paging.$inject = ['$http', '$scope'];
-
-export const NAME = 'vnPaging';
-export const COMPONENT = {
- template: require('./index.html'),
- bindings: {
- index: '<'
- },
- controller: Paging
-};
-module.component(NAME, COMPONENT);
diff --git a/client/core/src/password/password.js b/client/core/src/password/password.js
deleted file mode 100644
index 3ab7090d1..000000000
--- a/client/core/src/password/password.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as normalizerFactory from '../lib/inputAttrsNormalizer';
-import * as util from '../lib/util';
-
-const _NAME = 'password';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME, normalizerFactory.NAME];
-export function directive(resolve, normalizer) {
- return {
- restrict: 'E',
- template: function(_, attrs) {
- normalizer.normalize(attrs);
- return resolve.getTemplate(_NAME, attrs);
- },
- link: function(scope, element, attrs) {
- scope.$watch(attrs.model, () => {
- let mdlField = element[0].firstChild.MaterialTextfield;
- if (mdlField)
- mdlField.updateClasses_();
- });
- componentHandler.upgradeElement(element[0].firstChild);
- }
- }
-}
-_module.directive(NAME,directive);
diff --git a/client/core/src/password/password.mdl.html b/client/core/src/password/password.mdl.html
deleted file mode 100644
index a1daf50d4..000000000
--- a/client/core/src/password/password.mdl.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/client/core/src/password/password.mdl.js b/client/core/src/password/password.mdl.js
deleted file mode 100644
index a4102ef60..000000000
--- a/client/core/src/password/password.mdl.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import {module} from '../module';
-import template from './password.mdl.html';
-
-export const NAME = 'vnPasswordMdlFactory';
-
-export function factory() {
- return {
- template: template,
- default: {
- label: 'Password',
- enabled: 'enabled',
- className: 'mdl-textfield--floating-label'
- }
- }
-}
-
-module.factory(NAME, factory);
diff --git a/client/core/src/popover/index.js b/client/core/src/popover/index.js
deleted file mode 100644
index 559194c2e..000000000
--- a/client/core/src/popover/index.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import {module} from '../module';
-import './style.css';
-
-directive.$inject = ['vnPopover'];
-export function directive(popover) {
- return {
- restrict: 'A',
- link: function($scope, $element, $attrs, $ctrl) {
- $element.on('click', function(event) {
- popover.showComponent($attrs.vnDialog, $scope, $element);
- event.preventDefault();
- });
- }
- }
-}
-module.directive('vnPopover', directive);
-
-export class Popover {
- constructor($document, $compile) {
- this.document = $document[0];
- this.$compile = $compile;
- }
- show(childElement, parent) {
- let popover = this.document.createElement('div');
- popover.className = 'vn-popover';
- popover.addEventListener('mousedown',
- (event) => this.onPopoverMouseDown(event));
- popover.appendChild(childElement);
- this.popover = popover;
-
- let style = popover.style;
-
- let spacing = 0;
- let screenMargin = 20;
- let dblMargin = screenMargin * 2;
-
- let width = popover.offsetWidth;
- let height = popover.offsetHeight;
- let innerWidth = window.innerWidth;
- let innerHeight = window.innerHeight;
-
- if(width + dblMargin > innerWidth) {
- width = innerWidth - dblMargin;
- style.width = width +'px';
- }
- if(height + dblMargin > innerHeight) {
- height = innerHeight - dblMargin;
- style.height = height +'px';
- }
-
- if(parent) {
- let parentNode = parent;
- let rect = parentNode.getBoundingClientRect();
- let left = rect.left;
- let top = rect.top + spacing + parentNode.offsetHeight;
-
- if(left + width > innerWidth)
- left -= (left + width) - innerWidth + margin;
- if(top + height > innerHeight)
- top -= height + parentNode.offsetHeight + spacing * 2;
-
- if(left < 0)
- left = screenMargin;
- if(top < 0)
- top = screenMargin;
-
- style.top = (top) +'px';
- style.left = (left) +'px';
- style.minWidth = (rect.width) +'px';
- }
-
- this.document.body.appendChild(popover);
- this.docMouseDownHandler = (event) => this.onDocMouseDown(event);
- this.document.addEventListener('mousedown', this.docMouseDownHandler);
- }
- showComponent(childComponent, $scope, parent) {
- let childElement = this.document.createElement(childComponent);
- this.$compile(childElement)($scope);
- this.show(childElement, parent);
- }
- hide() {
- if(!this.popover) return;
- this.document.removeEventListener('mousedown', this.docMouseDownHandler);
- this.document.body.removeChild(this.popover);
- this.popover = null;
- this.lastEvent = null;
- this.docMouseDownHandler = null;
- }
- onDocMouseDown(event) {
- if (event != this.lastEvent)
- this.hide();
- }
- onPopoverMouseDown(event) {
- this.lastEvent = event;
- }
-}
-Popover.$inject = ['$document', '$compile'];
-module.service('vnPopover', Popover);
diff --git a/client/core/src/popover/style.css b/client/core/src/popover/style.css
deleted file mode 100644
index 536359a2f..000000000
--- a/client/core/src/popover/style.css
+++ /dev/null
@@ -1,9 +0,0 @@
-.vn-popover {
- position: fixed;
- box-shadow: 0 0 .4em rgba(1,1,1,.4);
- background-color: white;
- z-index: 100;
- border-radius: .1em;
- top: 0;
- left: 0;
-}
\ No newline at end of file
diff --git a/client/core/src/radio/radio.js b/client/core/src/radio/radio.js
deleted file mode 100644
index 77e388927..000000000
--- a/client/core/src/radio/radio.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as util from '../lib/util';
-
-const _NAME = 'radio';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME];
-export function directive(resolve) {
- return{
- restrict: 'E',
- template: function(_, attrs) {
- return resolve.getTemplate(_NAME, attrs);
- }
- }
-}
-
-_module.directive(NAME, directive);
diff --git a/client/core/src/radio/radio.mdl.html b/client/core/src/radio/radio.mdl.html
deleted file mode 100644
index ea61c7a90..000000000
--- a/client/core/src/radio/radio.mdl.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-*[text]*
diff --git a/client/core/src/radio/radio.mdl.js b/client/core/src/radio/radio.mdl.js
deleted file mode 100644
index 6c0ccc9f4..000000000
--- a/client/core/src/radio/radio.mdl.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import {module as _module} from '../module';
-import * as util from '../lib/util';
-import * as constant from '../lib/constants';
-import template from './radio.mdl.html';
-
-const _NAME = 'radio';
-const DEFAULT_CLASS = 'mdl-radio mdl-js-radio mdl-js-ripple-effect';
-
-export const NAME = util.getFactoryName(_NAME + constant.MATERIAL_DESIGN_FRAMEWORK);
-
-export function factory() {
- return {
- template: template,
- default: {
- enabled: 'true',
- className: DEFAULT_CLASS
- }
- }
-}
-
-_module.factory(NAME, factory);
diff --git a/client/core/src/snackbar/snackbar.js b/client/core/src/snackbar/snackbar.js
deleted file mode 100644
index 43cbf1903..000000000
--- a/client/core/src/snackbar/snackbar.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import {module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as util from '../lib/util';
-
-const _NAME = 'snackbar';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME];
-export function directive(resolve) {
- return {
- restrict: 'E',
- template: function(_, attrs) {
- return resolve.getTemplate(_NAME, attrs);
- },
- controller: controller
- }
-}
-module.directive(NAME, directive);
-
-controller.$inject = ['$scope', '$element'];
-function controller($scope, $element) {
- let snackbar = $element[0].firstChild;
- componentHandler.upgradeElement (snackbar);
-
- this.show = function(data) {
- snackbar.MaterialSnackbar.showSnackbar(data);
- }
-}
\ No newline at end of file
diff --git a/client/core/src/snackbar/snackbar.mdl.html b/client/core/src/snackbar/snackbar.mdl.html
deleted file mode 100644
index 7b78a7c52..000000000
--- a/client/core/src/snackbar/snackbar.mdl.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/client/core/src/snackbar/snackbar.mdl.js b/client/core/src/snackbar/snackbar.mdl.js
deleted file mode 100644
index 2811797b5..000000000
--- a/client/core/src/snackbar/snackbar.mdl.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import {module} from '../module';
-import template from './snackbar.mdl.html';
-
-export const NAME = 'vnSnackbarMdlFactory';
-
-export function factory() {
- return {
- template: template,
- default: {
- message: 'Default message'
- }
- }
-}
-
-module.factory(NAME, factory);
diff --git a/client/core/src/styles/fonts/Material-Design-Icons.woff2 b/client/core/src/styles/Material-Design-Icons.woff2
similarity index 100%
rename from client/core/src/styles/fonts/Material-Design-Icons.woff2
rename to client/core/src/styles/Material-Design-Icons.woff2
diff --git a/client/core/src/styles/fontello-head.css b/client/core/src/styles/fontello-head.css
new file mode 100644
index 000000000..7761cfac0
--- /dev/null
+++ b/client/core/src/styles/fontello-head.css
@@ -0,0 +1,30 @@
+@font-face {
+ font-family: 'fontello';
+
+ src: url('./fontello.woff2') format('woff2');
+ font-weight: normal;
+ font-style: normal;
+}
+
+[class^="icon-"]:before, [class*=" icon-"]:before {
+ font-family: "fontello";
+ font-style: normal;
+ font-weight: 400;
+ speak: none;
+
+ display: inline-block;
+ text-decoration: inherit;
+
+ text-align: center;
+ /* opacity: .8; */
+
+ /* For safety - reset parent styles, that can break glyph codes*/
+ font-variant: normal;
+ text-transform: none;
+
+ /* Font smoothing. That was taken from TWBS */
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+
+ }
+
\ No newline at end of file
diff --git a/client/core/src/styles/fontello-icons.css b/client/core/src/styles/fontello-icons.css
new file mode 100644
index 000000000..03698f3cf
--- /dev/null
+++ b/client/core/src/styles/fontello-icons.css
@@ -0,0 +1,18 @@
+
+.icon-barcode:before { content: '\e800'; } /* '' */
+.icon-volume:before { content: '\e801'; } /* '' */
+.icon-bucket:before { content: '\e802'; } /* '' */
+.icon-disabled:before { content: '\e80b'; } /* '' */
+.icon-invoices:before { content: '\e80c'; } /* '' */
+.icon-noweb:before { content: '\e812'; } /* '' */
+.icon-payment:before { content: '\e813'; } /* '' */
+.icon-recovery:before { content: '\e815'; } /* '' */
+.icon-risk:before { content: '\e816'; } /* '' */
+.icon-lines:before { content: '\e819'; } /* '' */
+.icon-volum:before { content: '\e81b'; } /* '' */
+.icon-components:before { content: '\e81c'; } /* '' */
+.icon-clone:before { content: '\e81d'; } /* '' */
+.icon-addperson:before { content: '\e81e'; } /* '' */
+.icon-bin:before { content: '\e81f'; } /* '' */
+.icon-sms:before { content: '\e820'; } /* '' */
+.icon-tags:before { content: '\e821'; } /* '' */
\ No newline at end of file
diff --git a/client/core/src/styles/fontello.woff2 b/client/core/src/styles/fontello.woff2
new file mode 100644
index 000000000..eea564017
Binary files /dev/null and b/client/core/src/styles/fontello.woff2 differ
diff --git a/client/core/src/styles/index.js b/client/core/src/styles/index.js
new file mode 100644
index 000000000..a8ed4b937
--- /dev/null
+++ b/client/core/src/styles/index.js
@@ -0,0 +1,5 @@
+import './mdl-override.css';
+import './mdi-override.css';
+import './zoom-image.scss';
+import './fontello-head.css';
+import './fontello-icons.css';
diff --git a/client/core/src/styles/fonts/mdi-override.css b/client/core/src/styles/mdi-override.css
similarity index 100%
rename from client/core/src/styles/fonts/mdi-override.css
rename to client/core/src/styles/mdi-override.css
diff --git a/client/core/src/styles/mdl-override.css b/client/core/src/styles/mdl-override.css
new file mode 100644
index 000000000..d781e5817
--- /dev/null
+++ b/client/core/src/styles/mdl-override.css
@@ -0,0 +1,29 @@
+/**
+ * Rewrited CSS rules from Material Design Lite.
+ * FIXME: don't use !important
+ */
+body {
+ line-height: initial;
+ font-size: 12pt;
+}
+.mdl-button {
+ font-weight: bolder;
+ color: #ffa410;
+}
+.mdl-button--colored {
+ color: white !important;
+}
+.mdl-button--colored,
+.mdl-button--colored:focus,
+.mdl-button--colored:active {
+ background-color: #ffa410 !important;
+}
+.mdl-button--colored:hover,
+.mdl-button--raised:hover {
+ background-color: #ffa410 !important;
+}
+.mdl-button--fab{
+ color: white !important;
+ background-color: #ff9400 !important;
+}
+
diff --git a/client/core/src/styles/zoom-image.scss b/client/core/src/styles/zoom-image.scss
new file mode 100644
index 000000000..cc0212006
--- /dev/null
+++ b/client/core/src/styles/zoom-image.scss
@@ -0,0 +1,29 @@
+img[zoom-image]{
+ cursor: zoom-in;
+}
+
+.vn-zoom-image {
+ width: 100%;
+ height: 100%;
+ position: fixed;
+ top: 0;
+ z-index: 11;
+ background-color: rgba(1, 1, 1, 0.6);
+
+ & > div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: inherit;
+ height: inherit;
+ box-sizing: border-box;
+ padding: 1em;
+
+ & > img {
+ cursor: zoom-out;
+ max-height: 100%;
+ max-width: 100%;
+ border-radius: .2em;
+ }
+ }
+}
diff --git a/client/core/src/submit/submit.js b/client/core/src/submit/submit.js
deleted file mode 100644
index 2ebda993e..000000000
--- a/client/core/src/submit/submit.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as util from '../lib/util';
-
-const _NAME = 'submit';
-export const NAME = util.getName(_NAME);
-
-directive.$inject =[resolveFactory.NAME];
-export function directive (resolve){
- return{
- restrict:'E',
- template: function(_,attr){
- return resolve.getTemplate(_NAME, attr);
- }
- }
-}
-
-_module.directive(NAME,directive);
diff --git a/client/core/src/submit/submit.mdl.html b/client/core/src/submit/submit.mdl.html
deleted file mode 100644
index d6fc98b52..000000000
--- a/client/core/src/submit/submit.mdl.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/client/core/src/submit/submit.mdl.js b/client/core/src/submit/submit.mdl.js
deleted file mode 100644
index c739ec321..000000000
--- a/client/core/src/submit/submit.mdl.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import {module} from '../module';
-import template from './submit.mdl.html';
-
-export const NAME = 'vnSubmitMdlFactory';
-
-export function factory() {
- return {
- template: template,
- default: {
- label: 'Submit',
- className: 'mdl-button mdl-js-button mdl-button--raised mdl-button--colored',
- enabled: 'true'
- }
- }
-}
-
-module.factory(NAME, factory);
diff --git a/client/core/src/subtitle/index.js b/client/core/src/subtitle/index.js
deleted file mode 100644
index 941e8eb54..000000000
--- a/client/core/src/subtitle/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import {module} from '../module';
-
-module.component('vnSubtitle', {
- template: require('./index.html'),
- transclude: true
-});
diff --git a/client/core/src/switch/switch.js b/client/core/src/switch/switch.js
deleted file mode 100644
index 8c8186b32..000000000
--- a/client/core/src/switch/switch.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as normalizerFactory from '../lib/inputAttrsNormalizer';
-import * as util from '../lib/util';
-
-const _NAME = 'switch';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME, normalizerFactory.NAME];
-export function directive(resolve, normalizer) {
- return {
- restrict: 'E',
- template: function(_, attrs) {
- normalizer.normalize(attrs);
- return resolve.getTemplate(_NAME, attrs);
- },
- link: function(scope, element, attrs) {
- scope.$watch(attrs.model, () => {
- let mdlField = element[0].firstChild.MaterialSwitch;
- if (mdlField)
- mdlField.updateClasses_();
- });
- componentHandler.upgradeElement(element[0].firstChild);
- }
- };
-}
-
-_module.directive(NAME, directive);
-
diff --git a/client/core/src/switch/switch.mdl.js b/client/core/src/switch/switch.mdl.js
deleted file mode 100644
index 34fda26ee..000000000
--- a/client/core/src/switch/switch.mdl.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import {module as _module} from '../module';
-import * as util from '../lib/util';
-import * as constant from '../lib/constants';
-import template from './switch.mdl.html';
-
-const _NAME = 'switch';
-const DEFAULT_CLASS = 'mdl-switch__input';
-
-export const NAME = util.getFactoryName(_NAME + constant.MATERIAL_DESIGN_FRAMEWORK);
-
-export function factory() {
- return {
- template: template,
- default: {
- className: DEFAULT_CLASS,
- label: ""
- }
- };
-}
-
-_module.factory(NAME, factory);
diff --git a/client/core/src/textarea/textarea.js b/client/core/src/textarea/textarea.js
deleted file mode 100644
index 192eb488b..000000000
--- a/client/core/src/textarea/textarea.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import {module as _module} from '../module';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as util from '../lib/util';
-
-const _NAME = 'textarea';
-export const NAME = util.getName(_NAME);
-
-directive.$inject = [resolveFactory.NAME];
-export function directive(resolve) {
- return {
- restrict: 'E',
- template: function(_, attr) {
- return resolve.getTemplate(_NAME, attr);
- },
- link: function(scope, element, attrs) {
- scope.$watch(attrs.model, () => {
- let mdlField = element[0].firstChild.MaterialTextfield;
- if (mdlField)
- mdlField.updateClasses_();
- });
- componentHandler.upgradeElement(element[0].firstChild);
- }
- };
-}
-
-_module.directive(NAME, directive);
-
diff --git a/client/core/src/textarea/textarea.mdl.html b/client/core/src/textarea/textarea.mdl.html
deleted file mode 100644
index 1b156b18b..000000000
--- a/client/core/src/textarea/textarea.mdl.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/client/core/src/textarea/textarea.mdl.js b/client/core/src/textarea/textarea.mdl.js
deleted file mode 100644
index 05c40e4ef..000000000
--- a/client/core/src/textarea/textarea.mdl.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import {module as _module} from '../module';
-import * as util from '../lib/util';
-import * as constant from '../lib/constants';
-import template from './textarea.mdl.html';
-
-const _NAME = 'textarea';
-const DEFAULT_LABEL = 'textarea';
-const DEFAULT_ROWS = 3;
-
-
-export const NAME = util.getFactoryName(_NAME + constant.MATERIAL_DESIGN_FRAMEWORK);
-
-export function factory() {
- return {
- template: template,
- default: {
- label: DEFAULT_LABEL,
- rows: DEFAULT_ROWS
- }
- };
-}
-
-_module.factory(NAME, factory);
diff --git a/client/core/src/textfield/index.js b/client/core/src/textfield/index.js
deleted file mode 100644
index 7320f7c6b..000000000
--- a/client/core/src/textfield/index.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import {module} from '../module';
-import Component from '../lib/component';
-import * as resolveFactory from '../lib/resolveDefaultComponents';
-import * as normalizerFactory from '../lib/inputAttrsNormalizer';
-import './style.scss';
-import './index.mdl';
-
-export default class Textfield extends Component {
- constructor($element, $scope, $attrs) {
- super($element);
-
- let input = this.input = this.element.querySelector('input');
- input.addEventListener('input',
- () => this.checkValue());
- input.addEventListener('focus',
- () => this.checkValue());
- input.addEventListener('blur',
- () => this.showClear(false));
-
- let clearButton = this.element.querySelector('button');
- clearButton.addEventListener('click',
- () => this.onClearClick());
- clearButton.addEventListener('mousedown',
- event => event.preventDefault());
-
- let div = this.element.firstChild;
- componentHandler.upgradeElement(div);
- }
- link($scope, $attrs) {
- let mdlTextField = this.element.firstChild.MaterialTextfield;
- mdlTextField.updateClasses_();
-
- $scope.$watch($attrs.model,
- () => mdlTextField.updateClasses_());
- }
- onClearClick() {
- this.input.value = '';
- this.checkValue();
-
- let event = this.document.createEvent('HTMLEvents');
- event.initEvent('change', false, true);
- this.input.dispatchEvent(event);
- }
- checkValue() {
- this.showClear(this.input.value);
- }
- showClear(show) {
- let clearButton = this.element.querySelector('button');
- clearButton.style.visibility = show ? 'visible' : 'hidden';
- }
-}
-Textfield.$inject = ['$element', '$scope', '$attrs'];
-
-directive.$inject = [resolveFactory.NAME, normalizerFactory.NAME];
-export function directive(resolve, normalizer) {
- return {
- restrict: 'E',
- template: function(_, attrs) {
- normalizer.normalize(attrs);
- return resolve.getTemplate('textfield', attrs);
- },
- link: function($scope, $element, $attrs, $ctrl) {
- $ctrl.link($scope, $attrs);
- },
- controller: Textfield
- };
-}
-
-module.directive('vnTextfield', directive);
diff --git a/client/core/src/textfield/index.mdl.html b/client/core/src/textfield/index.mdl.html
deleted file mode 100644
index f697c8790..000000000
--- a/client/core/src/textfield/index.mdl.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
diff --git a/client/core/src/textfield/index.mdl.js b/client/core/src/textfield/index.mdl.js
deleted file mode 100644
index 64e156885..000000000
--- a/client/core/src/textfield/index.mdl.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import {module} from '../module';
-
-export const NAME = 'vnTextfieldMdlFactory';
-
-export function factory() {
- return {
- template: require('./index.mdl.html'),
- default: {
- label: 'text',
- className: 'mdl-textfield--floating-label',
- type: 'text'
- }
- };
-}
-
-module.factory(NAME, factory);
diff --git a/client/core/src/textfield/style.scss b/client/core/src/textfield/style.scss
deleted file mode 100644
index 006d8bbd2..000000000
--- a/client/core/src/textfield/style.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-vn-textfield {
- .mdl-chip__action{
- position: absolute;
- top: 0px;
- right: -6px;
- margin: 22px 0px;
- visibility: hidden;
- }
- .material-icons{
- font-size: 18px;
- }
-}
\ No newline at end of file
diff --git a/client/core/src/title/index.html b/client/core/src/title/index.html
deleted file mode 100644
index e8ab561ed..000000000
--- a/client/core/src/title/index.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/client/core/src/title/index.js b/client/core/src/title/index.js
deleted file mode 100644
index 3fb71f567..000000000
--- a/client/core/src/title/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import {module} from '../module';
-
-module.component('vnTitle', {
- template: require('./index.html'),
- transclude: true
-});
diff --git a/client/core/src/watcher/index.js b/client/core/src/watcher/index.js
deleted file mode 100644
index d421405df..000000000
--- a/client/core/src/watcher/index.js
+++ /dev/null
@@ -1,162 +0,0 @@
-import {module} from '../module';
-import Component from '../lib/component';
-import getModifiedData from '../lib/modified';
-import copyObject from '../lib/copy';
-import isEqual from '../lib/equals';
-
-/**
- * Component that checks for changes on a specific model property and
- * asks the user to save or discard it when the state changes.
- * Also it can save the data to the server when the @url and @idField
- * properties are provided.
- */
-export default class Watcher extends Component {
- constructor($element, $scope, $state, $transitions, $http, vnAppLogger, $translate) {
- super($element);
- this.$scope = $scope;
- this.$state = $state;
- this.$http = $http;
- this.$translate = $translate;
- this.vnAppLogger = vnAppLogger;
-
- this.state = null;
- this.deregisterCallback = $transitions.onStart({},
- transition => this.callback(transition));
- this.copyData();
- }
- $onInit() {
- if (this.get) {
- this.fetchData();
- }
- }
- $onChanges(changes) {
- if (this.data) {
- this.copyData();
- }
- }
- $onDestroy() {
- this.deregisterCallback();
- }
- fetchData() {
- let id = this.data[this.idField];
- return new Promise((resolve, reject) => {
- this.$http.get(`${this.url}/${id}`).then(
- json => this.writeData(json, resolve),
- json => reject(json)
- );
- });
- }
- /**
- * Submits the data and goes back in the history.
- */
- submitBack() {
- this.submit().then(
- () => this.window.history.back()
- );
- }
- /**
- * Submits the data to the server.
- *
- * @return {Promise} The http request promise
- */
- submit() {
- if (this.form) {
- this.form.$setSubmitted();
-
- if (!this.form.$valid)
- return new Promise(
- (resolve, reject) => this.invalidForm(reject)
- );
- }
- if (!this.dataChanged()) {
- return new Promise(
- (resolve, reject) => this.noChanges(reject)
- );
- }
- let changedData = getModifiedData(this.data, this.orgData);
-
- if (this.save) {
- this.save.model = changedData;
- return new Promise((resolve, reject) => {
- this.save.accept().then(
- json => this.writeData({data: json}, resolve),
- json => reject(json)
- );
- });
- }
-
- // XXX: Alternative when mgCrud is not used
-
- let id = this.orgData[this.idField];
-
- if (id) {
- return new Promise((resolve, reject) => {
- this.$http.put(`${this.url}/${id}`, changedData).then(
- json => this.writeData(json, resolve),
- json => reject(json)
- );
- });
- }
-
- return new Promise((resolve, reject) => {
- this.$http.post(this.url, this.data).then(
- json => this.writeData(json, resolve),
- json => reject(json)
- );
- });
- }
- writeData(json, resolve) {
- copyObject(json.data, this.data);
- this.copyData();
- resolve(json);
- }
- noChanges(resolve) {
- this.vnAppLogger.showMessage(
- this.$translate.instant('No changes to save')
- );
- resolve();
- }
- invalidForm(resolve) {
- this.vnAppLogger.showMessage(
- this.$translate.instant('Some fields are invalid')
- );
- resolve();
- }
- copyData() {
- this.orgData = copyObject(this.data);
- }
- callback(transition) {
- if (!this.state && this.dataChanged()) {
- this.state = transition.to().name;
- this.$scope.confirm.show();
- return false;
- }
-
- return true;
- }
- dataChanged() {
- return !isEqual(this.data, this.orgData);
- }
- onConfirmResponse(response) {
- if (response === 'ACCEPT') {
- copyObject(this.orgData, this.data);
- this.$state.go(this.state);
- } else {
- this.state = null;
- }
- }
-}
-Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnAppLogger', '$translate'];
-
-module.component('vnWatcher', {
- template: require('./index.html'),
- bindings: {
- url: '@?',
- idField: '@?',
- data: '<',
- form: '<',
- save: '<',
- get: '=?'
- },
- controller: Watcher
-});
diff --git a/client/core/src/watcher/locale/es.json b/client/core/src/watcher/locale/es.json
deleted file mode 100644
index c82ecd3c4..000000000
--- a/client/core/src/watcher/locale/es.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "Are you sure exit without saving?": "¿Seguro que quieres salir sin guardar?",
- "Unsaved changes will be lost": "Los cambios que no hayas guardado se perderán",
- "No changes to save": "No hay cambios que guardar",
- "Some fields are invalid": "Algunos campos no son válidos"
-}
\ No newline at end of file
diff --git a/client/item/index.js b/client/item/index.js
new file mode 100644
index 000000000..c94fde7de
--- /dev/null
+++ b/client/item/index.js
@@ -0,0 +1 @@
+export * from './src/item';
diff --git a/client/item/routes.json b/client/item/routes.json
new file mode 100644
index 000000000..d6cb65da6
--- /dev/null
+++ b/client/item/routes.json
@@ -0,0 +1,122 @@
+{
+ "module": "item",
+ "name": "Items",
+ "icon": "inbox",
+ "validations" : true,
+ "routes": [
+ {
+ "url": "/item",
+ "state": "item",
+ "abstract": true,
+ "component": "ui-view"
+ },
+ {
+ "url": "/list?q",
+ "state": "item.index",
+ "component": "vn-item-list"
+ },
+ {
+ "url": "/create",
+ "state": "item.create",
+ "component": "vn-item-create"
+ },
+ {
+ "url": "/:id",
+ "state": "item.card",
+ "abstract": true,
+ "component": "vn-item-card"
+ },
+ {
+ "url" : "/data",
+ "state": "item.card.data",
+ "component": "vn-item-data",
+ "params": {
+ "item": "$ctrl.item"
+ },
+ "menu": {
+ "description": "Basic data",
+ "icon": "settings"
+ },
+ "acl": ["buyer"]
+ },
+ {
+ "url" : "/tags",
+ "state": "item.card.tags",
+ "component": "vn-item-tags",
+ "params": {
+ "item-tags": "$ctrl.itemTags"
+ },
+ "menu": {
+ "description": "Tags",
+ "icon": "icon-tags"
+ },
+ "acl": ["buyer"]
+ },
+ {
+ "url" : "/tax",
+ "state": "item.card.tax",
+ "component": "vn-item-tax",
+ "menu": {
+ "description": "Tax",
+ "icon": "folder"
+ }
+ },
+ {
+ "url" : "/history",
+ "state": "item.card.history",
+ "component": "vn-item-history",
+ "params": {
+ "item": "$ctrl.item"
+ },
+ "menu": {
+ "description": "History",
+ "icon": "history"
+ }
+ },
+ {
+ "url" : "/niche",
+ "state": "item.card.niche",
+ "component": "vn-item-niche",
+ "params": {
+ "item": "$ctrl.item"
+ },
+ "menu": {
+ "description": "Niche",
+ "icon": "folder"
+ },
+ "acl": ["buyer","replenisher"]
+ },
+ {
+ "url" : "/botanical",
+ "state": "item.card.botanical",
+ "component": "vn-item-botanical",
+ "params": {
+ "item": "$ctrl.item"
+ },
+ "menu": {
+ "description": "Botanical",
+ "icon": "folder"
+ },
+ "acl": ["buyer"]
+ },{
+ "url" : "/barcode",
+ "state": "item.card.itemBarcode",
+ "component": "vn-item-barcode",
+ "params": {
+ "item": "$ctrl.item"
+ },
+ "menu": {
+ "description": "Barcode",
+ "icon": "icon-barcode"
+ },
+ "acl": ["buyer","replenisher"]
+ },{
+ "url" : "/summary",
+ "state": "item.card.summary",
+ "component": "vn-item-summary",
+ "params": {
+ "item": "$ctrl.item"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/client/item/src/barcode/item-barcode.html b/client/item/src/barcode/item-barcode.html
new file mode 100644
index 000000000..3bd4c875b
--- /dev/null
+++ b/client/item/src/barcode/item-barcode.html
@@ -0,0 +1,34 @@
+
diff --git a/client/item/src/barcode/item-barcode.js b/client/item/src/barcode/item-barcode.js
new file mode 100644
index 000000000..eac4ab6cb
--- /dev/null
+++ b/client/item/src/barcode/item-barcode.js
@@ -0,0 +1,127 @@
+import ngModule from '../module';
+
+export default class Controller {
+ constructor($state, $scope, $http, $q, $translate, vnApp) {
+ this.$state = $state;
+ this.$scope = $scope;
+ this.$http = $http;
+ this.$q = $q;
+ this.$translate = $translate;
+ this.vnApp = vnApp;
+
+ this.barcodes = [];
+ this.removedBarcodes = [];
+ this.oldBarcodes = {};
+ }
+ _setIconAdd() {
+ if (this.barcodes.length) {
+ this.barcodes.map(element => {
+ element.showAddIcon = false;
+ return true;
+ });
+ this.barcodes[this.barcodes.length - 1].showAddIcon = true;
+ } else {
+ this.addBarcode();
+ }
+ }
+
+ _setDirtyForm() {
+ if (this.$scope.form) {
+ this.$scope.form.$setDirty();
+ }
+ }
+ _unsetDirtyForm() {
+ if (this.$scope.form) {
+ this.$scope.form.$setPristine();
+ }
+ }
+ _equalBarcodes(oldBarcode, newBarcode) {
+ return oldBarcode.id === newBarcode.id && oldBarcode.code === newBarcode.code;
+ }
+
+ addBarcode() {
+ this.barcodes.push({code: null, itemFk: this.$state.params.id, showAddIcon: true});
+ this._setIconAdd();
+ }
+
+ removeBarcode(index) {
+ let item = this.barcodes[index];
+ if (item) {
+ this.barcodes.splice(index, 1);
+ this._setIconAdd();
+ if (item.id) {
+ this.removedBarcodes.push(item.id);
+ this._setDirtyForm();
+ }
+ }
+ }
+
+ submit() {
+ let codes = [];
+ let repeatedBarcodes = false;
+ let canSubmit;
+ let barcodesObj = {
+ delete: this.removedBarcodes,
+ create: [],
+ update: []
+ };
+ for (let i = 0; i < this.barcodes.length; i++) {
+ let barcode = this.barcodes[i];
+ let isNewBarcode = barcode.id === undefined;
+
+ if (barcode.code && codes.indexOf(barcode.code) !== -1) {
+ repeatedBarcodes = true;
+ break;
+ }
+ if (barcode.code) codes.push(barcode.code);
+
+ if (isNewBarcode && barcode.code) {
+ barcodesObj.create.push(barcode);
+ } else if (!isNewBarcode && !this._equalBarcodes(this.oldBarcodes[barcode.id], barcode)) {
+ barcodesObj.update.push(barcode);
+ }
+ }
+
+ if (repeatedBarcodes) {
+ return this.vnApp.showMessage(this.$translate.instant('The barcode must be unique'));
+ }
+
+ canSubmit = barcodesObj.update.length > 0 || barcodesObj.create.length > 0 || barcodesObj.delete.length > 0;
+
+ if (canSubmit) {
+ return this.$http.post(`/item/api/ItemBarcodes/crudItemBarcodes`, barcodesObj).then(() => {
+ this.getBarcodes();
+ this._unsetDirtyForm();
+ });
+ }
+ this.vnApp.showMessage(this.$translate.instant('No changes to save'));
+ }
+
+ setOldBarcodes(response) {
+ this._setIconAdd();
+ response.data.forEach(barcode => {
+ this.oldBarcodes[barcode.id] = Object.assign({}, barcode);
+ });
+ }
+
+ getBarcodes() {
+ let filter = {
+ where: {itemFk: this.$state.params.id}
+ };
+ this.$http.get(`/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`).then(response => {
+ this.barcodes = response.data;
+ this.setOldBarcodes(response);
+ });
+ }
+
+ $onInit() {
+ this.getBarcodes();
+ }
+}
+
+Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp'];
+
+ngModule.component('vnItemBarcode', {
+ template: require('./item-barcode.html'),
+ controller: Controller
+});
diff --git a/client/item/src/barcode/item-barcode.spec.js b/client/item/src/barcode/item-barcode.spec.js
new file mode 100644
index 000000000..98e645c26
--- /dev/null
+++ b/client/item/src/barcode/item-barcode.spec.js
@@ -0,0 +1,142 @@
+import './item-barcode.js';
+
+describe('Item', () => {
+ describe('Component vnItemBarcode', () => {
+ let $componentController;
+ let $state;
+ let controller;
+ let $httpBackend;
+
+ beforeEach(() => {
+ angular.mock.module('item');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
+ $componentController = _$componentController_;
+ $state = _$state_;
+ $httpBackend = _$httpBackend_;
+ $state.params.id = '1';
+ controller = $componentController('vnItemBarcode', {$state: $state});
+ }));
+
+ describe('add / remove barcode()', () => {
+ it('should add one empty barcode into controller barcodes collection and call _setIconAdd()', () => {
+ controller.barcodes = [];
+ spyOn(controller, '_setIconAdd').and.callThrough();
+ controller.addBarcode();
+
+ expect(controller._setIconAdd).toHaveBeenCalledWith();
+ expect(controller.barcodes.length).toEqual(1);
+ expect(controller.barcodes[0].id).toBe(undefined);
+ expect(controller.barcodes[0].showAddIcon).toBeTruthy();
+ });
+
+ it('should remove a barcode that occupies the position in the index given and call _setIconAdd()', () => {
+ let index = 2;
+ controller.barcodes = [
+ {id: 1, code: '1111', showAddIcon: false},
+ {id: 2, code: '2222', showAddIcon: false},
+ {id: 3, code: '3333', showAddIcon: true}
+ ];
+
+ spyOn(controller, '_setIconAdd').and.callThrough();
+
+ controller.removeBarcode(index);
+
+ expect(controller._setIconAdd).toHaveBeenCalledWith();
+ expect(controller.barcodes.length).toEqual(2);
+ expect(controller.barcodes[0].showAddIcon).toBeFalsy();
+ expect(controller.barcodes[1].showAddIcon).toBeTruthy();
+ expect(controller.barcodes[index]).toBe(undefined);
+ });
+ });
+
+ describe('_equalBarcodes()', () => {
+ it('should return true if two barcodes are equals independent of control attributes', () => {
+ let code1 = {id: 1, code: '1111', showAddIcon: true};
+ let code2 = {id: 1, code: '1111', showAddIcon: false};
+ let equals = controller._equalBarcodes(code2, code1);
+
+ expect(equals).toBeTruthy();
+ });
+
+ it('should return false if two barcodes aint equals independent of control attributes', () => {
+ let code1 = {id: 1, code: '1111', showAddIcon: true};
+ let code2 = {id: 1, code: '2222', showAddIcon: true};
+ let equals = controller._equalBarcodes(code2, code1);
+
+ expect(equals).toBeFalsy();
+ });
+ });
+
+ describe('getBarcodes()', () => {
+ it('should perform a GET query to receive the item barcodes', () => {
+ let filter = {
+ where: {itemFk: '1'}
+ };
+ let res = [{id: 1, code: '1111'}];
+ $httpBackend.when('GET', `/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`).respond(res);
+ $httpBackend.expectGET(`/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`);
+ controller.getBarcodes();
+ $httpBackend.flush();
+ });
+ });
+
+ describe('submit()', () => {
+ it("should return an error message 'The barcode must be unique' when the code isnt unique", () => {
+ spyOn(controller.vnApp, 'showMessage').and.callThrough();
+ controller.barcodes = [
+ {code: 123454, itemFk: 1, id: 1},
+ {code: 123454, itemFk: 1}
+ ];
+ controller.oldBarcodes = {1: {id: 1, code: 123454, itemFk: 1}};
+ controller.submit();
+
+ expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The barcode must be unique');
+ });
+
+ it("should perfom a query to delete barcodes", () => {
+ controller.removedBarcodes = [1, 2, 3];
+
+ $httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{code: 123454, itemFk: 1, id: 1}]);
+ $httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!');
+ $httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`);
+ controller.submit();
+ $httpBackend.flush();
+ });
+
+ it("should perfom a query to update barcodes", () => {
+ controller.barcodes = [{code: 2222, itemFk: 1, id: 1}];
+ controller.oldBarcodes = {1: {id: 1, code: 1111, itemFk: 1}};
+
+ $httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{}]);
+ $httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!');
+ $httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`);
+ controller.submit();
+ $httpBackend.flush();
+ });
+
+ it("should perfom a query to create new barcode", () => {
+ controller.barcodes = [{code: 1111, itemFk: 1}];
+
+ $httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{}]);
+ $httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!');
+ $httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`);
+ controller.submit();
+ $httpBackend.flush();
+ });
+
+ it("should return a message 'No changes to save' when there are no changes to apply", () => {
+ spyOn(controller.vnApp, 'showMessage').and.callThrough();
+ controller.oldBarcodes = [
+ {code: 1, itemFk: 1, id: 1},
+ {code: 2, itemFk: 1, id: 2}
+ ];
+ controller.barcodes = [];
+ controller.submit();
+
+ expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save');
+ });
+ });
+ });
+});
diff --git a/client/item/src/botanical/item-botanical.html b/client/item/src/botanical/item-botanical.html
new file mode 100644
index 000000000..c95511be8
--- /dev/null
+++ b/client/item/src/botanical/item-botanical.html
@@ -0,0 +1,47 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/client/item/src/botanical/item-botanical.js b/client/item/src/botanical/item-botanical.js
new file mode 100644
index 000000000..c747b6b0d
--- /dev/null
+++ b/client/item/src/botanical/item-botanical.js
@@ -0,0 +1,36 @@
+import ngModule from '../module';
+
+class ItemBotanical {
+ constructor($http, $state) {
+ this.$http = $http;
+ this.$state = $state;
+ }
+ _getBotanical() {
+ let filter = {
+ where: {itemFk: this.$state.params.id},
+ include: [{relation: 'genus'}, {relation: 'specie'}]
+ };
+ this.$http.get(`/item/api/ItemBotanicals?filter=${JSON.stringify(filter)}`)
+ .then(res => {
+ if (res.data.length) {
+ this.botanical = res.data[0];
+ } else {
+ this.botanical = {
+ itemFk: this.$state.params.id,
+ botanical: null,
+ genusFk: null,
+ specieFk: null
+ };
+ }
+ });
+ }
+ $onInit() {
+ this._getBotanical();
+ }
+}
+ItemBotanical.$inject = ['$http', '$state'];
+
+ngModule.component('vnItemBotanical', {
+ template: require('./item-botanical.html'),
+ controller: ItemBotanical
+});
diff --git a/client/item/src/botanical/item-botanical.spec.js b/client/item/src/botanical/item-botanical.spec.js
new file mode 100644
index 000000000..f4e0e52d9
--- /dev/null
+++ b/client/item/src/botanical/item-botanical.spec.js
@@ -0,0 +1,34 @@
+import './item-botanical.js';
+
+describe('ItemBotanical', () => {
+ describe('Component vnItemBotanical', () => {
+ let $componentController;
+ let $httpBackend;
+ let $state;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('item');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
+ $componentController = _$componentController_;
+ $httpBackend = _$httpBackend_;
+ $state = {
+ params: {
+ id: 123
+ }
+ };
+ controller = $componentController('vnItemBotanical', {$state: $state});
+ }));
+
+ describe('_getBotanical()', () => {
+ it('should request to patch the propagation of botanical status', () => {
+ $httpBackend.whenGET('/item/api/ItemBotanicals?filter={"where":{"itemFk":123},"include":[{"relation":"genus"},{"relation":"specie"}]}').respond({data: 'item'});
+ $httpBackend.expectGET('/item/api/ItemBotanicals?filter={"where":{"itemFk":123},"include":[{"relation":"genus"},{"relation":"specie"}]}');
+ controller.$onInit();
+ $httpBackend.flush();
+ });
+ });
+ });
+});
diff --git a/client/item/src/card/item-card.html b/client/item/src/card/item-card.html
new file mode 100644
index 000000000..34ecff4a5
--- /dev/null
+++ b/client/item/src/card/item-card.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/item/src/card/item-card.js b/client/item/src/card/item-card.js
new file mode 100644
index 000000000..a1e4d9994
--- /dev/null
+++ b/client/item/src/card/item-card.js
@@ -0,0 +1,65 @@
+import ngModule from '../module';
+
+class ItemCard {
+ constructor($http, $state, $timeout) {
+ this.$http = $http;
+ this.$state = $state;
+ this.$timeout = $timeout;
+
+ this.item = null;
+ this.tags = {};
+ this.itemTags = null;
+ }
+ _getItemTags() {
+ let filter = {
+ where: {itemFk: this.$state.params.id},
+ order: "priority ASC",
+ include: {relation: "tag"}
+ };
+ this.$http.get(`/item/api/ItemTags?filter=${JSON.stringify(filter)}`).then(response => {
+ this.itemTags = response.data;
+ });
+ }
+
+ _getTags() {
+ this.$http.get(`/item/api/Tags`).then(response => {
+ response.data.forEach(tag => {
+ this.tags[tag.id] = Object.assign({}, tag);
+ });
+ });
+ }
+
+ _getItem() {
+ let filter = {
+ include: [
+ {relation: "itemType"},
+ {relation: "origin"},
+ {relation: "ink"},
+ {relation: "producer"},
+ {relation: "intrastat"},
+ {relation: "expence"}
+ ]
+ };
+ this.$http.get(`/item/api/Items/${this.$state.params.id}?filter=${JSON.stringify(filter)}`)
+ .then(res => {
+ if (res.data && res.data.id) {
+ this.$timeout(() => {
+ this.item = res.data;
+ });
+ }
+ }
+ );
+ }
+
+ $onInit() {
+ this._getItem();
+ this._getTags();
+ this._getItemTags();
+ }
+}
+ItemCard.$inject = ['$http', '$state', '$timeout'];
+
+ngModule.component('vnItemCard', {
+ template: require('./item-card.html'),
+ controller: ItemCard
+});
diff --git a/client/item/src/card/item-card.spec.js b/client/item/src/card/item-card.spec.js
new file mode 100644
index 000000000..50e3e0542
--- /dev/null
+++ b/client/item/src/card/item-card.spec.js
@@ -0,0 +1,43 @@
+import './item-card.js';
+
+describe('Item', () => {
+ describe('Component vnItemCard', () => {
+ let $componentController;
+ let $httpBackend;
+ let $state;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('item');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
+ $componentController = _$componentController_;
+ $httpBackend = _$httpBackend_;
+ $state = {
+ params: {
+ id: 123
+ }
+ };
+ controller = $componentController('vnItemCard', {$state: $state});
+ }));
+
+ describe('_getItem()', () => {
+ it('should request to get the item', () => {
+ $httpBackend.whenGET('/item/api/Items/123?filter={"include":[{"relation":"itemType"},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}').respond({data: 'item'});
+ $httpBackend.expectGET('/item/api/Items/123?filter={"include":[{"relation":"itemType"},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}');
+ controller._getItem();
+ $httpBackend.flush();
+ });
+ });
+
+ describe('_getItemTags()', () => {
+ it('should request to get the ItemTags', () => {
+ $httpBackend.whenGET('/item/api/ItemTags?filter={"where":{"itemFk":123},"order":"priority ASC","include":{"relation":"tag"}}').respond({data: 'item'});
+ $httpBackend.expectGET('/item/api/ItemTags?filter={"where":{"itemFk":123},"order":"priority ASC","include":{"relation":"tag"}}');
+ controller._getItemTags();
+ $httpBackend.flush();
+ });
+ });
+ });
+});
diff --git a/client/item/src/create/item-create.html b/client/item/src/create/item-create.html
new file mode 100644
index 000000000..d537fe7f6
--- /dev/null
+++ b/client/item/src/create/item-create.html
@@ -0,0 +1,51 @@
+
+
+
+
diff --git a/client/item/src/create/item-create.js b/client/item/src/create/item-create.js
new file mode 100644
index 000000000..415e67c4f
--- /dev/null
+++ b/client/item/src/create/item-create.js
@@ -0,0 +1,23 @@
+import ngModule from '../module';
+
+class ItemCreate {
+ constructor($scope, $state) {
+ this.$ = $scope;
+ this.$state = $state;
+ this.item = {
+ relevancy: 0
+ };
+ }
+
+ onSubmit() {
+ this.$.watcher.submit().then(
+ json => this.$state.go('item.card.data', {id: json.data.id})
+ );
+ }
+}
+ItemCreate.$inject = ['$scope', '$state'];
+
+ngModule.component('vnItemCreate', {
+ template: require('./item-create.html'),
+ controller: ItemCreate
+});
diff --git a/client/item/src/create/item-create.spec.js b/client/item/src/create/item-create.spec.js
new file mode 100644
index 000000000..e63265ee7
--- /dev/null
+++ b/client/item/src/create/item-create.spec.js
@@ -0,0 +1,40 @@
+import './item-create.js';
+
+describe('Item', () => {
+ describe('Component vnItemCreate', () => {
+ let $componentController;
+ let $scope;
+ let $state;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('item');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $state = _$state_;
+ $scope.watcher = {
+ submit: () => {
+ return {
+ then: callback => {
+ callback({data: {id: 1}});
+ }
+ };
+ }
+ };
+ controller = $componentController('vnItemCreate', {$scope: $scope});
+ }));
+
+ describe('onSubmit()', () => {
+ it(`should call submit() on the watcher then expect a callback`, () => {
+ spyOn($state, 'go');
+ controller.onSubmit();
+
+ expect(controller.$state.go).toHaveBeenCalledWith('item.card.data', {id: 1});
+ });
+ });
+ });
+});
+
diff --git a/client/item/src/data/item-data.html b/client/item/src/data/item-data.html
new file mode 100644
index 000000000..507fdc2b2
--- /dev/null
+++ b/client/item/src/data/item-data.html
@@ -0,0 +1,59 @@
+
+
+
+
+
diff --git a/client/item/src/data/item-data.js b/client/item/src/data/item-data.js
new file mode 100644
index 000000000..d9e7c551b
--- /dev/null
+++ b/client/item/src/data/item-data.js
@@ -0,0 +1,23 @@
+import ngModule from '../module';
+
+class ItemData {
+ constructor($scope, $timeout) {
+ this.$scope = $scope;
+ this.$timeout = $timeout;
+ }
+ $onChanges(data) {
+ this.$timeout(() => {
+ this.$scope.watcher.data = data.item.currentValue;
+ });
+ }
+}
+
+ItemData.$inject = ['$scope', '$timeout'];
+
+ngModule.component('vnItemData', {
+ template: require('./item-data.html'),
+ bindings: {
+ item: '<'
+ },
+ controller: ItemData
+});
diff --git a/client/item/src/descriptor/item-descriptor.html b/client/item/src/descriptor/item-descriptor.html
new file mode 100644
index 000000000..38002ed5a
--- /dev/null
+++ b/client/item/src/descriptor/item-descriptor.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{$ctrl.item.name}}
+ Id {{$ctrl.item.id}}
+
+
{{$ctrl.tags[itemTag.tagFk].name}} {{itemTag.value}}
+
+
+
+
diff --git a/client/item/src/descriptor/item-descriptor.js b/client/item/src/descriptor/item-descriptor.js
new file mode 100644
index 000000000..910895848
--- /dev/null
+++ b/client/item/src/descriptor/item-descriptor.js
@@ -0,0 +1,10 @@
+import ngModule from '../module';
+
+ngModule.component('vnItemDescriptor', {
+ template: require('./item-descriptor.html'),
+ bindings: {
+ item: '<',
+ itemTags: '<',
+ tags: '<'
+ }
+});
diff --git a/client/item/src/filter-item-list.js b/client/item/src/filter-item-list.js
new file mode 100644
index 000000000..e170186bd
--- /dev/null
+++ b/client/item/src/filter-item-list.js
@@ -0,0 +1,9 @@
+import FilterList from 'core/src/lib/filter-list';
+
+export default class FilterItemList extends FilterList {
+ constructor($scope, $timeout, $state) {
+ super($scope, $timeout, $state);
+ this.modelName = 'itemFk';
+ }
+}
+FilterItemList.$inject = ['$scope', '$timeout', '$state'];
diff --git a/client/item/src/filter-panel/filter-panel.html b/client/item/src/filter-panel/filter-panel.html
new file mode 100644
index 000000000..2f09c471c
--- /dev/null
+++ b/client/item/src/filter-panel/filter-panel.html
@@ -0,0 +1,47 @@
+
+
+
diff --git a/client/item/src/filter-panel/filter-panel.js b/client/item/src/filter-panel/filter-panel.js
new file mode 100644
index 000000000..608918b51
--- /dev/null
+++ b/client/item/src/filter-panel/filter-panel.js
@@ -0,0 +1,16 @@
+import ngModule from '../module';
+
+class ItemFilterPanel {
+ constructor() {
+ this.onSubmit = () => {};
+ }
+
+ onSearch() {
+ this.onSubmit(this.filter);
+ }
+}
+
+ngModule.component('vnItemFilterPanel', {
+ template: require('./filter-panel.html'),
+ controller: ItemFilterPanel
+});
diff --git a/client/item/src/filter-panel/locale/es.yml b/client/item/src/filter-panel/locale/es.yml
new file mode 100644
index 000000000..1411cc42d
--- /dev/null
+++ b/client/item/src/filter-panel/locale/es.yml
@@ -0,0 +1,3 @@
+Ink: Tinta
+Origin: Origen
+Producer: Productor
\ No newline at end of file
diff --git a/client/item/src/history/item-history.html b/client/item/src/history/item-history.html
new file mode 100644
index 000000000..9854894ce
--- /dev/null
+++ b/client/item/src/history/item-history.html
@@ -0,0 +1,31 @@
+
+
+
+
+ Item history
+
+
+
+
+
+
+
+
+ {{::itemLog.description}}
+ {{::itemLog.action}}
+ {{::itemLog.user.name}}
+ {{::itemLog.creationDate | date:'dd/MM/yyyy HH:mm'}}
+
+
+
+
+
+
+
diff --git a/client/item/src/history/item-history.js b/client/item/src/history/item-history.js
new file mode 100644
index 000000000..b89dca928
--- /dev/null
+++ b/client/item/src/history/item-history.js
@@ -0,0 +1,7 @@
+import ngModule from '../module';
+import FilterItemList from '../filter-item-list';
+
+ngModule.component('vnItemHistory', {
+ template: require('./item-history.html'),
+ controller: FilterItemList
+});
diff --git a/client/item/src/item.js b/client/item/src/item.js
new file mode 100644
index 000000000..504933d06
--- /dev/null
+++ b/client/item/src/item.js
@@ -0,0 +1,17 @@
+export * from './module';
+
+import './filter-item-list';
+import './list/list';
+import './filter-panel/filter-panel';
+import './create/item-create';
+import './card/item-card';
+import './descriptor/item-descriptor';
+import './data/item-data';
+import './tags/item-tags';
+import './tax/item-tax';
+import './history/item-history';
+import './niche/item-niche';
+import './botanical/item-botanical';
+import './barcode/item-barcode';
+import './summary/item-summary';
+
diff --git a/client/item/src/list/item-product.html b/client/item/src/list/item-product.html
new file mode 100644
index 000000000..30663314c
--- /dev/null
+++ b/client/item/src/list/item-product.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+ {{::$ctrl.item.name}}
+ Id {{::$ctrl.item.id}}
+ Description {{::$ctrl.item.description}}
+ Size {{::$ctrl.item.size}}
+ Type {{::$ctrl.item.itemType.name}}
+
+
+
+
+
+
+
+
+
+
diff --git a/client/item/src/list/item-product.js b/client/item/src/list/item-product.js
new file mode 100644
index 000000000..728b0cd80
--- /dev/null
+++ b/client/item/src/list/item-product.js
@@ -0,0 +1,29 @@
+import ngModule from '../module';
+
+class ItemProduct {
+ onClick(event) {
+ if (event.defaultPrevented)
+ event.stopImmediatePropagation();
+ }
+
+ clone(event) {
+ event.preventDefault();
+ this.ItemList.cloneItem(this.item);
+ }
+
+ preview(event) {
+ event.preventDefault();
+ this.ItemList.showItemPreview(this.item);
+ }
+}
+
+ngModule.component('vnItemProduct', {
+ template: require('./item-product.html'),
+ bindings: {
+ item: '<'
+ },
+ controller: ItemProduct,
+ require: {
+ ItemList: '^vnItemList'
+ }
+});
diff --git a/client/item/src/list/list.html b/client/item/src/list/list.html
new file mode 100644
index 000000000..5604b1039
--- /dev/null
+++ b/client/item/src/list/list.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/item/src/list/list.js b/client/item/src/list/list.js
new file mode 100644
index 000000000..388b89012
--- /dev/null
+++ b/client/item/src/list/list.js
@@ -0,0 +1,40 @@
+import ngModule from '../module';
+import './item-product';
+import './style.scss';
+
+class ItemList {
+ constructor($http, $state, $scope) {
+ this.$http = $http;
+ this.$state = $state;
+ this.$scope = $scope;
+ this.model = {};
+ this.itemSelected = null;
+ }
+ search(index) {
+ index.accept();
+ }
+ cloneItem(item) {
+ this.itemSelected = item;
+ this.$scope.clone.show();
+ }
+ onCloneAccept(response) {
+ if (response == 'ACCEPT' && this.itemSelected) {
+ this.$http.post(`/item/api/Items/${this.itemSelected.id}/clone`).then(res => {
+ if (res && res.data && res.data.id) {
+ this.$state.go('item.card.tags', {id: res.data.id});
+ }
+ });
+ }
+ this.itemSelected = null;
+ }
+ showItemPreview(item) {
+ this.itemSelected = item;
+ this.$scope.preview.show();
+ }
+}
+ItemList.$inject = ['$http', '$state', '$scope'];
+
+ngModule.component('vnItemList', {
+ template: require('./list.html'),
+ controller: ItemList
+});
diff --git a/client/item/src/list/preview.svg b/client/item/src/list/preview.svg
new file mode 100644
index 000000000..5d56b5f34
--- /dev/null
+++ b/client/item/src/list/preview.svg
@@ -0,0 +1,11 @@
+
+
+
diff --git a/client/item/src/list/style.scss b/client/item/src/list/style.scss
new file mode 100644
index 000000000..86f7f3ea1
--- /dev/null
+++ b/client/item/src/list/style.scss
@@ -0,0 +1,15 @@
+
+vn-item-product {
+ display: block;
+
+ .image {
+ height: 7em;
+ width: 7em;
+
+ & > img {
+ max-height: 100%;
+ max-width: 100%;
+ border-radius: .2em;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/item/src/locale/en.yml b/client/item/src/locale/en.yml
new file mode 100644
index 000000000..03f1b1f7f
--- /dev/null
+++ b/client/item/src/locale/en.yml
@@ -0,0 +1 @@
+Artículo: Items
\ No newline at end of file
diff --git a/client/item/src/locale/es.yml b/client/item/src/locale/es.yml
new file mode 100644
index 000000000..ac2411e96
--- /dev/null
+++ b/client/item/src/locale/es.yml
@@ -0,0 +1,29 @@
+Items: Artículos
+Item: Artículo
+View item: Ver artículo
+Category: Categoría
+Description: Descripción
+Size: Tamaño
+Type: Tipo
+Name: Nombre
+Relevancy: Relevancia
+New item: Nuevo artículo
+Basic data: Datos básicos
+History: Historial
+Item history: Historial del artículo
+Item tags: Tags del artículo
+Tax: IVA
+Niche: Nicho
+Picture: Foto
+Barcode: Código barras
+Item barcode: Código de barras del artículo
+Changed by: Cambiado por
+Action: Acción
+Date: Fecha
+Preview: Vista previa
+Clone: Clonar
+Do you want to clone this item?: ¿Desea clonar este artículo?
+All it's properties will be copied: Todas sus propiedades serán copiadas
+Yes, clone: Si, clonar
+Value: Valor
+Priority: Prioridad
\ No newline at end of file
diff --git a/client/item/src/module.js b/client/item/src/module.js
new file mode 100644
index 000000000..b44509fb2
--- /dev/null
+++ b/client/item/src/module.js
@@ -0,0 +1,5 @@
+import {ng} from 'vendor';
+import 'core';
+
+const ngModule = ng.module('item', ['vnCore']);
+export default ngModule;
diff --git a/client/item/src/niche/item-niche.html b/client/item/src/niche/item-niche.html
new file mode 100644
index 000000000..ae30034db
--- /dev/null
+++ b/client/item/src/niche/item-niche.html
@@ -0,0 +1,50 @@
+
+
+
\ No newline at end of file
diff --git a/client/item/src/niche/item-niche.js b/client/item/src/niche/item-niche.js
new file mode 100644
index 000000000..e762bcf90
--- /dev/null
+++ b/client/item/src/niche/item-niche.js
@@ -0,0 +1,146 @@
+import ngModule from '../module';
+
+export default class Controller {
+ constructor($stateParams, $scope, $http, $translate, vnApp) {
+ this.params = $stateParams;
+ this.$scope = $scope;
+ this.$http = $http;
+ this.$translate = $translate;
+ this.vnApp = vnApp;
+
+ this.warehouses = [];
+ this.niches = [];
+ this.removedNiches = [];
+ this.oldNiches = {};
+ }
+
+ _setIconAdd() {
+ if (this.niches.length) {
+ this.niches.map(element => {
+ element.showAddIcon = false;
+ return true;
+ });
+ this.niches[this.niches.length - 1].showAddIcon = true;
+ } else {
+ this.addNiche();
+ }
+ }
+
+ _setDirtyForm() {
+ if (this.$scope.form) {
+ this.$scope.form.$setDirty();
+ }
+ }
+ _unsetDirtyForm() {
+ if (this.$scope.form) {
+ this.$scope.form.$setPristine();
+ }
+ }
+
+ addNiche() {
+ this.niches.push({code: null, itemFk: this.params.id, showAddIcon: true});
+ this._setIconAdd();
+ }
+
+ removeNiche(index) {
+ let item = this.niches[index];
+ if (item) {
+ this.niches.splice(index, 1);
+ this._setIconAdd();
+ if (item.id) {
+ this.removedNiches.push(item.id);
+ this._setDirtyForm();
+ }
+ }
+ }
+
+ _equalNiches(oldNiche, newNiche) {
+ return oldNiche.id === newNiche.id && oldNiche.code === newNiche.code && oldNiche.warehouseFk === newNiche.warehouseFk;
+ }
+
+ setOldNiches(response) {
+ this._setIconAdd();
+ response.data.forEach(niche => {
+ this.oldNiches[niche.id] = Object.assign({}, niche);
+ });
+ }
+
+ getNiches() {
+ let filter = {
+ where: {itemFk: this.params.id},
+ include: {relation: 'warehouse'}
+ };
+ this.$http.get(`/item/api/ItemNiches?filter=${JSON.stringify(filter)}`).then(response => {
+ this.niches = response.data;
+ this.setOldNiches(response);
+ });
+ }
+
+ getWarehouse(id, warehouses) {
+ return warehouses.find(warehouse => warehouse.id === id);
+ }
+
+ getWarehouses() {
+ this.$http.get(`/item/api/Warehouses`).then(response => {
+ this.warehouses = response.data;
+ });
+ }
+
+ submit() {
+ let warehousesDefined = [];
+ let repeatedWarehouse = false;
+ let canSubmit;
+ let nichesObj = {
+ delete: this.removedNiches,
+ create: [],
+ update: []
+ };
+ this.niches.forEach(niche => {
+ let isNewNiche = !niche.id;
+
+ if (warehousesDefined.indexOf(niche.warehouseFk) !== -1) {
+ repeatedWarehouse = true;
+ return;
+ }
+ warehousesDefined.push(niche.warehouseFk);
+
+ if (isNewNiche) {
+ nichesObj.create.push(niche);
+ }
+
+ if (!isNewNiche && !this._equalNiches(this.oldNiches[niche.id], niche)) {
+ nichesObj.update.push(niche);
+ }
+ });
+
+ if (this.$scope.form.$invalid) {
+ return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid'));
+ }
+
+ if (repeatedWarehouse) {
+ return this.vnApp.showMessage(this.$translate.instant('The niche must be unique'));
+ }
+
+ canSubmit = nichesObj.update.length > 0 || nichesObj.create.length > 0 || nichesObj.delete.length > 0;
+
+ if (canSubmit) {
+ return this.$http.post(`/item/api/ItemNiches/crudItemNiches`, nichesObj).then(() => {
+ this.getNiches();
+ this._unsetDirtyForm();
+ });
+ }
+ this.vnApp.showMessage(this.$translate.instant('No changes to save'));
+ }
+
+ $onInit() {
+ this.getNiches();
+ this.getWarehouses();
+ }
+}
+
+Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
+
+ngModule.component('vnItemNiche', {
+ template: require('./item-niche.html'),
+ controller: Controller
+});
diff --git a/client/item/src/niche/item-niche.spec.js b/client/item/src/niche/item-niche.spec.js
new file mode 100644
index 000000000..3218f262e
--- /dev/null
+++ b/client/item/src/niche/item-niche.spec.js
@@ -0,0 +1,155 @@
+import './item-niche.js';
+
+describe('Item', () => {
+ describe('Component vnItemNiche', () => {
+ let $componentController;
+ let $state;
+ let controller;
+ let $httpBackend;
+
+ beforeEach(() => {
+ angular.mock.module('item');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
+ $componentController = _$componentController_;
+ $state = _$state_;
+ $httpBackend = _$httpBackend_;
+ controller = $componentController('vnItemNiche', {$state: $state});
+ }));
+
+ describe('add / remove niche', () => {
+ it('should add one empty niche into controller niches collection and call _setIconAdd()', () => {
+ controller.niches = [];
+ spyOn(controller, '_setIconAdd').and.callThrough();
+ controller.addNiche();
+
+ expect(controller._setIconAdd).toHaveBeenCalledWith();
+ expect(controller.niches.length).toEqual(1);
+ expect(controller.niches[0].id).toBe(undefined);
+ expect(controller.niches[0].showAddIcon).toBeTruthy();
+ });
+
+ it('should remove a niche that occupies the position in the index given and call _setIconAdd()', () => {
+ let index = 2;
+ controller.niches = [
+ {id: 1, warehouseFk: 1, code: '1111', showAddIcon: false},
+ {id: 2, warehouseFk: 2, code: '2222', showAddIcon: false},
+ {id: 3, warehouseFk: 3, code: '3333', showAddIcon: true}
+ ];
+
+ spyOn(controller, '_setIconAdd').and.callThrough();
+
+ controller.removeNiche(index);
+
+ expect(controller._setIconAdd).toHaveBeenCalledWith();
+ expect(controller.niches.length).toEqual(2);
+ expect(controller.niches[0].showAddIcon).toBeFalsy();
+ expect(controller.niches[1].showAddIcon).toBeTruthy();
+ expect(controller.niches[index]).toBe(undefined);
+ });
+ });
+
+ describe('_equalNiches()', () => {
+ it('should return true if two niches are equals independent of control attributes', () => {
+ let niche1 = {id: 1, warehouseFk: 1, code: '1111', showAddIcon: true};
+ let niche2 = {id: 1, warehouseFk: 1, code: '1111', showAddIcon: false};
+ let equals = controller._equalNiches(niche2, niche1);
+
+ expect(equals).toBeTruthy();
+ });
+
+ it('should return false if two niches aint equals independent of control attributes', () => {
+ let niche1 = {id: 1, warehouseFk: 1, code: '1111', showAddIcon: true};
+ let niche2 = {id: 1, warehouseFk: 1, code: '2222', showAddIcon: true};
+ let equals = controller._equalNiches(niche2, niche1);
+
+ expect(equals).toBeFalsy();
+ });
+ });
+
+ describe('get Niches / Warehouses', () => {
+ it('should perform a GET query to receive the item niches', () => {
+ let res = [{id: 1, warehouseFk: 1, code: '1111'}];
+
+ $httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond(res);
+ $httpBackend.expectGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`);
+ controller.getNiches();
+ $httpBackend.flush();
+ });
+
+ it('should perform a GET query to receive the all warehouses', () => {
+ let res = [
+ {id: 1, warehouseFk: 1, name: 'warehouse one'},
+ {id: 2, warehouseFk: 2, name: 'warehouse two'}
+ ];
+
+ $httpBackend.whenGET(`/item/api/Warehouses`).respond(res);
+ $httpBackend.expectGET(`/item/api/Warehouses`);
+ controller.getWarehouses();
+ $httpBackend.flush();
+ });
+ });
+
+ describe('submit()', () => {
+ it("should return an error message 'The niche must be unique' when the niche code isnt unique", () => {
+ controller.$scope.form = {};
+ spyOn(controller.vnApp, 'showMessage').and.callThrough();
+ controller.niches = [
+ {warehouseFk: 1, code: 123454, itemFk: 1, id: 1},
+ {warehouseFk: 1, code: 123454, itemFk: 1}
+ ];
+ controller.oldNiches = {1: {warehouseFk: 1, id: 1, code: 123454, itemFk: 1}};
+ controller.submit();
+
+ expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The niche must be unique');
+ });
+
+ it("should perfom a query to delete niches", () => {
+ controller.$scope.form = {$setPristine: () => {}};
+ controller.oldNiches = {1: {id: 1, warehouseFk: 1, code: '1111'}};
+ controller.niches = [];
+ controller.removedNiches = [1];
+
+ $httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond([]);
+ $httpBackend.expectPOST(`/item/api/ItemNiches/crudItemNiches`).respond('ok!');
+ controller.submit();
+ $httpBackend.flush();
+ });
+
+ it("should perfom a query to update niches", () => {
+ controller.$scope.form = {$setPristine: () => {}};
+ controller.niches = [{id: 1, warehouseFk: 1, code: '2222'}];
+ controller.oldNiches = {1: {id: 1, warehouseFk: 1, code: '1111'}};
+
+ $httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond([]);
+ $httpBackend.expectPOST(`/item/api/ItemNiches/crudItemNiches`).respond('ok!');
+ controller.submit();
+ $httpBackend.flush();
+ });
+
+ it("should perfom a query to create new niche", () => {
+ controller.$scope.form = {$setPristine: () => {}};
+ controller.niches = [{warehouseFk: 1, code: 1111, itemFk: 1}];
+
+ $httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond([]);
+ $httpBackend.expectPOST(`/item/api/ItemNiches/crudItemNiches`).respond('ok!');
+ controller.submit();
+ $httpBackend.flush();
+ });
+
+ it("should return a message 'No changes to save' when there are no changes to apply", () => {
+ controller.$scope.form = {$setPristine: () => {}};
+ spyOn(controller.vnApp, 'showMessage').and.callThrough();
+ controller.oldNiches = [
+ {warehouseFk: 1, code: 1, itemFk: 1, id: 1},
+ {warehouseFk: 2, code: 2, itemFk: 1, id: 2}
+ ];
+ controller.niches = [];
+ controller.submit();
+
+ expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save');
+ });
+ });
+ });
+});
diff --git a/client/item/src/summary/item-summary.html b/client/item/src/summary/item-summary.html
new file mode 100644
index 000000000..7ad31fd9d
--- /dev/null
+++ b/client/item/src/summary/item-summary.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{$ctrl.item.id}}
+
+
+
+
+
+
+
+
+ Basic data
+ Name: {{$ctrl.item.name}}
+ Type: {{$ctrl.item.itemType.name}}
+ Intrastat: {{$ctrl.item.intrastat.description}}
+ Relevancy: {{$ctrl.item.relevancy}}
+ Origin: {{$ctrl.item.origin.name}}
+ Expence: {{$ctrl.item.expence.name}}
+
+
+
+
+ Tax
+
+ {{tax.country.country}}: {{tax.taxClass.description}}
+
+
+
+
+
+
+ Tags
+
+ {{tag.tag.name}}: {{tag.value}}
+
+
+
+
+ Nicho
+
+ {{niche.warehouse.name}}: {{niche.code}}
+
+
+
+
+
+ Botanical
+ Botanical: {{$ctrl.item.botanical.botanical}}
+ Genus: {{$ctrl.item.botanical.genus.latin_genus_name}}
+ Specie: {{$ctrl.item.botanical.specie.latin_species_name}}
+
+
+
+
+ Barcode
+
+ {{barcode.code}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/item/src/summary/item-summary.js b/client/item/src/summary/item-summary.js
new file mode 100644
index 000000000..401d70f0a
--- /dev/null
+++ b/client/item/src/summary/item-summary.js
@@ -0,0 +1,94 @@
+import ngModule from '../module';
+
+class ItemSummary {
+ constructor($http) {
+ this.$http = $http;
+ }
+
+ _getTags() {
+ let filter = {
+ where: {
+ itemFk: this.item.id
+ }
+ };
+ this.tags = [];
+ this.$http.get(`/item/api/ItemTags?filter=${JSON.stringify(Object.assign({}, filter, {include: {relation: 'tag'}}))}`).then(res => {
+ this.tags = res.data;
+ });
+ }
+
+ _getTaxes() {
+ let filter = {
+ fields: ['id', 'countryFk', 'taxClassFk'],
+ include: [{
+ relation: 'country',
+ scope: {fields: ['country']}
+ }, {
+ relation: 'taxClass',
+ scope: {fields: ['id', 'description']}
+ }]
+ };
+
+ let urlFilter = encodeURIComponent(JSON.stringify(filter));
+ let url = `/item/api/Items/${this.item.id}/taxes?filter=${urlFilter}`;
+ this.$http.get(url).then(json => {
+ this.taxes = json.data;
+ });
+ }
+
+ _getBotanical() {
+ let filter = {
+ where: {itemFk: this.item.id},
+ include: [{relation: 'genus'}, {relation: 'specie'}]
+ };
+ this.item.botanical = {};
+ this.$http.get(`/item/api/ItemBotanicals?filter=${JSON.stringify(filter)}`)
+ .then(res => {
+ if (res.data.length) {
+ this.item.botanical = res.data[0];
+ }
+ });
+ }
+
+ _getNiches() {
+ let filter = {
+ where: {itemFk: this.item.id},
+ include: {relation: 'warehouse'}
+ };
+ this.$http.get(`/item/api/ItemNiches?filter=${JSON.stringify(filter)}`).then(response => {
+ this.niches = response.data;
+ });
+ }
+
+ _getBarcodes() {
+ let filter = {
+ where: {
+ itemFk: this.item.id
+ }
+ };
+ this.barcodes = [];
+ this.$http.get(`/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`).then(response => {
+ this.barcodes = response.data;
+ });
+ }
+
+ $onChanges() {
+ if (this.item && this.item.id) {
+ this._getTags();
+ this._getBarcodes();
+ this._getNiches();
+ this._getTaxes();
+ if (!this.item.botanical)
+ this._getBotanical();
+ }
+ }
+}
+ItemSummary.$inject = ['$http'];
+
+ngModule.component('vnItemSummary', {
+ template: require('./item-summary.html'),
+ controller: ItemSummary,
+ bindings: {
+ item: '<'
+ }
+});
diff --git a/client/item/src/tags/item-tags.html b/client/item/src/tags/item-tags.html
new file mode 100644
index 000000000..318a5dec7
--- /dev/null
+++ b/client/item/src/tags/item-tags.html
@@ -0,0 +1,57 @@
+
+
+
+
\ No newline at end of file
diff --git a/client/item/src/tags/item-tags.js b/client/item/src/tags/item-tags.js
new file mode 100644
index 000000000..f2a0b6e5d
--- /dev/null
+++ b/client/item/src/tags/item-tags.js
@@ -0,0 +1,143 @@
+import ngModule from '../module';
+
+class ItemTags {
+ constructor($stateParams, $scope, $http, $translate, vnApp) {
+ this.params = $stateParams;
+ this.$scope = $scope;
+ this.$http = $http;
+ this.$translate = $translate;
+ this.vnApp = vnApp;
+
+ this.itemTagTypes = [];
+ this.removedItemTags = [];
+ this.oldItemTags = {};
+ }
+
+ _setIconAdd() {
+ if (this.instancedItemTags && this.instancedItemTags.length) {
+ this.instancedItemTags.map(element => {
+ element.showAddIcon = false;
+ return true;
+ });
+ this.instancedItemTags[this.instancedItemTags.length - 1].showAddIcon = true;
+ } else {
+ this.addItemTag();
+ }
+ }
+ _setDirtyForm() {
+ if (this.$scope.form) {
+ this.$scope.form.$setDirty();
+ }
+ }
+ _unsetDirtyForm() {
+ if (this.$scope.form) {
+ this.$scope.form.$setPristine();
+ }
+ }
+
+ addItemTag() {
+ if (this.instancedItemTags) {
+ this.instancedItemTags.push({value: null, itemFk: this.params.id, tagFk: null, priority: null, showAddIcon: true});
+ this._setIconAdd();
+ }
+ }
+
+ removeItemTag(index) {
+ let item = this.instancedItemTags[index];
+ if (item) {
+ this.instancedItemTags.splice(index, 1);
+ this._setIconAdd();
+ if (item.id) {
+ this.removedItemTags.push(item.id);
+ this._setDirtyForm();
+ }
+ }
+ }
+
+ _equalItemTags(oldTag, newTag) {
+ return oldTag.tagFk === newTag.tagFk && oldTag.value === newTag.value && oldTag.priority === newTag.priority;
+ }
+
+ _setOlTags(instancedItemTags) {
+ this._setIconAdd();
+ instancedItemTags.forEach(tag => {
+ this.oldItemTags[tag.id] = Object.assign({}, tag);
+ });
+ }
+
+ _getItemTags() {
+ let filter = {
+ where: {itemFk: this.params.id},
+ order: "priority ASC",
+ include: {relation: "tag"}
+ };
+ this.$http.get(`/item/api/ItemTags?filter=${JSON.stringify(filter)}`).then(response => {
+ this.instancedItemTags = response.data;
+ this.itemTags = JSON.parse(JSON.stringify(this.instancedItemTags));
+ this._setOlTags(response.data);
+ });
+ }
+
+ submit() {
+ let itemTagsDefined = [];
+ let repeatedItemTags = false;
+ let canSubmit;
+ let tagsObj = {
+ delete: this.removedItemTags,
+ create: [],
+ update: []
+ };
+ this.instancedItemTags.forEach(tag => {
+ let isNewTag = !tag.id;
+
+ if (itemTagsDefined.indexOf(tag.tagFk) !== -1) {
+ repeatedItemTags = true;
+ return;
+ }
+ itemTagsDefined.push(tag.tagFk);
+
+ if (isNewTag) {
+ tagsObj.create.push(tag);
+ }
+
+ if (!isNewTag && !this._equalItemTags(this.oldItemTags[tag.id], tag)) {
+ let tagToUpdate = Object.assign({}, tag);
+ delete tagToUpdate.tag;
+ delete tagToUpdate.showAddIcon;
+ tagsObj.update.push(tagToUpdate);
+ }
+ });
+
+ if (this.$scope.form.$invalid) {
+ return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid'));
+ }
+
+ if (repeatedItemTags) {
+ return this.vnApp.showMessage(this.$translate.instant('The tag must be unique'));
+ }
+
+ canSubmit = tagsObj.update.length > 0 || tagsObj.create.length > 0 || tagsObj.delete.length > 0;
+
+ if (canSubmit) {
+ return this.$http.post(`/item/api/ItemTags/crudItemTags`, tagsObj).then(() => {
+ // this.itemTags = JSON.parse(JSON.stringify(this.instancedItemTags));
+ this._getItemTags();
+ this._unsetDirtyForm();
+ });
+ }
+ this.vnApp.showMessage(this.$translate.instant('No changes to save'));
+ }
+
+ $onInit() {
+ this._getItemTags();
+ }
+}
+ItemTags.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
+
+ngModule.component('vnItemTags', {
+ template: require('./item-tags.html'),
+ controller: ItemTags,
+ bindings: {
+ itemTags: '='
+ }
+});
diff --git a/client/item/src/tags/item-tags.spec.js b/client/item/src/tags/item-tags.spec.js
new file mode 100644
index 000000000..fd1cd00c4
--- /dev/null
+++ b/client/item/src/tags/item-tags.spec.js
@@ -0,0 +1,143 @@
+import './item-tags.js';
+
+describe('Item', () => {
+ describe('Component vnItemTags', () => {
+ let $componentController;
+ let $state;
+ let controller;
+ let $httpBackend;
+
+ beforeEach(() => {
+ angular.mock.module('item');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
+ $componentController = _$componentController_;
+ $state = _$state_;
+ $httpBackend = _$httpBackend_;
+ controller = $componentController('vnItemTags', {$state: $state});
+ }));
+
+ describe('add / remove tags', () => {
+ it('should add one empty tag into controller tags collection and call _setIconAdd()', () => {
+ controller.instancedItemTags = [];
+ spyOn(controller, '_setIconAdd').and.callThrough();
+ controller.addItemTag();
+
+ expect(controller._setIconAdd).toHaveBeenCalledWith();
+ expect(controller.instancedItemTags.length).toEqual(1);
+ expect(controller.instancedItemTags[0].id).toBe(undefined);
+ expect(controller.instancedItemTags[0].showAddIcon).toBeTruthy();
+ });
+
+ it('should remove a tag that occupies the position in the index given and call _setIconAdd()', () => {
+ let index = 2;
+ controller.instancedItemTags = [
+ {id: 1, typeFk: 1, value: '1111', showAddIcon: false},
+ {id: 2, typeFk: 2, value: '2222', showAddIcon: false},
+ {id: 3, typeFk: 3, value: '3333', showAddIcon: true}
+ ];
+
+ spyOn(controller, '_setIconAdd').and.callThrough();
+
+ controller.removeItemTag(index);
+
+ expect(controller._setIconAdd).toHaveBeenCalledWith();
+ expect(controller.instancedItemTags.length).toEqual(2);
+ expect(controller.instancedItemTags[0].showAddIcon).toBeFalsy();
+ expect(controller.instancedItemTags[1].showAddIcon).toBeTruthy();
+ expect(controller.instancedItemTags[index]).toBe(undefined);
+ });
+ });
+
+ describe('_equalItemTags()', () => {
+ it('should return true if two tags are equals independent of control attributes', () => {
+ let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true};
+ let tag2 = {id: 1, typeFk: 1, value: '1111', showAddIcon: false};
+ let equals = controller._equalItemTags(tag2, tag1);
+
+ expect(equals).toBeTruthy();
+ });
+
+ it('should return false if two tags aint equal independent of control attributes', () => {
+ let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true};
+ let tag2 = {id: 1, typeFk: 1, value: '2222', showAddIcon: true};
+ let equals = controller._equalItemTags(tag2, tag1);
+
+ expect(equals).toBeFalsy();
+ });
+ });
+
+ describe('get itemTags', () => {
+ it('should perform a GET query to receive the item tags', () => {
+ let res = [{id: 1, typeFk: 1, value: '1111'}];
+
+ $httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond(res);
+ $httpBackend.expectGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`);
+ controller._getItemTags();
+ $httpBackend.flush();
+ });
+ });
+
+ describe('submit()', () => {
+ it("should return an error message 'The tag must be unique' when the tag value isnt unique", () => {
+ controller.$scope.form = [];
+ spyOn(controller.vnApp, 'showMessage').and.callThrough();
+ controller.instancedItemTags = [
+ {typeFk: 1, value: 123454, itemFk: 1, id: 1},
+ {typeFk: 1, value: 123454, itemFk: 1}
+ ];
+ controller.oldItemTags = {1: {typeFk: 1, id: 1, value: 123454, itemFk: 1}};
+ controller.submit();
+
+ expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The tag must be unique');
+ });
+
+ it("should perfom a query to delete tags", () => {
+ controller.$scope.form = {$setPristine: () => {}};
+ controller.oldItemTags = {1: {id: 1, typeFk: 1, value: '1111'}};
+ controller.instancedItemTags = [];
+ controller.removedItemTags = [1];
+
+ $httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
+ $httpBackend.expectPOST(`/item/api/ItemTags/crudItemTags`).respond('ok!');
+ controller.submit();
+ $httpBackend.flush();
+ });
+
+ it("should perfom a query to update tags", () => {
+ controller.$scope.form = {$setPristine: () => {}};
+ controller.instancedItemTags = [{id: 1, typeFk: 1, value: '2222'}];
+ controller.oldItemTags = {1: {id: 1, typeFk: 1, value: '1111'}};
+
+ $httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
+ $httpBackend.expectPOST(`/item/api/ItemTags/crudItemTags`).respond('ok!');
+ controller.submit();
+ $httpBackend.flush();
+ });
+
+ it("should perfom a query to create new tag", () => {
+ controller.$scope.form = {$setPristine: () => {}};
+ controller.instancedItemTags = [{typeFk: 1, value: 1111, itemFk: 1}];
+
+ $httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
+ $httpBackend.expectPOST(`/item/api/ItemTags/crudItemTags`).respond('ok!');
+ controller.submit();
+ $httpBackend.flush();
+ });
+
+ it("should return a message 'No changes to save' when there are no changes to apply", () => {
+ controller.$scope.form = {$setPristine: () => {}};
+ spyOn(controller.vnApp, 'showMessage').and.callThrough();
+ controller.oldItemTags = [
+ {typeFk: 1, value: 1, itemFk: 1, id: 1},
+ {typeFk: 2, value: 2, itemFk: 1, id: 2}
+ ];
+ controller.instancedItemTags = [];
+ controller.submit();
+
+ expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save');
+ });
+ });
+ });
+});
diff --git a/client/item/src/tax/item-tax.html b/client/item/src/tax/item-tax.html
new file mode 100644
index 000000000..aa111756b
--- /dev/null
+++ b/client/item/src/tax/item-tax.html
@@ -0,0 +1,23 @@
+
\ No newline at end of file
diff --git a/client/item/src/tax/item-tax.js b/client/item/src/tax/item-tax.js
new file mode 100644
index 000000000..57b84fbab
--- /dev/null
+++ b/client/item/src/tax/item-tax.js
@@ -0,0 +1,46 @@
+import ngModule from '../module';
+
+export default class Controller {
+ constructor($stateParams, $http) {
+ this.$http = $http;
+ this.$stateParams = $stateParams;
+
+ let filter = {
+ fields: ['id', 'countryFk', 'taxClassFk'],
+ include: [{
+ relation: 'country',
+ scope: {fields: ['country']}
+ }, {
+ relation: 'taxClass',
+ scope: {fields: ['id', 'description']}
+ }]
+ };
+
+ let urlFilter = encodeURIComponent(JSON.stringify(filter));
+ let url = `/item/api/Items/${$stateParams.id}/taxes?filter=${urlFilter}`;
+ $http.get(url).then(json => {
+ this.taxes = json.data;
+ });
+
+ $http.get(`/item/api/TaxClasses`).then(json => {
+ this.classes = json.data;
+ });
+ }
+ submit() {
+ let data = [];
+ for (let tax of this.taxes)
+ data.push({id: tax.id, taxClassFk: tax.taxClassFk});
+
+ let url = `/item/api/Items/${this.$stateParams.id}/updateTaxes`;
+ this.$http.post(url, data);
+ }
+}
+Controller.$inject = ['$stateParams', '$http'];
+
+ngModule.component('vnItemTax', {
+ template: require('./item-tax.html'),
+ controller: Controller,
+ bindings: {
+ item: '<'
+ }
+});
diff --git a/client/locator/index.js b/client/locator/index.js
new file mode 100644
index 000000000..d2b755cd8
--- /dev/null
+++ b/client/locator/index.js
@@ -0,0 +1 @@
+export * from './src/locator';
diff --git a/client/locator/routes.json b/client/locator/routes.json
new file mode 100644
index 000000000..b508fcc5f
--- /dev/null
+++ b/client/locator/routes.json
@@ -0,0 +1,14 @@
+{
+ "module": "locator",
+ "name": "Locator",
+ "icon": "add_location",
+ "validations" : false,
+ "routes": [
+ {
+ "url": "/locator",
+ "state": "locator",
+ "component": "vn-locator-index",
+ "acl": ["developer"]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/client/locator/src/index/index.html b/client/locator/src/index/index.html
new file mode 100644
index 000000000..4194c9db8
--- /dev/null
+++ b/client/locator/src/index/index.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/locator/src/index/index.js b/client/locator/src/index/index.js
new file mode 100644
index 000000000..f691f9ece
--- /dev/null
+++ b/client/locator/src/index/index.js
@@ -0,0 +1,33 @@
+import ngModule from '../module';
+
+class LocatorIndex {
+ constructor($state) {
+ this.$state = $state;
+ this.routes = [];
+
+ for (let i = 1; i < 100; i++) {
+ let route = {
+ id: i,
+ zoneFk: Math.floor(Math.random() * 6) + 1,
+ postalcode: 46006,
+ order: Math.floor(Math.random() * 3) + 1,
+ preparado: '25/08',
+ entrada: '26/08',
+ ticket: 1547890 + i,
+ routeFk: Math.floor(Math.random() * 9999) + 1000,
+ alias: `Flores X${Math.floor(Math.random() * 3) + 1}`,
+ bultos: Math.floor(Math.random() * 20) + 10,
+ m3: (Math.random()).toFixed(2),
+ error: (Math.floor(Math.random() * 3) + 1) === 1
+ };
+ route.success = (!route.error && (Math.floor(Math.random() * 3) + 1) === 1);
+ this.routes.push(route);
+ }
+ }
+}
+LocatorIndex.$inject = ['$state'];
+
+ngModule.component('vnLocatorIndex', {
+ template: require('./index.html'),
+ controller: LocatorIndex
+});
diff --git a/client/locator/src/locale/en.yml b/client/locator/src/locale/en.yml
new file mode 100644
index 000000000..8d3c81c58
--- /dev/null
+++ b/client/locator/src/locale/en.yml
@@ -0,0 +1,4 @@
+Routes locator: Routes locator
+Filter: Filter
+Store: Store
+Address: Address
\ No newline at end of file
diff --git a/client/locator/src/locale/es.yml b/client/locator/src/locale/es.yml
new file mode 100644
index 000000000..462c393bf
--- /dev/null
+++ b/client/locator/src/locale/es.yml
@@ -0,0 +1,4 @@
+Routes locator: Localizador de rutas
+Filter: Filtro
+Store: Almacén
+Address: Dirección
\ No newline at end of file
diff --git a/client/locator/src/locator-actions/locator-actions.html b/client/locator/src/locator-actions/locator-actions.html
new file mode 100644
index 000000000..e057bf6fb
--- /dev/null
+++ b/client/locator/src/locator-actions/locator-actions.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/locator/src/locator-actions/locator-actions.js b/client/locator/src/locator-actions/locator-actions.js
new file mode 100644
index 000000000..6f61ac81d
--- /dev/null
+++ b/client/locator/src/locator-actions/locator-actions.js
@@ -0,0 +1,13 @@
+import ngModule from '../module';
+
+class LocatorActions {
+ constructor($state) {
+ this.$state = $state;
+ }
+}
+LocatorActions.$inject = ['$state'];
+
+ngModule.component('vnLocatorActions', {
+ template: require('./locator-actions.html'),
+ controller: LocatorActions
+});
diff --git a/client/locator/src/locator-table/locator-table.html b/client/locator/src/locator-table/locator-table.html
new file mode 100644
index 000000000..79fbcce45
--- /dev/null
+++ b/client/locator/src/locator-table/locator-table.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{::route.zoneFk}}
+ {{::route.postalcode}}
+ {{::route.order}}
+ {{::route.preparado}}
+ {{::route.entrada}}
+ {{::route.ticket}}
+ {{::route.routeFk}}
+ {{::route.alias}}
+ {{::route.bultos}}
+ {{::route.m3}}
+
+
+
+
+
+
+
+ Address: {{::route.address}}
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/locator/src/locator-table/locator-table.js b/client/locator/src/locator-table/locator-table.js
new file mode 100644
index 000000000..2b8834a65
--- /dev/null
+++ b/client/locator/src/locator-table/locator-table.js
@@ -0,0 +1,46 @@
+import ngModule from '../module';
+
+class LocatorTable {
+ constructor($filter) {
+ this.$filter = $filter;
+ this.itemsDisplayedInList = 7;
+ this.pageTable = {
+ filter: {
+ page: 1,
+ size: this.itemsDisplayedInList
+ },
+ model: []
+ };
+ this._routes = [];
+ }
+
+ set routes(value) {
+ this._routes = value;
+ this.totalFilter = this._routes.length;
+ this.pageTable.filter.page = 1;
+ this.paginate();
+ }
+ get routes() {
+ return this._routes;
+ }
+
+ onOrder(field, order) {
+ let reverse = order === 'DESC';
+ this.routes = this.$filter('orderBy')(this.routes, field, reverse);
+ this.paginate();
+ }
+ paginate() {
+ let init = (this.pageTable.filter.page - 1) * this.itemsDisplayedInList;
+ let fin = this.pageTable.filter.page * this.itemsDisplayedInList;
+ this.pageTable.model = this.routes.slice(init, fin);
+ }
+}
+LocatorTable.$inject = ['$filter'];
+
+ngModule.component('vnLocatorTable', {
+ template: require('./locator-table.html'),
+ bindings: {
+ routes: '<'
+ },
+ controller: LocatorTable
+});
diff --git a/client/locator/src/locator.js b/client/locator/src/locator.js
new file mode 100644
index 000000000..4f53c473a
--- /dev/null
+++ b/client/locator/src/locator.js
@@ -0,0 +1,5 @@
+export * from './module';
+
+import './index/index';
+import './locator-actions/locator-actions';
+import './locator-table/locator-table';
diff --git a/client/locator/src/module.js b/client/locator/src/module.js
new file mode 100644
index 000000000..2d50fd2ef
--- /dev/null
+++ b/client/locator/src/module.js
@@ -0,0 +1,5 @@
+import {ng} from 'vendor';
+import 'core';
+
+const ngModule = ng.module('locator', []);
+export default ngModule;
diff --git a/client/modules.yml b/client/modules.yml
new file mode 100644
index 000000000..f71f90ae6
--- /dev/null
+++ b/client/modules.yml
@@ -0,0 +1,9 @@
+auth: []
+client: []
+core: []
+item: []
+locator: []
+production: []
+salix: []
+route: []
+ticket: []
diff --git a/client/production/index.js b/client/production/index.js
new file mode 100644
index 000000000..4cbd2fb45
--- /dev/null
+++ b/client/production/index.js
@@ -0,0 +1 @@
+export * from './src/production';
diff --git a/client/production/routes.json b/client/production/routes.json
new file mode 100644
index 000000000..159a80144
--- /dev/null
+++ b/client/production/routes.json
@@ -0,0 +1,14 @@
+{
+ "module": "production",
+ "name": "Production",
+ "icon": "local_florist",
+ "validations" : false,
+ "routes": [
+ {
+ "url": "/production",
+ "state": "production",
+ "component": "vn-production-index",
+ "acl": ["developer"]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/client/production/src/index/index.html b/client/production/src/index/index.html
new file mode 100644
index 000000000..be21fd321
--- /dev/null
+++ b/client/production/src/index/index.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/production/src/index/index.js b/client/production/src/index/index.js
new file mode 100644
index 000000000..bf111e9f0
--- /dev/null
+++ b/client/production/src/index/index.js
@@ -0,0 +1,103 @@
+import ngModule from '../module';
+import './style.scss';
+
+export default class ProductionIndex {
+ constructor($element, $scope, $http, aclConstant) {
+ this.$element = $element;
+ this.$ = $scope;
+ this.$http = $http;
+ this.filter = {};
+ this.tickets = [];
+
+ this.checkAll = 0;
+ this.footer = {
+ total: null,
+ lines: null,
+ meters: null
+ };
+ this._search = null;
+
+ this.sharedData = {
+ states: [],
+ hourItems: []
+ };
+
+ this.child = undefined;
+ this.userProfile = aclConstant.userProfile;
+ this.filter.warehouseFk = this.userProfile.warehouseId;
+ }
+
+ get checkAll() {
+ return this._checkAll;
+ }
+ set checkAll(value) {
+ this._checkAll = value;
+ }
+
+ // Actions Callbacks
+
+ _changeState(ids, stateId, stateName, index) {
+ this.$http.put(`/production/api/TicketStates/${stateId}/changeState`, {tickets: ids}).then(() => {
+ index.forEach(val => {
+ this.tickets[val].state = stateName;
+ this.tickets[val].stateFk = stateId;
+ });
+ });
+ }
+
+ _sendMessage(tickets) {
+ this.$http.post(`/production/api/FakeProductions/messageSend`, {tickets: tickets}).then(() => {
+ this.vnApp.showMessage(this.$translate.instant('Success: message send!'));
+ });
+ }
+
+ _changeTime(ids, time, index) {
+ this.$http.put(`/production/api/Tickets/${time}/changeTime`, {tickets: ids}).then(() => {
+ index.forEach(val => {
+ this.tickets[val].hour = time;
+ });
+ });
+ }
+
+ searchTickets(filter) {
+ this.$.index.filter.filter = Object.assign({}, this.filter, filter || {});
+ this.checkAll = 0;
+ this.$.index.accept().then(json => {
+ this.tickets = json.tickets;
+ this.footer.lines = json.lines;
+ this.footer.meters = json.m3;
+ this.footer.total = json.total;
+ });
+ }
+
+ refreshTickets() {
+ this.filter = {};
+ this.filter.warehouseFk = this.$.displayValue = this.userProfile.warehouseId;
+ }
+
+ onChangeWareHouse(warehouse) {
+ if (warehouse && warehouse != this.filter.warehouseFk) {
+ this.filter.warehouseFk = warehouse;
+ this.searchTickets(this.filter);
+ }
+ }
+
+ $onInit() {
+ for (let i = 1; i <= 24; i++) {
+ let hour = [i].join('');
+ if (hour.length === 1) {
+ hour = [0, i].join('');
+ }
+ hour += ':00';
+ this.sharedData.hourItems.push({id: i, name: hour});
+ }
+ this.filter.warehouseFk = this.$.displayValue = this.userProfile.warehouseId;
+ }
+}
+
+ProductionIndex.$inject = ['$element', '$scope', '$http', 'aclConstant'];
+
+ngModule.component('vnProductionIndex', {
+ template: require('./index.html'),
+ controller: ProductionIndex
+});
diff --git a/client/production/src/index/index.spec.js b/client/production/src/index/index.spec.js
new file mode 100644
index 000000000..dc9f0d89b
--- /dev/null
+++ b/client/production/src/index/index.spec.js
@@ -0,0 +1,39 @@
+import './index.js';
+
+describe('Production', () => {
+ describe('Component vnProductionIndex', () => {
+ let $componentController;
+ let $httpBackend;
+ let $scope;
+ let controller;
+ let $element;
+ let aclConstant;
+
+ beforeEach(() => {
+ angular.mock.module('production');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
+ $element = angular.element('');
+ $componentController = _$componentController_;
+ $httpBackend = _$httpBackend_;
+ $scope = $rootScope.$new();
+ aclConstant = {userProfile: {warehouseId: 1}};
+ controller = $componentController('vnProductionIndex', {$scope: $scope, $element: $element, aclConstant: aclConstant});
+ }));
+
+ describe('_changeState()', () => {
+ it('should request to update the ticket state', () => {
+ let ids = [1, 2, 3, 4];
+ let stateId = 1;
+ let stateName = 'state';
+ let index = [];
+ controller.tickets = ['ticketVal'];
+ $httpBackend.whenPUT('/production/api/TicketStates/1/changeState', {tickets: ids}).respond({data: 'ticketVal'});
+ $httpBackend.expectPUT('/production/api/TicketStates/1/changeState', {tickets: ids});
+ controller._changeState(ids, stateId, stateName, index);
+ $httpBackend.flush();
+ });
+ });
+ });
+});
diff --git a/client/production/src/index/style.scss b/client/production/src/index/style.scss
new file mode 100644
index 000000000..eea97e50e
--- /dev/null
+++ b/client/production/src/index/style.scss
@@ -0,0 +1,36 @@
+vn-production-index {
+ flex: 1;
+
+ button {
+ height: 20px;
+ padding: 0 6px;
+ }
+ vn-searchbar {
+ vn-icon{
+ padding-top: 20px;
+ }
+ vn-icon-button{
+ padding-top: 10px;
+ }
+ }
+ [pad-ten-top] {
+ padding-top: 10px;
+ }
+ .icon-square{
+ height: 36px;
+ }
+ .locator-header{
+ i{
+ cursor: pointer;
+ }
+ .moreFilters{
+ position: absolute;
+ z-index: 99;
+ background-color: white;
+ padding: 15px;
+ border: 1px solid #9D9D9D;
+ margin-top: 60px;
+ width: 600px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/production/src/locale/en.yml b/client/production/src/locale/en.yml
new file mode 100644
index 000000000..2577c6f43
--- /dev/null
+++ b/client/production/src/locale/en.yml
@@ -0,0 +1 @@
+Production: Production
\ No newline at end of file
diff --git a/client/production/src/locale/es.yml b/client/production/src/locale/es.yml
new file mode 100644
index 000000000..7846f4b3d
--- /dev/null
+++ b/client/production/src/locale/es.yml
@@ -0,0 +1,27 @@
+Finder: Localizador
+Production: Producción
+'Error: No tickets selected!': 'Error: ¡No hay tickets seleccionados!'
+'Error: Action not implemented!': 'Error: ¡Acción no implementada!'
+State: Estado
+Alarm: Alarma
+Agencies: Agencias
+Agency: Agencia
+Store: Almacén
+Printed: Impreso
+Commercial: Comercial
+Hour: Hora
+Lines: Líneas
+Boxes: Cajas
+Comment: Comentario
+Message: Mensaje
+Send: Enviar
+Date: Fecha
+Ticket ID: ID Ticket
+Route ID: ID Ruta
+Province: Provincia
+Filter: Filtrar
+Cancel: Cancelar
+Worker: Trabajador
+Town: Población
+Client ID: ID Cliente
+Ticket with incidence: Ticket con incidencia
\ No newline at end of file
diff --git a/client/production/src/module.js b/client/production/src/module.js
new file mode 100644
index 000000000..1427bd898
--- /dev/null
+++ b/client/production/src/module.js
@@ -0,0 +1,5 @@
+import {ng} from 'vendor';
+import 'core';
+
+const ngModule = ng.module('production', []);
+export default ngModule;
diff --git a/client/production/src/production-actions/production-actions.html b/client/production/src/production-actions/production-actions.html
new file mode 100644
index 000000000..0e79e3b4a
--- /dev/null
+++ b/client/production/src/production-actions/production-actions.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/production/src/production-actions/production-actions.js b/client/production/src/production-actions/production-actions.js
new file mode 100644
index 000000000..fee7b687b
--- /dev/null
+++ b/client/production/src/production-actions/production-actions.js
@@ -0,0 +1,118 @@
+import ngModule from '../module';
+
+export default class ProductionActions {
+ constructor($http, $translate, vnApp) {
+ this.$http = $http;
+ this.$translate = $translate;
+ this.vnApp = vnApp;
+
+ this._actionState = null;
+ this._actionWorker = null;
+ this._actionHours = null;
+ }
+
+ set actionState(value) {
+ this._actionState = value;
+ this.doAction('changeState');
+ }
+ get actionState() {
+ return this._actionState;
+ }
+
+ set actionHours(value) {
+ this._actionHours = value;
+ this.doAction('changeTime');
+ }
+ get actionHours() {
+ return this._actionHours;
+ }
+
+ set actionWorker(value) {
+ this._actionWorker = value;
+ this.doAction('changeWorker');
+ }
+ get actionWorker() {
+ return this._actionWorker;
+ }
+
+ _changeState(ids, sateteId) {
+ this.$http.put(`/production/api/TicketStates/${sateteId}/changeState`, {tickets: ids})
+ .then(
+ () => {
+ this.parent.searchTickets();
+ }
+ );
+ }
+ _sendMessage(tickets) {
+ this.$http.post(`/production/api/FakeProductions/messageSend`, {tickets: tickets})
+ .then(
+ () => {
+ this.vnApp.showMessage(this.$translate.instant('Success: message send!'));
+ }
+ );
+ }
+ _changeTime(ids, time, index) {
+ this.$http.put(`/production/api/Tickets/${time}/changeTime`, {tickets: ids})
+ .then(
+ () => {
+ this.parent.searchTickets();
+ }
+ );
+ }
+ _changeWorker(ids, workerFk, index) {
+ this.$http.put(`/production/api/Tickets/${workerFk}/changeWorker`, {tickets: ids})
+ .then(
+ () => {
+ this.parent.searchTickets();
+ }
+ );
+ }
+
+ doAction(actionName) {
+ let ids = [];
+ let index = [];
+ let tickets = [];
+ this.parent.tickets.forEach(
+ (val, i) => {
+ if (val.checked) {
+ ids.push(val.ticketFk);
+ index.push(i);
+ tickets.push({ticketFk: val.ticketFk, salesPerson: val.salesPerson});
+ }
+ }
+ );
+ if (tickets.length) {
+ switch (actionName) {
+ case 'changeState' :
+ this._changeState(ids, this.actionState.id);
+ break;
+ case 'addComment':
+ this._sendMessage(tickets);
+ break;
+ case 'markPrinted':
+ this._changeState(ids, 4);
+ break;
+ case 'changeTime':
+ this._changeTime(ids, this.actionHours.name, index);
+ break;
+ case 'changeWorker':
+ this._changeWorker(ids, this.actionWorker.id, index);
+ break;
+ default:
+ this.vnApp.showMessage(this.$translate.instant('Error: Action not implemented!'));
+ }
+ } else {
+ this.vnApp.showMessage(this.$translate.instant('Error: No tickets selected!'));
+ }
+ }
+}
+
+ProductionActions.$inject = ['$http', '$translate', 'vnApp'];
+
+ngModule.component('vnProductionActions', {
+ template: require('./production-actions.html'),
+ controller: ProductionActions,
+ require: {
+ parent: '^^vnProductionIndex'
+ }
+});
diff --git a/client/production/src/production-comment/production-comment.html b/client/production/src/production-comment/production-comment.html
new file mode 100644
index 000000000..e094d47b8
--- /dev/null
+++ b/client/production/src/production-comment/production-comment.html
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/client/production/src/production-comment/production-comment.js b/client/production/src/production-comment/production-comment.js
new file mode 100644
index 000000000..390de47c2
--- /dev/null
+++ b/client/production/src/production-comment/production-comment.js
@@ -0,0 +1,5 @@
+import ngModule from '../module';
+
+ngModule.component('vnProductionComment', {
+ template: require('./production-comment.html')
+});
diff --git a/client/production/src/production-filters/production-filters.html b/client/production/src/production-filters/production-filters.html
new file mode 100644
index 000000000..587e03199
--- /dev/null
+++ b/client/production/src/production-filters/production-filters.html
@@ -0,0 +1,32 @@
+
diff --git a/client/production/src/production-filters/production-filters.js b/client/production/src/production-filters/production-filters.js
new file mode 100644
index 000000000..0e6143efc
--- /dev/null
+++ b/client/production/src/production-filters/production-filters.js
@@ -0,0 +1,5 @@
+import ngModule from '../module';
+
+ngModule.component('vnProductionFilterPanel', {
+ template: require('./production-filters.html')
+});
diff --git a/client/production/src/production-table/production-table.html b/client/production/src/production-table/production-table.html
new file mode 100644
index 000000000..e87410722
--- /dev/null
+++ b/client/production/src/production-table/production-table.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{::ticket.ticketFk}}
+ {{::ticket.agency}}
+ {{::ticket.routeFk}}
+ {{::ticket.salesPerson | ucwords}}
+ {{::ticket.worker | ucwords}}
+ {{::ticket.hour}}
+ {{::ticket.state}}
+ {{::ticket.lines}}
+ {{::ticket.m3}}
+ {{::ticket.boxes}}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/production/src/production-table/production-table.js b/client/production/src/production-table/production-table.js
new file mode 100644
index 000000000..288118a0d
--- /dev/null
+++ b/client/production/src/production-table/production-table.js
@@ -0,0 +1,56 @@
+import ngModule from '../module';
+
+export class ProductionTable {
+ constructor($filter) {
+ this.$filter = $filter;
+ this._tickets = [];
+ this.itemsDisplayedInList = 14;
+ this._checkAll = 0;
+ this.pageTable = {
+ filter: {
+ page: 1,
+ size: this.itemsDisplayedInList
+ },
+ model: []
+ };
+ this.filteredField = null;
+ this.filteredReverse = null;
+ }
+ get checkAll() {
+ return this._checkAll;
+ }
+ set checkAll(value) {
+ this._checkAll = value;
+ }
+ set tickets(value) {
+ this._tickets = this.filteredField ? this.$filter('orderBy')(value, this.filteredField, this.filteredReverse) : value;
+ this.totalFilter = this._tickets.length;
+ this.pageTable.filter.page = 1;
+ this.pageTickets();
+ }
+ get tickets() {
+ return this._tickets;
+ }
+ onOrder(field, order) {
+ this.filteredField = field;
+ this.filteredReverse = order === 'DESC';
+ this.tickets = this.tickets; // call tickets setter
+ }
+ pageTickets() {
+ let init = (this.pageTable.filter.page - 1) * this.itemsDisplayedInList;
+ let fin = this.pageTable.filter.page * this.itemsDisplayedInList;
+ this.pageTable.model = this.tickets.slice(init, fin);
+ }
+}
+
+ProductionTable.$inject = ['$filter'];
+
+ngModule.component('vnProductionTable', {
+ template: require('./production-table.html'),
+ bindings: {
+ tickets: '<',
+ footer: '<',
+ checkAll: '<'
+ },
+ controller: ProductionTable
+});
diff --git a/client/production/src/production.js b/client/production/src/production.js
new file mode 100644
index 000000000..aecd90eaf
--- /dev/null
+++ b/client/production/src/production.js
@@ -0,0 +1,7 @@
+export * from './module';
+
+// import components
+import './index/index';
+import './production-filters/production-filters';
+import './production-actions/production-actions';
+import './production-table/production-table';
diff --git a/client/route/index.js b/client/route/index.js
new file mode 100644
index 000000000..eadbde870
--- /dev/null
+++ b/client/route/index.js
@@ -0,0 +1 @@
+export * from './src/route';
diff --git a/client/route/routes.json b/client/route/routes.json
new file mode 100644
index 000000000..9e7c48833
--- /dev/null
+++ b/client/route/routes.json
@@ -0,0 +1,68 @@
+{
+ "module": "route",
+ "name": "Routes",
+ "icon" : "local_shipping",
+ "validations" : true,
+ "routes": [
+ {
+ "url": "/routes",
+ "state": "routes",
+ "abstract": true,
+ "component": "ui-view"
+ },
+ {
+ "url": "/list",
+ "state": "routes.index",
+ "component": "vn-route-index",
+ "acl": ["developer"]
+ },
+ {
+ "url": "/create",
+ "state": "routes.create",
+ "component": "vn-route-create"
+ },
+ {
+ "url": "/:id",
+ "state": "routes.card",
+ "abstract": true,
+ "component": "vn-route-card"
+ },
+ {
+ "url": "/basicData",
+ "state": "routes.card.basicData",
+ "component": "vn-route-basic-data",
+ "params": {
+ "route": "$ctrl.route"
+ },
+ "menu": {
+ "description": "Basic data",
+ "icon": "person"
+ }
+ },
+ {
+ "url": "/logisticData",
+ "state": "routes.card.logisticData",
+ "component": "vn-route-logistic-data",
+ "acl": ["employee"],
+ "params": {
+ "route": "$ctrl.route"
+ },
+ "menu": {
+ "description": "Logistic data",
+ "icon": "local_shipping"
+ }
+ },
+ {
+ "url": "/tickets",
+ "state": "routes.card.tickets",
+ "component": "vn-route-tickets",
+ "params": {
+ "route": "$ctrl.route"
+ },
+ "menu": {
+ "description": "Assigned tickets",
+ "icon": "assignment"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/client/route/src/basic-data/basic-data.html b/client/route/src/basic-data/basic-data.html
new file mode 100644
index 000000000..91a4bd70f
--- /dev/null
+++ b/client/route/src/basic-data/basic-data.html
@@ -0,0 +1,35 @@
+
+
+
\ No newline at end of file
diff --git a/client/route/src/basic-data/basic-data.js b/client/route/src/basic-data/basic-data.js
new file mode 100644
index 000000000..9f2278dbb
--- /dev/null
+++ b/client/route/src/basic-data/basic-data.js
@@ -0,0 +1,8 @@
+import ngModule from '../module';
+
+ngModule.component('vnRouteBasicData', {
+ template: require('./basic-data.html'),
+ bindings: {
+ route: '<'
+ }
+});
diff --git a/client/route/src/card/card.html b/client/route/src/card/card.html
new file mode 100644
index 000000000..b787b738f
--- /dev/null
+++ b/client/route/src/card/card.html
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+ local_shipping
+
+
+ Route {{::$ctrl.route.id}}
+ {{$ctrl.route.date | date:'dd/MM/yyyy'}}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/route/src/card/card.js b/client/route/src/card/card.js
new file mode 100644
index 000000000..e0655c069
--- /dev/null
+++ b/client/route/src/card/card.js
@@ -0,0 +1,12 @@
+import ngModule from '../module';
+
+class RouteCard {
+ constructor() {
+ this.route = null;
+ }
+}
+
+ngModule.component('vnRouteCard', {
+ template: require('./card.html'),
+ controller: RouteCard
+});
diff --git a/client/salix/src/components/searchbar/style.css b/client/route/src/card/style.css
similarity index 100%
rename from client/salix/src/components/searchbar/style.css
rename to client/route/src/card/style.css
diff --git a/client/route/src/create/create.html b/client/route/src/create/create.html
new file mode 100644
index 000000000..8b7b7c6ba
--- /dev/null
+++ b/client/route/src/create/create.html
@@ -0,0 +1,43 @@
+
+
+
+
diff --git a/client/route/src/create/create.js b/client/route/src/create/create.js
new file mode 100644
index 000000000..a51a32da7
--- /dev/null
+++ b/client/route/src/create/create.js
@@ -0,0 +1,20 @@
+import ngModule from '../module';
+
+class RouteCreate {
+ constructor($scope, $state) {
+ this.$ = $scope;
+ this.$state = $state;
+ this.delivery = {};
+ }
+ onSubmit() {
+ this.$.watcher.submit().then(
+ json => this.$state.go('routes.card.basicData', {id: json.data.id})
+ );
+ }
+}
+RouteCreate.$inject = ['$scope', '$state'];
+
+ngModule.component('vnRouteCreate', {
+ template: require('./create.html'),
+ controller: RouteCreate
+});
diff --git a/client/route/src/index/googleMaps.svg b/client/route/src/index/googleMaps.svg
new file mode 100644
index 000000000..9a7fc59d7
--- /dev/null
+++ b/client/route/src/index/googleMaps.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/client/route/src/index/index.html b/client/route/src/index/index.html
new file mode 100644
index 000000000..7cbf0100f
--- /dev/null
+++ b/client/route/src/index/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/route/src/index/index.js b/client/route/src/index/index.js
new file mode 100644
index 000000000..c8dc8ffd6
--- /dev/null
+++ b/client/route/src/index/index.js
@@ -0,0 +1,18 @@
+import ngModule from '../module';
+import './style.css';
+import './item-route';
+
+export default class Controller {
+ constructor() {
+ this.model = {};
+ }
+ search(index) {
+ index.filter.search = this.model.search;
+ index.accept();
+ }
+}
+
+ngModule.component('vnRouteIndex', {
+ template: require('./index.html'),
+ controller: Controller
+});
diff --git a/client/route/src/index/item-route.html b/client/route/src/index/item-route.html
new file mode 100644
index 000000000..226d75810
--- /dev/null
+++ b/client/route/src/index/item-route.html
@@ -0,0 +1,21 @@
+
+
+
+
+ ID_RUTA:
+ {{$ctrl.route.id}}
+
+
+ Fecha:
+ {{$ctrl.route.date | date:'dd/MM/yyyy'}}
+
+
+ m3:
+ {{$ctrl.route.m3}}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/route/src/index/item-route.js b/client/route/src/index/item-route.js
new file mode 100644
index 000000000..0eeb9fcd5
--- /dev/null
+++ b/client/route/src/index/item-route.js
@@ -0,0 +1,8 @@
+import ngModule from '../module';
+
+ngModule.component('vnItemRoute', {
+ template: require('./item-route.html'),
+ bindings: {
+ route: '<'
+ }
+});
diff --git a/client/route/src/index/routeIn.svg b/client/route/src/index/routeIn.svg
new file mode 100644
index 000000000..dec26dfbf
--- /dev/null
+++ b/client/route/src/index/routeIn.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/client/route/src/index/routeOut.svg b/client/route/src/index/routeOut.svg
new file mode 100644
index 000000000..7a69b7786
--- /dev/null
+++ b/client/route/src/index/routeOut.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/client/client/src/index/style.css b/client/route/src/index/style.css
similarity index 54%
rename from client/client/src/index/style.css
rename to client/route/src/index/style.css
index ba7f75844..0a369664e 100644
--- a/client/client/src/index/style.css
+++ b/client/route/src/index/style.css
@@ -1,16 +1,12 @@
-vn-item-client {
+vn-item-route {
display: block;
}
-vn-item-client a {
+vn-item-route a {
display: block;
text-decoration: none;
color: inherit;
}
-vn-item-client a:hover {
+vn-item-route a:hover {
color: white;
background-color: #424242;
-}
-
-.vn-item-client-name{
- font-family: raleway-bold;
-}
+}
\ No newline at end of file
diff --git a/client/route/src/locale/en.yml b/client/route/src/locale/en.yml
new file mode 100644
index 000000000..6659ba5dc
--- /dev/null
+++ b/client/route/src/locale/en.yml
@@ -0,0 +1 @@
+Routes: Routes
\ No newline at end of file
diff --git a/client/route/src/locale/es.yml b/client/route/src/locale/es.yml
new file mode 100644
index 000000000..4805a41e6
--- /dev/null
+++ b/client/route/src/locale/es.yml
@@ -0,0 +1,15 @@
+Basic data: Datos básicos
+Logistic data: Datos logísticos
+Assigned tickets: Tickets asignados
+Routes: Rutas
+Route: Ruta
+Date: Fecha
+Agency: Agencia
+Driver: Conductor
+Vehicle: Vehículo
+Start Hour: Hora Inicio
+End Hour: Hora Fin
+Start Km: Km Inicio
+End Km: Km Fin
+Packages: Bultos
+Route document: Documento de Ruta
diff --git a/client/route/src/logistic-data/logistic-data.html b/client/route/src/logistic-data/logistic-data.html
new file mode 100644
index 000000000..9ea4c802b
--- /dev/null
+++ b/client/route/src/logistic-data/logistic-data.html
@@ -0,0 +1,26 @@
+
+
+
\ No newline at end of file
diff --git a/client/route/src/logistic-data/logistic-data.js b/client/route/src/logistic-data/logistic-data.js
new file mode 100644
index 000000000..4230a8282
--- /dev/null
+++ b/client/route/src/logistic-data/logistic-data.js
@@ -0,0 +1,8 @@
+import ngModule from '../module';
+
+ngModule.component('vnRouteLogisticData', {
+ template: require('./logistic-data.html'),
+ bindings: {
+ route: '<'
+ }
+});
diff --git a/client/route/src/module.js b/client/route/src/module.js
new file mode 100644
index 000000000..779683e38
--- /dev/null
+++ b/client/route/src/module.js
@@ -0,0 +1,5 @@
+import {ng} from 'vendor';
+import 'core';
+
+const ngModule = ng.module('route', []);
+export default ngModule;
diff --git a/client/route/src/route.js b/client/route/src/route.js
new file mode 100644
index 000000000..a9db6db33
--- /dev/null
+++ b/client/route/src/route.js
@@ -0,0 +1,10 @@
+export * from './module';
+
+// import components
+import './index/index';
+import './search-panel/search-panel';
+import './create/create';
+import './card/card';
+import './basic-data/basic-data';
+import './logistic-data/logistic-data';
+import './tickets/tickets';
diff --git a/client/route/src/search-panel/locale/es.yml b/client/route/src/search-panel/locale/es.yml
new file mode 100644
index 000000000..590d0e6d8
--- /dev/null
+++ b/client/route/src/search-panel/locale/es.yml
@@ -0,0 +1,8 @@
+Client id: Id cliente
+Tax number: NIF/CIF
+Name: Nombre
+Social name: Razon social
+Town/City: Ciudad
+Postcode: Código postal
+Email: Correo electrónico
+Phone: Teléfono
\ No newline at end of file
diff --git a/client/route/src/search-panel/search-panel.html b/client/route/src/search-panel/search-panel.html
new file mode 100644
index 000000000..3661a2c5f
--- /dev/null
+++ b/client/route/src/search-panel/search-panel.html
@@ -0,0 +1,21 @@
+
+
+
diff --git a/client/route/src/search-panel/search-panel.js b/client/route/src/search-panel/search-panel.js
new file mode 100644
index 000000000..c1b79d5de
--- /dev/null
+++ b/client/route/src/search-panel/search-panel.js
@@ -0,0 +1,27 @@
+import ngModule from '../module';
+
+export default class Controller {
+ constructor($window) {
+ this.$window = $window;
+ // onSubmit() is defined by @vnSearchbar
+ this.onSubmit = () => {};
+ }
+ onSearch() {
+ this.setStorageValue();
+ this.onSubmit(this.filter);
+ }
+ $onChanges() {
+ var value = JSON.parse(this.$window.sessionStorage.getItem('filter'));
+ if (value !== undefined)
+ this.filter = value;
+ }
+ setStorageValue() {
+ this.$window.sessionStorage.setItem('filter', JSON.stringify(this.filter));
+ }
+}
+Controller.$inject = ['$window'];
+
+ngModule.component('vnRouteSearchPanel', {
+ template: require('./search-panel.html'),
+ controller: Controller
+});
diff --git a/client/route/src/tickets/tickets.html b/client/route/src/tickets/tickets.html
new file mode 100644
index 000000000..e78e9ab70
--- /dev/null
+++ b/client/route/src/tickets/tickets.html
@@ -0,0 +1,7 @@
+
+
+
+ Assigned tickets
+
+
+
\ No newline at end of file
diff --git a/client/route/src/tickets/tickets.js b/client/route/src/tickets/tickets.js
new file mode 100644
index 000000000..2405d5d9e
--- /dev/null
+++ b/client/route/src/tickets/tickets.js
@@ -0,0 +1,8 @@
+import ngModule from '../module';
+
+ngModule.component('vnRouteTickets', {
+ template: require('./tickets.html'),
+ bindings: {
+ route: '<'
+ }
+});
diff --git a/client/salix/index.js b/client/salix/index.js
index 86286a300..14e899cd0 100644
--- a/client/salix/index.js
+++ b/client/salix/index.js
@@ -1 +1 @@
-export * from './src/app';
+export * from './src/salix';
diff --git a/client/salix/package.json b/client/salix/package.json
deleted file mode 100644
index 97df134f1..000000000
--- a/client/salix/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "@salix/salix",
- "version": "0.0.0",
- "description": "",
- "main": "index.js",
- "repository": {
- "type": "git",
- "url": "http://git.verdnatura.es:/salix"
- }
-}
diff --git a/client/salix/src/app.js b/client/salix/src/app.js
deleted file mode 100644
index 13f3f09cd..000000000
--- a/client/salix/src/app.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import './module';
-import './spliting';
-import './configroutes';
-import './config';
-import './run';
-import './components';
-import './styles/index';
-
-import {bootstrap} from './bootstrap';
-
-bootstrap();
diff --git a/client/salix/src/bootstrap.js b/client/salix/src/bootstrap.js
index 119bbd5f4..dd7a61388 100644
--- a/client/salix/src/bootstrap.js
+++ b/client/salix/src/bootstrap.js
@@ -1,5 +1,5 @@
import {ng} from 'vendor';
-import {NAME as SALIX} from './module';
+import appName from './module';
export const bootstrap = () => {
const selector = 'selector';
@@ -11,7 +11,7 @@ export const bootstrap = () => {
let _element = _script && document.querySelector(_script.getAttribute(selector));
if (!_element) {
- throw new Error("element is not defined");
+ throw new Error('Element is not defined');
}
- ng.bootstrap(_element, [SALIX]);
+ ng.bootstrap(_element, [appName]);
};
diff --git a/client/salix/src/components.js b/client/salix/src/components.js
deleted file mode 100644
index 905f67603..000000000
--- a/client/salix/src/components.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export {NAME as APP, COMPONENT as APP_COMPONENT} from './components/app/app';
-export {NAME as VN_MAINMENU, COMPONENT as VN_MAINMENU_COMPONENT} from './components/main-menu/main-menu';
-export {NAME as ACTIONS, COMPONENT as ACTIONS_COMPONENT} from './components/left-menu/actions';
-export {NAME as LEFT_MENU, COMPONENT as LEFTMENU_COMPONENT} from './components/left-menu/left-menu';
-export {NAME as MENU_ITEM, COMPONENT as MENU_ITEM_COMPONENT} from './components/left-menu/menu-item';
-export {NAME as TOPBAR, COMPONENT as TOPBAR_COMPONENT} from './components/topbar/topbar';
-export {NAME as SEARCHBAR, COMPONENT as SEARCHBAR_COMPONENT} from './components/searchbar/searchbar';
\ No newline at end of file
diff --git a/client/salix/src/components/app/app.html b/client/salix/src/components/app/app.html
index 66f85880a..adbc23575 100644
--- a/client/salix/src/components/app/app.html
+++ b/client/salix/src/components/app/app.html
@@ -1,11 +1,13 @@
-
-
+
+
+
+
-
- Push on applications menu
+
+
-
+
\ No newline at end of file
diff --git a/client/salix/src/components/app/app.js b/client/salix/src/components/app/app.js
index bf0a0aaef..2368fdef2 100644
--- a/client/salix/src/components/app/app.js
+++ b/client/salix/src/components/app/app.js
@@ -1,58 +1,18 @@
-import {module} from '../../module';
+import ngModule from '../../module';
import './style.scss';
-export const NAME = 'vnApp';
-export const COMPONENT = {
- template: require('./app.html')
-};
-module.component(NAME, COMPONENT);
-
-vnAppLogger.$inject = ['$document'];
-function vnAppLogger($document) {
- return {
- showMessage: function (message) {
- let snackbar = $document.find('vn-snackbar').controller('vnSnackbar');
- snackbar.show({message: message});
- },
- showError: function(message) {
- this.showMessage(`Error: ${message}`);
- }
+export default class App {
+ constructor($scope, vnApp) {
+ this.$ = $scope;
+ this.vnApp = vnApp;
+ }
+ $postLink() {
+ this.vnApp.snackbar = this.$.snackbar;
}
}
-module.provider('vnAppLogger', function() {this.$get = vnAppLogger;});
+App.$inject = ['$scope', 'vnApp'];
-vnAppInterceptor.$inject = ['$q', '$rootScope', 'vnAppLogger', '$translate'];
-function vnAppInterceptor($q, $rootScope, logger, $translate) {
- $rootScope.loading = false;
- return {
- request: function(config) {
- $rootScope.loading = true;
- return config;
- },
- requestError: function(rejection) {
- return $q.reject(rejection);
- },
- response: function(response) {
- switch (response.config.method) {
- case 'PUT':
- case 'POST':
- logger.showMessage($translate.instant('Data saved!'));
- }
- $rootScope.loading = false;
- return response;
- },
- responseError: function(rejection) {
- $rootScope.loading = false;
- let message = rejection.data.error.message;
- logger.showError(message);
- return $q.reject(rejection);
- }
- };
-}
-module.factory('vnAppInterceptor', vnAppInterceptor);
-
-interceptorConfig.$inject = ['$httpProvider'];
-function interceptorConfig($httpProvider) {
- $httpProvider.interceptors.push('vnAppInterceptor');
-}
-module.config(interceptorConfig);
+ngModule.component('vnApp', {
+ template: require('./app.html'),
+ controller: App
+});
diff --git a/client/salix/src/components/app/style.scss b/client/salix/src/components/app/style.scss
index 3fa9c4840..fabe3dcca 100644
--- a/client/salix/src/components/app/style.scss
+++ b/client/salix/src/components/app/style.scss
@@ -7,16 +7,14 @@ vn-app {
height: 100%;
vn-topbar {
- overflow: hidden;
-
.logo {
float: left;
- height: 30px;
+ height: 1.8em;
padding: 1em;
}
vn-spinner {
float: left;
- padding: .9em;
+ padding: .4em;
}
}
.main-view {
@@ -24,10 +22,5 @@ vn-app {
height: 100%;
overflow: auto;
}
- & > .default {
- text-align: center;
- font-size: 1.3em;
- padding: 2em;
- }
}
}
diff --git a/client/salix/src/components/home/home.html b/client/salix/src/components/home/home.html
new file mode 100644
index 000000000..df6699a79
--- /dev/null
+++ b/client/salix/src/components/home/home.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/salix/src/components/home/home.js b/client/salix/src/components/home/home.js
new file mode 100644
index 000000000..d24fc4eaf
--- /dev/null
+++ b/client/salix/src/components/home/home.js
@@ -0,0 +1,15 @@
+import ngModule from '../../module';
+import './style.scss';
+
+export default class Home {
+ constructor(modulesFactory, $state) {
+ this.modules = modulesFactory.getModules();
+ this.state = $state;
+ }
+}
+Home.$inject = ['modulesFactory', '$state'];
+
+ngModule.component('vnHome', {
+ template: require('./home.html'),
+ controller: Home
+});
diff --git a/client/salix/src/components/home/style.scss b/client/salix/src/components/home/style.scss
new file mode 100644
index 000000000..b35c1a1c7
--- /dev/null
+++ b/client/salix/src/components/home/style.scss
@@ -0,0 +1,59 @@
+vn-home {
+ padding: 2em;
+ vn-horizontal{
+ margin-bottom: 15px;
+ }
+ h6{
+ color: #3C393B;
+ text-align: center;
+ }
+ a:link{
+ text-decoration: none;
+ }
+ vn-module-container{
+ display: flex;
+ flex: 1;
+ flex-direction: row;
+ justify-content: center;
+
+ .vn-module{
+ display: flex;
+ flex: none;
+ margin: 10px;
+ background-color: #FF9300;
+ color: white;
+
+ overflow:hidden;
+ -moz-border-radius: 6px;
+ -webkit-border-radius: 6px;
+ border-radius: 6px;
+
+ .home__icon{
+ width: 150px;
+ height: 150px;
+ img {
+ max-width: 50%;
+ margin-top: 20px;
+ }
+ }
+ h4{
+ text-transform: capitalize;
+ font-size: 16pt;
+ }
+ vn-one{
+ text-align: center;
+ }
+
+ i{
+ font-size: 75px !important;
+ margin: 0 auto;
+ padding-top: 15px;
+ }
+ &:hover{
+ opacity: 0.7;
+ }
+
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/salix/src/components/index.js b/client/salix/src/components/index.js
new file mode 100644
index 000000000..a2346bd91
--- /dev/null
+++ b/client/salix/src/components/index.js
@@ -0,0 +1,8 @@
+import './app/app';
+import './home/home';
+import './main-menu/main-menu';
+import './left-menu/actions';
+import './left-menu/left-menu';
+import './left-menu/menu-item';
+import './topbar/topbar';
+import './searchbar/searchbar';
diff --git a/client/salix/src/components/left-menu/actions.html b/client/salix/src/components/left-menu/actions.html
index b794c7faa..35fa96d32 100644
--- a/client/salix/src/components/left-menu/actions.html
+++ b/client/salix/src/components/left-menu/actions.html
@@ -1,5 +1,5 @@
-
diff --git a/client/salix/src/components/left-menu/actions.js b/client/salix/src/components/left-menu/actions.js
index a477eb0a3..30d379df1 100644
--- a/client/salix/src/components/left-menu/actions.js
+++ b/client/salix/src/components/left-menu/actions.js
@@ -1,12 +1,34 @@
-import template from './actions.html';
-import {module} from '../../module';
+import ngModule from '../../module';
-export const NAME = 'vnActions';
-export const COMPONENT = {
- template: template,
- controllerAs: "action",
+export default class MenuActions {
+ constructor($state, $transitions) {
+ this.$state = $state;
+ this.deregisterCallback = $transitions.onSuccess({},
+ transition => this.switchItem());
+ }
+ switchItem() {
+ if (!this.items || !this.items.length) return;
+
+ let stateName = this.$state.current.name.replace('.create', '.list').replace('.edit', '.list');
+
+ for (let i = 0; i < this.items.length; i++) {
+ this.items[i].active = (this.items[i].href === stateName);
+ }
+ }
+ $onInit() {
+ this.switchItem();
+ }
+ $onDestroy() {
+ this.deregisterCallback();
+ }
+
+}
+MenuActions.$inject = ['$state', '$transitions'];
+
+ngModule.component('vnActions', {
+ template: require('./actions.html'),
+ controller: MenuActions,
bindings: {
items: '<'
}
-};
-module.component(NAME, COMPONENT);
+});
diff --git a/client/salix/src/components/left-menu/left-menu.html b/client/salix/src/components/left-menu/left-menu.html
index faf6a7414..af7ffa922 100644
--- a/client/salix/src/components/left-menu/left-menu.html
+++ b/client/salix/src/components/left-menu/left-menu.html
@@ -1,5 +1,5 @@
-
+
diff --git a/client/salix/src/components/left-menu/left-menu.js b/client/salix/src/components/left-menu/left-menu.js
index e3dde0579..0426b74c9 100644
--- a/client/salix/src/components/left-menu/left-menu.js
+++ b/client/salix/src/components/left-menu/left-menu.js
@@ -1,13 +1,30 @@
-import {module} from '../../module';
-import template from './left-menu.html';
-import './style.css';
+import ngModule from '../../module';
+import './style.scss';
-export const NAME = 'vnLeftMenu';
-export const COMPONENT = {
- template: template,
- controllerAs: "menu",
- bindings: {
- items: '<'
+export default class LeftMenu {
+ constructor(aclService, $state) {
+ this.aclService = aclService;
+ this.$state = $state;
+ this.items = [];
+ this.init();
}
-};
-module.component(NAME, COMPONENT);
+ init() {
+ let routes = this.$state.current.data.routes || [];
+ if (routes.length) {
+ routes.forEach(i => {
+ if (i.menu && this.aclService.routeHasPermission(i))
+ this.items.push({
+ description: i.menu.description,
+ icon: i.menu.icon,
+ href: i.state
+ });
+ });
+ }
+ }
+}
+LeftMenu.$inject = ['aclService', '$state'];
+
+ngModule.component('vnLeftMenu', {
+ template: require('./left-menu.html'),
+ controller: LeftMenu
+});
diff --git a/client/salix/src/components/left-menu/menu-item.html b/client/salix/src/components/left-menu/menu-item.html
index 5bffa626d..43a6f68b0 100644
--- a/client/salix/src/components/left-menu/menu-item.html
+++ b/client/salix/src/components/left-menu/menu-item.html
@@ -1,7 +1,9 @@
-
-
- keyboard_arrow_right
- {{menu.item.icon}}
- {{menu.item.description}}
+
+
+
+
+ {{::$ctrl.item.description}}
\ No newline at end of file
diff --git a/client/salix/src/components/left-menu/menu-item.js b/client/salix/src/components/left-menu/menu-item.js
index cff33357c..f6c93c2da 100644
--- a/client/salix/src/components/left-menu/menu-item.js
+++ b/client/salix/src/components/left-menu/menu-item.js
@@ -1,11 +1,8 @@
-import {module} from '../../module';
+import ngModule from '../../module';
-export const NAME = 'vnMenuItem';
-export const COMPONENT = {
+ngModule.component('vnMenuItem', {
template: require('./menu-item.html'),
- controllerAs: 'menu',
bindings: {
item: '<'
}
-};
-module.component(NAME, COMPONENT);
+});
diff --git a/client/salix/src/components/left-menu/style.css b/client/salix/src/components/left-menu/style.css
deleted file mode 100644
index 31f3d8578..000000000
--- a/client/salix/src/components/left-menu/style.css
+++ /dev/null
@@ -1,4 +0,0 @@
-vn-menu-item a:hover {
- color: white !important;
- background-color: #424242;
-}
diff --git a/client/salix/src/components/left-menu/style.scss b/client/salix/src/components/left-menu/style.scss
new file mode 100644
index 000000000..c14fd797e
--- /dev/null
+++ b/client/salix/src/components/left-menu/style.scss
@@ -0,0 +1,7 @@
+
+vn-menu-item {
+ & > li.active {
+ background-color: #424242;
+ color: white;
+ }
+}
diff --git a/client/salix/src/components/main-menu/main-menu.html b/client/salix/src/components/main-menu/main-menu.html
index d3228f755..33703f371 100644
--- a/client/salix/src/components/main-menu/main-menu.html
+++ b/client/salix/src/components/main-menu/main-menu.html
@@ -1,19 +1,48 @@
-
+
+
{{currentUserName}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/salix/src/components/main-menu/main-menu.js b/client/salix/src/components/main-menu/main-menu.js
index 29b9a1fb4..33992ce1b 100644
--- a/client/salix/src/components/main-menu/main-menu.js
+++ b/client/salix/src/components/main-menu/main-menu.js
@@ -1,24 +1,35 @@
+import ngModule from '../../module';
import './style.scss';
-import {module} from '../../module';
-export const NAME = 'vnMainMenu';
-export const COMPONENT = {
+export default class MainMenu {
+ constructor($translate, $scope, $http, $window, modulesFactory) {
+ this.$ = $scope;
+ this.$http = $http;
+ this.$translate = $translate;
+ this.$window = $window;
+ this.modules = modulesFactory.getModules();
+ this.langs = $translate.getAvailableLanguageKeys();
+ }
+ getCurrentUserName() {
+ this.$http.get('/auth/api/Accounts/getCurrentUserName')
+ .then(json => {
+ this.$.currentUserName = json.data;
+ });
+ }
+
+ onLogoutClick() {
+ this.$window.location = '/logout';
+ }
+ onChangeLangClick(lang) {
+ this.$translate.use(lang);
+ }
+ $onInit() {
+ this.getCurrentUserName();
+ }
+}
+MainMenu.$inject = ['$translate', '$scope', '$http', '$window', 'modulesFactory'];
+
+ngModule.component('vnMainMenu', {
template: require('./main-menu.html'),
- controllerAs: "mainMenu",
- controller: controller
-};
-module.component(NAME, COMPONENT);
-
-controller.$inject = ['$translate'];
-function controller($translate, $translatePartialLoader) {
- this.onLogoutClick = function() {
- let appName = 'salix';
- document.cookie = `${appName}-session=; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
- window.location = `/auth?api_key=${appName}`;
- };
- this.onChangeLanguage = function() {
- let lang = $translate.use() == 'en' ? 'es' : 'en';
- $translate.use(lang);
- console.log (`Locale changed: ${lang}`);
- };
-}
\ No newline at end of file
+ controller: MainMenu
+});
diff --git a/client/salix/src/components/main-menu/style.scss b/client/salix/src/components/main-menu/style.scss
index 55dccc462..264d518f2 100644
--- a/client/salix/src/components/main-menu/style.scss
+++ b/client/salix/src/components/main-menu/style.scss
@@ -1,13 +1,43 @@
vn-main-menu {
- vn-icon {
- padding: .1em;
- border-radius: .1em;
+ #user {
+ display: inline-block;
+ padding-right: 0.2em;
+ margin-bottom: 8px;
+ height: 2.5em;
vertical-align: middle;
- font-size: 24px;
+ }
+ & > div > vn-icon {
+ font-size: 2.2em;
+ cursor: pointer;
&:hover {
+ color: #FF9300;
+ }
+ }
+ .vn-popover ul {
+ list-style-type: none;
+ margin: 0;
+ color: white;
+
+ li {
+ background-color: #FF9300;
+ margin-bottom: .6em;
cursor: pointer;
- opacity: .85;
+ padding: .8em;
+ border-radius: .1em;
+ min-width: 8em;
+
+ & > vn-icon {
+ padding-right: .3em;
+ vertical-align: middle;
+ }
+ &:hover {
+ background-color: #FF9300;
+ opacity: 0.7 !important;
+ }
+ &:last-child {
+ margin-bottom: 0;
+ }
}
}
}
\ No newline at end of file
diff --git a/client/salix/src/components/searchbar/searchbar.html b/client/salix/src/components/searchbar/searchbar.html
index 50ccac05d..e54a00ccd 100644
--- a/client/salix/src/components/searchbar/searchbar.html
+++ b/client/salix/src/components/searchbar/searchbar.html
@@ -1,12 +1,14 @@
\ No newline at end of file
diff --git a/client/salix/src/components/searchbar/searchbar.js b/client/salix/src/components/searchbar/searchbar.js
index 246d15cfc..324ddf5a4 100644
--- a/client/salix/src/components/searchbar/searchbar.js
+++ b/client/salix/src/components/searchbar/searchbar.js
@@ -1,50 +1,161 @@
-import {module} from '../../module';
-require('./style.css');
+import ngModule from '../../module';
-class Controller {
- constructor($element, $scope, $document, $compile, vnPopover, $window) {
+export default class Controller {
+ constructor($element, $scope, $document, $compile, vnPopover, $timeout, $state, $transitions) {
this.element = $element[0];
this.$scope = $scope;
this.$document = $document;
this.$compile = $compile;
this.vnPopover = vnPopover;
- this.$window = $window;
+ this.$timeout = $timeout;
+ this.stringSearch = '';
+ this.$state = $state;
+ this.deregisterCallback = $transitions.onStart({},
+ transition => this.changeState(transition));
}
- onClick(event) {
- var child = this.$document[0].createElement(this.popover);
- this.$compile(child)(this.$scope);
- this.vnPopover.show(child, this.element);
+
+ clearFilter() {
+ this.index.filter = {
+ page: 1,
+ size: 20
+ };
+ }
+
+ setFilter(filterObject) {
+ this.clearFilter();
+ Object.assign(this.index.filter, filterObject);
+ }
+
+ getFiltersFromString(stringSearch) {
+ let result = {};
+ if (stringSearch) {
+ // find pattern key:value or key:(extra value) and returns array
+ let findPattern = stringSearch.match(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi);
+ let remnantString = (stringSearch.replace(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi, '')).trim();
+ if (findPattern) {
+ for (let i = 0; i < findPattern.length; i++) {
+ let aux = findPattern[i].split(':');
+ let property = aux[0];
+ let value = aux[1].replace(/\(|\)/g, '');
+ result[property] = value.trim();
+ }
+ }
+ if (remnantString) {
+ result.search = remnantString;
+ }
+ }
+ return result;
+ }
+
+ createStringFromObject(filterObject) {
+ let search = [];
+ let keys = Object.keys(filterObject);
+ if (keys.length) {
+ keys.forEach(k => {
+ let ignore = (this.ignoreKeys && this.ignoreKeys instanceof Array && this.ignoreKeys.indexOf(k) !== -1);
+ if (!ignore) {
+ let value = filterObject[k];
+
+ if (typeof value === 'string' && value.indexOf(' ') !== -1) {
+ search.push(`${k}:(${value})`);
+ } else if (typeof value !== 'object') {
+ search.push(`${k}:${value}`);
+ }
+ }
+ });
+
+ if (filterObject.search)
+ search.unshift(filterObject.search);
+ }
+ return (search.length) ? search.join(' ') : '';
+ }
+
+ changeState(transition) {
+ return !(transition._targetState._identifier.name === this.$state.current.name);
+ }
+
+ pushFiltersToState(filters) {
+ let history = window.history || {pushState: () => {
+ console.error('Error in history.pushState(): Browser incompatibility error');
+ }};
+ let aux = window.location.hash.split('?q=');
+ if (Object.keys(filters).length)
+ history.pushState({}, null, `${aux[0]}?q=${encodeURIComponent(JSON.stringify(filters))}`);
+ else
+ history.pushState({}, null, aux[0]);
+ }
+
+ onpenFilters(event) {
+ let filter = {};
+ if (this.stringSearch) {
+ filter = this.getFiltersFromString(this.stringSearch);
+ }
+
+ this.child = this.vnPopover.showComponent(this.popover, this.$scope, this.element);
// XXX: ¿Existe una forma más adecuada de acceder al controlador de un componente?
- var childCtrl = angular.element(child).isolateScope().$ctrl;
- childCtrl.onSubmit = (filter) => this.onChildSubmit(filter);
-
+ var childCtrl = angular.element(this.child).isolateScope().$ctrl;
+ childCtrl.filter = Object.assign({}, filter);
+ childCtrl.onSubmit = filter => this.onChildSubmit(filter);
+ if (this.data)
+ childCtrl.data = Object.assign({}, this.data);
event.preventDefault();
}
+
onChildSubmit(filter) {
- this.vnPopover.hide();
- this.index.filter = filter;
- this.onSubmit();
+ this.stringSearch = this.createStringFromObject(filter);
+ this.clearFilter();
+ this.$timeout(() => {
+ this.onSubmit();
+ });
}
+
onSubmit() {
+ let filter = {};
+ if (this.stringSearch) {
+ filter = this.getFiltersFromString(this.stringSearch);
+ }
+ this.setFilter(filter);
+
if (this.onSearch)
this.onSearch();
+
+ if (angular.element(this.child)) {
+ if (angular.element(this.child).scope())
+ angular.element(this.child).scope().$destroy();
+ angular.element(this.child).remove();
+ }
+ delete this.child;
+ this.pushFiltersToState(filter);
}
+
$onDestroy() {
- this.$window.sessionStorage.removeItem('filter');
+ this.clearFilter();
+ this.deregisterCallback();
+ }
+
+ $onInit() {
+ if (this.$state.params.q) {
+ let filter = JSON.parse(decodeURIComponent(this.$state.params.q));
+ this.stringSearch = this.createStringFromObject(filter);
+ }
+ this.$timeout(() => {
+ this.onSubmit();
+ });
}
}
-Controller.$inject = ['$element', '$scope', '$document', '$compile', 'vnPopover', '$window'];
+Controller.$inject = ['$element', '$scope', '$document', '$compile', 'vnPopover', '$timeout', '$state', '$transitions'];
-export const NAME = 'vnSearchbar'
-export const COMPONENT = {
+ngModule.component('vnSearchbar', {
template: require('./searchbar.html'),
bindings: {
index: '<',
onSearch: '&',
advanced: '=',
- popover: '@'
+ popover: '@',
+ label: '@?',
+ ignoreKeys: '',
+ data: ''
},
controller: Controller
-};
-module.component(NAME, COMPONENT);
+});
diff --git a/client/salix/src/components/topbar/style.scss b/client/salix/src/components/topbar/style.scss
new file mode 100644
index 000000000..360018e01
--- /dev/null
+++ b/client/salix/src/components/topbar/style.scss
@@ -0,0 +1,6 @@
+header {
+ display: flex;
+ flex-direction: row;
+ flex: 1;
+ color: #fff;
+}
diff --git a/client/salix/src/components/topbar/topbar.html b/client/salix/src/components/topbar/topbar.html
index 1db5913ae..0a0498ca6 100644
--- a/client/salix/src/components/topbar/topbar.html
+++ b/client/salix/src/components/topbar/topbar.html
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/client/salix/src/components/topbar/topbar.js b/client/salix/src/components/topbar/topbar.js
index 72e676587..583354ad1 100644
--- a/client/salix/src/components/topbar/topbar.js
+++ b/client/salix/src/components/topbar/topbar.js
@@ -1,8 +1,7 @@
-import {module} from '../../module';
+import ngModule from '../../module';
+import './style.scss';
-export const NAME = 'vnTopbar';
-export const COMPONENT = {
+ngModule.component('vnTopbar', {
template: require('./topbar.html'),
transclude: true
-};
-module.component(NAME, COMPONENT);
+});
diff --git a/client/salix/src/config-routes.js b/client/salix/src/config-routes.js
new file mode 100644
index 000000000..4f3652ced
--- /dev/null
+++ b/client/salix/src/config-routes.js
@@ -0,0 +1,75 @@
+import ngModule from './module';
+import deps from 'client/modules.yml';
+import modules from 'client/spliting';
+import splitingRegister from 'core/src/lib/spliting-register';
+
+function loader(moduleName, validations) {
+ load.$inject = ['vnModuleLoader'];
+ function load(moduleLoader) {
+ return moduleLoader.load(moduleName, validations);
+ }
+ return load;
+}
+
+config.$inject = ['$stateProvider', '$urlRouterProvider', 'aclServiceProvider', 'modulesFactoryProvider'];
+function config($stateProvider, $urlRouterProvider, aclServiceProvider, modulesFactory) {
+ splitingRegister.graph = deps;
+ splitingRegister.modules = modules;
+
+ let aclService = aclServiceProvider.$get();
+
+ function getParams(route) {
+ let params = '';
+ let temporalParams = [];
+
+ if (!route.params) {
+ return params;
+ }
+
+ Object.keys(route.params).forEach(key => {
+ temporalParams.push(`${key} = "${route.params[key]}"`);
+ });
+ return temporalParams.join(' ');
+ }
+
+ $urlRouterProvider.otherwise('/');
+
+ $stateProvider.state('home', {
+ url: '/',
+ template: ''
+ });
+
+ for (let file in window.routes) {
+ let fileRoutes = window.routes[file].routes;
+ let moduleName = window.routes[file].module;
+ let validations = window.routes[file].validations || false;
+ let mainModule = modulesFactory.$get().getMainRoute(fileRoutes);
+ if (mainModule) {
+ let count = fileRoutes.length;
+ for (let i = 0; i < count; i++) {
+ let route = fileRoutes[i];
+ if (aclService.routeHasPermission(route)) {
+ let configRoute = {
+ url: route.url,
+ template: `<${route.component} ${getParams(route)}>${route.component}>`,
+ resolve: {
+ loader: loader(moduleName, validations)
+ },
+ data: {
+ routes: fileRoutes
+ }
+ };
+ if (route.abstract)
+ configRoute.abstract = true;
+ if (route.routeParams)
+ configRoute.params = route.routeParams;
+
+ $stateProvider.state(route.state, configRoute);
+ } else if (route.state === mainModule.state) {
+ break;
+ }
+ }
+ }
+ }
+}
+ngModule.config(config);
diff --git a/client/salix/src/config.js b/client/salix/src/config.js
deleted file mode 100644
index f5fb50527..000000000
--- a/client/salix/src/config.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import {module} from './module';
-
-config.$inject = ['$translatePartialLoaderProvider'];
-export function config($translatePartialLoaderProvider) {
- $translatePartialLoaderProvider.addPart('salix');
-}
-module.config(config);
-
-run.$inject = ['$window', '$rootScope'];
-export function run($window, $rootScope) {
- $window.validations = {};
-}
-module.run(run);
diff --git a/client/salix/src/configroutes.js b/client/salix/src/configroutes.js
deleted file mode 100644
index 795ef0aba..000000000
--- a/client/salix/src/configroutes.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import './spliting';
-import deps from 'spliting/modules.json';
-import {module} from './module';
-import {splitingRegister} from 'core';
-
-function loader(moduleName) {
- load.$inject = ['vnModuleLoader'];
- function load(moduleLoader) {
- return moduleLoader.load(moduleName);
- }
- return load;
-}
-
-config.$inject = ['$stateProvider', '$urlRouterProvider'];
-function config($stateProvider, $urlRouterProvider) {
- splitingRegister.registerGraph(deps);
-
- function getParams(route) {
- let params = '';
- let temporalParams = [];
-
- if (!route.params) {
- return params;
- }
-
- Object.keys(route.params).forEach(key => {
- temporalParams.push(`${key} = "${route.params[key]}"`);
- });
- return temporalParams.join(' ');
- }
-
- for (let file in routes) {
- let fileRoutes = routes[file].routes;
- let moduleName = routes[file].module;
-
- fileRoutes.forEach(function(route) {
- $stateProvider.state(route.state, {
- url: route.url,
- template: `<${route.component} ${getParams(route)}>${route.component}>`,
- resolve: {
- loader: loader(moduleName)
- }
- });
- });
- }
-}
-module.config(config);
diff --git a/client/salix/src/locale/en.json b/client/salix/src/locale/en.json
deleted file mode 100644
index 8b8e23ed6..000000000
--- a/client/salix/src/locale/en.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "Applications": "Applications",
- "Notifications":"Notifications",
- "Logout": "Logout",
- "Change language": "Change language",
- "Profile": "Profile",
- "Data saved!": "Data saved!",
- "Push on applications menu": "To open a module push on applications menu"
-}
\ No newline at end of file
diff --git a/client/salix/src/locale/en.yml b/client/salix/src/locale/en.yml
new file mode 100644
index 000000000..fbae9a742
--- /dev/null
+++ b/client/salix/src/locale/en.yml
@@ -0,0 +1,11 @@
+Applications: Applications
+Home: Home
+Notifications: Notifications
+Logout: Logout
+Change language: Change language
+Profile: Profile
+Data saved!: Data saved!
+Can't contact with server: Can't contact with server
+Push on applications menu: To open a module push on applications menu
+Clients: Clients
+Modules access: Modules access
\ No newline at end of file
diff --git a/client/salix/src/locale/es.json b/client/salix/src/locale/es.json
deleted file mode 100644
index 55e5dbab3..000000000
--- a/client/salix/src/locale/es.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "Applications": "Aplicaciones",
- "Notifications":"Notificaciones",
- "Logout": "Cerrar sesión",
- "Change language": "Cambiar idioma",
- "Profile": "Perfil",
- "Data saved!": "¡Datos guardados!",
- "Push on applications menu": "Para abrir un módulo pulsa en el menú de aplicaciones"
-}
\ No newline at end of file
diff --git a/client/salix/src/locale/es.yml b/client/salix/src/locale/es.yml
new file mode 100644
index 000000000..fe3cdf228
--- /dev/null
+++ b/client/salix/src/locale/es.yml
@@ -0,0 +1,21 @@
+Applications: Aplicaciones
+Home: Inicio
+Notifications: Notificaciones
+Logout: Cerrar sesión
+Change language: Cambiar idioma
+Profile: Perfil
+Data saved!: ¡Datos guardados!
+Can't contact with server: No se pudo contactar con el servidor
+Push on applications menu: Para abrir un módulo pulsa en el menú de aplicaciones
+Clients: Clientes
+Routes : Rutas
+Production : Producción
+Modules access : Acceso a módulos
+Locator: Localizador
+Items: Artículos
+name: Nombre
+credit: Crédito
+phone: Teléfono
+creditInsurance: Crédito Asegurado
+Return to module index: Volver a la página principal del módulo
+Preview: Vista previa
\ No newline at end of file
diff --git a/client/salix/src/module.js b/client/salix/src/module.js
index 99dbd0b5c..c0c539f3b 100644
--- a/client/salix/src/module.js
+++ b/client/salix/src/module.js
@@ -1,6 +1,33 @@
-import * as vendors from 'vendor';
-import * as core from 'core';
-import {NAME as CORE} from 'core';
+import {ng} from 'vendor';
+import 'core';
-export const NAME = 'salix';
-export const module = vendors.ng.module(NAME, [CORE]);
+export const appName = 'salix';
+
+const ngModule = ng.module('salix', ['vnCore']);
+export default ngModule;
+
+config.$inject = ['$translatePartialLoaderProvider', '$httpProvider', '$qProvider'];
+export function config($translatePartialLoaderProvider, $httpProvider, $qProvider) {
+ $translatePartialLoaderProvider.addPart(appName);
+ $httpProvider.interceptors.push('vnInterceptor');
+
+ // TODO: Handle or remove unhandled rejections
+ // $qProvider.errorOnUnhandledRejections(false);
+}
+ngModule.config(config);
+
+const HOOK_ABORTED_TRANSITION = 3;
+
+run.$inject = ['$window', '$rootScope', 'vnApp', '$state'];
+export function run($window, $rootScope, vnApp, $state) {
+ $window.validations = {};
+ vnApp.name = appName;
+
+ $rootScope.$on('$viewContentLoaded', () => {});
+ window.myAppErrorLog = [];
+ $state.defaultErrorHandler(function(error) {
+ if (error.type === HOOK_ABORTED_TRANSITION)
+ window.myAppErrorLog.push(error);
+ });
+}
+ngModule.run(run);
diff --git a/client/salix/src/modules-factory.js b/client/salix/src/modules-factory.js
new file mode 100644
index 000000000..02c3e845c
--- /dev/null
+++ b/client/salix/src/modules-factory.js
@@ -0,0 +1,37 @@
+import ngModule from './module';
+
+function modulesFactory(aclService) {
+ function getMainRoute(routeCollection) {
+ let cant = routeCollection.length;
+ for (let i = 0; i < cant; i++) {
+ if (!routeCollection[i].abstract) {
+ return routeCollection[i];
+ }
+ }
+ return null;
+ }
+
+ function getModules() {
+ let modules = [];
+ for (let file in window.routes) {
+ let card = {
+ name: routes[file].name || routes[file].module,
+ icon: routes[file].icon || ''
+ };
+ let mainRoute = getMainRoute(window.routes[file].routes);
+ if (mainRoute && aclService.routeHasPermission(mainRoute)) {
+ card.route = mainRoute;
+ modules.push(card);
+ }
+ }
+ return modules;
+ }
+
+ return {
+ getModules: getModules,
+ getMainRoute: getMainRoute
+ };
+}
+modulesFactory.$inject = ['aclService'];
+
+ngModule.factory('modulesFactory', modulesFactory);
diff --git a/client/salix/src/run.js b/client/salix/src/run.js
deleted file mode 100644
index 290b62683..000000000
--- a/client/salix/src/run.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import {module} from './module';
-
-const HOOK_ABORTED_TRANSITION = 3;
-
-run.$inject = ['$rootScope', '$state'];
-export function run($rootScope, $state) {
- $rootScope.$on('$viewContentLoaded', () => {});
- window.myAppErrorLog = [];
- $state.defaultErrorHandler(function(error) {
- if (error.type === HOOK_ABORTED_TRANSITION)
- window.myAppErrorLog.push(error);
- });
-}
-module.run(run);
diff --git a/client/salix/src/salix.js b/client/salix/src/salix.js
new file mode 100644
index 000000000..88ff6e001
--- /dev/null
+++ b/client/salix/src/salix.js
@@ -0,0 +1,5 @@
+import './module';
+import './config-routes';
+import './components/index';
+import './styles/index';
+import './modules-factory';
diff --git a/client/salix/src/styles/background.scss b/client/salix/src/styles/background.scss
index 478181070..b3a7ec7f2 100644
--- a/client/salix/src/styles/background.scss
+++ b/client/salix/src/styles/background.scss
@@ -26,11 +26,11 @@ html [bg-dark-menu], .bg-dark-menu {
background-color: darken($bg-dark-menu, 35%);
}
/* Color para items seleccionados */
-.bg-dark-item{
+.bg-dark-item {
background-color: $bg-dark-bar;
color: $color-white;
}
/* Color para items inactivos */
-.bg-opacity-item{
+.bg-opacity-item {
opacity: 0.6;
}
diff --git a/client/salix/src/styles/border.scss b/client/salix/src/styles/border.scss
index 3eb08176d..bd046c559 100644
--- a/client/salix/src/styles/border.scss
+++ b/client/salix/src/styles/border.scss
@@ -1,45 +1,51 @@
-@import "colors";
-
-$border-color: #AAA;
-$border-thin: 1px;
-$border-thick: 2px;
-
-html [border-none], .border-none {
- border: 0;
-}
-
-/* Solid border */
-
-html [border-solid], .border-solid {
- border: $border-thin solid $border-color;
-}
-html [border-solid-top], .border-solid-top {
- border-top: $border-thin solid $border-color;
-}
-html [border-solid-left], .border-solid-left {
- border-left: $border-thin solid $border-color;
-}
-html [border-solid-right], .border-solid-right {
- border-right: $border-thin solid $border-color;
-}
-html [border-solid-bottom], .border-solid-bottom {
- border-bottom: $border-thin solid $border-color;
-}
-
-/* Dashed border */
-
-html [border-dashed], .border-dashed {
- border: $border-thin dashed $border-color;
-}
-html [border-dashed-top], .border-dashed-top {
- border-top: $border-thin dashed $border-color;
-}
-html [border-dashed-left], .border-dashed-left {
- border-left: $border-thin dashed $border-color;
-}
-html [border-dashed-right], .border-dashed-right {
- border-right: $border-thin dashed $border-color;
-}
-html [border-dashed-bottom], .border-dashed-bottom {
- border-bottom: $border-thin dashed $border-color;
-}
+@import "colors";
+
+$border-color: #AAA;
+$border-thin: 1px;
+$border-thick: 2px;
+
+html [border-none], .border-none {
+ border: 0;
+}
+
+/* Solid border */
+
+html [border-solid], .border-solid {
+ border: $border-thin solid $border-color;
+}
+html [border-solid-top], .border-solid-top {
+ border-top: $border-thin solid $border-color;
+}
+html [border-solid-left], .border-solid-left {
+ border-left: $border-thin solid $border-color;
+}
+html [border-solid-right], .border-solid-right {
+ border-right: $border-thin solid $border-color;
+}
+html [border-solid-bottom], .border-solid-bottom {
+ border-bottom: $border-thin solid $border-color;
+}
+
+/* Dashed border */
+
+html [border-dashed], .border-dashed {
+ border: $border-thin dashed $border-color;
+}
+html [border-dashed-top], .border-dashed-top {
+ border-top: $border-thin dashed $border-color;
+}
+html [border-dashed-left], .border-dashed-left {
+ border-left: $border-thin dashed $border-color;
+}
+html [border-dashed-right], .border-dashed-right {
+ border-right: $border-thin dashed $border-color;
+}
+html [border-dashed-bottom], .border-dashed-bottom {
+ border-bottom: $border-thin dashed $border-color;
+}
+
+/* Border Radius */
+
+html [border-radius], .border-radius {
+ border-radius: .3em;
+}
\ No newline at end of file
diff --git a/client/salix/src/styles/colors.scss b/client/salix/src/styles/colors.scss
index 9638ac0c8..d2db195f1 100644
--- a/client/salix/src/styles/colors.scss
+++ b/client/salix/src/styles/colors.scss
@@ -4,4 +4,9 @@ $color-orange: rgb(255,171,64);
$color-white: white;
$color-dark: #3c393b;
$color-dark-grey: #424242;
-$color-light-grey: #e6e6e6;
\ No newline at end of file
+$color-light-grey: #e6e6e6;
+$color-medium-grey: #9D9D9D;
+$color-medium-green: #CCEC9E;
+$color-medium-orange: #FFD29C;
+$color-light-green: #D7F1BD;
+$color-light-orange: #FFDEBB;
\ No newline at end of file
diff --git a/client/salix/src/styles/display.css b/client/salix/src/styles/display.scss
similarity index 60%
rename from client/salix/src/styles/display.css
rename to client/salix/src/styles/display.scss
index 1e5c718cc..c296eec69 100644
--- a/client/salix/src/styles/display.css
+++ b/client/salix/src/styles/display.scss
@@ -1,6 +1,7 @@
-.display-block{
+.display-block {
display: block;
}
+
.well {
min-height: 20px;
padding: 19px;
@@ -10,20 +11,22 @@
border-radius: 4px;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
}
+
.form-group {
margin-bottom: 15px;
}
/* Label del popover */
-.popover-button{
+.popover-button {
padding: 3px 3px 3px 0px;
height: auto;
min-width: auto;
}
-.popover-label{
- font-weight: bold;
- color: black;
- padding-top:5px;
+
+.popover-label {
+ font-family: vn-font-bold;
+ color: black;
+ padding-top:5px;
}
/* Icon cuadrado */
@@ -32,3 +35,15 @@
height: 46px;
line-height: 0px;
}
+
+input:disabled, button:disabled {
+ cursor: not-allowed !important;
+}
+
+input[type="submit"]:disabled, button:disabled {
+ opacity: 0.7;
+}
+
+.descriptor-icon{
+ font-size:60px;
+}
diff --git a/client/salix/src/styles/font-family.css b/client/salix/src/styles/font-family.css
deleted file mode 100644
index 3fc6b8fcd..000000000
--- a/client/salix/src/styles/font-family.css
+++ /dev/null
@@ -1,21 +0,0 @@
-@font-face {
- font-family: raleway-italic;
- src: url(./fonts/Raleway-Italic.ttf);
-}
-@font-face {
- font-family: raleway-thin;
- src: url(./fonts/Raleway-Thin.ttf);
-}
-@font-face {
- font-family: raleway-regular;
- src: url(./fonts/Raleway-Regular.ttf);
-}
-@font-face {
- font-family: raleway-bold;
- src: url(./fonts/Raleway-Bold.ttf);
-}
-@font-face {
- font-family: raleway-semi-bold;
- src: url(./fonts/Raleway-SemiBold.ttf);
-}
-
diff --git a/client/salix/src/styles/font-family.scss b/client/salix/src/styles/font-family.scss
new file mode 100644
index 000000000..38a87a3e8
--- /dev/null
+++ b/client/salix/src/styles/font-family.scss
@@ -0,0 +1,12 @@
+@font-face {
+ font-family: vn-font-medium;
+ src: url(./fonts/Roboto-Medium.ttf);
+}
+@font-face {
+ font-family: vn-font;
+ src: url(./fonts/Roboto-Regular.ttf);
+}
+@font-face {
+ font-family: vn-font-bold;
+ src: url(./fonts/Roboto-Bold.ttf);
+}
diff --git a/client/salix/src/styles/font-style.scss b/client/salix/src/styles/font-style.scss
index fb4b055d3..bb26140ee 100644
--- a/client/salix/src/styles/font-style.scss
+++ b/client/salix/src/styles/font-style.scss
@@ -1,12 +1,24 @@
-@import "colors";
-@import "font-family";
-
-$font-color: $color-dark-grey;
-
-body {
- color: $font-color;
- font-family: raleway-regular;
-}
-html [uppercase], .uppercase {
- text-transform: uppercase;
-}
\ No newline at end of file
+@import "colors";
+@import "font-family";
+
+$font-color: $color-dark-grey;
+
+body {
+ color: $font-color;
+ font-family: vn-font;
+}
+html [uppercase], .uppercase {
+ text-transform: uppercase;
+}
+
+html [green], .green{color: $color-green}
+html [orange], .orange{color: $color-orange}
+html [white], .white{color: $color-white}
+html [dark], .dark{color: $color-dark}
+html [dark-grey], .dark-grey{color: $color-dark-grey}
+html [light-grey], .light-grey{color: $color-light-grey}
+html [medium-grey], .medium-grey{color: $color-medium-grey}
+html [medium-green], .medium-green{color: $color-medium-green}
+html [medium-orange], .medium-orange{color: $color-medium-orange}
+html [light-green], .light-green{color: $color-light-green}
+html [light-orange], .light-orange{color: $color-light-orange}
\ No newline at end of file
diff --git a/client/salix/src/styles/fonts/Raleway-Bold.ttf b/client/salix/src/styles/fonts/Raleway-Bold.ttf
deleted file mode 100755
index 38c099cc8..000000000
Binary files a/client/salix/src/styles/fonts/Raleway-Bold.ttf and /dev/null differ
diff --git a/client/salix/src/styles/fonts/Raleway-Italic.ttf b/client/salix/src/styles/fonts/Raleway-Italic.ttf
deleted file mode 100755
index 237d88d90..000000000
Binary files a/client/salix/src/styles/fonts/Raleway-Italic.ttf and /dev/null differ
diff --git a/client/salix/src/styles/fonts/Raleway-Regular.ttf b/client/salix/src/styles/fonts/Raleway-Regular.ttf
deleted file mode 100755
index e570a2d5c..000000000
Binary files a/client/salix/src/styles/fonts/Raleway-Regular.ttf and /dev/null differ
diff --git a/client/salix/src/styles/fonts/Raleway-SemiBold.ttf b/client/salix/src/styles/fonts/Raleway-SemiBold.ttf
deleted file mode 100755
index ed0a8b994..000000000
Binary files a/client/salix/src/styles/fonts/Raleway-SemiBold.ttf and /dev/null differ
diff --git a/client/salix/src/styles/fonts/Raleway-Thin.ttf b/client/salix/src/styles/fonts/Raleway-Thin.ttf
deleted file mode 100755
index a497b98a8..000000000
Binary files a/client/salix/src/styles/fonts/Raleway-Thin.ttf and /dev/null differ
diff --git a/client/salix/src/styles/fonts/Roboto-Bold.ttf b/client/salix/src/styles/fonts/Roboto-Bold.ttf
new file mode 100644
index 000000000..d3f01ad24
Binary files /dev/null and b/client/salix/src/styles/fonts/Roboto-Bold.ttf differ
diff --git a/client/salix/src/styles/fonts/Roboto-Medium.ttf b/client/salix/src/styles/fonts/Roboto-Medium.ttf
new file mode 100644
index 000000000..1a7f3b0bb
Binary files /dev/null and b/client/salix/src/styles/fonts/Roboto-Medium.ttf differ
diff --git a/client/salix/src/styles/fonts/Roboto-Regular.ttf b/client/salix/src/styles/fonts/Roboto-Regular.ttf
new file mode 100644
index 000000000..2c97eeadf
Binary files /dev/null and b/client/salix/src/styles/fonts/Roboto-Regular.ttf differ
diff --git a/client/salix/src/styles/index.js b/client/salix/src/styles/index.js
index e7dfd0622..a3e9f74a3 100644
--- a/client/salix/src/styles/index.js
+++ b/client/salix/src/styles/index.js
@@ -1,9 +1,10 @@
-import './title.css';
-import './layout.css';
-import './display.css';
+import './title.scss';
+import './layout.scss';
+import './display.scss';
import './margin.scss';
import './padding.scss';
import './background.scss';
import './border.scss';
import './font-style.scss';
import './misc.scss';
+import './summary.scss';
diff --git a/client/salix/src/styles/layout.css b/client/salix/src/styles/layout.scss
similarity index 94%
rename from client/salix/src/styles/layout.css
rename to client/salix/src/styles/layout.scss
index 1d35fd5c8..c952abe37 100644
--- a/client/salix/src/styles/layout.css
+++ b/client/salix/src/styles/layout.scss
@@ -1,110 +1,106 @@
-
-html, body {
- height: 100%;
- margin: 0px;
- padding: 0px;
-}
-
-html [full-height], .full-height {
- height: 100%;
-}
-html [self-scroll], .self-scroll {
- overflow: auto;
-}
-
-/* Horizontal & vertical */
-
-html [vn-horizontal], vn-horizontal, .vn-horizontal,
-html [vn-vertical], vn-vertical, .vn-vertical {
- display: flex;
-}
-html [vn-horizontal], vn-horizontal, .vn-horizontal {
- flex-direction: row;
-}
-vn-horizontal[reverse] {
- flex-direction: row-reverse;
-}
-html [vn-vertical], vn-vertical, .vn-vertical {
- flex-direction: column;
-}
-vn-vertical[reverse] {
- flex-direction: column-reverse;
-}
-html [wrap] {
- flex-wrap: wrap;
-}
-html [wrap-reverse] {
- flex-wrap: wrap-reverse;
-}
-html [scrollable] {
- min-height: 1px;
- flex: 1;
- flex-basis: 0.000000001px;
-}
-
-/* Horizontal & vertical childs */
-
-html [vn-auto],
-html [vn-none],
-html [vn-one],
-html [vn-two],
-html [vn-three],
-html [vn-four],
-html [vn-five],
-html [vn-six],
-html [vn-seven],
-html [vn-eight],
-html [vn-nine],
-html [vn-ten],
-html [vn-eleven],
-html [vn-twelve]{
- flex-basis: 0.000000001px;
-}
-html [vn-auto], vn-auto, .vn-auto {
- flex: 1;
- flex-basis: auto;
-}
-html [vn-empty], vn-empty, .vn-empty {
- display: block;
-}
-html [vn-none], vn-none, .vn-none {
- flex: 1;
- flex: none;
-}
-html [vn-one], vn-one, .vn-one {
- flex: 1;
-}
-html [vn-two], vn-two, .vn-two {
- flex: 2;
-}
-html [vn-three], vn-three, .vn-three {
- flex: 3;
-}
-html [vn-four], vn-four, .vn-four {
- flex: 4;
-}
-html [vn-five], vn-five, .vn-five {
- flex: 5;
-}
-html [vn-six], vn-six, .vn-six {
- flex: 6;
-}
-html [vn-seven], vn-seven, .vn-seven {
- flex: 7;
-}
-html [vn-eight], vn-eight, .vn-eight {
- flex: 8;
-}
-html [vn-nine], vn-nine, .vn-nine {
- flex: 9;
-}
-html [vn-ten], vn-ten, .vn-ten {
- flex: 10;
-}
-html [vn-eleven], vn-eleven, .vn-eleven {
- flex: 11;
-}
-html [vn-twelve], vn-twelve, .vn-twelve {
- flex: 12;
-}
-
+
+html, body {
+ height: 100%;
+ margin: 0px;
+ padding: 0px;
+}
+
+html [full-height], .full-height {
+ height: 100%;
+}
+html [self-scroll], .self-scroll {
+ overflow: auto;
+}
+
+/* Horizontal & vertical */
+
+html [vn-horizontal], vn-horizontal, .vn-horizontal,
+html [vn-vertical], vn-vertical, .vn-vertical {
+ display: flex;
+}
+html [vn-horizontal], vn-horizontal, .vn-horizontal {
+ flex-direction: row;
+}
+vn-horizontal[reverse] {
+ flex-direction: row-reverse;
+}
+html [vn-vertical], vn-vertical, .vn-vertical {
+ flex-direction: column;
+}
+vn-vertical[reverse] {
+ flex-direction: column-reverse;
+}
+html [wrap] {
+ flex-wrap: wrap;
+}
+html [wrap-reverse] {
+ flex-wrap: wrap-reverse;
+}
+html [scrollable] {
+ min-height: 1px;
+ flex: 1;
+ flex-basis: 0.000000001px;
+}
+
+/* Horizontal & vertical childs */
+
+html [vn-auto],
+html [vn-none],
+html [vn-one],
+html [vn-two],
+html [vn-three],
+html [vn-four],
+html [vn-five],
+html [vn-six],
+html [vn-seven],
+html [vn-eight],
+html [vn-nine],
+html [vn-ten],
+html [vn-eleven],
+html [vn-twelve]{
+ flex-basis: 0.000000001px;
+}
+html [vn-auto], vn-auto, .vn-auto {
+ flex-basis: auto;
+}
+html [vn-none], vn-none, .vn-none {
+ flex: 1;
+ flex: none;
+}
+html [vn-one], vn-one, .vn-one {
+ flex: 1;
+}
+html [vn-two], vn-two, .vn-two {
+ flex: 2;
+}
+html [vn-three], vn-three, .vn-three {
+ flex: 3;
+}
+html [vn-four], vn-four, .vn-four {
+ flex: 4;
+}
+html [vn-five], vn-five, .vn-five {
+ flex: 5;
+}
+html [vn-six], vn-six, .vn-six {
+ flex: 6;
+}
+html [vn-seven], vn-seven, .vn-seven {
+ flex: 7;
+}
+html [vn-eight], vn-eight, .vn-eight {
+ flex: 8;
+}
+html [vn-nine], vn-nine, .vn-nine {
+ flex: 9;
+}
+html [vn-ten], vn-ten, .vn-ten {
+ flex: 10;
+}
+html [vn-eleven], vn-eleven, .vn-eleven {
+ flex: 11;
+}
+html [vn-twelve], vn-twelve, .vn-twelve {
+ flex: 12;
+}
+
diff --git a/client/salix/src/styles/margin.scss b/client/salix/src/styles/margin.scss
index ea0baf291..800ed5e83 100644
--- a/client/salix/src/styles/margin.scss
+++ b/client/salix/src/styles/margin.scss
@@ -87,3 +87,30 @@ html [margin-large-h], .margin-large-h {
margin-left: $margin-large;
margin-right: $margin-large;
}
+
+
+/* Minus Small */
+
+html [margin--small], .margin--small {
+ margin: -$margin-small;
+}
+html [margin--small-top], .margin--small-top {
+margin-top: -$margin-small;
+}
+html [margin--small-left], .margin--small-left {
+margin-left: -$margin-small;
+}
+html [margin--small-right], .margin--small-right {
+margin-right: -$margin-small;
+}
+html [margin--small-bottom], .margin--small-bottom {
+margin-bottom: -$margin-small;
+}
+html [margin--small-v], .margin--small-v {
+margin-top: -$margin-small;
+margin-bottom: -$margin-small;
+}
+html [margin--small-h], .margin--small-h {
+margin-left: -$margin-small;
+margin-right: -$margin-small;
+}
\ No newline at end of file
diff --git a/client/salix/src/styles/misc.scss b/client/salix/src/styles/misc.scss
index 6b8523aab..e20bda7ed 100644
--- a/client/salix/src/styles/misc.scss
+++ b/client/salix/src/styles/misc.scss
@@ -1,5 +1,22 @@
@import "padding";
@import "margin";
+@import "colors";
+@import "border";
+
+
+a:focus,
+input:focus,
+button:focus
+{
+ outline: none;
+}
+button::-moz-focus-inner,
+input[type=submit]::-moz-focus-inner,
+input[type=button]::-moz-focus-inner,
+input[type=reset]::-moz-focus-inner
+{
+ border: none;
+}
.form {
height: 100%;
@@ -22,8 +39,196 @@ html [fixed-bottom-right] {
bottom: 2em;
right: 2em;
}
+html [text-center], .text-center {
+ text-align: center;
+}
+html [text-right], .text-right{
+ text-align: right;
+}
+html [text-left], .text-left{
+ text-align: left;
+}
+html [vn-right], .vn-right{
+ float: right;
+}
+html [vn-left], .vn-left{
+ float: left;
+}
+html [vn-center], .vn-center{
+ justify-content: center;
+}
+
+.list > vn-none{
+ min-width: 60px;
+}
+
+.list-element{
+ padding: 8px 0 0 0;
+ border-bottom: 1px solid $color-medium-grey;
+ i {
+ color: $color-orange;
+ }
+ &:hover{
+ background-color: $color-light-grey;
+ }
+}
+.tooltip {
+ .list-header{
+ border-bottom: 3px solid $color-medium-grey;
+ font-family: vn-font-bold;
+ text-align: center
+ }
+ .list-element{
+ white-space: nowrap;
+ }
+}
+.list-footer{
+ font-family: vn-font-bold;
+ border-top: 3px solid $color-medium-grey;
+}
+.list-element.warning{
+ background-color: $color-medium-orange;
+}
+.list-element.success{
+ background-color: $color-medium-green;
+
+}
+.list-element.success:hover{
+ background-color: $color-light-green;
+}
+.list-element.warning:hover{
+ background-color: $color-light-orange;
+}
+.flatpickr-month, .flatpickr-weekdays, span.flatpickr-weekday {
+ background-color: $color-orange;
+}
+
+html [pointer], .pointer{
+ cursor: pointer;
+}
+
+html [noDrop], .noDrop{
+ cursor: no-drop;
+}
+
+a {
+ color: inherit;
+}
+
+.vn-clickable {
+ cursor: pointer;
+ transition: background-color 250ms ease-out;
+
+ &:hover {
+ background-color: rgba(0, 0, 0, .1);
+ }
+}
+
+button {
+ @extend .vn-clickable;
+}
+
+vn-label {
+ font-size: .9em;
+ color: #666;
+}
vn-button-bar {
display: block;
margin-top: $margin-small;
-}
\ No newline at end of file
+}
+
+vn-main-block {
+ display:block;
+ max-width: 1920px;
+ width:100%;
+ margin: 0 auto;
+
+ .left-block {
+ width: 16em;
+ min-width: 16em;
+ padding-left: 1em;
+ padding-bottom: 1em;
+ }
+}
+
+.vn-descriptor {
+ .header {
+ background: #ffa410;
+ color: white;
+ justify-content: space-between;
+ align-items: stretch;
+
+ & > vn-icon {
+ padding: .1em;
+ font-size: 2.5em;
+ }
+ & > a {
+ @extend .vn-clickable;
+
+ display: flex;
+ align-items: center;
+ padding: .5em;
+ color: white;
+ text-decoration: none;
+ transition: background-color 250ms ease-out;
+
+ & > vn-icon {
+ font-size: 1.8em;
+ }
+ }
+ }
+ .footer {
+ text-align: center;
+ & > vn-icon {
+ color: #666;
+ opacity: .4;
+ padding: 0 5% 0 5%;
+ font-size: 1.5em;
+ }
+ & > vn-icon.bright {
+ color: #ffa410;
+ opacity: 1;
+ }
+ }
+}
+
+.vn-list {
+ max-width: 36em;
+ margin: 0 auto;
+}
+
+.vn-list-item {
+ @extend .pad-medium;
+ @extend .border-solid-bottom;
+ @extend .vn-clickable;
+
+ display: block;
+ text-decoration: none;
+ color: inherit;
+
+ & > vn-horizontal > .buttons {
+ align-items: center;
+
+ vn-icon {
+ opacity: .4;
+ color: #ffa410;
+ margin-left: .5em;
+ transition: opacity 250ms ease-out;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+ }
+}
+/** START - FORM ELEMENTS DISABLED **/
+fieldset[disabled] .mdl-textfield .mdl-textfield__input, .mdl-textfield.is-disabled .mdl-textfield__input,
+fieldset[disabled] .mdl-checkbox .mdl-checkbox__label, .mdl-checkbox.is-disabled .mdl-checkbox__label{
+ border: none !important;
+ color: inherit !important;
+}
+fieldset[disabled] .mdl-textfield .mdl-textfield__label, .mdl-textfield.is-disabled.is-disabled .mdl-textfield__label {
+ color: rgb(255,171,64) !important;
+}
+/** END - FORM ELEMENTS DISABLED **/
\ No newline at end of file
diff --git a/client/salix/src/styles/summary.scss b/client/salix/src/styles/summary.scss
new file mode 100644
index 000000000..9f1be4662
--- /dev/null
+++ b/client/salix/src/styles/summary.scss
@@ -0,0 +1,65 @@
+@import "./colors";
+
+.summary{
+ h5 {
+ border-bottom: 2px solid $color-orange;
+ margin: 0 0 5px 0
+ }
+ h5.tittle {
+ border: none;
+ background: $color-orange;
+ color: $color-white;
+ }
+ p {
+ margin: 0 0 5px 0
+ }
+ p:after {
+ content: ' ';
+ overflow: hidden;
+ display: block;
+ clear: both
+ }
+}
+
+.vn-dialog.dialog-summary {
+ vn-card {
+ border: none;
+ box-shadow: none;
+ }
+
+ vn-vertical {
+ padding: 0 !important
+ }
+
+ & > div > button.close > vn-icon {
+ color: $color-orange;
+ }
+
+ & > div {
+ padding: 0
+ }
+
+ tpl-body {
+ width:auto;
+ background-color: transparent;
+ padding: 0 2em
+ }
+
+ .body {
+ overflow: auto;
+ margin-top: 2em;
+ max-height: 700px;
+ }
+
+ form {
+ min-width: 680px;
+ }
+
+ .buttons {
+ margin: 0
+ }
+
+ vn-check label span {
+ font-size: .9em
+ }
+}
\ No newline at end of file
diff --git a/client/salix/src/styles/title.css b/client/salix/src/styles/title.scss
similarity index 67%
rename from client/salix/src/styles/title.css
rename to client/salix/src/styles/title.scss
index 4589f0b9c..c32735686 100644
--- a/client/salix/src/styles/title.css
+++ b/client/salix/src/styles/title.scss
@@ -1,25 +1,26 @@
-
-h1 {
- font-size: 32pt;
-}
-h2 {
- font-size: 28pt;
-}
-h3 {
- font-size: 24pt;
-}
-h4 {
- font-size: 20pt;
-}
-h5 {
- font-size: 16pt;
-}
-h6 {
- font-size: 12pt;
-}
-
-h1, h2, h3, h4, h5, h6 {
- padding: 0;
- margin: .4em 0;
- font-family: raleway-semi-bold;
+
+h1 {
+ font-size: 32pt;
+}
+h2 {
+ font-size: 28pt;
+}
+h3 {
+ font-size: 24pt;
+}
+h4 {
+ font-size: 20pt;
+}
+h5 {
+ font-size: 16pt;
+}
+h6 {
+ font-size: 12pt;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ padding: 0;
+ margin-top: 0;
+ margin-bottom: .2em;
+ font-family: vn-font-bold;
}
\ No newline at end of file
diff --git a/client/spliting.js b/client/spliting.js
new file mode 100644
index 000000000..d5f641029
--- /dev/null
+++ b/client/spliting.js
@@ -0,0 +1,14 @@
+export default {
+ client:
+ cb => require.ensure([], () => cb(require('client'))),
+ production:
+ cb => require.ensure([], () => cb(require('production'))),
+ route:
+ cb => require.ensure([], () => cb(require('route'))),
+ locator:
+ cb => require.ensure([], () => cb(require('locator'))),
+ item:
+ cb => require.ensure([], () => cb(require('item'))),
+ ticket:
+ cb => require.ensure([], () => cb(require('ticket')))
+};
diff --git a/client/test_index.js b/client/test_index.js
new file mode 100644
index 000000000..34d621356
--- /dev/null
+++ b/client/test_index.js
@@ -0,0 +1,6 @@
+// require all modules ending in ".spec" from the
+// current directory and all subdirectories
+import 'angular';
+import 'angular-mocks';
+var testsContext = require.context('./', true, /\.spec\.js$/);
+testsContext.keys().forEach(testsContext);
diff --git a/client/ticket/index.js b/client/ticket/index.js
new file mode 100644
index 000000000..dc559e2d9
--- /dev/null
+++ b/client/ticket/index.js
@@ -0,0 +1 @@
+export * from './src/ticket';
diff --git a/client/ticket/routes.json b/client/ticket/routes.json
new file mode 100644
index 000000000..8fd9b65f5
--- /dev/null
+++ b/client/ticket/routes.json
@@ -0,0 +1,14 @@
+{
+ "module": "ticket",
+ "name": "Tickets",
+ "icon": "receipt",
+ "validations": false,
+ "routes": [
+ {
+ "url": "/tickets",
+ "state": "tickets",
+ "component": "vn-ticket-index",
+ "acl": ["developer"]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/client/ticket/src/index/index.html b/client/ticket/src/index/index.html
new file mode 100644
index 000000000..51a50474c
--- /dev/null
+++ b/client/ticket/src/index/index.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/ticket/src/index/index.js b/client/ticket/src/index/index.js
new file mode 100644
index 000000000..bc514194c
--- /dev/null
+++ b/client/ticket/src/index/index.js
@@ -0,0 +1,14 @@
+import ngModule from '../module';
+import './item';
+
+export default class Controller {
+ search(index) {
+ index.accept();
+ }
+}
+Controller.$inject = [];
+
+ngModule.component('vnTicketIndex', {
+ template: require('./index.html'),
+ controller: Controller
+});
diff --git a/client/ticket/src/index/item.html b/client/ticket/src/index/item.html
new file mode 100644
index 000000000..eed354bff
--- /dev/null
+++ b/client/ticket/src/index/item.html
@@ -0,0 +1,17 @@
+
+
+
+ {{::$ctrl.ticket.name}}
+ Id {{::$ctrl.ticket.id}}
+
+
+
+
+
+
+
diff --git a/client/ticket/src/index/item.js b/client/ticket/src/index/item.js
new file mode 100644
index 000000000..c48d773f1
--- /dev/null
+++ b/client/ticket/src/index/item.js
@@ -0,0 +1,20 @@
+import ngModule from '../module';
+
+class Controller {
+ onClick(event) {
+ if (event.defaultPrevented)
+ event.stopImmediatePropagation();
+ }
+
+ preview(event) {
+ event.preventDefault();
+ }
+}
+
+ngModule.component('vnTicketItem', {
+ controller: Controller,
+ template: require('./item.html'),
+ bindings: {
+ ticket: '<'
+ }
+});
diff --git a/client/ticket/src/index/style.scss b/client/ticket/src/index/style.scss
new file mode 100644
index 000000000..eb363a9a7
--- /dev/null
+++ b/client/ticket/src/index/style.scss
@@ -0,0 +1,3 @@
+vn-ticket-item {
+ display: block;
+}
\ No newline at end of file
diff --git a/client/ticket/src/locale/en.yml b/client/ticket/src/locale/en.yml
new file mode 100644
index 000000000..1f272d420
--- /dev/null
+++ b/client/ticket/src/locale/en.yml
@@ -0,0 +1 @@
+Tickets: Tickets
\ No newline at end of file
diff --git a/client/ticket/src/locale/es.yml b/client/ticket/src/locale/es.yml
new file mode 100644
index 000000000..1f272d420
--- /dev/null
+++ b/client/ticket/src/locale/es.yml
@@ -0,0 +1 @@
+Tickets: Tickets
\ No newline at end of file
diff --git a/client/ticket/src/module.js b/client/ticket/src/module.js
new file mode 100644
index 000000000..9a852e647
--- /dev/null
+++ b/client/ticket/src/module.js
@@ -0,0 +1,5 @@
+import {ng} from 'vendor';
+import 'core';
+
+const ngModule = ng.module('ticket', ['vnCore']);
+export default ngModule;
diff --git a/client/ticket/src/ticket.js b/client/ticket/src/ticket.js
new file mode 100644
index 000000000..c7b861d2c
--- /dev/null
+++ b/client/ticket/src/ticket.js
@@ -0,0 +1,4 @@
+export * from './module';
+
+import './index/index';
+
diff --git a/client/vendor/index.js b/client/vendor/index.js
index a3d037373..8d2b31810 100644
--- a/client/vendor/index.js
+++ b/client/vendor/index.js
@@ -1 +1 @@
-export * from './src/vendor';
\ No newline at end of file
+export * from './src/vendor';
diff --git a/client/vendor/package.json b/client/vendor/package.json
deleted file mode 100644
index 8e69a7669..000000000
--- a/client/vendor/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "@salix/vendor",
- "version": "0.0.0",
- "description": "",
- "main": "index.js",
- "repository": {
- "type": "git",
- "url": "http://git.verdnatura.es:/salix"
- }
-}
diff --git a/client/vendor/src/angular-cookies.js b/client/vendor/src/angular-cookies.js
new file mode 100644
index 000000000..559ea067b
--- /dev/null
+++ b/client/vendor/src/angular-cookies.js
@@ -0,0 +1,5 @@
+import 'angular-cookies';
+
+export const angularCookies = {
+ name: 'ngCookies'
+};
diff --git a/client/vendor/src/angular-paging.js b/client/vendor/src/angular-paging.js
index a0d004036..8a2ad3a7b 100644
--- a/client/vendor/src/angular-paging.js
+++ b/client/vendor/src/angular-paging.js
@@ -1,5 +1,5 @@
import 'angular-paging';
-export const ngPaging = {
+export const angularPaging = {
name: 'bw.paging'
};
diff --git a/client/vendor/src/angular-translate.js b/client/vendor/src/angular-translate.js
index cb5655375..aedc10067 100644
--- a/client/vendor/src/angular-translate.js
+++ b/client/vendor/src/angular-translate.js
@@ -1,6 +1,6 @@
import 'angular-translate';
import 'angular-translate-loader-partial';
-export const ngTranslate = {
+export const angularTranslate = {
name: 'pascalprecht.translate'
};
diff --git a/client/vendor/src/angular-ui-router.js b/client/vendor/src/angular-ui-router.js
new file mode 100644
index 000000000..cb0d4a321
--- /dev/null
+++ b/client/vendor/src/angular-ui-router.js
@@ -0,0 +1,5 @@
+import '@uirouter/angularjs';
+
+export const angularUiRouter = {
+ name: 'ui.router'
+};
diff --git a/client/vendor/src/angular.js b/client/vendor/src/angular.js
index b5d6cad20..769e23ede 100644
--- a/client/vendor/src/angular.js
+++ b/client/vendor/src/angular.js
@@ -1,8 +1,8 @@
-import * as angular from 'angular';
+import * as angular from 'angular';
export const ng = {
module: angular.module,
bootstrap: angular.bootstrap,
- $$minErr :angular.$$minErr,
+ $$minErr: angular.$$minErr,
angular: angular
-}
+};
diff --git a/client/vendor/src/flatpickr.js b/client/vendor/src/flatpickr.js
new file mode 100644
index 000000000..8637b3b6a
--- /dev/null
+++ b/client/vendor/src/flatpickr.js
@@ -0,0 +1,6 @@
+import Flatpickr from 'flatpickr';
+import 'flatpickr/dist/flatpickr.min.css';
+import 'flatpickr/dist/themes/material_orange.css';
+import localeEs from 'flatpickr/dist/l10n/es';
+Flatpickr.l10ns.es = localeEs.es;
+export default Flatpickr;
diff --git a/client/vendor/src/material-design-lite.js b/client/vendor/src/material-design-lite.js
index 43034d151..3f0d1a719 100644
--- a/client/vendor/src/material-design-lite.js
+++ b/client/vendor/src/material-design-lite.js
@@ -1,4 +1,4 @@
import * as mdl from 'material-design-lite';
import 'material-design-lite/dist/material.orange-deep_orange.min.css';
-export const materialdesignlite = mdl;
\ No newline at end of file
+export const materialDesignLite = mdl;
diff --git a/client/vendor/src/oc-lazy-load.js b/client/vendor/src/oc-lazy-load.js
index 4e755b606..fbb7749a8 100644
--- a/client/vendor/src/oc-lazy-load.js
+++ b/client/vendor/src/oc-lazy-load.js
@@ -1,7 +1,5 @@
-import 'oclazyload';
-import {getComponentName} from './util';
+import 'oclazyload';
-export const oclazyload = {
- name: 'oc.lazyLoad',
- oclazyload: getComponentName('$ocLazyLoad',true)
-}
+export const ocLazyLoad = {
+ name: 'oc.lazyLoad'
+};
diff --git a/client/vendor/src/ui-router.js b/client/vendor/src/ui-router.js
deleted file mode 100644
index 4f74b4400..000000000
--- a/client/vendor/src/ui-router.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import 'angular-ui-router';
-import {getComponentName} from './util';
-
-export const uirouter = {
- name: 'ui.router',
- state: getComponentName('$state',true)
-}
diff --git a/client/vendor/src/util.js b/client/vendor/src/util.js
deleted file mode 100644
index 494f1f6e0..000000000
--- a/client/vendor/src/util.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export function getComponentName(name, isProvider) {
- if (isProvider) {
- return {
- name: name,
- provider: name + "Provider"
- };
- }
- return {
- name: name
- };
-}
diff --git a/client/vendor/src/validator.js b/client/vendor/src/validator.js
index 9e3485d87..1bed18e46 100644
--- a/client/vendor/src/validator.js
+++ b/client/vendor/src/validator.js
@@ -1,3 +1,3 @@
-import * as validatorJs from 'validator';
+import * as validatorJs from 'validator';
export const validator = validatorJs;
diff --git a/client/vendor/src/vendor.js b/client/vendor/src/vendor.js
index 09a92d155..a9bda3ee5 100644
--- a/client/vendor/src/vendor.js
+++ b/client/vendor/src/vendor.js
@@ -1,8 +1,9 @@
export * from './angular';
-export * from './ui-router';
+export * from './angular-cookies';
+export * from './angular-translate';
+export * from './angular-paging';
+export * from './angular-ui-router';
export * from './mg-crud';
export * from './oc-lazy-load';
-export * from './angular-translate';
export * from './material-design-lite';
-export * from './angular-paging';
export * from './validator';
diff --git a/dev.cmd b/dev.cmd
deleted file mode 100644
index 57908de14..000000000
--- a/dev.cmd
+++ /dev/null
@@ -1,28 +0,0 @@
-@echo off
-
-set currentDir=%cd%
-set nginxPrefix=%currentDir%\services\nginx
-set nginxConf=%nginxPrefix%\conf-dev.conf
-
-if "%1"=="" goto caseStart
-if "%1"=="start" goto caseStart
-if "%1"=="stop" goto caseStop
-goto caseUsage
-
-:caseStart
- call "%0" stop
- echo "################################ Starting services"
- if not exist "%nginxPrefix%\temp" (mkdir "%nginxPrefix%\temp")
- start /I nginx -c "%nginxConf%" -p "%nginxPrefix%"
- node dev.js
- goto caseEnd
-
-:caseStop
- echo "################################ Stoping services"
- if exist "%nginxPrefix%\temp\nginx.pid" (nginx -c "%nginxConf%" -p "%nginxPrefix%" -s stop)
- goto caseEnd
-
-:caseUsage
- echo "Usage: %0 [start|stop]"
-
-:caseEnd
diff --git a/dev.js b/dev.js
deleted file mode 100644
index d6fb5b167..000000000
--- a/dev.js
+++ /dev/null
@@ -1,11 +0,0 @@
-require('./gulpfile');
-var auth = require('./services/auth/server/server.js');
-var client = require('./services/client/server/server.js');
-var server = require('./services/salix/server/server.js');
-var gulp = require('gulp');
-
-gulp.start(['default']);
-
-auth.start();
-client.start();
-server.start();
diff --git a/dev.sh b/dev.sh
deleted file mode 100755
index cdf040d5b..000000000
--- a/dev.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-
-nginxBin="/usr/sbin/nginx"
-nginxPrefix="${PWD}/services/nginx"
-nginxConf="$nginxPrefix/conf-dev.conf"
-
-if [ ! -f $nginxBin ]; then
- nginxBin="nginx"
-fi
-
-case "$1" in
- start|"")
- $0 stop
- echo "################################ Starting services"
- "$nginxBin" -c "$nginxConf" -p "$nginxPrefix"
- node dev.js
- ;;
- stop)
- echo "################################ Stoping services"
- "$nginxBin" -c "$nginxConf" -p "$nginxPrefix" -s stop
- ;;
- *)
- echo "Usage: `basename "$0"` [start|stop]"
- exit 1
-esac
diff --git a/docker-compose.tpl.yml b/docker-compose.tpl.yml
new file mode 100644
index 000000000..1777118a7
--- /dev/null
+++ b/docker-compose.tpl.yml
@@ -0,0 +1,12 @@
+version: '2'
+services:
+ nginx:
+ container_name: "${BRANCH_NAME}-nginx"
+ image: "nginx:${TAG}"
+ privileged: true
+ build:
+ context: ./services/nginx
+ ports:
+ - "80:80"
+ mem_limit: 200m
+ links: []
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index 5489200f9..000000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-version: '2'
-services:
- salix:
- build:
- context: ./services/salix
- ports:
- - "3001:3001"
- account:
- build:
- context: ./services/account
- ports:
- - "3000:3000"
- nginx:
- build:
- context: ./@salix
- ports:
- - "8080:8080"
- client:
- build:
- context: ./services/client
- ports:
- - "3002:3002"
\ No newline at end of file
diff --git a/e2e/helpers/components_selectors.js b/e2e/helpers/components_selectors.js
new file mode 100644
index 000000000..488d002e0
--- /dev/null
+++ b/e2e/helpers/components_selectors.js
@@ -0,0 +1,19 @@
+// eslint max-len: ["error", 500]
+// eslint key-spacing: ["error", 500]
+
+// delete me, this comment is to add a commit
+export default {
+ vnTextfield: 'vn-textfield > div > input',
+ vnTextarea: 'vn-textarea',
+ vnSubmit: 'vn-submit > input',
+ vnTopbar: 'vn-topbar > header',
+ vnIcon: 'vn-icon',
+ vnModuleContainer: 'vn-module-container > a',
+ vnSearchBar: 'vn-searchbar > form > vn-horizontal',
+ vnFloatButton: 'vn-float-button > button',
+ vnMenuItem: 'vn-menu-item > li > a',
+ vnAutocomplete: 'vn-autocomplete',
+ vnCheck: 'vn-check',
+ vnIconButton: 'vn-icon-button',
+ vnItemSummary: 'vn-item-summary > vn-card > div > vn-vertical'
+};
diff --git a/e2e/helpers/config.js b/e2e/helpers/config.js
new file mode 100644
index 000000000..d52f08b39
--- /dev/null
+++ b/e2e/helpers/config.js
@@ -0,0 +1,3 @@
+export default {
+ url: 'http://localhost:5000/'
+};
diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js
new file mode 100644
index 000000000..7f146d30e
--- /dev/null
+++ b/e2e/helpers/extensions.js
@@ -0,0 +1,204 @@
+import config from './config.js';
+import Nightmare from 'nightmare';
+import {URL} from 'url';
+
+Nightmare.action('login', function(userName, done) {
+ this.goto(`${config.url}auth/?apiKey=salix`)
+ .wait(`vn-login input[name=user]`)
+ .write(`vn-login input[name=user]`, userName)
+ .write(`vn-login input[name=password]`, 'nightmare')
+ .click(`vn-login input[type=submit]`)
+ // FIXME: Wait for dom to be ready: https://github.com/segmentio/nightmare/issues/481
+ .wait(1000)
+ .then(done);
+});
+
+Nightmare.action('changeLanguageToEnglish', function(done) {
+ this.wait('#lang')
+ .evaluate(selector => {
+ return document.querySelector(selector).title;
+ }, '#lang')
+ .then(title => {
+ if (title === 'Change language') {
+ this.then(done);
+ } else {
+ this.click('#lang')
+ .click('vn-main-menu [vn-id="langs-menu"] ul > li[name="en"]')
+ .then(done);
+ }
+ });
+});
+
+Nightmare.action('waitForLogin', function(userName, done) {
+ this.login(userName)
+ .waitForURL('#!/')
+ .url()
+ .changeLanguageToEnglish()
+ .then(done);
+});
+
+Nightmare.action('parsedUrl', function(done) {
+ this.url()
+ .then(url => {
+ done(null, new URL(url));
+ });
+});
+
+Nightmare.action('getInnerText', function(selector, done) {
+ this.wait(selector)
+ .evaluate_now(function(elementToSelect) {
+ return document.querySelector(elementToSelect).innerText;
+ }, done, selector);
+});
+
+Nightmare.action('getInputValue', function(selector, done) {
+ this.wait(selector)
+ .evaluate_now(function(elementToSelect) {
+ return document.querySelector(elementToSelect).value;
+ }, done, selector);
+});
+
+Nightmare.action('clearInput', function(selector, done) {
+ let backSpaces = [];
+ for (let i = 0; i < 50; i += 1) {
+ backSpaces.push('\u0008');
+ }
+ this.wait(selector)
+ .type(selector, backSpaces.join(''))
+ .then(done);
+});
+
+Nightmare.action('write', function(selector, text, done) {
+ this.wait(selector)
+ .type(selector, text)
+ .then(done);
+});
+
+Nightmare.action('waitToClick', function(selector, done) {
+ this.wait(selector)
+ .click(selector)
+ .then(done);
+});
+
+Nightmare.action('isVisible', function(selector, done) {
+ this.wait(selector)
+ .evaluate_now(elementSelector => {
+ const selectorMatches = document.querySelectorAll(elementSelector);
+ const element = selectorMatches[0];
+ if (selectorMatches.length > 1) {
+ throw new Error(`multiple matches of ${elementSelector} found`);
+ }
+ let isVisible = false;
+ if (element) {
+ const eventHandler = event => {
+ event.preventDefault();
+ isVisible = true;
+ };
+ element.addEventListener('mouseover', eventHandler);
+ const elementBoundaries = element.getBoundingClientRect();
+ const x = elementBoundaries.left + element.offsetWidth / 2;
+ const y = elementBoundaries.top + element.offsetHeight / 2;
+ const elementInCenter = document.elementFromPoint(x, y);
+ const elementInTopLeft = document.elementFromPoint(elementBoundaries.left, elementBoundaries.top);
+ const elementInBottomRight = document.elementFromPoint(elementBoundaries.right, elementBoundaries.bottom);
+ const e = new MouseEvent('mouseover', {
+ view: window,
+ bubbles: true,
+ cancelable: true
+ });
+ if (elementInCenter) {
+ elementInCenter.dispatchEvent(e);
+ }
+ if (elementInTopLeft) {
+ elementInTopLeft.dispatchEvent(e);
+ }
+ if (elementInBottomRight) {
+ elementInBottomRight.dispatchEvent(e);
+ }
+ element.removeEventListener('mouseover', eventHandler);
+ }
+ return isVisible;
+ }, done, selector);
+});
+
+Nightmare.action('selectText', function(selector, done) {
+ this.wait(selector)
+ .evaluate(elementToSelect => {
+ const range = document.createRange();
+ range.selectNodeContents(document.querySelector(elementToSelect));
+ const sel = window.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }, selector)
+ .mouseup(selector)
+ .then(done);
+});
+
+Nightmare.action('countSearchResults', function(selector, done) {
+ this.evaluate_now(selector => {
+ return document.querySelectorAll(selector).length;
+ }, done, selector);
+});
+
+Nightmare.action('waitForNumberOfElements', function(selector, count, done) {
+ this.wait((resultSelector, expectedCount) => {
+ return document.querySelectorAll(resultSelector).length === expectedCount;
+ }, selector, count)
+ .then(done);
+});
+
+Nightmare.action('waitForTextInElement', function(selector, name, done) {
+ this.wait(selector)
+ .wait((resultSelector, expectedText) => {
+ return document.querySelector(resultSelector).innerText.toLowerCase().includes(expectedText.toLowerCase());
+ }, selector, name)
+ .then(done);
+});
+
+Nightmare.action('waitForTextInInput', function(selector, name, done) {
+ this.wait(selector)
+ .wait((resultSelector, expectedText) => {
+ return document.querySelector(resultSelector).value.toLowerCase().includes(expectedText.toLowerCase());
+ }, selector, name)
+ .then(done);
+});
+
+Nightmare.action('waitForInnerText', function(selector, done) {
+ this.wait(selector)
+ .wait(selector => {
+ let innerText = document.querySelector(selector).innerText;
+ return innerText != null && innerText != '';
+ }, selector)
+ .evaluate_now(selector => {
+ return document.querySelector(selector).innerText;
+ }, done, selector);
+});
+
+Nightmare.action('waitForEmptyInnerText', function(selector, done) {
+ this.wait(selector => {
+ return document.querySelector(selector).innerText == '';
+ }, selector)
+ .then(done);
+});
+
+Nightmare.action('waitForSnackbarReset', function(done) {
+ this.click('vn-snackbar button')
+ .waitForEmptyInnerText('vn-snackbar .text')
+ .then(done);
+});
+
+Nightmare.action('waitForSnackbar', function(done) {
+ this.wait(500)
+ .waitForInnerText('vn-snackbar .text')
+ .then(value => {
+ this.waitForSnackbarReset()
+ .then(() => done(null, value));
+ });
+});
+
+Nightmare.action('waitForURL', function(hashURL, done) {
+ this.wait(hash => {
+ return document.location.hash.includes(hash);
+ }, hashURL)
+ .then(done);
+});
diff --git a/e2e/helpers/helpers.js b/e2e/helpers/helpers.js
new file mode 100644
index 000000000..a7866c2d2
--- /dev/null
+++ b/e2e/helpers/helpers.js
@@ -0,0 +1,14 @@
+import createNightmare from './nightmare';
+export default myCreateNightmare;
+
+function myCreateNightmare() {
+ let nightmare = createNightmare();
+ nightmare.header('Accept-Language', 'en');
+
+ afterAll(() => {
+ return nightmare
+ .end();
+ });
+
+ return nightmare;
+}
diff --git a/e2e/helpers/nightmare.js b/e2e/helpers/nightmare.js
new file mode 100644
index 000000000..9f28d0151
--- /dev/null
+++ b/e2e/helpers/nightmare.js
@@ -0,0 +1,26 @@
+/* eslint no-console: 0 */
+import Nightmare from 'nightmare';
+
+export default function createNightmare(width = 1280, height = 720) {
+ const nightmare = new Nightmare({show: true, typeInterval: 10, x: 0, y: 0}).viewport(width, height);
+
+ nightmare.on('page', (type, message, error) => {
+ fail(error);
+ });
+
+ nightmare.on('dom-ready', function() {
+ nightmare.inject('js', `${__dirname}/nightmareModifiers.js`);
+ });
+
+ nightmare.on('console', (type, message) => {
+ if (type === 'error') {
+ fail(message);
+ }
+ if (type === 'log') {
+ // console.log(message);
+ }
+ });
+ return nightmare;
+}
+
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
diff --git a/e2e/helpers/nightmareModifiers.js b/e2e/helpers/nightmareModifiers.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js
new file mode 100644
index 000000000..ab30e2db7
--- /dev/null
+++ b/e2e/helpers/selectors.js
@@ -0,0 +1,265 @@
+// eslint max-len: ["error", 500]
+// eslint key-spacing: ["error", 500]
+import components from './components_selectors.js';
+
+export default {
+ globalItems: {
+ logOutButton: `#logout`,
+ applicationsMenuButton: `#apps`,
+ applicationsMenuVisible: `vn-main-menu [vn-id="apps-menu"] ul`,
+ clientsButton: `vn-main-menu [vn-id="apps-menu"] ul > li:nth-child(1)`
+ },
+ moduleAccessView: {
+ clientsSectionButton: `${components.vnModuleContainer}[ui-sref="clients"]`,
+ itemsSectionButton: `${components.vnModuleContainer}[ui-sref="item.index"]`
+ },
+ clientsIndex: {
+ searchClientInput: `${components.vnTextfield}`,
+ searchButton: `${components.vnSearchBar} > vn-icon-button > button`,
+ searchResult: `vn-item-client a`,
+ createClientButton: `${components.vnFloatButton}`
+ },
+ createClientView: {
+ name: `${components.vnTextfield}[name="name"]`,
+ taxNumber: `${components.vnTextfield}[name="fi"]`,
+ socialName: `${components.vnTextfield}[name="socialName"]`,
+ userName: `${components.vnTextfield}[name="userName"]`,
+ email: `${components.vnTextfield}[name="email"]`,
+ salesPersonInput: `vn-autocomplete[field="$ctrl.client.salesPersonFk"] input`,
+ salesBruceBannerOption: `vn-autocomplete[field="$ctrl.client.salesPersonFk"] vn-drop-down ul > li:nth-child(1)`,
+ createButton: `${components.vnSubmit}`
+ },
+ clientBasicData: {
+ basicDataButton: `${components.vnMenuItem}[ui-sref="clientCard.basicData"]`,
+ nameInput: `${components.vnTextfield}[name="name"]`,
+ contactInput: `${components.vnTextfield}[name="contact"]`,
+ phoneInput: `${components.vnTextfield}[name="phone"]`,
+ mobileInput: `${components.vnTextfield}[name="mobile"]`,
+ faxInput: `${components.vnTextfield}[name="fax"]`,
+ emailInput: `${components.vnTextfield}[name="email"]`,
+ salesPersonInput: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] input`,
+ salesPersonOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] vn-drop-down ul > li:nth-child(1)`,
+ channelInput: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] input`,
+ channelMetropolisOption: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] vn-drop-down ul > li:nth-child(3)`,
+ saveButton: `${components.vnSubmit}`
+ },
+ clientFiscalData: {
+ fiscalDataButton: `${components.vnMenuItem}[ui-sref="clientCard.fiscalData"]`,
+ socialNameInput: `${components.vnTextfield}[name="socialName"]`,
+ fiscalIdInput: `${components.vnTextfield}[name="fi"]`,
+ equalizationTaxCheckboxLabel: `${components.vnCheck}[label='Is equalizated'] > label > input`,
+ acceptPropagationButton: `vn-client-fiscal-data > vn-confirm button[response=ACCEPT]`,
+ addressInput: `${components.vnTextfield}[name="street"]`,
+ cityInput: `${components.vnTextfield}[name="city"]`,
+ postcodeInput: `${components.vnTextfield}[name="postcode"]`,
+ provinceInput: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] input`,
+ provinceFifthOption: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] vn-drop-down ul > li:nth-child(5)`,
+ countryInput: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] input`,
+ countryThirdOption: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] vn-drop-down ul > li:nth-child(3)`,
+ activeCheckboxLabel: `${components.vnCheck}[label='Active'] > label`,
+ invoiceByAddressCheckboxInput: `${components.vnCheck}[label='Invoice by address'] > label > input`,
+ verifiedDataCheckboxInput: `${components.vnCheck}[label='Verified data'] > label > input`,
+ hasToInvoiceCheckboxLabel: `${components.vnCheck}[label='Has to invoice'] > label`,
+ invoiceByMailCheckboxLabel: `${components.vnCheck}[label='Invoice by mail'] > label`,
+ viesCheckboxInput: `${components.vnCheck}[label='Vies'] > label > input`,
+ saveButton: `${components.vnSubmit}`
+ },
+ clientPayMethod: {
+ payMethodButton: `${components.vnMenuItem}[ui-sref="clientCard.billingData"]`,
+ payMethodInput: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] input`,
+ payMethodIBANOption: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] vn-drop-down ul > li:nth-child(5)`,
+ payMethodOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] vn-drop-down ul > li:nth-child(2)`,
+ IBANInput: `${components.vnTextfield}[name="iban"]`,
+ dueDayInput: `${components.vnTextfield}[name="dueDay"]`,
+ cancelNotificationButton: 'vn-client-billing-data > vn-confirm button[response=CANCEL]',
+ receivedCoreVNHCheckbox: `${components.vnCheck}[label='Received core VNH'] > label > input`,
+ receivedCoreVNLCheckbox: `${components.vnCheck}[label='Received core VNL'] > label > input`,
+ receivedB2BVNLCheckbox: `${components.vnCheck}[label='Received B2B VNL'] > label > input`,
+ saveButton: `${components.vnSubmit}`
+ },
+ clientAddresses: {
+ addressesButton: `${components.vnMenuItem}[ui-sref="clientCard.addresses.list"]`,
+ createAddress: `${components.vnFloatButton}`,
+ defaultCheckboxInput: `${components.vnCheck}[label='Default'] > label > input`,
+ consigneeInput: `${components.vnTextfield}[name="nickname"]`,
+ streetAddressInput: `${components.vnTextfield}[name="street"]`,
+ postcodeInput: `${components.vnTextfield}[name="postalCode"]`,
+ cityInput: `${components.vnTextfield}[name="city"]`,
+ provinceInput: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] input`,
+ provinceSecondOption: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] vn-drop-down ul > li:nth-child(2)`,
+ agencyInput: `${components.vnAutocomplete}[field="$ctrl.address.agencyModeFk"] input`,
+ agenctySecondOption: `${components.vnAutocomplete}[field="$ctrl.address.agencyModeFk"] vn-drop-down ul > li:nth-child(2)`,
+ phoneInput: `${components.vnTextfield}[name="phone"]`,
+ mobileInput: `${components.vnTextfield}[name="mobile"]`,
+ defaultAddress: 'vn-client-addresses > vn-vertical > vn-card > div > vn-horizontal:nth-child(2) > vn-one > vn-horizontal > vn-one > div:nth-child(2)',
+ secondMakeDefaultStar: 'vn-client-addresses > vn-vertical > vn-card > div > vn-horizontal:nth-child(3) > vn-one > vn-horizontal > vn-none > i',
+ firstEditButton: `${components.vnIconButton}[icon='edit']`,
+ secondEditButton: `vn-horizontal:nth-child(3) > vn-one > vn-horizontal > a > ${components.vnIconButton}[icon='edit']`,
+ activeCheckbox: `${components.vnCheck}[label='Enabled'] > label > input`,
+ equalizationTaxCheckboxLabel: `${components.vnCheck}[label='Is equalizated'] > label > input`,
+ firstObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(1) input`,
+ firstObservationTypeSelectOptionOne: `${components.vnAutocomplete}[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(1)`,
+ firstObservationDescriptionInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Description"] > div > input`,
+ secondObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(2) input`,
+ secondObservationTypeSelectOptionTwo: `${components.vnAutocomplete}[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`,
+ secondObservationDescriptionInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Description"] > div > input`,
+ thirdObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(3) input`,
+ thirdObservationTypeSelectOptionThree: `${components.vnAutocomplete}[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(3)`,
+ thirdObservationDescriptionInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Description"] > div > input`,
+ addObservationButton: `${components.vnIcon}[icon="add_circle"]`,
+ saveButton: `${components.vnSubmit}`
+ },
+ clientWebAccess: {
+ webAccessButton: `${components.vnMenuItem}[ui-sref="clientCard.webAccess"]`,
+ enableWebAccessCheckbox: `${components.vnCheck}[label='Enable web access'] > label > input`,
+ userNameInput: `${components.vnTextfield}[name="name"]`,
+ saveButton: `${components.vnSubmit}`
+ },
+ clientNotes: {
+ notesButton: `${components.vnMenuItem}[ui-sref="clientCard.notes.list"]`,
+ addNoteFloatButton: `${components.vnFloatButton}`,
+ noteInput: `${components.vnTextarea}[label="Note"]`,
+ saveButton: `${components.vnSubmit}`,
+ firstNoteText: 'vn-client-notes .text'
+ },
+ clientCredit: {
+ creditButton: `${components.vnMenuItem}[ui-sref="clientCard.credit.list"]`,
+ addCreditFloatButton: `${components.vnFloatButton}`,
+ creditInput: `${components.vnTextfield}[name="credit"]`,
+ saveButton: `${components.vnSubmit}`,
+ firstCreditText: 'vn-client-credit-list .list-element'
+ },
+ clientGreuge: {
+ greugeButton: `${components.vnMenuItem}[ui-sref="clientCard.greuge.list"]`,
+ addGreugeFloatButton: `${components.vnFloatButton}`,
+ amountInput: `${components.vnTextfield}[name="amount"]`,
+ descriptionInput: `${components.vnTextfield}[name="description"]`,
+ typeInput: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] input`,
+ typeSecondOption: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] vn-drop-down ul > li`,
+ saveButton: `${components.vnSubmit}`,
+ firstGreugeText: 'vn-client-greuge-list .list-element'
+ },
+ clientMandate: {
+ mandateButton: `${components.vnMenuItem}[ui-sref="clientCard.mandate"]`,
+ firstMandateText: 'vn-client-mandate .list-element'
+ },
+ clientInvoices: {
+ invoicesButton: `${components.vnMenuItem}[ui-sref="clientCard.invoices"]`,
+ firstInvoiceText: 'vn-client-invoices .list-element'
+ },
+ itemsIndex: {
+ createItemButton: `${components.vnFloatButton}`,
+ searchResult: `vn-item-product a`,
+ searchResultPreviewButton: `vn-item-product .buttons > [icon="desktop_windows"]`,
+ searchResultCloneButton: `vn-item-product .buttons > [icon="icon-clone"]`,
+ acceptClonationAlertButton: `vn-item-list [vn-id="clone"] [response="ACCEPT"]`,
+ searchItemInput: `${components.vnTextfield}`,
+ searchButton: `${components.vnSearchBar} > vn-icon-button > button`,
+ closeItemSummaryPreview: 'vn-item-list [vn-id="preview"] button.close'
+ },
+ itemCreateView: {
+ name: `${components.vnTextfield}[name="name"]`,
+ typeSelect: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] input`,
+ typeSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`,
+ intrastatSelect: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] input`,
+ intrastatSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(2)`,
+ originSelect: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] input`,
+ originSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] vn-drop-down ul > li:nth-child(2)`,
+ expenceSelect: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] input`,
+ expenceSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] vn-drop-down ul > li:nth-child(2)`,
+ createButton: `${components.vnSubmit}`
+
+ },
+ itemBasicData: {
+ goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
+ basicDataButton: `${components.vnMenuItem}[ui-sref="item.card.data"]`,
+ typeSelect: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] input`,
+ typeSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`,
+ intrastatSelect: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] input`,
+ intrastatSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(1)`,
+ nameInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
+ relevancyInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`,
+ originSelect: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] input`,
+ originSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] vn-drop-down ul > li:nth-child(2)`,
+ expenceSelect: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] input`,
+ expenceSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] vn-drop-down ul > li:nth-child(2)`,
+ submitBasicDataButton: `${components.vnSubmit}`
+ },
+ itemTags: {
+ goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
+ tagsButton: `${components.vnMenuItem}[ui-sref="item.card.tags"]`,
+ firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
+ firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
+ firstValueInput: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Value"] > div > input`,
+ firstRelevancyInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Relevancy"] > div > input`,
+ secondTagSelect: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
+ secondTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
+ secondValueInput: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Value"] > div > input`,
+ secondRelevancyInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Relevancy"] > div > input`,
+ thirdTagSelect: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
+ thirdTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
+ thirdValueInput: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Value"] > div > input`,
+ thirdRelevancyInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Relevancy"] > div > input`,
+ fourthTagSelect: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
+ fourthTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
+ fourthValueInput: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Value"] > div > input`,
+ fourthRelevancyInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Relevancy"] > div > input`,
+ fifthRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnIcon}[icon="remove_circle_outline"]`,
+ fifthTagSelect: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
+ fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`,
+ fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] > div > input`,
+ fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] > div > input`,
+ addItemTagButton: `${components.vnIcon}[icon="add_circle"]`,
+ submitItemTagsButton: `${components.vnSubmit}`
+ },
+ itemTax: {
+ taxButton: `${components.vnMenuItem}[ui-sref="item.card.tax"]`,
+ firstClassSelect: `vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="tax.taxClassFk"] input`,
+ firstClassSelectOptionTwo: `vn-horizontal:nth-child(2) > ${components.vnAutocomplete} vn-drop-down ul > li:nth-child(2)`,
+ secondClassSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="tax.taxClassFk"] input`,
+ secondClassSelectOptionOne: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete} vn-drop-down ul > li:nth-child(1)`,
+ thirdClassSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="tax.taxClassFk"] input`,
+ thirdClassSelectOptionTwo: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete} vn-drop-down ul > li:nth-child(2)`,
+ submitTaxButton: `${components.vnSubmit}`
+ },
+ itemBarcodes: {
+ barcodeButton: `${components.vnMenuItem}[ui-sref="item.card.itemBarcode"]`,
+ addBarcodeButton: `${components.vnIcon}[icon="add_circle"]`,
+ thirdCodeInput: `vn-horizontal:nth-child(4) > ${components.vnTextfield}`,
+ submitBarcodesButton: `${components.vnSubmit}`,
+ firstCodeRemoveButton: `vn-horizontal:nth-child(2) > vn-one > ${components.vnIcon}[icon="remove_circle_outline"]`
+ },
+ itemNiches: {
+ nicheButton: `${components.vnMenuItem}[ui-sref="item.card.niche"]`,
+ addNicheButton: `${components.vnIcon}[icon="add_circle"]`,
+ firstWarehouseSelect: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
+ firstWarehouseSelectSecondOption: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`,
+ secondWarehouseSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
+ thirdWarehouseSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
+ thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`,
+ secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-one > ${components.vnIcon}[icon="remove_circle_outline"]`,
+ firstCodeInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
+ secondCodeInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`,
+ thirdCodeInput: `vn-horizontal:nth-child(4) > ${components.vnTextfield}`,
+ submitNichesButton: `${components.vnSubmit}`
+ },
+ itemBotanical: {
+ botanicalButton: `${components.vnMenuItem}[ui-sref="item.card.botanical"]`,
+ botanicalInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
+ genusSelect: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] input`,
+ genusSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] vn-drop-down ul > li:nth-child(1)`,
+ genusSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] vn-drop-down ul > li:nth-child(2)`,
+ speciesSelect: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] input`,
+ speciesSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] vn-drop-down ul > li:nth-child(1)`,
+ speciesSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] vn-drop-down ul > li:nth-child(2)`,
+ submitBotanicalButton: `${components.vnSubmit}`
+ },
+ itemSummary: {
+ basicData: `${components.vnItemSummary} > vn-horizontal:nth-child(1) > vn-one:nth-child(2) > vn-vertical > p:nth-child(2)`,
+ vat: `${components.vnItemSummary} > vn-horizontal:nth-child(1) > vn-one:nth-child(3) > vn-vertical > p`,
+ tags: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(1) > p`,
+ niche: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(2) > vn-vertical > p:nth-child(2)`,
+ botanical: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(3) > vn-vertical > p`,
+ barcode: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(4) > vn-vertical > p`
+ }
+};
diff --git a/e2e/paths/client-module/01_create_client.spec.js b/e2e/paths/client-module/01_create_client.spec.js
new file mode 100644
index 000000000..4b7df7464
--- /dev/null
+++ b/e2e/paths/client-module/01_create_client.spec.js
@@ -0,0 +1,114 @@
+import selectors from '../../helpers/selectors';
+import createNightmare from '../../helpers/helpers';
+
+describe('create client path', () => {
+ let nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should access to the clients index by clicking the clients button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.clientsSectionButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it(`should search for the user Carol Danvers to confirm it isn't created yet`, () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Carol Danvers')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 0)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(0);
+ });
+ });
+
+ it('should access to the create client view by clicking the create-client floating button', () => {
+ return nightmare
+ .click(selectors.clientsIndex.createClientButton)
+ .wait(selectors.createClientView.createButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/create');
+ });
+ });
+
+ it('should receive an error when clicking the create button having all the form fields empty', () => {
+ return nightmare
+ .click(selectors.createClientView.createButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Some fields are invalid');
+ });
+ });
+
+ it('should receive an error when clicking the create button having name and Business name fields empty', () => {
+ return nightmare
+ .type(selectors.createClientView.taxNumber, '16195279J')
+ .type(selectors.createClientView.userName, 'CaptainMarvel')
+ .type(selectors.createClientView.email, 'CarolDanvers@verdnatura.es')
+ .waitToClick(selectors.createClientView.salesPersonInput)
+ .waitToClick(selectors.createClientView.salesBruceBannerOption)
+ .click(selectors.createClientView.createButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Some fields are invalid');
+ });
+ });
+
+ it(`should attempt to create a new user with all it's data but wrong email`, () => {
+ return nightmare
+ .type(selectors.createClientView.name, 'Carol Danvers')
+ .type(selectors.createClientView.socialName, 'AVG tax')
+ .clearInput(selectors.createClientView.email)
+ .type(selectors.createClientView.email, 'incorrect email format')
+ .click(selectors.createClientView.createButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Some fields are invalid');
+ });
+ });
+
+ it(`should create a new user with all correct data`, () => {
+ return nightmare
+ .clearInput(selectors.createClientView.email)
+ .type(selectors.createClientView.email, 'caroldanvers@verdnatura.es')
+ .click(selectors.createClientView.createButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it(`should search for the user Carol Danvers to confirm it exists`, () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Carol Danvers')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+});
diff --git a/e2e/paths/client-module/02_edit_basic_data.spec.js b/e2e/paths/client-module/02_edit_basic_data.spec.js
new file mode 100644
index 000000000..ea58176cf
--- /dev/null
+++ b/e2e/paths/client-module/02_edit_basic_data.spec.js
@@ -0,0 +1,130 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Edit basicData path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Bruce Wayne', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Bruce Wayne')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it('should click on the search result to access to the clients basic data', () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Wayne')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitForURL('basic-data')
+ .url()
+ .then(url => {
+ expect(url).toContain('basic-data');
+ });
+ });
+
+ it('should edit the client basic data', () => {
+ return nightmare
+ .wait(selectors.clientBasicData.nameInput)
+ .clearInput(selectors.clientBasicData.nameInput)
+ .type(selectors.clientBasicData.nameInput, 'Ororo Munroe')
+ .clearInput(selectors.clientBasicData.contactInput)
+ .type(selectors.clientBasicData.contactInput, 'Black Panther')
+ .clearInput(selectors.clientBasicData.phoneInput)
+ .type(selectors.clientBasicData.phoneInput, '123456789')
+ .clearInput(selectors.clientBasicData.mobileInput)
+ .type(selectors.clientBasicData.mobileInput, '987654321')
+ .clearInput(selectors.clientBasicData.emailInput)
+ .type(selectors.clientBasicData.emailInput, 'Storm@verdnatura.es')
+ .waitToClick(selectors.clientBasicData.salesPersonInput)
+ .waitToClick(selectors.clientBasicData.salesPersonOptionOne)
+ .waitToClick(selectors.clientBasicData.channelInput)
+ .waitToClick(selectors.clientBasicData.channelMetropolisOption)
+ .click(selectors.clientBasicData.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it('should confirm the name have been edited', () => {
+ return nightmare
+ .click(selectors.clientFiscalData.fiscalDataButton)
+ .wait(selectors.clientFiscalData.addressInput)
+ .click(selectors.clientBasicData.basicDataButton)
+ .wait(selectors.clientBasicData.nameInput)
+ .getInputValue(selectors.clientBasicData.nameInput)
+ .then(result => {
+ expect(result).toEqual('Ororo Munroe');
+ });
+ });
+
+ it('should confirm the contact name have been edited', () => {
+ return nightmare
+ .getInputValue(selectors.clientBasicData.contactInput)
+ .then(result => {
+ expect(result).toEqual('Black Panther');
+ });
+ });
+
+ it('should confirm the landline phone number have been added', () => {
+ return nightmare
+ .getInputValue(selectors.clientBasicData.phoneInput)
+ .then(result => {
+ expect(result).toEqual('123456789');
+ });
+ });
+
+ it('should confirm the mobile phone number have been added', () => {
+ return nightmare
+ .getInputValue(selectors.clientBasicData.mobileInput)
+ .then(result => {
+ expect(result).toEqual('987654321');
+ });
+ });
+
+ it('should confirm the email have been edited', () => {
+ return nightmare
+ .getInputValue(selectors.clientBasicData.emailInput)
+ .then(result => {
+ expect(result).toEqual('Storm@verdnatura.es');
+ });
+ });
+
+ it('should confirm the sales person have been selected', () => {
+ return nightmare
+ .getInputValue(selectors.clientBasicData.salesPersonInput)
+ .then(result => {
+ expect(result).toEqual('accessory accessory');
+ });
+ });
+
+ it('should confirm the channel have been selected', () => {
+ return nightmare
+ .getInputValue(selectors.clientBasicData.channelInput)
+ .then(result => {
+ expect(result).toEqual('Metropolis newspaper');
+ });
+ });
+});
diff --git a/e2e/paths/client-module/03_edit_fiscal_data.spec.js b/e2e/paths/client-module/03_edit_fiscal_data.spec.js
new file mode 100644
index 000000000..099c422ab
--- /dev/null
+++ b/e2e/paths/client-module/03_edit_fiscal_data.spec.js
@@ -0,0 +1,279 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Edit fiscalData path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Bruce Banner', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ describe('Confirm all addresses have EQtax false for future propagation test', () => {
+ it(`should click on the search result to access to the client's addresses`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientAddresses.addressesButton)
+ .waitForURL('/addresses/list')
+ .url()
+ .then(url => {
+ expect(url).toContain('/addresses/list');
+ });
+ });
+
+ it(`should click on the 1st edit icon to check EQtax is checked`, () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.firstEditButton)
+ .wait(selectors.clientAddresses.equalizationTaxCheckboxLabel)
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientAddresses.equalizationTaxCheckboxLabel)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+
+ it(`should go back to addresses then select the second one and confirm the EQtax is checked`, () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.addressesButton)
+ .waitToClick(selectors.clientAddresses.secondEditButton)
+ .wait(selectors.clientAddresses.equalizationTaxCheckboxLabel)
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientAddresses.equalizationTaxCheckboxLabel)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+ });
+
+ it(`should click on the fiscal data button to start editing`, () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .url()
+ .then(url => {
+ expect(url).toContain('fiscal-data');
+ });
+ });
+
+ it('should edit the clients fiscal data', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .clearInput(selectors.clientFiscalData.socialNameInput)
+ .type(selectors.clientFiscalData.socialNameInput, 'SMASH!')
+ .clearInput(selectors.clientFiscalData.fiscalIdInput)
+ .type(selectors.clientFiscalData.fiscalIdInput, '94980061C')
+ .waitToClick(selectors.clientFiscalData.equalizationTaxCheckboxLabel)
+ .clearInput(selectors.clientFiscalData.addressInput)
+ .type(selectors.clientFiscalData.addressInput, 'Somewhere edited')
+ .clearInput(selectors.clientFiscalData.cityInput)
+ .type(selectors.clientFiscalData.cityInput, 'N/A')
+ .clearInput(selectors.clientFiscalData.postcodeInput)
+ .type(selectors.clientFiscalData.postcodeInput, '12345')
+ .waitToClick(selectors.clientFiscalData.provinceInput)
+ .waitToClick(selectors.clientFiscalData.provinceFifthOption)
+ .waitToClick(selectors.clientFiscalData.activeCheckboxLabel)
+ .waitToClick(selectors.clientFiscalData.invoiceByAddressCheckboxInput)
+ .waitToClick(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .waitToClick(selectors.clientFiscalData.hasToInvoiceCheckboxLabel)
+ .waitToClick(selectors.clientFiscalData.invoiceByMailCheckboxLabel)
+ .waitToClick(selectors.clientFiscalData.viesCheckboxInput)
+ .click(selectors.clientFiscalData.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it('should propagate the Equalization tax', () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.acceptPropagationButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Equivalent tax spreaded');
+ });
+ });
+
+ describe('confirm all addresses have now EQtax checked', () => {
+ it(`should click on the addresses button to access to the client's addresses`, () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.addressesButton)
+ .waitForURL('/addresses/list')
+ .url()
+ .then(url => {
+ expect(url).toContain('/addresses/list');
+ });
+ });
+
+ it(`should click on the 1st edit icon to confirm EQtax is checked`, () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.firstEditButton)
+ .wait(selectors.clientAddresses.equalizationTaxCheckboxLabel)
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientAddresses.equalizationTaxCheckboxLabel)
+ .then(value => {
+ expect(value).toBeTruthy();
+ });
+ });
+
+ it(`should go back to addresses then select the second one and confirm the EQtax is checked`, () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.addressesButton)
+ .waitToClick(selectors.clientAddresses.secondEditButton)
+ .wait(selectors.clientAddresses.equalizationTaxCheckboxLabel)
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientAddresses.equalizationTaxCheckboxLabel)
+ .then(value => {
+ expect(value).toBeTruthy();
+ });
+ });
+ });
+
+ it('should navigate back to fiscal data to confirm it have been edited', () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .getInputValue(selectors.clientFiscalData.socialNameInput)
+ .then(result => {
+ expect(result).toEqual('SMASH!');
+ });
+ });
+
+ it('should confirm the fiscal id have been edited', () => {
+ return nightmare
+ .getInputValue(selectors.clientFiscalData.fiscalIdInput)
+ .then(result => {
+ expect(result).toEqual('94980061C');
+ });
+ });
+
+ it('should confirm Equalization tax checkbox is checked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientFiscalData.equalizationTaxCheckboxLabel)
+ .then(value => {
+ expect(value).toBeTruthy();
+ });
+ });
+
+ it('should confirm the address have been edited', () => {
+ return nightmare
+ .getInputValue(selectors.clientFiscalData.addressInput)
+ .then(result => {
+ expect(result).toEqual('Somewhere edited');
+ });
+ });
+
+ it('should confirm the city have been edited', () => {
+ return nightmare
+ .getInputValue(selectors.clientFiscalData.cityInput)
+ .then(result => {
+ expect(result).toEqual('N/A');
+ });
+ });
+
+ it('should confirm the postcode have been edited', () => {
+ return nightmare
+ .getInputValue(selectors.clientFiscalData.postcodeInput)
+ .then(result => {
+ expect(result).toEqual('12345');
+ });
+ });
+
+ it(`should confirm the province have been selected`, () => {
+ return nightmare
+ .getInputValue(selectors.clientFiscalData.provinceInput)
+ .then(result => {
+ expect(result).toEqual('Province two');
+ });
+ });
+
+ it('should confirm active checkbox is unchecked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientFiscalData.activeCheckboxLabel)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+
+ it('should confirm invoice by address checkbox is unchecked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientFiscalData.invoiceByAddressCheckboxInput)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+
+ it('should confirm Verified data checkbox is checked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .then(value => {
+ expect(value).toBeTruthy();
+ });
+ });
+
+ it('should confirm Has to invoice checkbox is unchecked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientFiscalData.hasToInvoiceCheckboxLabel)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+
+ it('should confirm Invoice by mail checkbox is unchecked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientFiscalData.invoiceByMailCheckboxLabel)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+
+ it('should confirm Vies checkbox is checked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientFiscalData.viesCheckboxInput)
+ .then(value => {
+ expect(value).toBeTruthy();
+ });
+ });
+});
diff --git a/e2e/paths/client-module/04_edit_pay_method.spec.js b/e2e/paths/client-module/04_edit_pay_method.spec.js
new file mode 100644
index 000000000..108a5494e
--- /dev/null
+++ b/e2e/paths/client-module/04_edit_pay_method.spec.js
@@ -0,0 +1,122 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Edit pay method path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Bruce Banner', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client's pay method`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientPayMethod.payMethodButton)
+ .waitForURL('billing-data')
+ .url()
+ .then(url => {
+ expect(url).toContain('billing-data');
+ });
+ });
+
+ it(`should attempt to edit the Pay method without an IBAN but fail`, () => {
+ return nightmare
+ .waitToClick(selectors.clientPayMethod.payMethodInput)
+ .waitToClick(selectors.clientPayMethod.payMethodIBANOption)
+ .clearInput(selectors.clientPayMethod.dueDayInput)
+ .type(selectors.clientPayMethod.dueDayInput, '60')
+ .waitToClick(selectors.clientPayMethod.receivedCoreVNHCheckbox)
+ .waitToClick(selectors.clientPayMethod.receivedCoreVNLCheckbox)
+ .waitToClick(selectors.clientPayMethod.receivedB2BVNLCheckbox)
+ .waitToClick(selectors.clientPayMethod.saveButton)
+ .waitToClick(selectors.clientPayMethod.cancelNotificationButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Error');
+ });
+ });
+
+ it(`should add the IBAN`, () => {
+ return nightmare
+ .clearInput(selectors.clientPayMethod.IBANInput)
+ .type(selectors.clientPayMethod.IBANInput, 'ES91 2100 0418 4502 0005 1332')
+ .waitToClick(selectors.clientPayMethod.saveButton)
+ .waitToClick(selectors.clientPayMethod.cancelNotificationButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it(`should confirm the IBAN pay method is sucessfully saved`, () => {
+ return nightmare
+ .getInputValue(selectors.clientPayMethod.payMethodInput)
+ .then(result => {
+ expect(result).toEqual('PayMethod with IBAN');
+ });
+ });
+
+ it('should confirm the due day have been edited', () => {
+ return nightmare
+ .getInputValue(selectors.clientPayMethod.dueDayInput)
+ .then(result => {
+ expect(result).toEqual('60');
+ });
+ });
+
+ it('should confirm Received core VNH checkbox is unchecked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientPayMethod.receivedCoreVNHCheckbox)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+
+ it('should confirm Received core VNL checkbox is unchecked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientPayMethod.receivedCoreVNLCheckbox)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+
+ it('should confirm Received B2B VNL checkbox is unchecked', () => {
+ return nightmare
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientPayMethod.receivedB2BVNLCheckbox)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+});
diff --git a/e2e/paths/client-module/05_add_address.spec.js b/e2e/paths/client-module/05_add_address.spec.js
new file mode 100644
index 000000000..e765aea72
--- /dev/null
+++ b/e2e/paths/client-module/05_add_address.spec.js
@@ -0,0 +1,128 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Add address path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Bruce Banner', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client addresses`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientAddresses.addressesButton)
+ .waitForURL('addresses/list')
+ .url()
+ .then(url => {
+ expect(url).toContain('addresses/list');
+ });
+ });
+
+ it(`should click on the add new address button to access to the new address form`, () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.createAddress)
+ .waitForURL('addresses/create')
+ .url()
+ .then(url => {
+ expect(url).toContain('addresses/create');
+ });
+ });
+
+ it('should receive an error after clicking save button as consignee, street and town fields are empty', () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.defaultCheckboxInput)
+ .clearInput(selectors.clientAddresses.streetAddressInput)
+ .type(selectors.clientAddresses.postcodeInput, '10022')
+ .waitToClick(selectors.clientAddresses.provinceInput)
+ .waitToClick(selectors.clientAddresses.provinceSecondOption)
+ .waitToClick(selectors.clientAddresses.agencyInput)
+ .waitToClick(selectors.clientAddresses.agenctySecondOption)
+ .type(selectors.clientAddresses.phoneInput, '999887744')
+ .type(selectors.clientAddresses.mobileInput, '999887744')
+ .waitToClick(selectors.clientFiscalData.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Some fields are invalid');
+ });
+ });
+
+ it(`should create a new address with all it's data`, () => {
+ return nightmare
+ .type(selectors.clientAddresses.consigneeInput, 'Bruce Bunner')
+ .type(selectors.clientAddresses.streetAddressInput, '320 Park Avenue New York')
+ .type(selectors.clientAddresses.cityInput, 'New York')
+ .click(selectors.clientAddresses.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it(`should click on the addresses button confirm the new address exists and it's the default one`, () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.addressesButton)
+ .wait(selectors.clientAddresses.defaultAddress)
+ .getInnerText(selectors.clientAddresses.defaultAddress)
+ .then(result => {
+ expect(result).toContain('320 Park Avenue New York');
+ });
+ });
+
+ it(`should click on the make default icon of the second address then confirm it is the default one now`, () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.secondMakeDefaultStar)
+ .waitForTextInElement(selectors.clientAddresses.defaultAddress, 'Somewhere in Thailand')
+ .getInnerText(selectors.clientAddresses.defaultAddress)
+ .then(result => {
+ expect(result).toContain('Somewhere in Thailand');
+ });
+ });
+
+ it(`should click on the edit icon of the default address`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientAddresses.defaultAddress, 'Somewhere in Thailand')
+ .waitToClick(selectors.clientAddresses.firstEditButton)
+ .waitForURL('/edit')
+ .url()
+ .then(result => {
+ expect(result).toContain('/edit');
+ });
+ });
+
+ it(`should click on the active checkbox and receive an error to save it becouse it is the default address`, () => {
+ return nightmare
+ .waitToClick(selectors.clientAddresses.activeCheckbox)
+ .waitToClick(selectors.clientAddresses.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Error:');
+ });
+ });
+});
diff --git a/e2e/paths/client-module/06_add_address_notes.spec.js b/e2e/paths/client-module/06_add_address_notes.spec.js
new file mode 100644
index 000000000..0c2008bd0
--- /dev/null
+++ b/e2e/paths/client-module/06_add_address_notes.spec.js
@@ -0,0 +1,97 @@
+// import selectors from '../../helpers/selectors.js';
+// import createNightmare from '../../helpers/helpers';
+
+// describe('Add address notes path', () => {
+// const nightmare = createNightmare();
+
+// beforeAll(() => {
+// return nightmare
+// .waitForLogin('developer');
+// });
+
+// it('should click on the Clients button of the top bar menu', () => {
+// return nightmare
+// .waitToClick(selectors.globalItems.applicationsMenuButton)
+// .wait(selectors.globalItems.applicationsMenuVisible)
+// .waitToClick(selectors.globalItems.clientsButton)
+// .wait(selectors.clientsIndex.createClientButton)
+// .parsedUrl()
+// .then(url => {
+// expect(url.hash).toEqual('#!/clients');
+// });
+// });
+
+// it('should search for the user Petter Parker', () => {
+// return nightmare
+// .wait(selectors.clientsIndex.searchResult)
+// .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+// .click(selectors.clientsIndex.searchButton)
+// .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+// .countSearchResults(selectors.clientsIndex.searchResult)
+// .then(result => {
+// expect(result).toEqual(1);
+// });
+// });
+
+// it(`should click on the search result to access to the client addresses`, () => {
+// return nightmare
+// .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
+// .waitToClick(selectors.clientsIndex.searchResult)
+// .waitToClick(selectors.clientAddresses.addressesButton)
+// .waitForURL('addresses/list')
+// .url()
+// .then(url => {
+// expect(url).toContain('addresses/list');
+// });
+// });
+
+// it(`should click on the edit icon of the default address`, () => {
+// return nightmare
+// .waitForTextInElement(selectors.clientAddresses.defaultAddress, '20 Ingram Street')
+// .waitToClick(selectors.clientAddresses.firstEditButton)
+// .waitForURL('/edit')
+// .url()
+// .then(result => {
+// expect(result).toContain('/edit');
+// });
+// });
+
+// it('should not save a description without observation type', () => {
+// return nightmare
+// .waitToClick(selectors.clientAddresses.addObservationButton)
+// .wait(selectors.clientAddresses.firstObservationDescriptionInput)
+// .type(selectors.clientAddresses.firstObservationDescriptionInput, 'first description')
+// .waitToClick(selectors.clientAddresses.saveButton)
+// .waitForSnackbar()
+// .then(result => {
+// expect(result).toContain('Some fields are invalid');
+// });
+// });
+
+// it('should not save an observation type without description', () => {
+// return nightmare
+// .clearInput(selectors.clientAddresses.firstObservationDescriptionInput)
+// .waitToClick(selectors.clientAddresses.firstObservationTypeSelect)
+// .waitToClick(selectors.clientAddresses.firstObservationTypeSelectOptionOne)
+// .waitToClick(selectors.clientAddresses.saveButton)
+// .waitForSnackbar()
+// .then(result => {
+// expect(result).toContain('Some fields are invalid');
+// });
+// });
+
+// it('should create two new observations', () => {
+// return nightmare
+// .type(selectors.clientAddresses.firstObservationDescriptionInput, 'first description')
+// .waitToClick(selectors.clientAddresses.addObservationButton)
+// .waitToClick(selectors.clientAddresses.secondObservationTypeSelect)
+// .waitToClick(selectors.clientAddresses.secondObservationTypeSelectOptionTwo)
+// .type(selectors.clientAddresses.secondObservationDescriptionInput, 'second description')
+// .waitToClick(selectors.clientAddresses.saveButton)
+// .waitForSnackbar()
+// .then(result => {
+// expect(result).toContain('pepinillos saved!');
+// });
+// });
+// });
+
diff --git a/e2e/paths/client-module/07_edit_web_access.spec.js b/e2e/paths/client-module/07_edit_web_access.spec.js
new file mode 100644
index 000000000..bb0c29304
--- /dev/null
+++ b/e2e/paths/client-module/07_edit_web_access.spec.js
@@ -0,0 +1,78 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Edit web access path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Bruce Banner', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client's web access`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientWebAccess.webAccessButton)
+ .waitForURL('web-access')
+ .url()
+ .then(url => {
+ expect(url).toContain('web-access');
+ });
+ });
+
+ it(`should uncheck the Enable web access checkbox and update the name`, () => {
+ return nightmare
+ .waitToClick(selectors.clientWebAccess.enableWebAccessCheckbox)
+ .clearInput(selectors.clientWebAccess.userNameInput)
+ .type(selectors.clientWebAccess.userNameInput, 'Hulk')
+ .waitToClick(selectors.clientWebAccess.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain(`Data saved!`);
+ });
+ });
+
+ it('should confirm web access is unchecked and name updated', () => {
+ return nightmare
+ .waitToClick(selectors.clientBasicData.basicDataButton)
+ .wait(selectors.clientBasicData.nameInput)
+ .waitToClick(selectors.clientWebAccess.webAccessButton)
+ .wait(selectors.clientWebAccess.enableWebAccessCheckbox)
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientWebAccess.enableWebAccessCheckbox)
+ .then(value => {
+ expect(value).toBeFalsy();
+ return nightmare
+ .getInputValue(selectors.clientWebAccess.userNameInput);
+ })
+ .then(result => {
+ expect(result).toEqual('Hulk');
+ });
+ });
+});
diff --git a/e2e/paths/client-module/08_add_notes.spec.js b/e2e/paths/client-module/08_add_notes.spec.js
new file mode 100644
index 000000000..5193ee7d4
--- /dev/null
+++ b/e2e/paths/client-module/08_add_notes.spec.js
@@ -0,0 +1,76 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Add notes path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Bruce Banner', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client's notes`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientNotes.notesButton)
+ .waitForURL('notes/list')
+ .url()
+ .then(url => {
+ expect(url).toContain('notes/list');
+ });
+ });
+
+ it(`should click on the add note button`, () => {
+ return nightmare
+ .waitToClick(selectors.clientNotes.addNoteFloatButton)
+ .waitForURL('/notes/create')
+ .url()
+ .then(url => {
+ expect(url).toContain('/notes/create');
+ });
+ });
+
+ it(`should create a note`, () => {
+ return nightmare
+ .type(selectors.clientNotes.noteInput, 'Meeting with Black Widow 21st 9am')
+ .click(selectors.clientNotes.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it('should confirm the note was created', () => {
+ return nightmare
+ .wait(selectors.clientNotes.firstNoteText)
+ .getInnerText(selectors.clientNotes.firstNoteText)
+ .then(value => {
+ expect(value).toEqual('Meeting with Black Widow 21st 9am');
+ });
+ });
+});
diff --git a/e2e/paths/client-module/09_add_credit.spec.js b/e2e/paths/client-module/09_add_credit.spec.js
new file mode 100644
index 000000000..c5ad8088d
--- /dev/null
+++ b/e2e/paths/client-module/09_add_credit.spec.js
@@ -0,0 +1,78 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Add credit path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Petter Parker', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client's credit`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientCredit.creditButton)
+ .waitForURL('credit/list')
+ .url()
+ .then(url => {
+ expect(url).toContain('credit/list');
+ });
+ });
+
+ it(`should click on the add credit button`, () => {
+ return nightmare
+ .waitToClick(selectors.clientCredit.addCreditFloatButton)
+ .waitForURL('/credit/create')
+ .url()
+ .then(url => {
+ expect(url).toContain('/credit/create');
+ });
+ });
+
+ it(`should edit the credit`, () => {
+ return nightmare
+ .clearInput(selectors.clientCredit.creditInput)
+ .type(selectors.clientCredit.creditInput, 999)
+ .click(selectors.clientCredit.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it('should confirm the credit was updated', () => {
+ return nightmare
+ .wait(selectors.clientCredit.firstCreditText)
+ .getInnerText(selectors.clientCredit.firstCreditText)
+ .then(value => {
+ expect(value).toContain(999);
+ expect(value).toContain('developer');
+ });
+ });
+});
diff --git a/e2e/paths/client-module/10_add_greuge.spec.js b/e2e/paths/client-module/10_add_greuge.spec.js
new file mode 100644
index 000000000..9f8f93771
--- /dev/null
+++ b/e2e/paths/client-module/10_add_greuge.spec.js
@@ -0,0 +1,90 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Add greuge path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Petter Parker', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client's greuge`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientGreuge.greugeButton)
+ .waitForURL('greuge/list')
+ .url()
+ .then(url => {
+ expect(url).toContain('greuge/list');
+ });
+ });
+
+ it(`should click on the add greuge button`, () => {
+ return nightmare
+ .waitToClick(selectors.clientGreuge.addGreugeFloatButton)
+ .waitForURL('greuge/create')
+ .url()
+ .then(url => {
+ expect(url).toContain('greuge/create');
+ });
+ });
+
+ it(`should receive an error if all fields are empty but date and type on submit`, () => {
+ return nightmare
+ .waitToClick(selectors.clientGreuge.typeInput)
+ .waitToClick(selectors.clientGreuge.typeSecondOption)
+ .click(selectors.clientGreuge.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Some fields are invalid');
+ });
+ });
+
+ it(`should create a new greuge with all its data`, () => {
+ return nightmare
+ .type(selectors.clientGreuge.amountInput, 999)
+ .type(selectors.clientGreuge.descriptionInput, 'new armor for Batman!')
+ .click(selectors.clientGreuge.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it('should confirm the greuge was added to the list', () => {
+ return nightmare
+ .wait(selectors.clientGreuge.firstGreugeText)
+ .getInnerText(selectors.clientGreuge.firstGreugeText)
+ .then(value => {
+ expect(value).toContain(999);
+ expect(value).toContain('new armor for Batman!');
+ expect(value).toContain('Diff');
+ });
+ });
+});
diff --git a/e2e/paths/client-module/11_mandate.spec.js b/e2e/paths/client-module/11_mandate.spec.js
new file mode 100644
index 000000000..9728afa02
--- /dev/null
+++ b/e2e/paths/client-module/11_mandate.spec.js
@@ -0,0 +1,58 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('mandate path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Petter Parker', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client's mandate`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientMandate.mandateButton)
+ .waitForURL('mandate')
+ .url()
+ .then(url => {
+ expect(url).toContain('mandate');
+ });
+ });
+
+ it('should confirm the client has a mandate of the CORE type', () => {
+ return nightmare
+ .wait(selectors.clientMandate.firstMandateText)
+ .getInnerText(selectors.clientMandate.firstMandateText)
+ .then(value => {
+ expect(value).toContain('1');
+ expect(value).toContain('WAY');
+ expect(value).toContain('CORE');
+ });
+ });
+});
diff --git a/e2e/paths/client-module/12_lock_of_verified_data.spec.js b/e2e/paths/client-module/12_lock_of_verified_data.spec.js
new file mode 100644
index 000000000..764476e62
--- /dev/null
+++ b/e2e/paths/client-module/12_lock_of_verified_data.spec.js
@@ -0,0 +1,472 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('lock verified data path', () => {
+ const nightmare = createNightmare();
+
+ describe('as salesPerson', () => {
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('salesPerson');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Petter Parker', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client's fiscal data`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it(`should click on the fiscal data button to start editing`, () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it('should confirm verified data button is disabled for salesPerson', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .evaluate(selector => {
+ return document.querySelector(selector).className;
+ }, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(3) > label')
+ .then(result => {
+ expect(result).toContain('is-disabled');
+ });
+ });
+
+ it('should edit the social name', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .clearInput(selectors.clientFiscalData.socialNameInput)
+ .type(selectors.clientFiscalData.socialNameInput, 'salesPerson was here')
+ .click(selectors.clientFiscalData.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it('should confirm the social name have been edited', () => {
+ return nightmare
+ .waitToClick(selectors.clientBasicData.basicDataButton)
+ .wait(selectors.clientBasicData.nameInput)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .getInputValue(selectors.clientFiscalData.socialNameInput)
+ .then(result => {
+ expect(result).toEqual('salesPerson was here');
+ });
+ });
+ });
+
+ describe('as administrative', () => {
+ beforeAll(() => {
+ return nightmare
+ .waitToClick(selectors.globalItems.logOutButton)
+ .waitForLogin('administrative');
+ });
+
+ it('should navigate to clients index', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search again for the user Petter Parker', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the Petter Parkers fiscal data`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it(`should click on the fiscal data button`, () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it('should confirm verified data button is enabled for administrative', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .evaluate(selector => {
+ return document.querySelector(selector).className;
+ }, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(3) > label')
+ .then(result => {
+ expect(result).not.toContain('is-disabled');
+ });
+ });
+
+ it('should check the Verified data checkbox', () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .waitToClick(selectors.clientFiscalData.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it('should confirm Verified data checkbox is checked', () => {
+ return nightmare
+ .waitToClick(selectors.clientBasicData.basicDataButton)
+ .wait(selectors.clientBasicData.nameInput)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .then(value => {
+ expect(value).toBeTruthy();
+ });
+ });
+
+ it('should again edit the social name', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .clearInput(selectors.clientFiscalData.socialNameInput)
+ .type(selectors.clientFiscalData.socialNameInput, 'administrative was here')
+ .click(selectors.clientFiscalData.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it('should confirm the social name have been edited once and for all', () => {
+ return nightmare
+ .waitToClick(selectors.clientBasicData.basicDataButton)
+ .wait(selectors.clientBasicData.nameInput)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .getInputValue(selectors.clientFiscalData.socialNameInput)
+ .then(result => {
+ expect(result).toEqual('administrative was here');
+ });
+ });
+ });
+
+ describe('as salesPerson second run', () => {
+ beforeAll(() => {
+ return nightmare
+ .waitToClick(selectors.globalItems.logOutButton)
+ .waitForLogin('salesPerson');
+ });
+
+ it('should again click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should again search for the user Petter Parker', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client's fiscal data`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it(`should click on the fiscal data button to start editing`, () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it('should confirm verified data button is disabled once again for salesPerson', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .evaluate(selector => {
+ return document.querySelector(selector).className;
+ }, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(3) > label')
+ .then(result => {
+ expect(result).toContain('is-disabled');
+ });
+ });
+
+ it('should confirm the form have been disabled for salesPerson', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .evaluate(selector => {
+ return document.querySelector(selector).className;
+ }, 'vn-textfield[field="$ctrl.client.socialName"] > div')
+ .then(result => {
+ expect(result).toContain('is-disabled');
+ });
+ });
+ });
+
+ describe('as salesAssistant', () => {
+ beforeAll(() => {
+ return nightmare
+ .waitToClick(selectors.globalItems.logOutButton)
+ .waitForLogin('salesAssistant');
+ });
+
+ it('should navigate to clients index', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search again for the user Petter Parker', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the Petter Parkers fiscal data`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it(`should click on the fiscal data button`, () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it('should confirm verified data button is enabled for salesAssistant', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .evaluate(selector => {
+ return document.querySelector(selector).className;
+ }, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(3) > label')
+ .then(result => {
+ expect(result).not.toContain('is-disabled');
+ });
+ });
+
+ it('should uncheck the Verified data checkbox', () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .waitToClick(selectors.clientFiscalData.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it('should confirm Verified data checkbox is unchecked', () => {
+ return nightmare
+ .waitToClick(selectors.clientBasicData.basicDataButton)
+ .wait(selectors.clientBasicData.nameInput)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .evaluate(selector => {
+ return document.querySelector(selector).checked;
+ }, selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .then(value => {
+ expect(value).toBeFalsy();
+ });
+ });
+
+ it('should again edit the social name', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .clearInput(selectors.clientFiscalData.socialNameInput)
+ .type(selectors.clientFiscalData.socialNameInput, 'salesAssistant was here')
+ .click(selectors.clientFiscalData.saveButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toEqual('Data saved!');
+ });
+ });
+
+ it('should confirm the social name have been edited once and for all', () => {
+ return nightmare
+ .waitToClick(selectors.clientBasicData.basicDataButton)
+ .wait(selectors.clientBasicData.nameInput)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .getInputValue(selectors.clientFiscalData.socialNameInput)
+ .then(result => {
+ expect(result).toEqual('salesAssistant was here');
+ });
+ });
+ });
+
+ describe('as salesPerson third run', () => {
+ beforeAll(() => {
+ return nightmare
+ .waitToClick(selectors.globalItems.logOutButton)
+ .waitForLogin('salesPerson');
+ });
+
+ it('should again click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should once again search for the user Petter Parker', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client's fiscal data`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it(`should click on the fiscal data button to start editing`, () => {
+ return nightmare
+ .waitToClick(selectors.clientFiscalData.fiscalDataButton)
+ .waitForURL('fiscal-data')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('fiscal-data');
+ });
+ });
+
+ it('should confirm verified data button is enabled once again', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
+ .evaluate(selector => {
+ return document.querySelector(selector).className;
+ }, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(3) > label')
+ .then(result => {
+ expect(result).toContain('is-disabled');
+ });
+ });
+
+ it('should confirm the form is enabled for salesPerson', () => {
+ return nightmare
+ .wait(selectors.clientFiscalData.socialNameInput)
+ .evaluate(selector => {
+ return document.querySelector(selector).className;
+ }, 'vn-textfield[field="$ctrl.client.socialName"] > div')
+ .then(result => {
+ expect(result).not.toContain('is-disabled');
+ });
+ });
+ });
+});
diff --git a/e2e/paths/client-module/13_invoices.spec.js b/e2e/paths/client-module/13_invoices.spec.js
new file mode 100644
index 000000000..1bc5bec99
--- /dev/null
+++ b/e2e/paths/client-module/13_invoices.spec.js
@@ -0,0 +1,57 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('invoice path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should click on the Clients button of the top bar menu', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .wait(selectors.globalItems.applicationsMenuVisible)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should search for the user Petter Parker', () => {
+ return nightmare
+ .wait(selectors.clientsIndex.searchResult)
+ .type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
+ .click(selectors.clientsIndex.searchButton)
+ .waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
+ .countSearchResults(selectors.clientsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the client invoices`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter')
+ .waitToClick(selectors.clientsIndex.searchResult)
+ .waitToClick(selectors.clientInvoices.invoicesButton)
+ .waitForURL('invoices')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('invoices');
+ });
+ });
+
+ it('should confirm the client has an invoice', () => {
+ return nightmare
+ .wait(selectors.clientInvoices.firstInvoiceText)
+ .getInnerText(selectors.clientInvoices.firstInvoiceText)
+ .then(value => {
+ expect(value).toContain('V1800001');
+ expect(value).toContain('350.50');
+ });
+ });
+});
diff --git a/e2e/paths/item-module/01_item_summary.spec.js b/e2e/paths/item-module/01_item_summary.spec.js
new file mode 100644
index 000000000..5100a84c5
--- /dev/null
+++ b/e2e/paths/item-module/01_item_summary.spec.js
@@ -0,0 +1,141 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Item summary path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should access to the items index by clicking the items button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.itemsSectionButton)
+ .wait(selectors.itemsIndex.createItemButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/item/list');
+ });
+ });
+
+ it('should search for the item Gem of Time', () => {
+ return nightmare
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Gem of Time')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result summary button to open the item summary popup`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Time')
+ .isVisible(selectors.itemSummary.basicData)
+ .then(result => {
+ expect(result).toBeFalsy();
+ return nightmare
+ .waitToClick(selectors.itemsIndex.searchResultPreviewButton)
+ .isVisible(selectors.itemSummary.basicData);
+ })
+ .then(result => {
+ expect(result).toBeTruthy();
+ });
+ });
+
+ it(`should check the item summary preview shows fields from basic data`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemSummary.basicData, 'Name: Gem of Time')
+ .getInnerText(selectors.itemSummary.basicData)
+ .then(result => {
+ expect(result).toContain('Name: Gem of Time');
+ });
+ });
+
+ it(`should check the item summary preview shows fields from tags`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemSummary.tags, 'Color: Yellow')
+ .getInnerText(selectors.itemSummary.tags)
+ .then(result => {
+ expect(result).toContain('Color: Yellow');
+ });
+ });
+
+ it(`should check the item summary preview shows fields from niche`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemSummary.niche, 'Warehouse One: A1')
+ .getInnerText(selectors.itemSummary.niche)
+ .then(result => {
+ expect(result).toContain('Warehouse One: A1');
+ });
+ });
+
+ it(`should check the item summary preview shows fields from botanical`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemSummary.botanical, 'Botanical: Hedera helix')
+ .getInnerText(selectors.itemSummary.botanical)
+ .then(result => {
+ expect(result).toContain('Botanical: Hedera helix');
+ });
+ });
+
+ it(`should check the item summary preview shows fields from barcode`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemSummary.barcode, '1')
+ .getInnerText(selectors.itemSummary.barcode)
+ .then(result => {
+ expect(result).toContain('1');
+ });
+ });
+
+ it(`should close the summary popup`, () => {
+ return nightmare
+ .waitToClick(selectors.itemsIndex.closeItemSummaryPreview)
+ .isVisible(selectors.itemSummary.basicData)
+ .then(result => {
+ expect(result).toBeFalsy();
+ });
+ });
+
+ it(`should navigate to the one of the items detailed section`, () => {
+ return nightmare
+ .waitToClick(selectors.itemsIndex.searchResult)
+ .waitForURL('summary')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('summary');
+ });
+ });
+
+ it(`should check the item summary shows fields from all its sections`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemSummary.basicData, 'Name: Gem of Time')
+ .getInnerText(selectors.itemSummary.basicData)
+ .then(result => {
+ expect(result).toContain('Name: Gem of Time');
+ return nightmare
+ .getInnerText(selectors.itemSummary.tags);
+ })
+ .then(result => {
+ expect(result).toContain('Color: Yellow');
+ return nightmare
+ .getInnerText(selectors.itemSummary.niche);
+ })
+ .then(result => {
+ expect(result).toContain('Warehouse One: A1');
+ return nightmare
+ .getInnerText(selectors.itemSummary.botanical);
+ })
+ .then(result => {
+ expect(result).toContain('Botanical: Hedera helix');
+ return nightmare
+ .getInnerText(selectors.itemSummary.barcode);
+ })
+ .then(result => {
+ expect(result).toContain('1');
+ });
+ });
+});
diff --git a/e2e/paths/item-module/02_edit_item_basic_data.spec.js b/e2e/paths/item-module/02_edit_item_basic_data.spec.js
new file mode 100644
index 000000000..c2de03c06
--- /dev/null
+++ b/e2e/paths/item-module/02_edit_item_basic_data.spec.js
@@ -0,0 +1,117 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('edit item basic data path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should access to the items index by clicking the items button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.itemsSectionButton)
+ .wait(selectors.itemsIndex.createItemButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/item/list');
+ });
+ });
+
+ it('should search for the item Gem of Mind', () => {
+ return nightmare
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Gem of Mind')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the item basic data`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Mind')
+ .waitToClick(selectors.itemsIndex.searchResult)
+ .waitToClick(selectors.itemBasicData.basicDataButton)
+ .waitForURL('data')
+ .url()
+ .then(url => {
+ expect(url).toContain('data');
+ });
+ });
+
+ it(`should edit the item basic data`, () => {
+ return nightmare
+ .clearInput(selectors.itemBasicData.nameInput)
+ .type(selectors.itemBasicData.nameInput, 'Rose of Purity')
+ .waitToClick(selectors.itemBasicData.typeSelect)
+ .waitToClick(selectors.itemBasicData.typeSelectOptionTwo)
+ .waitToClick(selectors.itemBasicData.intrastatSelect)
+ .waitToClick(selectors.itemBasicData.intrastatSelectOptionOne)
+ .clearInput(selectors.itemBasicData.relevancyInput)
+ .type(selectors.itemBasicData.relevancyInput, '1')
+ .waitToClick(selectors.itemBasicData.originSelect)
+ .waitToClick(selectors.itemBasicData.originSelectOptionTwo)
+ .waitToClick(selectors.itemBasicData.expenceSelect)
+ .waitToClick(selectors.itemBasicData.expenceSelectOptionTwo)
+ .click(selectors.itemBasicData.submitBasicDataButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it(`should confirm the item name was edited`, () => {
+ return nightmare
+ .click(selectors.itemNiches.firstCodeInput)
+ .wait(selectors.itemNiches.firstCodeInput)
+ .waitToClick(selectors.itemBasicData.basicDataButton)
+ .getInputValue(selectors.itemBasicData.nameInput)
+ .then(result => {
+ expect(result).toEqual('Rose of Purity');
+ });
+ });
+
+ it(`should confirm the item type was edited`, () => {
+ return nightmare
+ .getInputValue(selectors.itemBasicData.typeSelect)
+ .then(result => {
+ expect(result).toEqual('Crisantemo');
+ });
+ });
+
+ it(`should confirm the item intrastad was edited`, () => {
+ return nightmare
+ .getInputValue(selectors.itemBasicData.intrastatSelect)
+ .then(result => {
+ expect(result).toEqual('Coral y materiales similares');
+ });
+ });
+
+ it(`should confirm the item relevancy was edited`, () => {
+ return nightmare
+ .getInputValue(selectors.itemBasicData.relevancyInput)
+ .then(result => {
+ expect(result).toEqual('1');
+ });
+ });
+
+ it(`should confirm the item origin was edited`, () => {
+ return nightmare
+ .getInputValue(selectors.itemBasicData.originSelect)
+ .then(result => {
+ expect(result).toEqual('Spain');
+ });
+ });
+
+ it(`should confirm the item expence was edited`, () => {
+ return nightmare
+ .getInputValue(selectors.itemBasicData.expenceSelect)
+ .then(result => {
+ expect(result).toEqual('loan');
+ });
+ });
+});
diff --git a/e2e/paths/item-module/03_edit_item_tax.spec.js b/e2e/paths/item-module/03_edit_item_tax.spec.js
new file mode 100644
index 000000000..07bb75414
--- /dev/null
+++ b/e2e/paths/item-module/03_edit_item_tax.spec.js
@@ -0,0 +1,82 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('add item tax path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should access to the items index by clicking the items button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.itemsSectionButton)
+ .wait(selectors.itemsIndex.createItemButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/item/list');
+ });
+ });
+
+ it('should search for the item Gem of Time', () => {
+ return nightmare
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Gem of Time')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the item tax`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Time')
+ .waitToClick(selectors.itemsIndex.searchResult)
+ .waitToClick(selectors.itemTax.taxButton)
+ .waitForURL('tax')
+ .url()
+ .then(url => {
+ expect(url).toContain('tax');
+ });
+ });
+
+ it(`should add the item tax to all countries`, () => {
+ return nightmare
+ .waitToClick(selectors.itemTax.firstClassSelect)
+ .waitToClick(selectors.itemTax.firstClassSelectOptionTwo)
+ .waitToClick(selectors.itemTax.secondClassSelect)
+ .waitToClick(selectors.itemTax.secondClassSelectOptionOne)
+ .waitToClick(selectors.itemTax.thirdClassSelect)
+ .waitToClick(selectors.itemTax.thirdClassSelectOptionTwo)
+ .click(selectors.itemTax.submitTaxButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it(`should confirm the item tax class was edited`, () => {
+ return nightmare
+ .click(selectors.itemTags.tagsButton)
+ .wait(selectors.itemTags.firstTagSelect)
+ .waitToClick(selectors.itemTax.taxButton)
+ .waitForTextInInput(selectors.itemTax.firstClassSelect, 'general')
+ .getInputValue(selectors.itemTax.firstClassSelect)
+ .then(result => {
+ expect(result).toEqual('General VAT');
+ return nightmare
+ .getInputValue(selectors.itemTax.secondClassSelect);
+ })
+ .then(result => {
+ expect(result).toEqual('Reduced VAT');
+ return nightmare
+ .getInputValue(selectors.itemTax.thirdClassSelect);
+ })
+ .then(result => {
+ expect(result).toEqual('General VAT');
+ });
+ });
+});
diff --git a/e2e/paths/item-module/04_create_item_tags.spec.js b/e2e/paths/item-module/04_create_item_tags.spec.js
new file mode 100644
index 000000000..19d9ef26a
--- /dev/null
+++ b/e2e/paths/item-module/04_create_item_tags.spec.js
@@ -0,0 +1,206 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('create item tags path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should access to the items index by clicking the items button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.itemsSectionButton)
+ .wait(selectors.itemsIndex.createItemButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/item/list');
+ });
+ });
+
+ it('should search for the item Gem of Time', () => {
+ return nightmare
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Gem of Time')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the item tags`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Time')
+ .waitToClick(selectors.itemsIndex.searchResult)
+ .waitToClick(selectors.itemTags.tagsButton)
+ .waitForURL('tags')
+ .url()
+ .then(url => {
+ expect(url).toContain('tags');
+ });
+ });
+
+ it(`should create a new tag, edit another and delete a former one`, () => {
+ return nightmare
+ .waitToClick(selectors.itemTags.firstTagSelect)
+ .waitToClick(selectors.itemTags.firstTagSelectOptionOne)
+ .clearInput(selectors.itemTags.firstValueInput)
+ .type(selectors.itemTags.firstValueInput, 'Dark Blue')
+ .clearInput(selectors.itemTags.firstRelevancyInput)
+ .type(selectors.itemTags.firstRelevancyInput, '2')
+ .waitToClick(selectors.itemTags.fifthRemoveTagButton)
+ .waitToClick(selectors.itemTags.addItemTagButton)
+ .waitToClick(selectors.itemTags.fifthTagSelect)
+ .waitToClick(selectors.itemTags.fifthTagSelectOptionFive)
+ .type(selectors.itemTags.fifthValueInput, 'Thanos')
+ .type(selectors.itemTags.fifthRelevancyInput, '1')
+ .clearInput(selectors.itemTags.secondRelevancyInput)
+ .type(selectors.itemTags.secondRelevancyInput, '5')
+ .click(selectors.itemTags.submitItemTagsButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it(`should confirm the first select is the expected one`, () => {
+ return nightmare
+ .click(selectors.itemBasicData.basicDataButton)
+ .wait(selectors.itemBasicData.nameInput)
+ .click(selectors.itemTags.tagsButton)
+ .waitForTextInInput(selectors.itemTags.firstTagSelect, 'Owner')
+ .getInputValue(selectors.itemTags.firstTagSelect)
+ .then(result => {
+ expect(result).toEqual('Owner');
+ });
+ });
+
+ it(`should confirm the first value is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.firstValueInput, 'Thanos')
+ .getInputValue(selectors.itemTags.firstValueInput)
+ .then(result => {
+ expect(result).toEqual('Thanos');
+ });
+ });
+
+ it(`should confirm the first relevancy is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.firstRelevancyInput, '1')
+ .getInputValue(selectors.itemTags.firstRelevancyInput)
+ .then(result => {
+ expect(result).toEqual('1');
+ });
+ });
+
+ it(`should confirm the second select is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.secondTagSelect, 'Color')
+ .getInputValue(selectors.itemTags.secondTagSelect)
+ .then(result => {
+ expect(result).toEqual('Color');
+ });
+ });
+
+ it(`should confirm the second value is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.secondValueInput, 'Dark Blue')
+ .getInputValue(selectors.itemTags.secondValueInput)
+ .then(result => {
+ expect(result).toEqual('Dark Blue');
+ });
+ });
+
+ it(`should confirm the second relevancy is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.secondRelevancyInput, '2')
+ .getInputValue(selectors.itemTags.secondRelevancyInput)
+ .then(result => {
+ expect(result).toEqual('2');
+ });
+ });
+
+ it(`should confirm the third select is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.thirdTagSelect, 'Shape')
+ .getInputValue(selectors.itemTags.thirdTagSelect)
+ .then(result => {
+ expect(result).toEqual('Shape');
+ });
+ });
+
+ it(`should confirm the third value is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.thirdValueInput, 'round')
+ .getInputValue(selectors.itemTags.thirdValueInput)
+ .then(result => {
+ expect(result).toEqual('round');
+ });
+ });
+
+ it(`should confirm the third relevancy is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.thirdRelevancyInput, '3')
+ .getInputValue(selectors.itemTags.thirdRelevancyInput)
+ .then(result => {
+ expect(result).toEqual('3');
+ });
+ });
+
+ it(`should confirm the fourth select is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.fourthTagSelect, 'Power')
+ .getInputValue(selectors.itemTags.fourthTagSelect)
+ .then(result => {
+ expect(result).toEqual('Power');
+ });
+ });
+
+ it(`should confirm the fourth value is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.fourthValueInput, 'Manipulates time')
+ .getInputValue(selectors.itemTags.fourthValueInput)
+ .then(result => {
+ expect(result).toEqual('Manipulates time');
+ });
+ });
+
+ it(`should confirm the fourth relevancy is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.fourthRelevancyInput, '4')
+ .getInputValue(selectors.itemTags.fourthRelevancyInput)
+ .then(result => {
+ expect(result).toEqual('4');
+ });
+ });
+
+ it(`should confirm the fifth select is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.fifthTagSelect, 'Location')
+ .getInputValue(selectors.itemTags.fifthTagSelect)
+ .then(result => {
+ expect(result).toEqual('Location');
+ });
+ });
+
+ it(`should confirm the fifth value is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.fifthValueInput, 'Gamoras hideout')
+ .getInputValue(selectors.itemTags.fifthValueInput)
+ .then(result => {
+ expect(result).toEqual('Gamoras hideout');
+ });
+ });
+
+ it(`should confirm the fifth relevancy is the expected one`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemTags.fifthRelevancyInput, '5')
+ .getInputValue(selectors.itemTags.fifthRelevancyInput)
+ .then(result => {
+ expect(result).toEqual('5');
+ });
+ });
+});
diff --git a/e2e/paths/item-module/05_create_item_niche.spec.js b/e2e/paths/item-module/05_create_item_niche.spec.js
new file mode 100644
index 000000000..588dad678
--- /dev/null
+++ b/e2e/paths/item-module/05_create_item_niche.spec.js
@@ -0,0 +1,106 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('create item niche path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should access to the items index by clicking the items button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.itemsSectionButton)
+ .wait(selectors.itemsIndex.createItemButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/item/list');
+ });
+ });
+
+ it('should search for the item Gem of Time', () => {
+ return nightmare
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Gem of Time')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the item niches`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Time')
+ .waitToClick(selectors.itemsIndex.searchResult)
+ .waitToClick(selectors.itemNiches.nicheButton)
+ .waitForURL('niche')
+ .url()
+ .then(url => {
+ expect(url).toContain('niche');
+ });
+ });
+
+ it(`should click create a new niche, edit another and delete a former one`, () => {
+ return nightmare
+ .waitToClick(selectors.itemNiches.addNicheButton)
+ .waitToClick(selectors.itemNiches.firstWarehouseSelect)
+ .waitToClick(selectors.itemNiches.firstWarehouseSelectSecondOption)
+ .clearInput(selectors.itemNiches.firstCodeInput)
+ .type(selectors.itemNiches.firstCodeInput, 'A2')
+ .waitToClick(selectors.itemNiches.secondNicheRemoveButton)
+ .waitToClick(selectors.itemNiches.thirdWarehouseSelect)
+ .waitToClick(selectors.itemNiches.thirdWarehouseSelectFourthOption)
+ .type(selectors.itemNiches.thirdCodeInput, 'A4')
+ .click(selectors.itemNiches.submitNichesButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it(`should confirm the first niche is the expected one`, () => {
+ return nightmare
+ .click(selectors.itemBasicData.basicDataButton)
+ .wait(selectors.itemBasicData.nameInput)
+ .click(selectors.itemNiches.nicheButton)
+ .waitForTextInInput(selectors.itemNiches.firstWarehouseSelect, 'Warehouse Two')
+ .getInputValue(selectors.itemNiches.firstWarehouseSelect)
+ .then(result => {
+ expect(result).toEqual('Warehouse Two');
+ return nightmare
+ .getInputValue(selectors.itemNiches.firstCodeInput);
+ })
+ .then(result => {
+ expect(result).toEqual('A2');
+ });
+ });
+
+ it(`should confirm the second niche is the expected one`, () => {
+ return nightmare
+ .getInputValue(selectors.itemNiches.secondWarehouseSelect)
+ .then(result => {
+ expect(result).toEqual('Warehouse Three');
+ return nightmare
+ .getInputValue(selectors.itemNiches.secondCodeInput);
+ })
+ .then(result => {
+ expect(result).toEqual('A3');
+ });
+ });
+
+ it(`should confirm the third niche is the expected one`, () => {
+ return nightmare
+ .getInputValue(selectors.itemNiches.thirdWarehouseSelect)
+ .then(result => {
+ expect(result).toEqual('Warehouse Four');
+ return nightmare
+ .getInputValue(selectors.itemNiches.thirdCodeInput);
+ })
+ .then(result => {
+ expect(result).toEqual('A4');
+ });
+ });
+});
diff --git a/e2e/paths/item-module/06_create_item_botanical.spec.js b/e2e/paths/item-module/06_create_item_botanical.spec.js
new file mode 100644
index 000000000..18462c2a6
--- /dev/null
+++ b/e2e/paths/item-module/06_create_item_botanical.spec.js
@@ -0,0 +1,132 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('create item botanical path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should access to the items index by clicking the items button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.itemsSectionButton)
+ .wait(selectors.itemsIndex.createItemButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/item/list');
+ });
+ });
+
+ it('should search for the item Gem of Time', () => {
+ return nightmare
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Mjolnir')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the item botanical`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemsIndex.searchResult, 'Mjolnir')
+ .waitToClick(selectors.itemsIndex.searchResult)
+ .waitToClick(selectors.itemBotanical.botanicalButton)
+ .waitForURL('botanical')
+ .url()
+ .then(url => {
+ expect(url).toContain('botanical');
+ });
+ });
+
+ it(`should create a new botanical for the item with id Mjolnir`, () => {
+ return nightmare
+ .type(selectors.itemBotanical.botanicalInput, 'Cicuta maculata')
+ .waitToClick(selectors.itemBotanical.genusSelect)
+ .waitToClick(selectors.itemBotanical.genusSelectOptionOne)
+ .waitToClick(selectors.itemBotanical.speciesSelect)
+ .waitToClick(selectors.itemBotanical.speciesSelectOptionOne)
+ .waitToClick(selectors.itemBotanical.submitBotanicalButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it(`should confirm the botanical for item Mjolnir was created`, () => {
+ return nightmare
+ .click(selectors.itemBasicData.basicDataButton)
+ .wait(selectors.itemBasicData.nameInput)
+ .click(selectors.itemBotanical.botanicalButton)
+ .waitForTextInInput(selectors.itemBotanical.botanicalInput, 'Cicuta maculata')
+ .getInputValue(selectors.itemBotanical.botanicalInput)
+ .then(result => {
+ expect(result).toEqual('Cicuta maculata');
+ });
+ });
+
+ it(`should confirm the Genus for item Mjolnir was created`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemBotanical.genusSelect, 'Abelia')
+ .getInputValue(selectors.itemBotanical.genusSelect)
+ .then(result => {
+ expect(result).toEqual('Abelia');
+ });
+ });
+
+ it(`should confirm the Species for item Mjolnir was created`, () => {
+ return nightmare
+ .getInputValue(selectors.itemBotanical.speciesSelect)
+ .then(result => {
+ expect(result).toEqual('dealbata');
+ });
+ });
+
+ it(`should edit botanical for the item Mjolnir`, () => {
+ return nightmare
+ .clearInput(selectors.itemBotanical.botanicalInput)
+ .type(selectors.itemBotanical.botanicalInput, 'Herp Derp')
+ .waitToClick(selectors.itemBotanical.genusSelect)
+ .waitToClick(selectors.itemBotanical.genusSelectOptionTwo)
+ .waitToClick(selectors.itemBotanical.speciesSelect)
+ .waitToClick(selectors.itemBotanical.speciesSelectOptionTwo)
+ .waitToClick(selectors.itemBotanical.submitBotanicalButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it(`should confirm the botanical for item Mjolnir was edited`, () => {
+ return nightmare
+ .click(selectors.itemBasicData.basicDataButton)
+ .wait(selectors.itemBasicData.nameInput)
+ .click(selectors.itemBotanical.botanicalButton)
+ .waitForTextInInput(selectors.itemBotanical.botanicalInput, 'Herp Derp')
+ .getInputValue(selectors.itemBotanical.botanicalInput)
+ .then(result => {
+ expect(result).toEqual('Herp Derp');
+ });
+ });
+
+ it(`should confirm the Genus for item Mjolnir was edited`, () => {
+ return nightmare
+ .waitForTextInInput(selectors.itemBotanical.genusSelect, 'Abies')
+ .getInputValue(selectors.itemBotanical.genusSelect)
+ .then(result => {
+ expect(result).toEqual('Abies');
+ });
+ });
+
+ it(`should confirm the Species for item Mjolnir was edited`, () => {
+ return nightmare
+ .getInputValue(selectors.itemBotanical.speciesSelect)
+ .then(result => {
+ expect(result).toEqual('decurrens');
+ });
+ });
+});
diff --git a/e2e/paths/item-module/07_create_item_barcode.spec.js b/e2e/paths/item-module/07_create_item_barcode.spec.js
new file mode 100644
index 000000000..f2900988a
--- /dev/null
+++ b/e2e/paths/item-module/07_create_item_barcode.spec.js
@@ -0,0 +1,70 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('create item barcodes path', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should access to the items index by clicking the items button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.itemsSectionButton)
+ .wait(selectors.itemsIndex.createItemButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/item/list');
+ });
+ });
+
+ it('should search for the item Gem of Time', () => {
+ return nightmare
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Gem of Time')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should click on the search result to access to the item barcodes`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Time')
+ .waitToClick(selectors.itemsIndex.searchResult)
+ .waitToClick(selectors.itemBarcodes.barcodeButton)
+ .waitForURL('barcode')
+ .url()
+ .then(url => {
+ expect(url).toContain('barcode');
+ });
+ });
+
+ it(`should click create a new code and delete a former one`, () => {
+ return nightmare
+ .waitToClick(selectors.itemBarcodes.firstCodeRemoveButton)
+ .waitToClick(selectors.itemBarcodes.addBarcodeButton)
+ .wait(selectors.itemBarcodes.thirdCodeInput)
+ .type(selectors.itemBarcodes.thirdCodeInput, '5')
+ .waitToClick(selectors.itemBarcodes.submitBarcodesButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it(`should confirm the barcode 5 is created and it is now the third barcode as the first was deleted`, () => {
+ return nightmare
+ .click(selectors.itemBasicData.basicDataButton)
+ .wait(selectors.itemBasicData.nameInput)
+ .click(selectors.itemBarcodes.barcodeButton)
+ .waitForTextInInput(selectors.itemBarcodes.thirdCodeInput, '5')
+ .getInputValue(selectors.itemBarcodes.thirdCodeInput)
+ .then(result => {
+ expect(result).toEqual('5');
+ });
+ });
+});
diff --git a/e2e/paths/item-module/08_item_create_and_clone.spec.js b/e2e/paths/item-module/08_item_create_and_clone.spec.js
new file mode 100644
index 000000000..a4a54263a
--- /dev/null
+++ b/e2e/paths/item-module/08_item_create_and_clone.spec.js
@@ -0,0 +1,142 @@
+import selectors from '../../helpers/selectors.js';
+import createNightmare from '../../helpers/helpers';
+
+describe('Item', () => {
+ const nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ describe('create path', () => {
+ it('should access to the items index by clicking the items button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.itemsSectionButton)
+ .wait(selectors.itemsIndex.createItemButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/item/list');
+ });
+ });
+
+ it(`should search for the item Infinity Gauntlet to confirm it isn't created yet`, () => {
+ return nightmare
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Infinity Gauntlet')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 0)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(0);
+ });
+ });
+
+ it('should access to the create item view by clicking the create floating button', () => {
+ return nightmare
+ .click(selectors.itemsIndex.createItemButton)
+ .wait(selectors.itemCreateView.createButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/item/create');
+ });
+ });
+
+ it('should create the Infinity Gauntlet item', () => {
+ return nightmare
+ .type(selectors.itemCreateView.name, 'Infinity Gauntlet')
+ .waitToClick(selectors.itemCreateView.typeSelect)
+ .waitToClick(selectors.itemCreateView.typeSelectOptionOne)
+ .waitToClick(selectors.itemCreateView.intrastatSelect)
+ .waitToClick(selectors.itemCreateView.intrastatSelectOptionOne)
+ .waitToClick(selectors.itemCreateView.originSelect)
+ .waitToClick(selectors.itemCreateView.originSelectOptionOne)
+ .waitToClick(selectors.itemCreateView.expenceSelect)
+ .waitToClick(selectors.itemCreateView.expenceSelectOptionOne)
+ .click(selectors.itemCreateView.createButton)
+ .waitForSnackbar()
+ .then(result => {
+ expect(result).toContain('Data saved!');
+ });
+ });
+
+ it('should confirm Infinity Gauntlet item was created', () => {
+ return nightmare
+ .wait(selectors.itemBasicData.nameInput)
+ .getInputValue(selectors.itemBasicData.nameInput)
+ .then(result => {
+ expect(result).toBe('Infinity Gauntlet');
+ return nightmare
+ .getInputValue(selectors.itemBasicData.typeSelect);
+ })
+ .then(result => {
+ expect(result).toBe('Crisantemo');
+ return nightmare
+ .getInputValue(selectors.itemBasicData.intrastatSelect);
+ })
+ .then(result => {
+ expect(result).toBe('Plantas vivas: Esqueje/injerto, Vid');
+ return nightmare
+ .getInputValue(selectors.itemBasicData.originSelect);
+ })
+ .then(result => {
+ expect(result).toBe('Spain');
+ return nightmare
+ .getInputValue(selectors.itemBasicData.expenceSelect);
+ })
+ .then(result => {
+ expect(result).toBe('loan');
+ });
+ });
+ });
+
+ describe('clone path', () => {
+ it('should return to the items index by clicking the return to items button', () => {
+ return nightmare
+ .click(selectors.itemBasicData.goToItemIndexButton)
+ .wait(selectors.itemsIndex.createItemButton)
+ .waitForURL('#!/item/list')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('#!/item/list');
+ });
+ });
+
+ it(`should search for the item Infinity Gauntlet`, () => {
+ return nightmare
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Infinity Gauntlet')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(1);
+ });
+ });
+
+ it(`should clone the Infinity Gauntlet`, () => {
+ return nightmare
+ .waitForTextInElement(selectors.itemsIndex.searchResult, 'Infinity Gauntlet')
+ .click(selectors.itemsIndex.searchResultCloneButton)
+ .waitToClick(selectors.itemsIndex.acceptClonationAlertButton)
+ .waitForURL('tags')
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toContain('tags');
+ });
+ });
+
+ it('should search for the item Infinity Gauntlet and find two', () => {
+ return nightmare
+ .waitToClick(selectors.itemTags.goToItemIndexButton)
+ .wait(selectors.itemsIndex.searchResult)
+ .type(selectors.itemsIndex.searchItemInput, 'Infinity Gauntlet')
+ .click(selectors.itemsIndex.searchButton)
+ .waitForNumberOfElements(selectors.itemsIndex.searchResult, 2)
+ .countSearchResults(selectors.itemsIndex.searchResult)
+ .then(result => {
+ expect(result).toEqual(2);
+ });
+ });
+ });
+});
diff --git a/e2e/smokes/01_client_path.spec.js b/e2e/smokes/01_client_path.spec.js
new file mode 100644
index 000000000..f441d4f7b
--- /dev/null
+++ b/e2e/smokes/01_client_path.spec.js
@@ -0,0 +1,42 @@
+import selectors from '../helpers/selectors';
+import createNightmare from '../helpers/helpers';
+
+describe('create client path', () => {
+ let nightmare = createNightmare();
+
+ beforeAll(() => {
+ return nightmare
+ .waitForLogin('developer');
+ });
+
+ it('should access to the clients index by clicking the clients button', () => {
+ return nightmare
+ .click(selectors.moduleAccessView.clientsSectionButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+
+ it('should access to the create client view by clicking the create-client floating button', () => {
+ return nightmare
+ .click(selectors.clientsIndex.createClientButton)
+ .wait(selectors.createClientView.createButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/create');
+ });
+ });
+
+ it('should cancel the client creation to go back to clients index', () => {
+ return nightmare
+ .waitToClick(selectors.globalItems.applicationsMenuButton)
+ .waitToClick(selectors.globalItems.clientsButton)
+ .wait(selectors.clientsIndex.createClientButton)
+ .parsedUrl()
+ .then(url => {
+ expect(url.hash).toEqual('#!/clients');
+ });
+ });
+});
diff --git a/e2e_tests.js b/e2e_tests.js
new file mode 100644
index 000000000..dd1d7a079
--- /dev/null
+++ b/e2e_tests.js
@@ -0,0 +1,38 @@
+require('babel-core/register')({presets: ['es2015']});
+
+process.on('warning', warning => {
+ console.log(warning.name);
+ console.log(warning.message);
+ console.log(warning.stack);
+});
+
+var verbose = false;
+
+if (process.argv[2] === '--v') {
+ verbose = true;
+}
+
+var Jasmine = require('jasmine');
+var jasmine = new Jasmine();
+var SpecReporter = require('jasmine-spec-reporter').SpecReporter;
+
+jasmine.loadConfig({
+ spec_files: [
+ './e2e/**/*[sS]pec.js',
+ './e2e/helpers/extensions.js'
+ ],
+ helpers: [
+ '/services/utils/jasmineHelpers.js'
+ ]
+});
+
+jasmine.addReporter(new SpecReporter({
+ spec: {
+ // displayStacktrace: 'summary',
+ displaySuccessful: verbose,
+ displayFailedSpec: true,
+ displaySpecDuration: true
+ }
+}));
+
+jasmine.execute();
diff --git a/forever.json b/forever.json
deleted file mode 100644
index c1e82fa35..000000000
--- a/forever.json
+++ /dev/null
@@ -1,24 +0,0 @@
-[
- {
- "uid": "salix",
- "append": true,
- "watch": true,
- "script": "server.js",
- "sourceDir": "./services/salix/server",
- "workingDir": "."
- }, {
- "uid": "auth",
- "append": true,
- "watch": true,
- "script": "server.js",
- "sourceDir": "./services/auth/server",
- "workingDir": "."
- }, {
- "uid": "client",
- "append": true,
- "watch": true,
- "script": "server.js",
- "sourceDir": "./services/client/server",
- "workingDir": "."
- }
-]
\ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
index 72e8832b6..1b4578c86 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -1,83 +1,349 @@
-var gulp = require('gulp');
-var gutil = require('gulp-util');
-var wrap = require('gulp-wrap');
-var concat = require('gulp-concat');
-var extend = require('gulp-extend');
-var fs = require('fs');
-var merge = require('merge-stream');
-var del = require('del');
-var webpack = require('webpack');
-var WebpackDevServer = require('webpack-dev-server');
+require('require-yaml');
+const gulp = require('gulp');
+const runSequence = require('run-sequence');
+const fs = require('fs-extra');
+const exec = require('child_process').exec;
+const PluginError = require('plugin-error');
+const argv = require('minimist')(process.argv.slice(2));
+const log = require('fancy-log');
+const environment = require('gulp-env');
// Configuration
-var srcDir = './client';
-var buildDir = './services/nginx/static';
-var langs = ['es', 'en'];
+let isWindows = /^win/.test(process.platform);
-var modules = require('./spliting/modules.json');
-var webpackConfig = require('./webpack.config.js');
+if (argv.NODE_ENV)
+ process.env.NODE_ENV = argv.NODE_ENV;
-// Clean
+let env = process.env.NODE_ENV ? process.env.NODE_ENV : 'development';
-gulp.task('clean', function() {
- return del(`${buildDir}/*`, {force: true});
+let langs = ['es', 'en'];
+let srcDir = './client';
+let servicesDir = './services';
+
+let wpConfig = require('./webpack.config.yml');
+let buildDir = wpConfig.buildDir;
+let devServerPort = wpConfig.devServerPort;
+
+let nginxDir = `${servicesDir}/nginx`;
+let proxyConf = require(`${nginxDir}/config.yml`);
+let proxyEnvFile = `${nginxDir}/config.${env}.yml`;
+
+if (fs.existsSync(proxyEnvFile))
+ Object.assign(proxyConf, require(proxyEnvFile));
+
+let defaultService = proxyConf.main;
+let defaultPort = proxyConf.defaultPort;
+
+// Development
+
+gulp.task('default', () => {
+ return gulp.start('environment', 'services', 'client');
});
-// Spliting
+gulp.task('environment', async () => {
+ await environment({
+ file: '.env.json'
+ });
+});
-var splitingFiles = './spliting/*';
+gulp.task('client', ['build-clean'], async () => {
+ await runSequenceP(['routes', 'locales'], 'watch', 'webpack-dev-server');
+});
-gulp.task('spliting', function() {
- var importTpl = fs.readFileSync('./spliting/import.tpl.js', 'utf8');
- var requireTpl = fs.readFileSync('./spliting/require.tpl.js', 'utf8');
+/**
+ * Starts all backend services, including the nginx proxy and the database.
+ */
+gulp.task('services', async () => {
+ await runSequenceP('environment', 'docker-start', 'services-only', 'nginx');
+});
- for (var modName in modules) {
- var deps = modules[modName];
- var splitFile = `${srcDir}/${modName}/src/spliting.js`;
+/**
+ * Starts backend services.
+ */
+gulp.task('services-only', async () => {
+ const services = await getServices();
+ for (let service of services)
+ require(service.index).start(service.port);
+});
- try {
- fs.unlinkSync(splitFile);
- } catch (e) {}
+/**
+ * Runs the e2e tests, restoring the fixtures first.
+ */
+gulp.task('e2e', ['docker'], async () => {
+ await runSequenceP('e2e-only');
+});
- fs.appendFileSync(splitFile, importTpl);
+gulp.task('smokes', ['docker'], async () => {
+ await runSequenceP('smokes-only');
+});
- var i = deps.length;
- while (i--) {
- fs.appendFileSync(splitFile,
- requireTpl.replace(/\$module/g, deps[i]));
- }
+/**
+ * Runs the e2e tests.
+ */
+gulp.task('e2e-only', () => {
+ const jasmine = require('gulp-jasmine');
+ return gulp.src('./e2e_tests.js')
+ .pipe(jasmine({reporter: 'none'}));
+});
+
+gulp.task('smokes-only', () => {
+ const jasmine = require('gulp-jasmine');
+ return gulp.src('./smokes_tests.js')
+ .pipe(jasmine({reporter: 'none'}));
+});
+
+/**
+ * Runs the backend tests.
+ */
+// gulp.task('test', ['test-only'], async () => {
+// gulp.watch('./services/**/*', ['test-only']);
+// gulp.unwatch('./services/node_modules');
+// });
+
+// gulp.task('test-only', () => {
+// const jasmine = require('gulp-jasmine');
+// gulp.src('./services/loopback/common/**/*[sS]pec.js')
+// .pipe(jasmine(
+// require('./services-test.config')
+// ));
+// });
+
+/**
+ * Cleans all generated project files.
+ */
+gulp.task('clean', ['build-clean', 'nginx-clean']);
+
+/**
+ * Alias for the 'install' task.
+ */
+gulp.task('i', ['install']);
+
+/**
+ * Installs node dependencies in all project directories.
+ */
+gulp.task('install', () => {
+ const install = require('gulp-install');
+ const print = require('gulp-print');
+
+ let packageFiles = [];
+ let services = fs.readdirSync(servicesDir);
+ services.push('..');
+ services.forEach(service => {
+ packageFiles.push(`${servicesDir}/${service}/package.json`);
+ });
+ return gulp.src(packageFiles)
+ .pipe(print(filepath => {
+ return `Installing packages in ${filepath}`;
+ }))
+ .pipe(install({
+ npm: ['--no-package-lock']
+ }));
+});
+
+// Deployment
+
+gulp.task('build', ['clean'], async () => {
+ await runSequenceP(['environment', 'routes', 'locales', 'webpack', 'docker-compose', 'nginx-conf']);
+});
+
+gulp.task('docker-compose', async () => {
+ const yaml = require('js-yaml');
+
+ let compose = await fs.readFile('./docker-compose.tpl.yml', 'utf8');
+ let composeYml = yaml.safeLoad(compose);
+ let services = await getServices();
+
+ for (let service of services) {
+ let dockerFile = `${__dirname}/services/${service.name}/Dockerfile`;
+
+ // if (await fs.exists(`./services/${service.name}/Dockerfile`))
+ // dockerFile = 'Dockerfile';
+
+ composeYml.services[service.name] = {
+ environment: [
+ 'NODE_ENV=${NODE_ENV}',
+ 'salixHost=${salixHost}',
+ 'salixPort=${salixPort}',
+ 'salixUser=${salixUser}',
+ 'salixPassword=${salixPassword}'
+ ],
+ container_name: `\${BRANCH_NAME}-${service.name}`,
+ image: `${service.name}:\${TAG}`,
+ build: {
+ context: `./services`,
+ dockerfile: dockerFile
+ },
+ ports: [`${service.port}:${defaultPort}`]
+ };
+ composeYml.services.nginx.links.push(
+ `${service.name}:\${BRANCH_NAME}-${service.name}`
+ );
}
+
+ let ymlString = yaml.safeDump(composeYml);
+ await fs.writeFile('./docker-compose.yml', ymlString);
});
+/**
+ * Cleans all files generated by the 'build' task.
+ */
+gulp.task('build-clean', () => {
+ const del = require('del');
+ const files = [
+ `${buildDir}/*`,
+ `!${buildDir}/templates`,
+ `!${buildDir}/images`,
+ `docker-compose.yml`
+ ];
+ return del(files, {force: true});
+});
+
+// Nginx & services
+
+let nginxConf = 'temp/nginx.conf';
+let nginxTemp = `${nginxDir}/temp`;
+
+/**
+ * Starts the nginx process, if it is started, restarts it.
+ */
+gulp.task('nginx', async () => {
+ await runSequenceP('nginx-stop', 'nginx-start');
+});
+
+/**
+ * Starts the nginx process, generating it's configuration file first.
+ */
+gulp.task('nginx-start', ['nginx-conf'], async () => {
+ let nginxBin = await nginxGetBin();
+
+ if (isWindows)
+ nginxBin = `start /B ${nginxBin}`;
+
+ log(`Application will be available at http://${proxyConf.host}:${proxyConf.port}/`);
+ await execP(`${nginxBin} -c "${nginxConf}" -p "${nginxDir}"`);
+});
+
+/**
+ * Stops the nginx process.
+ */
+gulp.task('nginx-stop', async () => {
+ try {
+ let nginxBin = await nginxGetBin();
+ await fs.stat(`${nginxTemp}/nginx.pid`);
+ await execP(`${nginxBin} -c "${nginxConf}" -p "${nginxDir}" -s stop`);
+ } catch (e) {}
+});
+
+/**
+ * Generates the nginx configuration file. If NODE_ENV is defined and the
+ * 'nginx.[environment].mst' file exists, it is used as a template, otherwise,
+ * the 'nginx.mst' template file is used.
+ */
+gulp.task('nginx-conf', ['nginx-stop'], async () => {
+ const mustache = require('mustache');
+
+ if (!await fs.exists(nginxTemp))
+ await fs.mkdir(nginxTemp);
+
+ let params = {
+ services: await getServices(),
+ defaultService: defaultService,
+ defaultPort: defaultPort,
+ devServerPort: devServerPort,
+ port: proxyConf.port,
+ host: proxyConf.host
+ };
+
+ let confFile = `${nginxDir}/nginx.${env}.mst`;
+
+ if (!await fs.exists(confFile))
+ confFile = `${nginxDir}/nginx.mst`;
+
+ let template = await fs.readFile(confFile, 'utf8');
+ let nginxConf = mustache.render(template, params);
+
+ await fs.writeFile(`${nginxTemp}/nginx.conf`, nginxConf);
+});
+
+/**
+ * Cleans all files generated by nginx.
+ */
+gulp.task('nginx-clean', ['nginx-stop'], () => {
+ const del = require('del');
+ return del([`${nginxTemp}/*`], {force: true});
+});
+
+async function nginxGetBin() {
+ if (isWindows)
+ return 'nginx';
+ try {
+ let nginxBin = '/usr/sbin/nginx';
+ await fs.stat(nginxBin);
+ return nginxBin;
+ } catch (e) {
+ return 'nginx';
+ }
+}
+
+async function getServices() {
+ let services;
+ let startPort = defaultPort + 1;
+ services = [];
+
+ const serviceDirs = await fs.readdir(servicesDir);
+ const exclude = ['loopback'];
+
+ for (let service of serviceDirs) {
+ let index = `${servicesDir}/${service}/server/server.js`;
+ if (!await fs.exists(index) || exclude.indexOf(service) !== -1) continue;
+
+ let port = service == defaultService ? defaultPort : startPort++;
+ services.push({
+ name: service,
+ index: index,
+ port: port
+ });
+ }
+
+ return services;
+}
+
// Webpack
-gulp.task('webpack', ['spliting'], function(callback) {
- var configCopy = Object.create(webpackConfig);
- var compiler = webpack(configCopy);
+gulp.task('webpack', function(callback) {
+ const webpack = require('webpack');
+
+ const webpackConfig = require('./webpack.config.js');
+ let configCopy = Object.create(webpackConfig);
+ let compiler = webpack(configCopy);
compiler.run(function(err, stats) {
- if (err) throw new gutil.PluginError('webpack', err);
- gutil.log('[webpack]', stats.toString({colors: true}));
+ if (err) throw new PluginError('webpack', err);
+ log('[webpack]', stats.toString({colors: true}));
callback();
});
});
-gulp.task('webpack-dev-server', ['spliting'], function(callback) {
- var configCopy = Object.create(webpackConfig);
+gulp.task('webpack-dev-server', function() {
+ const WebpackDevServer = require('webpack-dev-server');
+ const webpack = require('webpack');
- for (var entry in configCopy.entry) {
+ const webpackConfig = require('./webpack.config.js');
+ let configCopy = Object.create(webpackConfig);
+
+ for (let entry in configCopy.entry) {
configCopy.entry[entry]
- .unshift('webpack-dev-server/client?http://0.0.0.0:8081/');
+ .unshift(`webpack-dev-server/client?http://127.0.0.1:${devServerPort}/`);
}
- var compiler = webpack(configCopy);
+ let compiler = webpack(configCopy);
new WebpackDevServer(compiler, {
publicPath: '/',
contentBase: buildDir,
quiet: false,
noInfo: false,
- // hot: true,
+ // hot: true,
stats: {
assets: true,
colors: true,
@@ -87,22 +353,33 @@ gulp.task('webpack-dev-server', ['spliting'], function(callback) {
chunks: false,
chunkModules: false
}
- }).listen(8081, '0.0.0.0', function(err) {
- if (err) throw new gutil.PluginError('webpack-dev-server', err);
+ }).listen(devServerPort, '127.0.0.1', function(err) {
+ if (err) throw new PluginError('webpack-dev-server', err);
});
});
// Locale
-var localeFiles = `./${srcDir}/**/locale/*.json`;
+let localeFiles = `${srcDir}/**/locale/*.yml`;
+/**
+ * Mixes all locale files into one JSON file per module and language. It looks
+ * recursively in all project directories for locale folders with per language
+ * yaml translation files.
+ */
gulp.task('locales', function() {
- var streams = [];
+ const extend = require('gulp-extend');
+ const yaml = require('gulp-yaml');
+ const merge = require('merge-stream');
+ const modules = require('./client/modules.yml');
- for (var mod in modules)
- for (var lang of langs) {
- var localeFiles = `./client/${mod}/**/locale/${lang}.json`;
+ let streams = [];
+
+ for (let mod in modules)
+ for (let lang of langs) {
+ let localeFiles = `./client/${mod}/**/locale/${lang}.yml`;
streams.push(gulp.src(localeFiles)
+ .pipe(yaml())
.pipe(extend(`${lang}.json`))
.pipe(gulp.dest(`${buildDir}/locale/${mod}`)));
}
@@ -112,40 +389,163 @@ gulp.task('locales', function() {
// Routes
-var routeFiles = `./${srcDir}/**/routes.js`;
+let routeFiles = `${srcDir}/**/routes.json`;
gulp.task('routes', function() {
- var fileTpl = '\n"<%=dirname%>": <%=contents%>';
- var globalTpl = 'var routes = {<%=contents%>\n}';
- var regex = new RegExp('^(.*)/routes\.js$');
-
- function cb(file) {
- var relative = file.relative.replace(/\\/g, '/');
- var dirname = relative.match(regex)[1];
- return {dirname: dirname};
- }
+ const concat = require('gulp-concat');
+ const wrap = require('gulp-wrap');
return gulp.src(routeFiles)
- .pipe(wrap(fileTpl, cb))
- .pipe(concat('routes.js', {newLine: ','}))
- .pipe(wrap(globalTpl))
- .pipe(gulp.dest(buildDir));
+ .pipe(concat('routes.js', {newLine: ','}))
+ .pipe(wrap('var routes = [<%=contents%>\n];'))
+ .pipe(gulp.dest(buildDir));
});
// Watch
gulp.task('watch', function() {
- gulp.watch(splitingFiles, ['spliting']);
gulp.watch(routeFiles, ['routes']);
gulp.watch(localeFiles, ['locales']);
});
-// Default
+// Docker
-gulp.task('build', ['clean'], function() {
- return gulp.start('routes', 'locales', 'webpack');
+/**
+ * Rebuilds the docker and it's image, if these already exist, destroys and
+ * rebuilds them.
+ */
+gulp.task('docker', async () => {
+ try {
+ await execP('docker rm -f dblocal');
+ } catch (e) {}
+ try {
+ await execP('docker rmi dblocal:latest');
+ } catch (e) {}
+
+ await runSequenceP('docker-run');
});
-gulp.task('default', ['clean'], function() {
- return gulp.start('watch', 'routes', 'locales', 'webpack-dev-server');
+/**
+ * Does the minium effort to start the docker, if it doesn't exists calls
+ * the 'docker-run' task, if it is started does nothing. Keep in mind that when
+ * you do not rebuild the docker you may be using an outdated version of it.
+ * See the 'docker' task for more info.
+ */
+gulp.task('docker-start', async () => {
+ let state;
+ try {
+ let result = await execP('docker container inspect -f "{{json .State}}" dblocal');
+ state = JSON.parse(result.stdout);
+ } catch (err) {
+ return await runSequenceP('docker-run');
+ }
+
+ switch (state.Status) {
+ case 'running':
+ return;
+ case 'exited':
+ return await execP('docker start dblocal');
+ default:
+ throw new Error(`Unknown docker status: ${status}`);
+ }
});
+
+/**
+ * Runs the docker, if the container or it's image doesn't exists builds them.
+ */
+gulp.task('docker-run', async () => {
+ try {
+ await execP('docker image inspect -f "{{json .Id}}" dblocal');
+ } catch (err) {
+ await execP('docker build -t dblocal:latest ./services/db');
+ }
+
+ await execP('docker run -d --name dblocal -p 3306:3306 dblocal');
+ await runSequenceP('docker-wait');
+});
+
+/**
+ * Waits until MySQL docker is started and ready to serve connections.
+ */
+gulp.task('docker-wait', callback => {
+ const mysql = require('mysql2');
+
+ let interval = 1;
+ let elapsedTime = 0;
+ let maxInterval = 30 * 60;
+
+ log('Waiting for MySQL init process...');
+ checker();
+
+ async function checker() {
+ elapsedTime += interval;
+ let state;
+
+ try {
+ let result = await execP('docker container inspect -f "{{json .State}}" dblocal');
+ state = JSON.parse(result.stdout);
+ } catch (err) {
+ return callback(new Error(err.message));
+ }
+
+ if (state.Status === 'exited')
+ return callback(new Error('Docker exited, please see the docker logs for more info'));
+
+ let conn = mysql.createConnection({
+ host: 'localhost',
+ user: 'root',
+ password: 'root'
+ });
+ conn.on('error', () => {});
+ conn.connect(err => {
+ conn.destroy();
+ if (!err) return callback();
+
+ if (elapsedTime >= maxInterval)
+ callback(new Error(`MySQL not initialized whithin ${elapsedTime} secs`));
+ else
+ setTimeout(checker, interval * 1000);
+ });
+ }
+});
+
+// Helpers
+
+/**
+ * Promisified version of exec().
+ *
+ * @param {String} command The exec command
+ * @return {Promise} The promise
+ */
+function execP(command) {
+ return new Promise((resolve, reject) => {
+ exec(command, (err, stdout, stderr) => {
+ if (err)
+ reject(err);
+ else
+ resolve({
+ stdout: stdout,
+ stderr: stderr
+ });
+ });
+ });
+}
+
+/**
+ * Promisified version of runSequence().
+ *
+ * @param {String} args The list of gulp task names
+ * @return {Promise} The promise
+ */
+function runSequenceP() {
+ return new Promise((resolve, reject) => {
+ let args = Array.prototype.slice.call(arguments);
+ args.push(err => {
+ if (err)
+ reject(err);
+ else
+ resolve();
+ });
+ runSequence(...args);
+ });
+}
diff --git a/karma.conf.js b/karma.conf.js
new file mode 100644
index 000000000..0518f8cd0
--- /dev/null
+++ b/karma.conf.js
@@ -0,0 +1,116 @@
+var webpackConfig = require('./webpack.config.js');
+delete webpackConfig.entry;
+delete webpackConfig.output;
+webpackConfig.devtool = 'inline-source-map';
+webpackConfig.plugins = [];
+
+// Karma configuration
+// Generated on Tue Aug 22 2017 13:37:43 GMT+0200 (CEST)
+
+module.exports = function(config) {
+ let baseConfig = {
+
+ // base path that will be used to resolve all patterns (eg. files, exclude)
+ basePath: '',
+
+ // frameworks to use
+ // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+ frameworks: ['jasmine'],
+
+ // list of files / patterns to load in the browser
+ files: [
+ {pattern: 'client/test_index.js', watched: false}
+ ],
+
+ // list of files to exclude
+ exclude: [],
+
+ webpack: webpackConfig,
+
+ webpackMiddleware: {
+ stats: 'errors-only'
+ },
+
+ webpackServer: {
+ noInfo: true
+ },
+
+ // preprocess matching files before serving them to the browser
+ // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+ preprocessors: {
+ './client/test_index.js': ['webpack', 'sourcemap']
+ },
+
+ // test results reporter to use
+ // possible values: 'dots', 'progress'
+ // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+ reporters: ['progress'],
+
+ // web server port
+ port: 9876,
+
+ // enable / disable colors in the output (reporters and logs)
+ colors: true,
+
+ // level of logging
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: true,
+
+ // start these browsers
+ // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+ browsers: [],
+
+ // Continuous Integration mode
+ // if true, Karma captures browsers, runs the tests and exits
+ singleRun: false,
+
+ // Concurrency level
+ // how many browser should be started simultaneous
+ concurrency: Infinity,
+
+ plugins: [
+ 'karma-jasmine',
+ 'karma-webpack',
+ 'karma-chrome-launcher',
+ 'karma-firefox-launcher',
+ 'karma-sourcemap-loader'
+ ]
+ };
+
+ let browserConfig;
+
+ if (process.env.FIREFOX_BIN) {
+ browserConfig = {
+ browsers: ['FirefoxHeadless'],
+ customLaunchers: {
+ FirefoxHeadless: {
+ base: 'Firefox',
+ flags: ['-headless']
+ }
+ }
+ };
+ } else {
+ browserConfig = {
+ browsers: ['ChromeNoSandboxHeadless'],
+ customLaunchers: {
+ ChromeNoSandboxHeadless: {
+ base: 'Chrome',
+ flags: [
+ '--no-sandbox',
+ // See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
+ '--headless',
+ '--disable-gpu',
+ // Without a remote debugging port, Google Chrome exits immediately.
+ ' --remote-debugging-port=9222'
+ ]
+ }
+ }
+ };
+ }
+
+ Object.assign(baseConfig, browserConfig);
+ config.set(baseConfig);
+};
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 000000000..8d9be895f
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,17508 @@
+{
+ "name": "salix-app",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@types/node": {
+ "version": "7.0.48",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.48.tgz",
+ "integrity": "sha1-JL/cCqguj229AXFZxYCUouBtCrs=",
+ "dev": true
+ },
+ "@uirouter/angularjs": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.3.tgz",
+ "integrity": "sha1-UYuHVUK02G3RqvX0JizO5BbywWY=",
+ "requires": {
+ "@uirouter/core": "5.0.3"
+ }
+ },
+ "@uirouter/core": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/@uirouter/core/-/core-5.0.3.tgz",
+ "integrity": "sha1-4rWx5FGQ4gxnuk4VwBPeXU4MyrM="
+ },
+ "abbrev": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
+ "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=",
+ "dev": true
+ },
+ "accepts": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz",
+ "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=",
+ "dev": true,
+ "requires": {
+ "mime-types": "2.1.12",
+ "negotiator": "0.6.1"
+ }
+ },
+ "acorn": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz",
+ "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ=="
+ },
+ "acorn-dynamic-import": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz",
+ "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=",
+ "dev": true,
+ "requires": {
+ "acorn": "4.0.13"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
+ "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=",
+ "dev": true
+ }
+ }
+ },
+ "acorn-jsx": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+ "requires": {
+ "acorn": "3.3.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
+ }
+ }
+ },
+ "after": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+ "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
+ "dev": true
+ },
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "requires": {
+ "co": "4.6.0",
+ "fast-deep-equal": "1.0.0",
+ "fast-json-stable-stringify": "2.0.0",
+ "json-schema-traverse": "0.3.1"
+ }
+ },
+ "ajv-keywords": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I="
+ },
+ "align-text": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.0.4",
+ "longest": "1.0.1",
+ "repeat-string": "1.6.1"
+ }
+ },
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+ "dev": true
+ },
+ "angular": {
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/angular/-/angular-1.6.8.tgz",
+ "integrity": "sha1-W+N4pYvpGlSJ54tZxFGM2f0nP/s="
+ },
+ "angular-cookies": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.6.4.tgz",
+ "integrity": "sha1-wo8/aqx6mCbB5F8daAckADblsm0="
+ },
+ "angular-mocks": {
+ "version": "1.6.6",
+ "resolved": "https://registry.npmjs.org/angular-mocks/-/angular-mocks-1.6.6.tgz",
+ "integrity": "sha1-yTAY54OMbcXOrxprz5vhPIMOpRU=",
+ "dev": true
+ },
+ "angular-paging": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/angular-paging/-/angular-paging-2.2.2.tgz",
+ "integrity": "sha1-cC9XTW0UBpADXqxkOV/jEfeYf7s="
+ },
+ "angular-translate": {
+ "version": "2.17.0",
+ "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.17.0.tgz",
+ "integrity": "sha512-SudfI0R0Hhtvngc0X3wFChXQGmw90o95i+QPZ11LhJJryneTq8LR3+3E4E7jgHA4fu6TcswgcfZ9+cp5ckbUHw==",
+ "requires": {
+ "angular": "1.6.8"
+ }
+ },
+ "angular-translate-loader-partial": {
+ "version": "2.17.0",
+ "resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.17.0.tgz",
+ "integrity": "sha512-pyRJcRc93iwiUnRnh9ZfehbQE/yxO5T6jmEqIvLEVz8gKLjDqDLKcaQFgPef9wCIN2n3e531YbStkkbSH3LYmQ==",
+ "requires": {
+ "angular-translate": "2.17.0"
+ }
+ },
+ "ansi-align": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
+ "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
+ "dev": true,
+ "requires": {
+ "string-width": "2.1.1"
+ },
+ "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
+ },
+ "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
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.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"
+ }
+ }
+ }
+ },
+ "ansi-colors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.0.1.tgz",
+ "integrity": "sha512-yopkAU0ZD/WQ56Tms3xLn6jRuX3SyUMAVi0FdmDIbmmnHW3jHiI1sQFdUl3gfVddjnrsP3Y6ywFKvCRopvoVIA==",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-cyan": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz",
+ "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-escapes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz",
+ "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ=="
+ },
+ "ansi-gray": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
+ "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "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-red": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz",
+ "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=",
+ "dev": true,
+ "requires": {
+ "ansi-wrap": "0.1.0"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc="
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "ansi-wrap": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
+ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
+ "dev": true
+ },
+ "ansicolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz",
+ "integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=",
+ "dev": true
+ },
+ "anymatch": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz",
+ "integrity": "sha1-o+Uvo5FoyCX/V7AkgSbOWo/5VQc=",
+ "dev": true,
+ "requires": {
+ "arrify": "1.0.1",
+ "micromatch": "2.3.11"
+ }
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+ "dev": true
+ },
+ "archy": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+ "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=",
+ "dev": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
+ "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
+ "dev": true,
+ "requires": {
+ "delegates": "1.0.0",
+ "readable-stream": "2.1.5"
+ }
+ },
+ "argparse": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+ "requires": {
+ "sprintf-js": "1.0.3"
+ }
+ },
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "1.0.1"
+ }
+ },
+ "arr-flatten": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz",
+ "integrity": "sha1-5f/lTUXhnzLyFukeuZyM6JK7YEs=",
+ "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-differ": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
+ "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
+ "dev": true
+ },
+ "array-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
+ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=",
+ "dev": true
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ },
+ "array-flatten": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz",
+ "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=",
+ "dev": true
+ },
+ "array-includes": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
+ "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
+ "dev": true,
+ "requires": {
+ "define-properties": "1.1.2",
+ "es-abstract": "1.10.0"
+ }
+ },
+ "array-slice": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
+ "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
+ "dev": true
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "requires": {
+ "array-uniq": "1.0.3"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "arraybuffer.slice": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz",
+ "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+ "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
+ "dev": true
+ },
+ "asn1.js": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz",
+ "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==",
+ "dev": true,
+ "requires": {
+ "bn.js": "4.11.8",
+ "inherits": "2.0.3",
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
+ "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+ "dev": true,
+ "requires": {
+ "util": "0.10.3"
+ }
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+ "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
+ "dev": true
+ },
+ "assets-webpack-plugin": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/assets-webpack-plugin/-/assets-webpack-plugin-3.5.1.tgz",
+ "integrity": "sha1-kxzg1m1C6I7V5/GNZVIpQ8V6OH0=",
+ "dev": true,
+ "requires": {
+ "camelcase": "1.2.1",
+ "escape-string-regexp": "1.0.5",
+ "lodash.assign": "3.2.0",
+ "lodash.merge": "3.3.2",
+ "mkdirp": "0.5.1"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+ "dev": true
+ },
+ "lodash.assign": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz",
+ "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=",
+ "dev": true,
+ "requires": {
+ "lodash._baseassign": "3.2.0",
+ "lodash._createassigner": "3.1.1",
+ "lodash.keys": "3.1.2"
+ }
+ }
+ }
+ },
+ "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": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.2.tgz",
+ "integrity": "sha1-LMGZedFcZVEIv1ZTI7jn7jh1H2s=",
+ "dev": true
+ },
+ "async": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.1.2.tgz",
+ "integrity": "sha1-YSpKtF70KnDN6Aa62G7m2wR+g4U=",
+ "dev": true,
+ "requires": {
+ "lodash": "4.16.6"
+ }
+ },
+ "async-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+ "dev": true
+ },
+ "async-foreach": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
+ "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
+ "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.0.3",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz",
+ "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=",
+ "dev": true
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+ "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.5.0.tgz",
+ "integrity": "sha1-Cin/t5wxyecS7rCH6OemS0pW11U=",
+ "dev": true
+ },
+ "babel": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
+ "integrity": "sha1-0NHn2APpdHZb7qMjLU4VPA77kPQ=",
+ "dev": true
+ },
+ "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=",
+ "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="
+ }
+ }
+ },
+ "babel-core": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz",
+ "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "6.26.0",
+ "babel-generator": "6.26.1",
+ "babel-helpers": "6.24.1",
+ "babel-messages": "6.23.0",
+ "babel-register": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0",
+ "babylon": "6.18.0",
+ "convert-source-map": "1.5.1",
+ "debug": "2.6.9",
+ "json5": "0.5.1",
+ "lodash": "4.17.5",
+ "minimatch": "3.0.4",
+ "path-is-absolute": "1.0.1",
+ "private": "0.1.8",
+ "slash": "1.0.0",
+ "source-map": "0.5.6"
+ },
+ "dependencies": {
+ "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"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "dev": true,
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "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"
+ }
+ },
+ "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
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "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
+ }
+ }
+ },
+ "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.5",
+ "source-map": "0.5.7",
+ "trim-right": "1.0.1"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "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-helper-call-delegate": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
+ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
+ "dev": true,
+ "requires": {
+ "babel-helper-hoist-variables": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-define-map": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
+ "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
+ "dev": true,
+ "requires": {
+ "babel-helper-function-name": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "lodash": "4.17.5"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ }
+ }
+ },
+ "babel-helper-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
+ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
+ "dev": true,
+ "requires": {
+ "babel-helper-get-function-arity": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-get-function-arity": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
+ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-hoist-variables": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
+ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-optimise-call-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
+ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helper-regex": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
+ "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "lodash": "4.17.5"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ }
+ }
+ },
+ "babel-helper-replace-supers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
+ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
+ "dev": true,
+ "requires": {
+ "babel-helper-optimise-call-expression": "6.24.1",
+ "babel-messages": "6.23.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-helpers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
+ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-loader": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.2.tgz",
+ "integrity": "sha512-jRwlFbINAeyDStqK6Dd5YuY0k5YuzQUvlz2ZamuXrXmxav3pNqe9vfJ402+2G+OmlJSXxCOpB6Uz0INM7RQe2A==",
+ "dev": true,
+ "requires": {
+ "find-cache-dir": "1.0.0",
+ "loader-utils": "1.1.0",
+ "mkdirp": "0.5.1"
+ },
+ "dependencies": {
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "dev": true,
+ "requires": {
+ "big.js": "3.1.3",
+ "emojis-list": "2.1.0",
+ "json5": "0.5.0"
+ }
+ }
+ }
+ },
+ "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.26.0"
+ }
+ },
+ "babel-plugin-check-es2015-constants": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
+ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-arrow-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
+ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-block-scoped-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
+ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-block-scoping": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
+ "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0",
+ "lodash": "4.17.5"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ }
+ }
+ },
+ "babel-plugin-transform-es2015-classes": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
+ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
+ "dev": true,
+ "requires": {
+ "babel-helper-define-map": "6.26.0",
+ "babel-helper-function-name": "6.24.1",
+ "babel-helper-optimise-call-expression": "6.24.1",
+ "babel-helper-replace-supers": "6.24.1",
+ "babel-messages": "6.23.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-computed-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
+ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-destructuring": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
+ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-duplicate-keys": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
+ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-for-of": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
+ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
+ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
+ "dev": true,
+ "requires": {
+ "babel-helper-function-name": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
+ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-amd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
+ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-es2015-modules-commonjs": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-commonjs": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz",
+ "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-strict-mode": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-systemjs": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
+ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
+ "dev": true,
+ "requires": {
+ "babel-helper-hoist-variables": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-modules-umd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
+ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-transform-es2015-modules-amd": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-object-super": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
+ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
+ "dev": true,
+ "requires": {
+ "babel-helper-replace-supers": "6.24.1",
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-parameters": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
+ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
+ "dev": true,
+ "requires": {
+ "babel-helper-call-delegate": "6.24.1",
+ "babel-helper-get-function-arity": "6.24.1",
+ "babel-runtime": "6.26.0",
+ "babel-template": "6.26.0",
+ "babel-traverse": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-shorthand-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
+ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-spread": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
+ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-sticky-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
+ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
+ "dev": true,
+ "requires": {
+ "babel-helper-regex": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-template-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
+ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-typeof-symbol": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
+ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0"
+ }
+ },
+ "babel-plugin-transform-es2015-unicode-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
+ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
+ "dev": true,
+ "requires": {
+ "babel-helper-regex": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "regexpu-core": "2.0.0"
+ }
+ },
+ "babel-plugin-transform-regenerator": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
+ "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
+ "dev": true,
+ "requires": {
+ "regenerator-transform": "0.10.1"
+ }
+ },
+ "babel-plugin-transform-strict-mode": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
+ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0"
+ }
+ },
+ "babel-preset-es2015": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz",
+ "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
+ "dev": true,
+ "requires": {
+ "babel-plugin-check-es2015-constants": "6.22.0",
+ "babel-plugin-transform-es2015-arrow-functions": "6.22.0",
+ "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0",
+ "babel-plugin-transform-es2015-block-scoping": "6.26.0",
+ "babel-plugin-transform-es2015-classes": "6.24.1",
+ "babel-plugin-transform-es2015-computed-properties": "6.24.1",
+ "babel-plugin-transform-es2015-destructuring": "6.23.0",
+ "babel-plugin-transform-es2015-duplicate-keys": "6.24.1",
+ "babel-plugin-transform-es2015-for-of": "6.23.0",
+ "babel-plugin-transform-es2015-function-name": "6.24.1",
+ "babel-plugin-transform-es2015-literals": "6.22.0",
+ "babel-plugin-transform-es2015-modules-amd": "6.24.1",
+ "babel-plugin-transform-es2015-modules-commonjs": "6.26.0",
+ "babel-plugin-transform-es2015-modules-systemjs": "6.24.1",
+ "babel-plugin-transform-es2015-modules-umd": "6.24.1",
+ "babel-plugin-transform-es2015-object-super": "6.24.1",
+ "babel-plugin-transform-es2015-parameters": "6.24.1",
+ "babel-plugin-transform-es2015-shorthand-properties": "6.24.1",
+ "babel-plugin-transform-es2015-spread": "6.22.0",
+ "babel-plugin-transform-es2015-sticky-regex": "6.24.1",
+ "babel-plugin-transform-es2015-template-literals": "6.22.0",
+ "babel-plugin-transform-es2015-typeof-symbol": "6.23.0",
+ "babel-plugin-transform-es2015-unicode-regex": "6.24.1",
+ "babel-plugin-transform-regenerator": "6.26.0"
+ }
+ },
+ "babel-register": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
+ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
+ "dev": true,
+ "requires": {
+ "babel-core": "6.26.0",
+ "babel-runtime": "6.26.0",
+ "core-js": "2.5.3",
+ "home-or-tmp": "2.0.0",
+ "lodash": "4.17.5",
+ "mkdirp": "0.5.1",
+ "source-map-support": "0.4.18"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz",
+ "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ }
+ }
+ },
+ "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.1",
+ "regenerator-runtime": "0.11.1"
+ }
+ },
+ "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.5"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ }
+ }
+ },
+ "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.9",
+ "globals": "9.18.0",
+ "invariant": "2.2.2",
+ "lodash": "4.17.5"
+ },
+ "dependencies": {
+ "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"
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "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.5",
+ "to-fast-properties": "1.0.3"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "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": "0.4.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=",
+ "dev": true,
+ "requires": {
+ "cache-base": "1.0.1",
+ "class-utils": "0.3.6",
+ "component-emitter": "1.2.1",
+ "define-property": "1.0.0",
+ "isobject": "3.0.1",
+ "mixin-deep": "1.3.0",
+ "pascalcase": "0.1.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
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "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.2.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
+ "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==",
+ "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.0",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz",
+ "integrity": "sha1-PKdrhSQccXC/fZcD57mqdGMAQNQ=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "tweetnacl": "0.14.3"
+ }
+ },
+ "beeper": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz",
+ "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=",
+ "dev": true
+ },
+ "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": "3.1.3",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz",
+ "integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg=",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.8.0.tgz",
+ "integrity": "sha1-SOyNFt9Dd+rl+liEaCSAr02Vx3Q=",
+ "dev": true
+ },
+ "blob": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
+ "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=",
+ "dev": true
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "bluebird": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
+ "integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=",
+ "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.18.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
+ "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
+ "dev": true,
+ "requires": {
+ "bytes": "3.0.0",
+ "content-type": "1.0.4",
+ "debug": "2.6.9",
+ "depd": "1.1.2",
+ "http-errors": "1.6.2",
+ "iconv-lite": "0.4.19",
+ "on-finished": "2.3.0",
+ "qs": "6.5.1",
+ "raw-body": "2.3.2",
+ "type-is": "1.6.15"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+ "dev": true
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
+ "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
+ "dev": true,
+ "requires": {
+ "depd": "1.1.1",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.0.3",
+ "statuses": "1.3.1"
+ },
+ "dependencies": {
+ "depd": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+ "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
+ "dev": true
+ }
+ }
+ },
+ "mime-db": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
+ "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
+ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.30.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.5.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
+ "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=",
+ "dev": true
+ },
+ "setprototypeof": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
+ "dev": true
+ },
+ "type-is": {
+ "version": "1.6.15",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
+ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "2.1.17"
+ }
+ }
+ }
+ },
+ "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.1",
+ "deep-equal": "1.0.1",
+ "dns-equal": "1.0.0",
+ "dns-txt": "2.0.2",
+ "multicast-dns": "6.2.3",
+ "multicast-dns-service-types": "1.1.0"
+ }
+ },
+ "boom": {
+ "version": "2.10.1",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
+ "dev": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "boxen": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.2.1.tgz",
+ "integrity": "sha1-DxHn/jRO25OXl3/BPt5/ZNlWSB0=",
+ "dev": true,
+ "requires": {
+ "ansi-align": "2.0.0",
+ "camelcase": "4.1.0",
+ "chalk": "2.1.0",
+ "cli-boxes": "1.0.0",
+ "string-width": "2.1.1",
+ "term-size": "1.2.0",
+ "widest-line": "1.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
+ },
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.0"
+ }
+ },
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
+ "integrity": "sha1-rFvs8U+iG5nGySynp9fP1bF+dD4=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.4.0"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "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
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.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"
+ }
+ },
+ "supports-color": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+ "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
+ "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=",
+ "requires": {
+ "balanced-match": "0.4.2",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true,
+ "requires": {
+ "expand-range": "1.8.2",
+ "preserve": "0.2.0",
+ "repeat-element": "1.1.2"
+ }
+ },
+ "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.1.1",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz",
+ "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==",
+ "dev": true,
+ "requires": {
+ "buffer-xor": "1.0.3",
+ "cipher-base": "1.0.4",
+ "create-hash": "1.1.3",
+ "evp_bytestokey": "1.0.3",
+ "inherits": "2.0.3",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz",
+ "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=",
+ "dev": true,
+ "requires": {
+ "browserify-aes": "1.1.1",
+ "browserify-des": "1.0.0",
+ "evp_bytestokey": "1.0.3"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz",
+ "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=",
+ "dev": true,
+ "requires": {
+ "cipher-base": "1.0.4",
+ "des.js": "1.0.0",
+ "inherits": "2.0.3"
+ }
+ },
+ "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.11.8",
+ "randombytes": "2.0.6"
+ }
+ },
+ "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.11.8",
+ "browserify-rsa": "4.0.1",
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "elliptic": "6.4.0",
+ "inherits": "2.0.3",
+ "parse-asn1": "5.1.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.6"
+ }
+ },
+ "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.2.1",
+ "ieee754": "1.1.8",
+ "isarray": "1.0.0"
+ }
+ },
+ "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-shims": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
+ "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E="
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+ "dev": true
+ },
+ "bufferstreams": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.1.0.tgz",
+ "integrity": "sha1-BzzRIDCMBnjufXxItp4G60U4reA=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.1.5"
+ }
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+ "dev": true
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=",
+ "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"
+ },
+ "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
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "caller-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
+ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+ "requires": {
+ "callsites": "0.2.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": "0.2.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo="
+ },
+ "camel-case": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+ "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+ "dev": true,
+ "requires": {
+ "no-case": "2.3.0",
+ "upper-case": "1.1.3"
+ }
+ },
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "2.1.1",
+ "map-obj": "1.0.1"
+ }
+ },
+ "capture-stack-trace": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz",
+ "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=",
+ "dev": true
+ },
+ "cardinal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz",
+ "integrity": "sha1-UOIcGwqjdyn5N33vGWtanOyTLuk=",
+ "dev": true,
+ "requires": {
+ "ansicolors": "0.2.1",
+ "redeyed": "1.0.1"
+ }
+ },
+ "caseless": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
+ "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=",
+ "dev": true
+ },
+ "center-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+ "dev": true,
+ "requires": {
+ "align-text": "0.1.4",
+ "lazy-cache": "1.0.4"
+ }
+ },
+ "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.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ }
+ },
+ "chardet": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
+ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I="
+ },
+ "chokidar": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz",
+ "integrity": "sha1-L0RHq16W5Q+z14n9kNTHLg5McMI=",
+ "dev": true,
+ "requires": {
+ "anymatch": "1.3.0",
+ "async-each": "1.0.1",
+ "fsevents": "1.1.3",
+ "glob-parent": "2.0.0",
+ "inherits": "2.0.3",
+ "is-binary-path": "1.0.1",
+ "is-glob": "2.0.1",
+ "path-is-absolute": "1.0.1",
+ "readdirp": "2.1.0"
+ }
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "circular-json": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A=="
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=",
+ "dev": true,
+ "requires": {
+ "arr-union": "3.1.0",
+ "define-property": "0.2.5",
+ "isobject": "3.0.1",
+ "static-extend": "0.1.2"
+ },
+ "dependencies": {
+ "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
+ },
+ "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.6"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "0.1.6",
+ "is-data-descriptor": "0.1.4",
+ "kind-of": "5.1.0"
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
+ "dev": true
+ }
+ }
+ },
+ "clean-css": {
+ "version": "3.4.21",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.21.tgz",
+ "integrity": "sha1-IQHV29GdY9vBanXr1XDnwzlI9ls=",
+ "dev": true,
+ "requires": {
+ "commander": "2.8.1",
+ "source-map": "0.4.4"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
+ "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
+ "dev": true,
+ "requires": {
+ "graceful-readlink": "1.0.1"
+ }
+ },
+ "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": "1.0.1"
+ }
+ }
+ }
+ },
+ "cli-boxes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
+ "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=",
+ "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=",
+ "requires": {
+ "restore-cursor": "2.0.0"
+ }
+ },
+ "cli-width": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
+ },
+ "cliui": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+ "dev": true,
+ "requires": {
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wrap-ansi": "2.0.0"
+ }
+ },
+ "clone": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz",
+ "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=",
+ "dev": true
+ },
+ "clone-deep": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.3.0.tgz",
+ "integrity": "sha1-NIxhrpzb4O3+BT2R/0zFIdeQ7eg=",
+ "dev": true,
+ "requires": {
+ "for-own": "1.0.0",
+ "is-plain-object": "2.0.4",
+ "kind-of": "3.2.2",
+ "shallow-clone": "0.1.2"
+ },
+ "dependencies": {
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+ "dev": true,
+ "requires": {
+ "for-in": "1.0.2"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.6"
+ }
+ }
+ }
+ },
+ "clone-stats": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
+ "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
+ "dev": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
+ },
+ "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
+ },
+ "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.1"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz",
+ "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=",
+ "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="
+ },
+ "color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+ "dev": true
+ },
+ "combine-lists": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz",
+ "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=",
+ "dev": true,
+ "requires": {
+ "lodash": "4.16.6"
+ }
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
+ "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
+ "dev": true,
+ "requires": {
+ "graceful-readlink": "1.0.1"
+ }
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "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.1.2",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz",
+ "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=",
+ "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.12",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz",
+ "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.32.0"
+ },
+ "dependencies": {
+ "mime-db": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.32.0.tgz",
+ "integrity": "sha512-+ZWo/xZN40Tt6S+HyakUxnSOgff+JEdaneLWIm0Z6LmpCn5DMcZntLyUY5c/rTDog28LhXLKOUZKoTxTCAdBVw==",
+ "dev": true
+ }
+ }
+ },
+ "compression": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.1.tgz",
+ "integrity": "sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s=",
+ "dev": true,
+ "requires": {
+ "accepts": "1.3.4",
+ "bytes": "3.0.0",
+ "compressible": "2.0.12",
+ "debug": "2.6.9",
+ "on-headers": "1.0.1",
+ "safe-buffer": "5.1.1",
+ "vary": "1.1.2"
+ },
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
+ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=",
+ "dev": true,
+ "requires": {
+ "mime-types": "2.1.17",
+ "negotiator": "0.6.1"
+ }
+ },
+ "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"
+ }
+ },
+ "mime-db": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
+ "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
+ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.30.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.0",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
+ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3",
+ "typedarray": "0.0.6"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=",
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "configstore": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz",
+ "integrity": "sha1-CU7mYquD+tmRdnjeEU+q6o/NypA=",
+ "dev": true,
+ "requires": {
+ "dot-prop": "4.2.0",
+ "graceful-fs": "4.1.10",
+ "make-dir": "1.0.0",
+ "unique-string": "1.0.0",
+ "write-file-atomic": "2.3.0",
+ "xdg-basedir": "3.0.0"
+ }
+ },
+ "connect": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.5.tgz",
+ "integrity": "sha1-+43ee6B2OHfQ7J352sC0tA5yx9o=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "finalhandler": "1.0.6",
+ "parseurl": "1.3.2",
+ "utils-merge": "1.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "finalhandler": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz",
+ "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "1.0.1",
+ "escape-html": "1.0.3",
+ "on-finished": "2.3.0",
+ "parseurl": "1.3.2",
+ "statuses": "1.3.1",
+ "unpipe": "1.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "parseurl": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+ "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
+ "dev": true
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true
+ }
+ }
+ },
+ "connect-history-api-fallback": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz",
+ "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=",
+ "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"
+ }
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+ "dev": true
+ },
+ "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.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
+ "dev": true
+ },
+ "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
+ },
+ "convert-source-map": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
+ "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=",
+ "dev": true
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+ "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-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "core-js": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
+ "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=",
+ "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="
+ },
+ "cors": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.1.tgz",
+ "integrity": "sha1-YYGqVqu0WiglvjMEcDdHrk6dI4M=",
+ "dev": true,
+ "requires": {
+ "vary": "1.1.0"
+ },
+ "dependencies": {
+ "vary": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz",
+ "integrity": "sha1-4eWv+70WrnaN0mdDlLmtMCJlMUA=",
+ "dev": true
+ }
+ }
+ },
+ "create-ecdh": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
+ "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=",
+ "dev": true,
+ "requires": {
+ "bn.js": "4.11.8",
+ "elliptic": "6.4.0"
+ }
+ },
+ "create-error-class": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
+ "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
+ "dev": true,
+ "requires": {
+ "capture-stack-trace": "1.0.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
+ "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=",
+ "dev": true,
+ "requires": {
+ "cipher-base": "1.0.4",
+ "inherits": "2.0.3",
+ "ripemd160": "2.0.1",
+ "sha.js": "2.4.10"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz",
+ "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=",
+ "dev": true,
+ "requires": {
+ "cipher-base": "1.0.4",
+ "create-hash": "1.1.3",
+ "inherits": "2.0.3",
+ "ripemd160": "2.0.1",
+ "safe-buffer": "5.1.1",
+ "sha.js": "2.4.10"
+ }
+ },
+ "cross-spawn": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
+ "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "4.0.1",
+ "which": "1.2.11"
+ }
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+ "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
+ "dev": true,
+ "requires": {
+ "boom": "2.10.1"
+ }
+ },
+ "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.4",
+ "create-ecdh": "4.0.0",
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "diffie-hellman": "5.0.2",
+ "inherits": "2.0.3",
+ "pbkdf2": "3.0.14",
+ "public-encrypt": "4.0.0",
+ "randombytes": "2.0.6",
+ "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-loader": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.25.0.tgz",
+ "integrity": "sha1-w/68jOKPTINXa2sTcH9H+Qw5AiM=",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "6.16.0",
+ "css-selector-tokenizer": "0.6.0",
+ "cssnano": "3.7.7",
+ "loader-utils": "0.2.16",
+ "lodash.camelcase": "3.0.1",
+ "object-assign": "4.1.0",
+ "postcss": "5.2.4",
+ "postcss-modules-extract-imports": "1.0.1",
+ "postcss-modules-local-by-default": "1.1.1",
+ "postcss-modules-scope": "1.0.2",
+ "postcss-modules-values": "1.2.2",
+ "source-list-map": "0.1.6"
+ },
+ "dependencies": {
+ "babel-code-frame": {
+ "version": "6.16.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.16.0.tgz",
+ "integrity": "sha1-+Q5g2ghikJ084JhzO105h8l8uN4=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "esutils": "2.0.2",
+ "js-tokens": "2.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz",
+ "integrity": "sha1-eZA/VWPud4zBFi5tzxoAJ8l/nLU=",
+ "dev": true
+ }
+ }
+ },
+ "css-selector-tokenizer": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.6.0.tgz",
+ "integrity": "sha1-ZEX1gseTDSQdzFAHpD1vy48HMVI=",
+ "dev": true,
+ "requires": {
+ "cssesc": "0.1.0",
+ "fastparse": "1.1.1",
+ "regexpu-core": "1.0.0"
+ },
+ "dependencies": {
+ "cssesc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
+ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
+ "dev": true
+ },
+ "fastparse": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
+ "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=",
+ "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.3.1",
+ "regjsgen": "0.2.0",
+ "regjsparser": "0.1.5"
+ },
+ "dependencies": {
+ "regenerate": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.1.tgz",
+ "integrity": "sha1-AwAgOl0v3PiRFtzoQnXQEfWQPzM=",
+ "dev": true
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "requires": {
+ "jsesc": "0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "cssnano": {
+ "version": "3.7.7",
+ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.7.7.tgz",
+ "integrity": "sha1-J/rGETgMaknW9yLAU35amIp4UBA=",
+ "dev": true,
+ "requires": {
+ "autoprefixer": "6.5.1",
+ "decamelize": "1.2.0",
+ "defined": "1.0.0",
+ "has": "1.0.1",
+ "object-assign": "4.1.0",
+ "postcss": "5.2.4",
+ "postcss-calc": "5.3.1",
+ "postcss-colormin": "2.2.1",
+ "postcss-convert-values": "2.4.1",
+ "postcss-discard-comments": "2.0.4",
+ "postcss-discard-duplicates": "2.0.1",
+ "postcss-discard-empty": "2.1.0",
+ "postcss-discard-overridden": "0.1.1",
+ "postcss-discard-unused": "2.2.1",
+ "postcss-filter-plugins": "2.0.2",
+ "postcss-merge-idents": "2.1.7",
+ "postcss-merge-longhand": "2.0.1",
+ "postcss-merge-rules": "2.0.10",
+ "postcss-minify-font-values": "1.0.5",
+ "postcss-minify-gradients": "1.0.3",
+ "postcss-minify-params": "1.0.5",
+ "postcss-minify-selectors": "2.0.5",
+ "postcss-normalize-charset": "1.1.0",
+ "postcss-normalize-url": "3.0.7",
+ "postcss-ordered-values": "2.2.2",
+ "postcss-reduce-idents": "2.3.0",
+ "postcss-reduce-initial": "1.0.0",
+ "postcss-reduce-transforms": "1.0.3",
+ "postcss-svgo": "2.1.5",
+ "postcss-unique-selectors": "2.0.2",
+ "postcss-value-parser": "3.3.0",
+ "postcss-zindex": "2.1.1"
+ },
+ "dependencies": {
+ "autoprefixer": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.5.1.tgz",
+ "integrity": "sha1-rnWaUiHnCfPaF8LWViMOZ8Q8u3U=",
+ "dev": true,
+ "requires": {
+ "browserslist": "1.4.0",
+ "caniuse-db": "1.0.30000559",
+ "normalize-range": "0.1.2",
+ "num2fraction": "1.2.2",
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ },
+ "dependencies": {
+ "browserslist": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.4.0.tgz",
+ "integrity": "sha1-nP3PU4TZFY9bcNoqoAsw6P8BkEk=",
+ "dev": true,
+ "requires": {
+ "caniuse-db": "1.0.30000559"
+ }
+ },
+ "caniuse-db": {
+ "version": "1.0.30000559",
+ "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000559.tgz",
+ "integrity": "sha1-r71okW3SO/1UnCZSDHhjH7Xi45M=",
+ "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
+ },
+ "num2fraction": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
+ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
+ "dev": true
+ }
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "defined": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
+ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
+ "dev": true,
+ "requires": {
+ "function-bind": "1.1.0"
+ },
+ "dependencies": {
+ "function-bind": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz",
+ "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=",
+ "dev": true
+ }
+ }
+ },
+ "postcss-calc": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz",
+ "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4",
+ "postcss-message-helpers": "2.0.0",
+ "reduce-css-calc": "1.3.0"
+ },
+ "dependencies": {
+ "postcss-message-helpers": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz",
+ "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=",
+ "dev": true
+ },
+ "reduce-css-calc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz",
+ "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=",
+ "dev": true,
+ "requires": {
+ "balanced-match": "0.4.2",
+ "math-expression-evaluator": "1.2.14",
+ "reduce-function-call": "1.0.1"
+ },
+ "dependencies": {
+ "balanced-match": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=",
+ "dev": true
+ },
+ "math-expression-evaluator": {
+ "version": "1.2.14",
+ "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.14.tgz",
+ "integrity": "sha1-OVEXce2WAkBfupr//xfrTSo4Q6s=",
+ "dev": true,
+ "requires": {
+ "lodash.indexof": "4.0.5"
+ },
+ "dependencies": {
+ "lodash.indexof": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/lodash.indexof/-/lodash.indexof-4.0.5.tgz",
+ "integrity": "sha1-U3FK3Czd1u2HY4+JOqm2wk4x7zw=",
+ "dev": true
+ }
+ }
+ },
+ "reduce-function-call": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.1.tgz",
+ "integrity": "sha1-+gLhJuaVgkJjyrkdOlsP3B3Sepo=",
+ "dev": true,
+ "requires": {
+ "balanced-match": "0.1.0"
+ },
+ "dependencies": {
+ "balanced-match": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.1.0.tgz",
+ "integrity": "sha1-tQS9BYabOSWd0MXvw12EMXbczEo=",
+ "dev": true
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "postcss-colormin": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.1.tgz",
+ "integrity": "sha1-3FQhtq5vd572v9RzUrlKvlnQMWs=",
+ "dev": true,
+ "requires": {
+ "colormin": "1.1.2",
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ },
+ "dependencies": {
+ "colormin": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz",
+ "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=",
+ "dev": true,
+ "requires": {
+ "color": "0.11.3",
+ "css-color-names": "0.0.4",
+ "has": "1.0.1"
+ },
+ "dependencies": {
+ "color": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-0.11.3.tgz",
+ "integrity": "sha1-S60dDVJJndANvW8IaEQkZ+STlOY=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.2",
+ "color-convert": "1.5.0",
+ "color-string": "0.3.0"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz",
+ "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.5.0.tgz",
+ "integrity": "sha1-eitO+0SI34W8pkQ8sDi3EA++feE=",
+ "dev": true
+ },
+ "color-string": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz",
+ "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.1"
+ },
+ "dependencies": {
+ "color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "css-color-names": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
+ "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "postcss-convert-values": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.4.1.tgz",
+ "integrity": "sha1-Rdzk1OM7fZZ7l6TZN/Jw6pjS/no=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-discard-comments": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz",
+ "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-discard-duplicates": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.0.1.tgz",
+ "integrity": "sha1-X64/GnHfPhnP+zcwnRp9ulbEWJw=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-discard-empty": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz",
+ "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-discard-overridden": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz",
+ "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-discard-unused": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.1.tgz",
+ "integrity": "sha1-XQIfAhpu1s7HMQ1GA3lKdd3VMjI=",
+ "dev": true,
+ "requires": {
+ "flatten": "1.0.2",
+ "postcss": "5.2.4",
+ "uniqs": "2.0.0"
+ },
+ "dependencies": {
+ "flatten": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
+ "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=",
+ "dev": true
+ },
+ "uniqs": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz",
+ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
+ "dev": true
+ }
+ }
+ },
+ "postcss-filter-plugins": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz",
+ "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4",
+ "uniqid": "4.1.0"
+ },
+ "dependencies": {
+ "uniqid": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.0.tgz",
+ "integrity": "sha1-M9lnn2UCL0iYigP9JOfcr48Qnso=",
+ "dev": true,
+ "requires": {
+ "macaddress": "0.2.8"
+ },
+ "dependencies": {
+ "macaddress": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz",
+ "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "postcss-merge-idents": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz",
+ "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=",
+ "dev": true,
+ "requires": {
+ "has": "1.0.1",
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-merge-longhand": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.1.tgz",
+ "integrity": "sha1-/1m13sbVhs4s6hgxOPVcWHb6nNw=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-merge-rules": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.0.10.tgz",
+ "integrity": "sha1-VLNgvoBOfmmlxyImNSR7kqNWnps=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4",
+ "vendors": "1.0.1"
+ },
+ "dependencies": {
+ "vendors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz",
+ "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=",
+ "dev": true
+ }
+ }
+ },
+ "postcss-minify-font-values": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz",
+ "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=",
+ "dev": true,
+ "requires": {
+ "object-assign": "4.1.0",
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-minify-gradients": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.3.tgz",
+ "integrity": "sha1-CdIoFIyUL6gSZnnen/dzi1SRn+M=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-minify-params": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.0.5.tgz",
+ "integrity": "sha1-gtYCZDuGFqYfs2NNft4CiYNtZ/k=",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "1.0.2",
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0",
+ "uniqs": "2.0.0"
+ },
+ "dependencies": {
+ "alphanum-sort": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
+ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
+ "dev": true
+ },
+ "uniqs": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz",
+ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
+ "dev": true
+ }
+ }
+ },
+ "postcss-minify-selectors": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.0.5.tgz",
+ "integrity": "sha1-Th+Wb7SclSZoBAFrqaPGZFu2AeA=",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "1.0.2",
+ "postcss": "5.2.4",
+ "postcss-selector-parser": "2.2.1"
+ },
+ "dependencies": {
+ "alphanum-sort": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
+ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
+ "dev": true
+ },
+ "postcss-selector-parser": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.1.tgz",
+ "integrity": "sha1-/b9pYQOxKwpkBg5WEFB/QQSR98g=",
+ "dev": true,
+ "requires": {
+ "flatten": "1.0.2",
+ "indexes-of": "1.0.1",
+ "uniq": "1.0.1"
+ },
+ "dependencies": {
+ "flatten": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
+ "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=",
+ "dev": true
+ },
+ "indexes-of": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
+ "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
+ "dev": true
+ },
+ "uniq": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
+ "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "postcss-normalize-charset": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.0.tgz",
+ "integrity": "sha1-L70w4SJIxEKYHTHqJITUb9BiiXA=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-normalize-url": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.7.tgz",
+ "integrity": "sha1-a9kNCkvFod8iwm6mXFMlfcOCn04=",
+ "dev": true,
+ "requires": {
+ "is-absolute-url": "2.0.0",
+ "normalize-url": "1.6.1",
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ },
+ "dependencies": {
+ "is-absolute-url": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.0.0.tgz",
+ "integrity": "sha1-nEsgsOXAy++aR5o2ft5vmRZ581k=",
+ "dev": true
+ },
+ "normalize-url": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.6.1.tgz",
+ "integrity": "sha1-qfJU+gZbvCk0RhwMCUI4FZdhVaI=",
+ "dev": true,
+ "requires": {
+ "object-assign": "4.1.0",
+ "prepend-http": "1.0.4",
+ "query-string": "4.2.3",
+ "sort-keys": "1.1.2"
+ },
+ "dependencies": {
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
+ "dev": true
+ },
+ "query-string": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.2.3.tgz",
+ "integrity": "sha1-nycnPSB6JajuTHuMdNzUXVVtuCI=",
+ "dev": true,
+ "requires": {
+ "object-assign": "4.1.0",
+ "strict-uri-encode": "1.1.0"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ },
+ "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.1.0"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "postcss-ordered-values": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.2.tgz",
+ "integrity": "sha1-votRF0H6strI5hSiMC6dECZ7B3E=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-reduce-idents": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.3.0.tgz",
+ "integrity": "sha1-ppe1KVPtaCX/6kBOJqTxBdi41Wk=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-reduce-initial": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.0.tgz",
+ "integrity": "sha1-j3Obk4KJ7y5Ik21xAXg+R0HKm7s=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-reduce-transforms": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.3.tgz",
+ "integrity": "sha1-/Bk+Q1qXPBD5gBx0cAqDD3lkM0M=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-svgo": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.5.tgz",
+ "integrity": "sha1-RvwDY/Abq2o2qauwHCKfzEU2MJQ=",
+ "dev": true,
+ "requires": {
+ "is-svg": "2.0.1",
+ "postcss": "5.2.4",
+ "postcss-value-parser": "3.3.0",
+ "svgo": "0.7.1"
+ },
+ "dependencies": {
+ "is-svg": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.0.1.tgz",
+ "integrity": "sha1-+Tqzvx1rvKMOl1PNNIWxMA7rwBM=",
+ "dev": true,
+ "requires": {
+ "html-comment-regex": "1.1.1"
+ },
+ "dependencies": {
+ "html-comment-regex": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz",
+ "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=",
+ "dev": true
+ }
+ }
+ },
+ "svgo": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.1.tgz",
+ "integrity": "sha1-KHMg/tlyywl+csK7FoX5b+CPgDQ=",
+ "dev": true,
+ "requires": {
+ "coa": "1.0.1",
+ "colors": "1.1.2",
+ "csso": "2.2.1",
+ "js-yaml": "3.6.1",
+ "mkdirp": "0.5.1",
+ "sax": "1.2.1",
+ "whet.extend": "0.9.9"
+ },
+ "dependencies": {
+ "coa": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.1.tgz",
+ "integrity": "sha1-f5WTRs/IcZ4/cjPNaFKFSnxn2KM=",
+ "dev": true,
+ "requires": {
+ "q": "1.4.1"
+ },
+ "dependencies": {
+ "q": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
+ "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
+ "dev": true
+ }
+ }
+ },
+ "colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+ "dev": true
+ },
+ "csso": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-2.2.1.tgz",
+ "integrity": "sha1-Ufu1NH5Q6B5u1RZopISQrm/ir+I=",
+ "dev": true,
+ "requires": {
+ "clap": "1.1.1",
+ "source-map": "0.5.6"
+ },
+ "dependencies": {
+ "clap": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/clap/-/clap-1.1.1.tgz",
+ "integrity": "sha1-qKk+C/t1gawZnE8AGlUlpyTOaW0=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "dev": true
+ }
+ }
+ },
+ "js-yaml": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz",
+ "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=",
+ "dev": true,
+ "requires": {
+ "argparse": "1.0.9",
+ "esprima": "2.7.3"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "1.0.3"
+ },
+ "dependencies": {
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ }
+ }
+ },
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+ "dev": true
+ }
+ }
+ },
+ "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
+ }
+ }
+ },
+ "sax": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
+ "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=",
+ "dev": true
+ },
+ "whet.extend": {
+ "version": "0.9.9",
+ "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz",
+ "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "postcss-unique-selectors": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz",
+ "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "1.0.2",
+ "postcss": "5.2.4",
+ "uniqs": "2.0.0"
+ },
+ "dependencies": {
+ "alphanum-sort": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
+ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
+ "dev": true
+ },
+ "uniqs": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz",
+ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
+ "dev": true
+ }
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
+ "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=",
+ "dev": true
+ },
+ "postcss-zindex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.1.1.tgz",
+ "integrity": "sha1-6j++ZWyXOKqHKeLuluwqRgibcg8=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4",
+ "uniqs": "2.0.0"
+ },
+ "dependencies": {
+ "uniqs": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz",
+ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "loader-utils": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.16.tgz",
+ "integrity": "sha1-8IYyBm7YKCg13/iN+1JwR2Wt7m0=",
+ "dev": true,
+ "requires": {
+ "big.js": "3.1.3",
+ "emojis-list": "2.1.0",
+ "json5": "0.5.0",
+ "object-assign": "4.1.0"
+ },
+ "dependencies": {
+ "big.js": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz",
+ "integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg=",
+ "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
+ },
+ "json5": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.0.tgz",
+ "integrity": "sha1-myBxWwJsvjd4/Xae3M2CLYMypbI=",
+ "dev": true
+ }
+ }
+ },
+ "lodash.camelcase": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-3.0.1.tgz",
+ "integrity": "sha1-kyyLh/ikN3iXxnGXUzKC+Xrqwpg=",
+ "dev": true,
+ "requires": {
+ "lodash._createcompounder": "3.0.0"
+ },
+ "dependencies": {
+ "lodash._createcompounder": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._createcompounder/-/lodash._createcompounder-3.0.0.tgz",
+ "integrity": "sha1-XdLLVTctbnDg4jkvsjBNZjEJEHU=",
+ "dev": true,
+ "requires": {
+ "lodash.deburr": "3.2.0",
+ "lodash.words": "3.2.0"
+ },
+ "dependencies": {
+ "lodash.deburr": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-3.2.0.tgz",
+ "integrity": "sha1-baj1QzSjZqfPTEx2742Aqhs2XtU=",
+ "dev": true,
+ "requires": {
+ "lodash._root": "3.0.1"
+ },
+ "dependencies": {
+ "lodash._root": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
+ "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=",
+ "dev": true
+ }
+ }
+ },
+ "lodash.words": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.words/-/lodash.words-3.2.0.tgz",
+ "integrity": "sha1-TiqGSbwIdFsXxpWxo86P7llmI7M=",
+ "dev": true,
+ "requires": {
+ "lodash._root": "3.0.1"
+ },
+ "dependencies": {
+ "lodash._root": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
+ "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=",
+ "dev": true
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "object-assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
+ "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=",
+ "dev": true
+ },
+ "postcss": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.4.tgz",
+ "integrity": "sha1-jrS+4+XE4JFYWxFt8y2NskpTXyE=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "js-base64": "2.1.9",
+ "source-map": "0.5.6",
+ "supports-color": "3.1.2"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "js-base64": {
+ "version": "2.1.9",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz",
+ "integrity": "sha1-8OgK4DmkvWVLXygfyT8EqRSn/M4=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
+ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
+ "dev": true,
+ "requires": {
+ "has-flag": "1.0.0"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "postcss-modules-extract-imports": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.0.1.tgz",
+ "integrity": "sha1-j7P++abdBCDT9tQ1PPH/c/Kyo0E=",
+ "dev": true,
+ "requires": {
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-modules-local-by-default": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.1.1.tgz",
+ "integrity": "sha1-KaEGc/o30ZJRJlyiujFQ2QQOtM4=",
+ "dev": true,
+ "requires": {
+ "css-selector-tokenizer": "0.6.0",
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-modules-scope": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.0.2.tgz",
+ "integrity": "sha1-/5dzleXgYgLXNiKQuIsejNBJ3ik=",
+ "dev": true,
+ "requires": {
+ "css-selector-tokenizer": "0.6.0",
+ "postcss": "5.2.4"
+ }
+ },
+ "postcss-modules-values": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.2.2.tgz",
+ "integrity": "sha1-8OfUdv4e2IxeTH+XUzo+dyrZTKE=",
+ "dev": true,
+ "requires": {
+ "icss-replace-symbols": "1.0.2",
+ "postcss": "5.2.4"
+ },
+ "dependencies": {
+ "icss-replace-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.0.2.tgz",
+ "integrity": "sha1-ywtgVOs69u3Jqx1i0Bkz4tTIv6U=",
+ "dev": true
+ }
+ }
+ },
+ "source-list-map": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.6.tgz",
+ "integrity": "sha1-4eb5TwtAxNKNz49bh2bg5FY2h38=",
+ "dev": true
+ }
+ }
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "1.0.2"
+ }
+ },
+ "custom-event": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
+ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=",
+ "dev": true
+ },
+ "d": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz",
+ "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=",
+ "dev": true,
+ "requires": {
+ "es5-ext": "0.10.12"
+ }
+ },
+ "dargs": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz",
+ "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=",
+ "dev": true
+ },
+ "dashdash": {
+ "version": "1.14.0",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz",
+ "integrity": "sha1-KeSGxUGL8PNWA0qZPVFoajPoQUE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "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
+ },
+ "dateformat": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1",
+ "meow": "3.7.0"
+ }
+ },
+ "debug": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+ "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+ "dev": true,
+ "requires": {
+ "ms": "0.7.1"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "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
+ },
+ "deep-defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/deep-defaults/-/deep-defaults-1.0.4.tgz",
+ "integrity": "sha1-Gpdi4rbI1qTpkxuO5/+M3O4dF1A=",
+ "dev": true,
+ "requires": {
+ "lodash": "3.0.1"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.0.1.tgz",
+ "integrity": "sha1-FNSQKKOLx0AkHRHi7NV+wG1zwZo=",
+ "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=",
+ "dev": true
+ },
+ "deep-extend": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
+ "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=",
+ "dev": true
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
+ },
+ "defaults": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
+ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.2"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
+ "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
+ "dev": true,
+ "requires": {
+ "foreach": "2.0.5",
+ "object-keys": "1.0.11"
+ },
+ "dependencies": {
+ "object-keys": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
+ "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=",
+ "dev": true
+ }
+ }
+ },
+ "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.2"
+ }
+ },
+ "del": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+ "requires": {
+ "globby": "5.0.0",
+ "is-path-cwd": "1.0.0",
+ "is-path-in-cwd": "1.0.0",
+ "object-assign": "4.1.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "rimraf": "2.5.4"
+ }
+ },
+ "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
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+ "dev": true
+ },
+ "denque": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-1.2.3.tgz",
+ "integrity": "sha512-BOjyD1zPf7gqgXlXBCnCsz84cbRNfqpQNvWOUiw3Onu9s7a2afW2LyHzctoie/2KELfUoZkNHTnW02C3hCU20w==",
+ "dev": true
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "dev": true
+ },
+ "deprecated": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz",
+ "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=",
+ "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.3",
+ "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-file": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
+ "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
+ "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.1"
+ }
+ },
+ "detect-node": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
+ "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=",
+ "dev": true
+ },
+ "di": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
+ "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz",
+ "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
+ "dev": true,
+ "requires": {
+ "bn.js": "4.11.8",
+ "miller-rabin": "4.0.1",
+ "randombytes": "2.0.6"
+ }
+ },
+ "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.5",
+ "safe-buffer": "5.1.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.1.1"
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "requires": {
+ "esutils": "2.0.2"
+ }
+ },
+ "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.1",
+ "ent": "2.2.0",
+ "extend": "3.0.0",
+ "void-elements": "2.0.1"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
+ "requires": {
+ "domelementtype": "1.1.3",
+ "entities": "1.1.1"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+ "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
+ }
+ }
+ },
+ "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
+ },
+ "domelementtype": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+ "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI="
+ },
+ "domhandler": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz",
+ "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=",
+ "requires": {
+ "domelementtype": "1.3.0"
+ }
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "requires": {
+ "dom-serializer": "0.1.0",
+ "domelementtype": "1.3.0"
+ }
+ },
+ "dot-prop": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+ "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=",
+ "dev": true,
+ "requires": {
+ "is-obj": "1.0.1"
+ }
+ },
+ "duplexer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+ "dev": true
+ },
+ "duplexer2": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
+ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.1.14"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ }
+ }
+ },
+ "duplexer3": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+ "dev": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.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": {
+ "version": "1.7.9",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-1.7.9.tgz",
+ "integrity": "sha1-rdVOn4+D7QL2UZ7BATX2mLGTNs8=",
+ "dev": true,
+ "requires": {
+ "@types/node": "7.0.48",
+ "electron-download": "3.3.0",
+ "extract-zip": "1.6.6"
+ }
+ },
+ "electron-download": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz",
+ "integrity": "sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=",
+ "dev": true,
+ "requires": {
+ "debug": "2.2.0",
+ "fs-extra": "0.30.0",
+ "home-path": "1.0.5",
+ "minimist": "1.2.0",
+ "nugget": "2.0.1",
+ "path-exists": "2.1.0",
+ "rc": "1.2.1",
+ "semver": "5.3.0",
+ "sumchecker": "1.3.1"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "0.30.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
+ "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10",
+ "jsonfile": "2.4.0",
+ "klaw": "1.3.1",
+ "path-is-absolute": "1.0.1",
+ "rimraf": "2.5.4"
+ }
+ },
+ "jsonfile": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10"
+ }
+ }
+ }
+ },
+ "elliptic": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
+ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+ "dev": true,
+ "requires": {
+ "bn.js": "4.11.8",
+ "brorand": "1.1.0",
+ "hash.js": "1.1.3",
+ "hmac-drbg": "1.0.1",
+ "inherits": "2.0.3",
+ "minimalistic-assert": "1.0.0",
+ "minimalistic-crypto-utils": "1.0.1"
+ }
+ },
+ "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.1",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz",
+ "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=",
+ "dev": true
+ },
+ "end-of-stream": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz",
+ "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=",
+ "dev": true,
+ "requires": {
+ "once": "1.3.3"
+ },
+ "dependencies": {
+ "once": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
+ "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ }
+ }
+ },
+ "engine.io": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz",
+ "integrity": "sha1-jef5eJXSDTm4X4ju7nd7K9QrE9Q=",
+ "dev": true,
+ "requires": {
+ "accepts": "1.3.3",
+ "base64id": "1.0.0",
+ "cookie": "0.3.1",
+ "debug": "2.3.3",
+ "engine.io-parser": "1.3.2",
+ "ws": "1.1.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
+ "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
+ "dev": true,
+ "requires": {
+ "ms": "0.7.2"
+ }
+ },
+ "ms": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+ "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
+ "dev": true
+ }
+ }
+ },
+ "engine.io-client": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.3.tgz",
+ "integrity": "sha1-F5jtk0USRkU9TG9jXXogH+lA1as=",
+ "dev": true,
+ "requires": {
+ "component-emitter": "1.2.1",
+ "component-inherit": "0.0.3",
+ "debug": "2.3.3",
+ "engine.io-parser": "1.3.2",
+ "has-cors": "1.1.0",
+ "indexof": "0.0.1",
+ "parsejson": "0.0.3",
+ "parseqs": "0.0.5",
+ "parseuri": "0.0.5",
+ "ws": "1.1.2",
+ "xmlhttprequest-ssl": "1.5.3",
+ "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": "2.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
+ "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
+ "dev": true,
+ "requires": {
+ "ms": "0.7.2"
+ }
+ },
+ "ms": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+ "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
+ "dev": true
+ }
+ }
+ },
+ "engine.io-parser": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz",
+ "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=",
+ "dev": true,
+ "requires": {
+ "after": "0.8.2",
+ "arraybuffer.slice": "0.0.6",
+ "base64-arraybuffer": "0.1.5",
+ "blob": "0.0.4",
+ "has-binary": "0.1.7",
+ "wtf-8": "1.0.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz",
+ "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10",
+ "memory-fs": "0.4.1",
+ "object-assign": "4.1.0",
+ "tapable": "0.2.8"
+ }
+ },
+ "enqueue": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/enqueue/-/enqueue-1.0.2.tgz",
+ "integrity": "sha1-kBTpvOVw7pPKlubI5jrVTBkra8g=",
+ "dev": true,
+ "requires": {
+ "sliced": "0.0.5"
+ },
+ "dependencies": {
+ "sliced": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz",
+ "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=",
+ "dev": true
+ }
+ }
+ },
+ "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.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
+ "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
+ },
+ "errno": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz",
+ "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=",
+ "dev": true,
+ "requires": {
+ "prr": "0.0.0"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz",
+ "integrity": "sha1-5ntD8+gsluo6WE/+4Ln8MyXYAtk=",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz",
+ "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "1.1.1",
+ "function-bind": "1.1.1",
+ "has": "1.0.1",
+ "is-callable": "1.1.3",
+ "is-regex": "1.0.4"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
+ "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
+ "dev": true,
+ "requires": {
+ "is-callable": "1.1.3",
+ "is-date-object": "1.0.1",
+ "is-symbol": "1.0.1"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.12",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.12.tgz",
+ "integrity": "sha1-qoRkHU23a2Krul5F/YBey6sUAEc=",
+ "dev": true,
+ "requires": {
+ "es6-iterator": "2.0.0",
+ "es6-symbol": "3.1.0"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.0.tgz",
+ "integrity": "sha1-vZaFZ9YWNeM8C4BydhPJy0sJa6w=",
+ "dev": true,
+ "requires": {
+ "d": "0.1.1",
+ "es5-ext": "0.10.12",
+ "es6-symbol": "3.1.0"
+ }
+ },
+ "es6-map": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
+ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30",
+ "es6-iterator": "2.0.1",
+ "es6-set": "0.1.5",
+ "es6-symbol": "3.1.1",
+ "event-emitter": "0.3.5"
+ },
+ "dependencies": {
+ "d": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
+ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
+ "dev": true,
+ "requires": {
+ "es5-ext": "0.10.30"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.30",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz",
+ "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=",
+ "dev": true,
+ "requires": {
+ "es6-iterator": "2.0.1",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz",
+ "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30"
+ }
+ }
+ }
+ },
+ "es6-promise": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz",
+ "integrity": "sha1-iBHpCRXZoNujYnTwskLb2nj5ySo=",
+ "dev": true
+ },
+ "es6-set": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
+ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30",
+ "es6-iterator": "2.0.1",
+ "es6-symbol": "3.1.1",
+ "event-emitter": "0.3.5"
+ },
+ "dependencies": {
+ "d": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
+ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
+ "dev": true,
+ "requires": {
+ "es5-ext": "0.10.30"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.30",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz",
+ "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=",
+ "dev": true,
+ "requires": {
+ "es6-iterator": "2.0.1",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz",
+ "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30"
+ }
+ }
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.0.tgz",
+ "integrity": "sha1-lEgcZV56fK2C66gy2X1UM0ltf/o=",
+ "dev": true,
+ "requires": {
+ "d": "0.1.1",
+ "es5-ext": "0.10.12"
+ }
+ },
+ "es6-templates": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz",
+ "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=",
+ "dev": true,
+ "requires": {
+ "recast": "0.11.18",
+ "through": "2.3.8"
+ }
+ },
+ "es6-weak-map": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz",
+ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30",
+ "es6-iterator": "2.0.1",
+ "es6-symbol": "3.1.1"
+ },
+ "dependencies": {
+ "d": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
+ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
+ "dev": true,
+ "requires": {
+ "es5-ext": "0.10.30"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.30",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz",
+ "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=",
+ "dev": true,
+ "requires": {
+ "es6-iterator": "2.0.1",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz",
+ "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30",
+ "es6-symbol": "3.1.1"
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30"
+ }
+ }
+ }
+ },
+ "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="
+ },
+ "escope": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
+ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=",
+ "dev": true,
+ "requires": {
+ "es6-map": "0.1.5",
+ "es6-weak-map": "2.0.2",
+ "esrecurse": "4.2.0",
+ "estraverse": "4.2.0"
+ }
+ },
+ "eslint": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz",
+ "integrity": "sha512-AyxBUCANU/o/xC0ijGMKavo5Ls3oK6xykiOITlMdjFjrKOsqLrA7Nf5cnrDgcKrHzBirclAZt63XO7YZlVUPwA==",
+ "requires": {
+ "ajv": "5.5.2",
+ "babel-code-frame": "6.26.0",
+ "chalk": "2.3.1",
+ "concat-stream": "1.6.0",
+ "cross-spawn": "5.1.0",
+ "debug": "3.1.0",
+ "doctrine": "2.1.0",
+ "eslint-scope": "3.7.1",
+ "eslint-visitor-keys": "1.0.0",
+ "espree": "3.5.3",
+ "esquery": "1.0.0",
+ "esutils": "2.0.2",
+ "file-entry-cache": "2.0.0",
+ "functional-red-black-tree": "1.0.1",
+ "glob": "7.1.2",
+ "globals": "11.3.0",
+ "ignore": "3.3.7",
+ "imurmurhash": "0.1.4",
+ "inquirer": "3.3.0",
+ "is-resolvable": "1.1.0",
+ "js-yaml": "3.10.0",
+ "json-stable-stringify-without-jsonify": "1.0.1",
+ "levn": "0.3.0",
+ "lodash": "4.17.5",
+ "minimatch": "3.0.3",
+ "mkdirp": "0.5.1",
+ "natural-compare": "1.4.0",
+ "optionator": "0.8.2",
+ "path-is-inside": "1.0.2",
+ "pluralize": "7.0.0",
+ "progress": "2.0.0",
+ "require-uncached": "1.0.3",
+ "semver": "5.3.0",
+ "strip-ansi": "4.0.0",
+ "strip-json-comments": "2.0.1",
+ "table": "4.0.2",
+ "text-table": "0.2.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.0"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "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"
+ }
+ },
+ "chalk": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz",
+ "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "5.2.0"
+ }
+ },
+ "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=",
+ "requires": {
+ "lru-cache": "4.0.1",
+ "shebang-command": "1.2.0",
+ "which": "1.2.11"
+ }
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ },
+ "dependencies": {
+ "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.11"
+ }
+ }
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "pluralize": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
+ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow=="
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "3.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz",
+ "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==",
+ "requires": {
+ "has-flag": "3.0.0"
+ }
+ }
+ }
+ },
+ "eslint-config-angular": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-angular/-/eslint-config-angular-0.5.0.tgz",
+ "integrity": "sha1-4KrgEy4550Z98/dUf+yBpE02hcQ=",
+ "dev": true
+ },
+ "eslint-config-google": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.6.0.tgz",
+ "integrity": "sha1-xULsGPsyR5g6wWu6MWYtAWJbdj8=",
+ "dev": true,
+ "requires": {
+ "eslint-config-xo": "0.13.0"
+ },
+ "dependencies": {
+ "eslint-config-xo": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.13.0.tgz",
+ "integrity": "sha1-+RZ2VDK6Z9L8enF3uLz+8/brBWQ=",
+ "dev": true
+ }
+ }
+ },
+ "eslint-config-loopback": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-loopback/-/eslint-config-loopback-4.0.0.tgz",
+ "integrity": "sha1-0iwQUq19TNELij7KJStKkYSey9I=",
+ "dev": true
+ },
+ "eslint-config-xo": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.17.0.tgz",
+ "integrity": "sha1-Hn1Khr9JF5gFxGIugyp7G+606IE=",
+ "dev": true
+ },
+ "eslint-plugin-html": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-4.0.2.tgz",
+ "integrity": "sha512-CrQd0F8GWdNWnu4PFrYZl+LjUCXNVy2h0uhDMtnf/7VKc9HRcnkXSrlg0BSGfptZPSzmwnnwCaREAa9+fnQhYw==",
+ "requires": {
+ "htmlparser2": "3.9.2"
+ }
+ },
+ "eslint-plugin-jasmine": {
+ "version": "2.8.4",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.8.4.tgz",
+ "integrity": "sha1-Z6VVHj0dXguMa1Sq66uVNw9dN94=",
+ "dev": true
+ },
+ "eslint-scope": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
+ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
+ "requires": {
+ "esrecurse": "4.2.0",
+ "estraverse": "4.2.0"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+ "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ=="
+ },
+ "espree": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz",
+ "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==",
+ "requires": {
+ "acorn": "5.4.1",
+ "acorn-jsx": "3.0.1"
+ }
+ },
+ "esprima": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.2.tgz",
+ "integrity": "sha1-lUtdGTIcpDYJL6kPBtZ5hTH+gYQ=",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz",
+ "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=",
+ "requires": {
+ "estraverse": "4.2.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
+ "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=",
+ "requires": {
+ "estraverse": "4.2.0",
+ "object-assign": "4.1.0"
+ }
+ },
+ "estraverse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+ "dev": true
+ },
+ "event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
+ "dev": true,
+ "requires": {
+ "d": "1.0.0",
+ "es5-ext": "0.10.30"
+ },
+ "dependencies": {
+ "d": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
+ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
+ "dev": true,
+ "requires": {
+ "es5-ext": "0.10.30"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.30",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz",
+ "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=",
+ "dev": true,
+ "requires": {
+ "es6-iterator": "2.0.0",
+ "es6-symbol": "3.1.0"
+ }
+ }
+ }
+ },
+ "event-stream": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
+ "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
+ "dev": true,
+ "requires": {
+ "duplexer": "0.1.1",
+ "from": "0.1.3",
+ "map-stream": "0.1.0",
+ "pause-stream": "0.0.11",
+ "split": "0.3.3",
+ "stream-combiner": "0.0.4",
+ "through": "2.3.8"
+ }
+ },
+ "eventemitter3": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz",
+ "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=",
+ "dev": true
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
+ "dev": true
+ },
+ "eventsource": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz",
+ "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=",
+ "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": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "5.1.0",
+ "get-stream": "3.0.0",
+ "is-stream": "1.1.0",
+ "npm-run-path": "2.0.2",
+ "p-finally": "1.0.0",
+ "signal-exit": "3.0.1",
+ "strip-eof": "1.0.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.11"
+ }
+ }
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true
+ },
+ "expand-braces": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz",
+ "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=",
+ "dev": true,
+ "requires": {
+ "array-slice": "0.2.3",
+ "array-unique": "0.2.1",
+ "braces": "0.1.5"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz",
+ "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=",
+ "dev": true,
+ "requires": {
+ "expand-range": "0.1.1"
+ }
+ },
+ "expand-range": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz",
+ "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=",
+ "dev": true,
+ "requires": {
+ "is-number": "0.1.1",
+ "repeat-string": "0.2.2"
+ }
+ },
+ "is-number": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz",
+ "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz",
+ "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=",
+ "dev": true
+ }
+ }
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true,
+ "requires": {
+ "is-posix-bracket": "0.1.1"
+ }
+ },
+ "expand-range": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+ "dev": true,
+ "requires": {
+ "fill-range": "2.2.3"
+ }
+ },
+ "expand-tilde": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
+ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
+ "dev": true,
+ "requires": {
+ "homedir-polyfill": "1.0.1"
+ }
+ },
+ "express": {
+ "version": "4.16.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz",
+ "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=",
+ "dev": true,
+ "requires": {
+ "accepts": "1.3.4",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.18.2",
+ "content-disposition": "0.5.2",
+ "content-type": "1.0.4",
+ "cookie": "0.3.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "1.1.2",
+ "encodeurl": "1.0.1",
+ "escape-html": "1.0.3",
+ "etag": "1.8.1",
+ "finalhandler": "1.1.0",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "1.1.2",
+ "on-finished": "2.3.0",
+ "parseurl": "1.3.2",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "2.0.2",
+ "qs": "6.5.1",
+ "range-parser": "1.2.0",
+ "safe-buffer": "5.1.1",
+ "send": "0.16.1",
+ "serve-static": "1.13.1",
+ "setprototypeof": "1.1.0",
+ "statuses": "1.3.1",
+ "type-is": "1.6.15",
+ "utils-merge": "1.0.1",
+ "vary": "1.1.2"
+ },
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
+ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=",
+ "dev": true,
+ "requires": {
+ "mime-types": "2.1.17",
+ "negotiator": "0.6.1"
+ }
+ },
+ "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"
+ }
+ },
+ "mime-db": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
+ "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
+ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.30.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.5.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
+ "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==",
+ "dev": true
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz",
+ "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=",
+ "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": "2.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz",
+ "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==",
+ "requires": {
+ "chardet": "0.4.2",
+ "iconv-lite": "0.4.19",
+ "tmp": "0.0.33"
+ },
+ "dependencies": {
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "requires": {
+ "os-tmpdir": "1.0.2"
+ }
+ }
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "extract-zip": {
+ "version": "1.6.6",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz",
+ "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=",
+ "dev": true,
+ "requires": {
+ "concat-stream": "1.6.0",
+ "debug": "2.6.9",
+ "mkdirp": "0.5.0",
+ "yauzl": "2.4.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz",
+ "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "extsprintf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz",
+ "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=",
+ "dev": true
+ },
+ "fancy-log": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz",
+ "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=",
+ "dev": true,
+ "requires": {
+ "ansi-gray": "0.1.1",
+ "color-support": "1.1.3",
+ "time-stamp": "1.1.0"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
+ "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8="
+ },
+ "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="
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
+ },
+ "fastparse": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
+ "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=",
+ "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.7.0"
+ }
+ },
+ "fd-slicer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
+ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
+ "dev": true,
+ "requires": {
+ "pend": "1.2.0"
+ }
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "requires": {
+ "escape-string-regexp": "1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+ "requires": {
+ "flat-cache": "1.3.0",
+ "object-assign": "4.1.0"
+ }
+ },
+ "file-loader": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.6.tgz",
+ "integrity": "sha512-873ztuL+/hfvXbLDJ262PGO6XjERnybJu2gW1/5j8HUfxSiFJI9Hj/DhZ50ZGRUxBvuNiazb/cM2rh9pqrxP6Q==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "1.1.0",
+ "schema-utils": "0.3.0"
+ },
+ "dependencies": {
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "dev": true,
+ "requires": {
+ "big.js": "3.1.3",
+ "emojis-list": "2.1.0",
+ "json5": "0.5.0"
+ }
+ }
+ }
+ },
+ "filename-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz",
+ "integrity": "sha1-mW4+gEebmLmJfxWopYs9CE6SZ3U=",
+ "dev": true
+ },
+ "fill-range": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
+ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+ "dev": true,
+ "requires": {
+ "is-number": "2.1.0",
+ "isobject": "2.1.0",
+ "randomatic": "1.1.6",
+ "repeat-element": "1.1.2",
+ "repeat-string": "1.6.1"
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
+ "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "1.0.1",
+ "escape-html": "1.0.3",
+ "on-finished": "2.3.0",
+ "parseurl": "1.3.2",
+ "statuses": "1.3.1",
+ "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": "1.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
+ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+ "dev": true,
+ "requires": {
+ "commondir": "1.0.1",
+ "make-dir": "1.0.0",
+ "pkg-dir": "2.0.0"
+ }
+ },
+ "find-index": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz",
+ "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=",
+ "dev": true
+ },
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "2.1.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "findup-sync": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz",
+ "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=",
+ "dev": true,
+ "requires": {
+ "detect-file": "1.0.0",
+ "is-glob": "3.1.0",
+ "micromatch": "3.1.5",
+ "resolve-dir": "1.0.1"
+ },
+ "dependencies": {
+ "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
+ },
+ "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
+ },
+ "braces": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz",
+ "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "1.1.0",
+ "array-unique": "0.3.2",
+ "define-property": "1.0.0",
+ "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.1.1",
+ "split-string": "3.1.0",
+ "to-regex": "3.0.1"
+ }
+ },
+ "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"
+ }
+ },
+ "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.6.9",
+ "define-property": "0.2.5",
+ "extend-shallow": "2.0.1",
+ "posix-character-classes": "0.1.1",
+ "regex-not": "1.0.0",
+ "snapdragon": "0.8.1",
+ "to-regex": "3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "0.1.6"
+ }
+ }
+ }
+ },
+ "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.1"
+ }
+ },
+ "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"
+ }
+ },
+ "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.1"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "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.1.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-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-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.1"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "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
+ },
+ "micromatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.5.tgz",
+ "integrity": "sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "4.0.0",
+ "array-unique": "0.3.2",
+ "braces": "2.3.0",
+ "define-property": "1.0.0",
+ "extend-shallow": "2.0.1",
+ "extglob": "2.0.4",
+ "fragment-cache": "0.2.1",
+ "kind-of": "6.0.2",
+ "nanomatch": "1.2.7",
+ "object.pick": "1.3.0",
+ "regex-not": "1.0.0",
+ "snapdragon": "0.8.1",
+ "to-regex": "3.0.1"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "fined": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz",
+ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=",
+ "dev": true,
+ "requires": {
+ "expand-tilde": "2.0.2",
+ "is-plain-object": "2.0.4",
+ "object.defaults": "1.1.0",
+ "object.pick": "1.3.0",
+ "parse-filepath": "1.0.2"
+ }
+ },
+ "first-chunk-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz",
+ "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=",
+ "dev": true
+ },
+ "flagged-respawn": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz",
+ "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=",
+ "dev": true
+ },
+ "flat-cache": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
+ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+ "requires": {
+ "circular-json": "0.3.3",
+ "del": "2.2.2",
+ "graceful-fs": "4.1.10",
+ "write": "0.2.1"
+ }
+ },
+ "flatpickr": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-2.6.3.tgz",
+ "integrity": "sha1-RXNXUy3rE189pktCW/RDVzeWFWQ="
+ },
+ "for-in": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.6.tgz",
+ "integrity": "sha1-yfluib+tGKVFr17D7TUqHZ5bTcg=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.4.tgz",
+ "integrity": "sha1-AUm0GjkIjHUV9R6+HBOG1F+TUHI=",
+ "dev": true,
+ "requires": {
+ "for-in": "0.1.6"
+ }
+ },
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
+ "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.1.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.1.tgz",
+ "integrity": "sha1-St8DQuGnmvoehMjDIKn/yCOSofM=",
+ "dev": true,
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.5",
+ "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
+ },
+ "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
+ },
+ "from": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/from/-/from-0.1.3.tgz",
+ "integrity": "sha1-72OsIGKsMqz3hi4NQLRLiW8i87w=",
+ "dev": true
+ },
+ "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": "5.0.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
+ "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
+ "requires": {
+ "graceful-fs": "4.1.10",
+ "jsonfile": "4.0.0",
+ "universalify": "0.1.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
+ "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "nan": "2.8.0",
+ "node-pre-gyp": "0.6.39"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "co": "4.6.0",
+ "json-stable-stringify": "1.0.1"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "1.0.0",
+ "readable-stream": "2.2.9"
+ }
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "bundled": true,
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "tweetnacl": "0.14.5"
+ }
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "boom": {
+ "version": "2.10.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.7",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "balanced-match": "0.4.2",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-shims": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "delayed-stream": "1.0.0"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "boom": "2.10.1"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "debug": {
+ "version": "2.6.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.4.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "extend": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "extsprintf": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.5",
+ "mime-types": "2.1.15"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "inherits": "2.0.3",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.1"
+ }
+ },
+ "fstream-ignore": {
+ "version": "1.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fstream": "1.0.11",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4"
+ }
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "1.1.1",
+ "console-control-strings": "1.1.0",
+ "has-unicode": "2.0.1",
+ "object-assign": "4.1.1",
+ "signal-exit": "3.0.2",
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wide-align": "1.1.2"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "bundled": true,
+ "dev": true
+ },
+ "har-schema": {
+ "version": "1.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "har-validator": {
+ "version": "4.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ajv": "4.11.8",
+ "har-schema": "1.0.5"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "boom": "2.10.1",
+ "cryptiles": "2.0.5",
+ "hoek": "2.16.3",
+ "sntp": "1.0.9"
+ }
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "bundled": true,
+ "dev": true
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "0.2.0",
+ "jsprim": "1.4.0",
+ "sshpk": "1.13.0"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "number-is-nan": "1.0.1"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jodid25519": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "jsonify": "0.0.0"
+ }
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jsprim": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.0.2",
+ "json-schema": "0.2.3",
+ "verror": "1.3.6"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "mime-db": {
+ "version": "1.27.0",
+ "bundled": true,
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.15",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "mime-db": "1.27.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "node-pre-gyp": {
+ "version": "0.6.39",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "1.0.2",
+ "hawk": "3.1.3",
+ "mkdirp": "0.5.1",
+ "nopt": "4.0.1",
+ "npmlog": "4.1.0",
+ "rc": "1.2.1",
+ "request": "2.81.0",
+ "rimraf": "2.6.1",
+ "semver": "5.3.0",
+ "tar": "2.2.1",
+ "tar-pack": "3.4.0"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1.1.0",
+ "osenv": "0.1.4"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "1.1.4",
+ "console-control-strings": "1.1.0",
+ "gauge": "2.7.4",
+ "set-blocking": "2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "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,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "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.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "performance-now": {
+ "version": "0.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "bundled": true,
+ "dev": true
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "qs": {
+ "version": "6.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "0.4.2",
+ "ini": "1.3.4",
+ "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.2.9",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "buffer-shims": "1.0.0",
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "1.0.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "request": {
+ "version": "2.81.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aws-sign2": "0.6.0",
+ "aws4": "1.6.0",
+ "caseless": "0.12.0",
+ "combined-stream": "1.0.5",
+ "extend": "3.0.1",
+ "forever-agent": "0.6.1",
+ "form-data": "2.1.4",
+ "har-validator": "4.2.1",
+ "hawk": "3.1.3",
+ "http-signature": "1.1.1",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.15",
+ "oauth-sign": "0.8.2",
+ "performance-now": "0.2.0",
+ "qs": "6.4.0",
+ "safe-buffer": "5.0.1",
+ "stringstream": "0.0.5",
+ "tough-cookie": "2.3.2",
+ "tunnel-agent": "0.6.0",
+ "uuid": "3.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "semver": {
+ "version": "5.3.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
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "sshpk": {
+ "version": "1.13.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "asn1": "0.2.3",
+ "assert-plus": "1.0.0",
+ "bcrypt-pbkdf": "1.0.1",
+ "dashdash": "1.14.1",
+ "ecc-jsbn": "0.1.1",
+ "getpass": "0.1.7",
+ "jodid25519": "1.0.2",
+ "jsbn": "0.1.1",
+ "tweetnacl": "0.14.5"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "code-point-at": "1.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.0.1"
+ }
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "2.2.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "block-stream": "0.0.9",
+ "fstream": "1.0.11",
+ "inherits": "2.0.3"
+ }
+ },
+ "tar-pack": {
+ "version": "3.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "2.6.8",
+ "fstream": "1.0.11",
+ "fstream-ignore": "1.0.5",
+ "once": "1.4.0",
+ "readable-stream": "2.2.9",
+ "rimraf": "2.6.1",
+ "tar": "2.2.1",
+ "uid-number": "0.0.6"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "punycode": "1.4.1"
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "uid-number": {
+ "version": "0.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "verror": {
+ "version": "1.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "extsprintf": "1.0.2"
+ }
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ }
+ }
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
+ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10",
+ "inherits": "2.0.3",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.5.4"
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "function-source": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/function-source/-/function-source-0.1.0.tgz",
+ "integrity": "sha1-2RBL8+RniLVUaMAr8bL6vPj8Ga8=",
+ "dev": true
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "dev": true,
+ "requires": {
+ "aproba": "1.2.0",
+ "console-control-strings": "1.1.0",
+ "has-unicode": "2.0.1",
+ "object-assign": "4.1.0",
+ "signal-exit": "3.0.1",
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wide-align": "1.1.2"
+ }
+ },
+ "gaze": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz",
+ "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=",
+ "dev": true,
+ "requires": {
+ "globule": "1.2.0"
+ }
+ },
+ "generate-function": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz",
+ "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=",
+ "dev": true
+ },
+ "generate-object-property": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
+ "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
+ "dev": true,
+ "requires": {
+ "is-property": "1.0.2"
+ }
+ },
+ "get-caller-file": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
+ "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
+ "dev": true
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "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
+ },
+ "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.6",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz",
+ "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ }
+ }
+ },
+ "glob": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.3",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "glob-base": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+ "dev": true,
+ "requires": {
+ "glob-parent": "2.0.0",
+ "is-glob": "2.0.1"
+ }
+ },
+ "glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+ "dev": true,
+ "requires": {
+ "is-glob": "2.0.1"
+ }
+ },
+ "glob-stream": {
+ "version": "3.1.18",
+ "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz",
+ "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=",
+ "dev": true,
+ "requires": {
+ "glob": "4.5.3",
+ "glob2base": "0.0.12",
+ "minimatch": "2.0.10",
+ "ordered-read-streams": "0.1.0",
+ "through2": "0.6.5",
+ "unique-stream": "1.0.0"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "4.5.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz",
+ "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=",
+ "dev": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "2.0.10",
+ "once": "1.4.0"
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
+ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.6"
+ }
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "through2": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "4.0.1"
+ }
+ }
+ }
+ },
+ "glob-watcher": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz",
+ "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=",
+ "dev": true,
+ "requires": {
+ "gaze": "0.5.2"
+ },
+ "dependencies": {
+ "gaze": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz",
+ "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=",
+ "dev": true,
+ "requires": {
+ "globule": "0.1.0"
+ }
+ },
+ "glob": {
+ "version": "3.1.21",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz",
+ "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "1.2.3",
+ "inherits": "1.0.2",
+ "minimatch": "0.2.14"
+ }
+ },
+ "globule": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz",
+ "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=",
+ "dev": true,
+ "requires": {
+ "glob": "3.1.21",
+ "lodash": "1.0.2",
+ "minimatch": "0.2.14"
+ }
+ },
+ "graceful-fs": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz",
+ "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=",
+ "dev": true
+ },
+ "inherits": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz",
+ "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz",
+ "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
+ "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
+ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "2.7.3",
+ "sigmund": "1.0.1"
+ }
+ }
+ }
+ },
+ "glob2base": {
+ "version": "0.0.12",
+ "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz",
+ "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=",
+ "dev": true,
+ "requires": {
+ "find-index": "0.1.1"
+ }
+ },
+ "global-modules": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
+ "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=",
+ "dev": true,
+ "requires": {
+ "global-prefix": "1.0.2",
+ "is-windows": "1.0.1",
+ "resolve-dir": "1.0.1"
+ }
+ },
+ "global-prefix": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
+ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
+ "dev": true,
+ "requires": {
+ "expand-tilde": "2.0.2",
+ "homedir-polyfill": "1.0.1",
+ "ini": "1.3.4",
+ "is-windows": "1.0.1",
+ "which": "1.3.0"
+ },
+ "dependencies": {
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
+ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
+ "dev": true,
+ "requires": {
+ "isexe": "2.0.0"
+ }
+ }
+ }
+ },
+ "globals": {
+ "version": "11.3.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz",
+ "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw=="
+ },
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "requires": {
+ "array-union": "1.0.2",
+ "arrify": "1.0.1",
+ "glob": "7.1.1",
+ "object-assign": "4.1.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "globule": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz",
+ "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.1",
+ "lodash": "4.17.4",
+ "minimatch": "3.0.3"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.4",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+ "dev": true
+ }
+ }
+ },
+ "glogg": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz",
+ "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=",
+ "dev": true,
+ "requires": {
+ "sparkles": "1.0.0"
+ }
+ },
+ "got": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
+ "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+ "dev": true,
+ "requires": {
+ "create-error-class": "3.0.2",
+ "duplexer3": "0.1.4",
+ "get-stream": "3.0.0",
+ "is-redirect": "1.0.0",
+ "is-retry-allowed": "1.1.0",
+ "is-stream": "1.1.0",
+ "lowercase-keys": "1.0.0",
+ "safe-buffer": "5.1.1",
+ "timed-out": "4.0.1",
+ "unzip-response": "2.0.1",
+ "url-parse-lax": "1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.10.tgz",
+ "integrity": "sha1-8tcgwiCS90Mih3XHXjYSYyUB8TE="
+ },
+ "graceful-readlink": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
+ "dev": true
+ },
+ "gulp": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz",
+ "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=",
+ "dev": true,
+ "requires": {
+ "archy": "1.0.0",
+ "chalk": "1.1.3",
+ "deprecated": "0.0.1",
+ "gulp-util": "3.0.7",
+ "interpret": "1.0.1",
+ "liftoff": "2.5.0",
+ "minimist": "1.2.0",
+ "orchestrator": "0.3.8",
+ "pretty-hrtime": "1.0.3",
+ "semver": "4.3.6",
+ "tildify": "1.2.0",
+ "v8flags": "2.1.1",
+ "vinyl-fs": "0.3.14"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
+ "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
+ "dev": true
+ }
+ }
+ },
+ "gulp-concat": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.0.tgz",
+ "integrity": "sha1-WFz7EVQR80h3MTEUBWa2qBxpy5E=",
+ "dev": true,
+ "requires": {
+ "concat-with-sourcemaps": "1.0.4",
+ "gulp-util": "3.0.7",
+ "through2": "0.6.5"
+ },
+ "dependencies": {
+ "concat-with-sourcemaps": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz",
+ "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=",
+ "dev": true,
+ "requires": {
+ "source-map": "0.5.6"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "dev": true
+ }
+ }
+ },
+ "gulp-util": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz",
+ "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=",
+ "dev": true,
+ "requires": {
+ "array-differ": "1.0.0",
+ "array-uniq": "1.0.3",
+ "beeper": "1.1.0",
+ "chalk": "1.1.3",
+ "dateformat": "1.0.12",
+ "fancy-log": "1.2.0",
+ "gulplog": "1.0.0",
+ "has-gulplog": "0.1.0",
+ "lodash._reescape": "3.0.0",
+ "lodash._reevaluate": "3.0.0",
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.template": "3.6.2",
+ "minimist": "1.2.0",
+ "multipipe": "0.1.2",
+ "object-assign": "3.0.0",
+ "replace-ext": "0.0.1",
+ "through2": "2.0.1",
+ "vinyl": "0.5.3"
+ },
+ "dependencies": {
+ "array-differ": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
+ "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
+ "dev": true
+ },
+ "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
+ },
+ "beeper": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.0.tgz",
+ "integrity": "sha1-nub8HOf1T+qs585zWIsFYDeGaiw=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "dateformat": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1",
+ "meow": "3.7.0"
+ },
+ "dependencies": {
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "2.1.0",
+ "decamelize": "1.2.0",
+ "loud-rejection": "1.6.0",
+ "map-obj": "1.0.1",
+ "minimist": "1.2.0",
+ "normalize-package-data": "2.3.5",
+ "object-assign": "4.1.0",
+ "read-pkg-up": "1.0.1",
+ "redent": "1.0.0",
+ "trim-newlines": "1.0.0"
+ },
+ "dependencies": {
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "2.1.1",
+ "map-obj": "1.0.1"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ }
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "0.4.1",
+ "signal-exit": "3.0.1"
+ },
+ "dependencies": {
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "1.0.2"
+ },
+ "dependencies": {
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ }
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.1.tgz",
+ "integrity": "sha1-WkyISZK2OnrNm623iUw+6c/MrYE=",
+ "dev": true
+ }
+ }
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "normalize-package-data": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz",
+ "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "2.1.5",
+ "is-builtin-module": "1.0.0",
+ "semver": "5.3.0",
+ "validate-npm-package-license": "3.0.1"
+ },
+ "dependencies": {
+ "hosted-git-info": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz",
+ "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=",
+ "dev": true
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "1.1.1"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ },
+ "semver": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
+ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "1.0.2",
+ "spdx-expression-parse": "1.0.4"
+ },
+ "dependencies": {
+ "spdx-correct": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
+ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
+ "dev": true,
+ "requires": {
+ "spdx-license-ids": "1.2.2"
+ },
+ "dependencies": {
+ "spdx-license-ids": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
+ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
+ "dev": true
+ }
+ }
+ },
+ "spdx-expression-parse": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
+ "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "object-assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
+ "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=",
+ "dev": true
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "1.1.2",
+ "read-pkg": "1.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "2.1.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "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.4"
+ },
+ "dependencies": {
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "1.1.0",
+ "normalize-package-data": "2.3.5",
+ "path-type": "1.1.0"
+ },
+ "dependencies": {
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.9",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "strip-bom": "2.0.0"
+ },
+ "dependencies": {
+ "graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha1-uqy6N9GdEfnRRtNXi8mZWMN4fik=",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "1.3.0"
+ },
+ "dependencies": {
+ "error-ex": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz",
+ "integrity": "sha1-5ntD8+gsluo6WE/+4Ln8MyXYAtk=",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "0.2.1"
+ },
+ "dependencies": {
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "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.4"
+ },
+ "dependencies": {
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ }
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ },
+ "dependencies": {
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.9",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha1-uqy6N9GdEfnRRtNXi8mZWMN4fik=",
+ "dev": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "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.4"
+ },
+ "dependencies": {
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "2.1.0",
+ "strip-indent": "1.0.1"
+ },
+ "dependencies": {
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "2.0.1"
+ },
+ "dependencies": {
+ "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.2"
+ },
+ "dependencies": {
+ "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.1"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1"
+ }
+ }
+ }
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "fancy-log": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.2.0.tgz",
+ "integrity": "sha1-1aUbU+mrIsoH1VjytnrlX9tfy9g=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "time-stamp": "1.0.1"
+ },
+ "dependencies": {
+ "time-stamp": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.0.1.tgz",
+ "integrity": "sha1-n0vSNVnJNllm8zAtu6KwfGuZsVE=",
+ "dev": true
+ }
+ }
+ },
+ "gulplog": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
+ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=",
+ "dev": true,
+ "requires": {
+ "glogg": "1.0.0"
+ },
+ "dependencies": {
+ "glogg": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz",
+ "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=",
+ "dev": true,
+ "requires": {
+ "sparkles": "1.0.0"
+ },
+ "dependencies": {
+ "sparkles": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz",
+ "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "has-gulplog": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz",
+ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=",
+ "dev": true,
+ "requires": {
+ "sparkles": "1.0.0"
+ },
+ "dependencies": {
+ "sparkles": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz",
+ "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=",
+ "dev": true
+ }
+ }
+ },
+ "lodash._reescape": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz",
+ "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=",
+ "dev": true
+ },
+ "lodash._reevaluate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz",
+ "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=",
+ "dev": true
+ },
+ "lodash._reinterpolate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
+ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
+ "dev": true
+ },
+ "lodash.template": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz",
+ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=",
+ "dev": true,
+ "requires": {
+ "lodash._basecopy": "3.0.1",
+ "lodash._basetostring": "3.0.1",
+ "lodash._basevalues": "3.0.0",
+ "lodash._isiterateecall": "3.0.9",
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.escape": "3.2.0",
+ "lodash.keys": "3.1.2",
+ "lodash.restparam": "3.6.1",
+ "lodash.templatesettings": "3.1.1"
+ },
+ "dependencies": {
+ "lodash._basecopy": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
+ "dev": true
+ },
+ "lodash._basetostring": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz",
+ "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=",
+ "dev": true
+ },
+ "lodash._basevalues": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz",
+ "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=",
+ "dev": true
+ },
+ "lodash._isiterateecall": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
+ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
+ "dev": true
+ },
+ "lodash.escape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz",
+ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=",
+ "dev": true,
+ "requires": {
+ "lodash._root": "3.0.1"
+ },
+ "dependencies": {
+ "lodash._root": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
+ "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=",
+ "dev": true
+ }
+ }
+ },
+ "lodash.keys": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+ "dev": true,
+ "requires": {
+ "lodash._getnative": "3.9.1",
+ "lodash.isarguments": "3.1.0",
+ "lodash.isarray": "3.0.4"
+ },
+ "dependencies": {
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+ "dev": true
+ },
+ "lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+ "dev": true
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+ "dev": true
+ }
+ }
+ },
+ "lodash.restparam": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
+ "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=",
+ "dev": true
+ },
+ "lodash.templatesettings": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz",
+ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=",
+ "dev": true,
+ "requires": {
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.escape": "3.2.0"
+ }
+ }
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "multipipe": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
+ "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=",
+ "dev": true,
+ "requires": {
+ "duplexer2": "0.0.2"
+ },
+ "dependencies": {
+ "duplexer2": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
+ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.1.14"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ },
+ "dependencies": {
+ "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
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "object-assign": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
+ "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
+ "dev": true
+ },
+ "replace-ext": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
+ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz",
+ "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.0.6",
+ "xtend": "4.0.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "0.10.31",
+ "util-deprecate": "1.0.2"
+ },
+ "dependencies": {
+ "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
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "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
+ }
+ }
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ }
+ }
+ },
+ "vinyl": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz",
+ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.2",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz",
+ "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
+ "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "through2": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "4.0.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ },
+ "dependencies": {
+ "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
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ }
+ }
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "gulp-extend": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/gulp-extend/-/gulp-extend-0.2.0.tgz",
+ "integrity": "sha1-BRHbpAj5JAP5xSDAEw3oGWYLDZA=",
+ "dev": true,
+ "requires": {
+ "event-stream": "3.3.4",
+ "gulp-util": "2.2.20",
+ "node.extend": "1.0.10",
+ "through": "2.3.8"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
+ "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz",
+ "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz",
+ "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "1.1.0",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "0.1.0",
+ "strip-ansi": "0.3.0",
+ "supports-color": "0.2.0"
+ }
+ },
+ "gulp-util": {
+ "version": "2.2.20",
+ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz",
+ "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=",
+ "dev": true,
+ "requires": {
+ "chalk": "0.5.1",
+ "dateformat": "1.0.12",
+ "lodash._reinterpolate": "2.4.1",
+ "lodash.template": "2.4.1",
+ "minimist": "0.2.0",
+ "multipipe": "0.1.2",
+ "through2": "0.5.1",
+ "vinyl": "0.2.3"
+ }
+ },
+ "has-ansi": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz",
+ "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "0.2.1"
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "lodash._reinterpolate": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz",
+ "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=",
+ "dev": true
+ },
+ "lodash.escape": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz",
+ "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=",
+ "dev": true,
+ "requires": {
+ "lodash._escapehtmlchar": "2.4.1",
+ "lodash._reunescapedhtml": "2.4.1",
+ "lodash.keys": "2.4.1"
+ }
+ },
+ "lodash.keys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz",
+ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=",
+ "dev": true,
+ "requires": {
+ "lodash._isnative": "2.4.1",
+ "lodash._shimkeys": "2.4.1",
+ "lodash.isobject": "2.4.1"
+ }
+ },
+ "lodash.template": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz",
+ "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=",
+ "dev": true,
+ "requires": {
+ "lodash._escapestringchar": "2.4.1",
+ "lodash._reinterpolate": "2.4.1",
+ "lodash.defaults": "2.4.1",
+ "lodash.escape": "2.4.1",
+ "lodash.keys": "2.4.1",
+ "lodash.templatesettings": "2.4.1",
+ "lodash.values": "2.4.1"
+ }
+ },
+ "lodash.templatesettings": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz",
+ "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=",
+ "dev": true,
+ "requires": {
+ "lodash._reinterpolate": "2.4.1",
+ "lodash.escape": "2.4.1"
+ }
+ },
+ "minimist": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz",
+ "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "strip-ansi": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",
+ "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "0.2.1"
+ }
+ },
+ "supports-color": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz",
+ "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=",
+ "dev": true
+ },
+ "through2": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz",
+ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "3.0.0"
+ }
+ },
+ "vinyl": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz",
+ "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=",
+ "dev": true,
+ "requires": {
+ "clone-stats": "0.0.1"
+ }
+ },
+ "xtend": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz",
+ "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=",
+ "dev": true
+ }
+ }
+ },
+ "gulp-install": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/gulp-install/-/gulp-install-1.1.0.tgz",
+ "integrity": "sha1-k4a0bLRmm0cle2rfTj6i6DySiho=",
+ "dev": true,
+ "requires": {
+ "dargs": "5.1.0",
+ "gulp-util": "3.0.7",
+ "lodash.groupby": "4.6.0",
+ "p-queue": "1.2.0",
+ "through2": "2.0.3",
+ "which": "1.3.0"
+ },
+ "dependencies": {
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.1.5",
+ "xtend": "4.0.1"
+ }
+ },
+ "which": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
+ "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=",
+ "dev": true,
+ "requires": {
+ "isexe": "2.0.0"
+ }
+ }
+ }
+ },
+ "gulp-jasmine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/gulp-jasmine/-/gulp-jasmine-3.0.0.tgz",
+ "integrity": "sha1-ATFIbwzVmv/toY4AxkOZKpGWljs=",
+ "dev": true,
+ "requires": {
+ "arrify": "1.0.1",
+ "jasmine": "2.9.0",
+ "jasmine-terminal-reporter": "1.0.3",
+ "plugin-error": "0.1.2",
+ "through2": "2.0.1"
+ },
+ "dependencies": {
+ "arr-diff": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz",
+ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "1.0.1",
+ "array-slice": "0.2.3"
+ }
+ },
+ "arr-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz",
+ "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
+ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
+ "dev": true,
+ "requires": {
+ "kind-of": "1.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
+ "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
+ "dev": true
+ },
+ "plugin-error": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz",
+ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=",
+ "dev": true,
+ "requires": {
+ "ansi-cyan": "0.1.1",
+ "ansi-red": "0.1.1",
+ "arr-diff": "1.1.0",
+ "arr-union": "2.1.0",
+ "extend-shallow": "1.1.4"
+ }
+ }
+ }
+ },
+ "gulp-print": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/gulp-print/-/gulp-print-2.0.1.tgz",
+ "integrity": "sha1-Gs7ljqyK8tPErTMp2+RldYOTxBQ=",
+ "dev": true,
+ "requires": {
+ "gulp-util": "3.0.7",
+ "map-stream": "0.0.7"
+ },
+ "dependencies": {
+ "map-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz",
+ "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=",
+ "dev": true
+ }
+ }
+ },
+ "gulp-util": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz",
+ "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=",
+ "dev": true,
+ "requires": {
+ "array-differ": "1.0.0",
+ "array-uniq": "1.0.3",
+ "beeper": "1.1.1",
+ "chalk": "1.1.3",
+ "dateformat": "1.0.12",
+ "fancy-log": "1.3.2",
+ "gulplog": "1.0.0",
+ "has-gulplog": "0.1.0",
+ "lodash._reescape": "3.0.0",
+ "lodash._reevaluate": "3.0.0",
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.template": "3.6.2",
+ "minimist": "1.2.0",
+ "multipipe": "0.1.2",
+ "object-assign": "3.0.0",
+ "replace-ext": "0.0.1",
+ "through2": "2.0.1",
+ "vinyl": "0.5.3"
+ },
+ "dependencies": {
+ "object-assign": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
+ "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
+ "dev": true
+ }
+ }
+ },
+ "gulp-wrap": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/gulp-wrap/-/gulp-wrap-0.13.0.tgz",
+ "integrity": "sha1-kPsLSieiZkM4Mv98YSLbXB7olMY=",
+ "dev": true,
+ "requires": {
+ "consolidate": "0.14.1",
+ "es6-promise": "3.3.1",
+ "fs-readfile-promise": "2.0.1",
+ "gulp-util": "3.0.7",
+ "js-yaml": "3.6.1",
+ "lodash": "4.16.4",
+ "node.extend": "1.1.6",
+ "through2": "2.0.1",
+ "tryit": "1.0.2",
+ "vinyl-bufferstream": "1.0.1"
+ },
+ "dependencies": {
+ "consolidate": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.1.tgz",
+ "integrity": "sha1-UG1SnvfiEWJNLkpfM334vhNu9yc=",
+ "dev": true,
+ "requires": {
+ "bluebird": "3.4.6"
+ },
+ "dependencies": {
+ "bluebird": {
+ "version": "3.4.6",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz",
+ "integrity": "sha1-AdqNgh2HgT0ViWfnQ9X+bGLPjA8=",
+ "dev": true
+ }
+ }
+ },
+ "es6-promise": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
+ "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
+ "dev": true
+ },
+ "fs-readfile-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fs-readfile-promise/-/fs-readfile-promise-2.0.1.tgz",
+ "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.9"
+ },
+ "dependencies": {
+ "graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha1-uqy6N9GdEfnRRtNXi8mZWMN4fik=",
+ "dev": true
+ }
+ }
+ },
+ "gulp-util": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz",
+ "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=",
+ "dev": true,
+ "requires": {
+ "array-differ": "1.0.0",
+ "array-uniq": "1.0.3",
+ "beeper": "1.1.0",
+ "chalk": "1.1.3",
+ "dateformat": "1.0.12",
+ "fancy-log": "1.2.0",
+ "gulplog": "1.0.0",
+ "has-gulplog": "0.1.0",
+ "lodash._reescape": "3.0.0",
+ "lodash._reevaluate": "3.0.0",
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.template": "3.6.2",
+ "minimist": "1.2.0",
+ "multipipe": "0.1.2",
+ "object-assign": "3.0.0",
+ "replace-ext": "0.0.1",
+ "through2": "2.0.1",
+ "vinyl": "0.5.3"
+ },
+ "dependencies": {
+ "array-differ": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
+ "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
+ "dev": true
+ },
+ "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
+ },
+ "beeper": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.0.tgz",
+ "integrity": "sha1-nub8HOf1T+qs585zWIsFYDeGaiw=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "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=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+ "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=",
+ "dev": true
+ }
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "dateformat": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1",
+ "meow": "3.7.0"
+ },
+ "dependencies": {
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "2.1.0",
+ "decamelize": "1.2.0",
+ "loud-rejection": "1.6.0",
+ "map-obj": "1.0.1",
+ "minimist": "1.2.0",
+ "normalize-package-data": "2.3.5",
+ "object-assign": "4.1.0",
+ "read-pkg-up": "1.0.1",
+ "redent": "1.0.0",
+ "trim-newlines": "1.0.0"
+ },
+ "dependencies": {
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "2.1.1",
+ "map-obj": "1.0.1"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ }
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "0.4.1",
+ "signal-exit": "3.0.1"
+ },
+ "dependencies": {
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "1.0.2"
+ },
+ "dependencies": {
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ }
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.1.tgz",
+ "integrity": "sha1-WkyISZK2OnrNm623iUw+6c/MrYE=",
+ "dev": true
+ }
+ }
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "normalize-package-data": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz",
+ "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "2.1.5",
+ "is-builtin-module": "1.0.0",
+ "semver": "5.3.0",
+ "validate-npm-package-license": "3.0.1"
+ },
+ "dependencies": {
+ "hosted-git-info": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz",
+ "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=",
+ "dev": true
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "1.1.1"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ },
+ "semver": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
+ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "1.0.2",
+ "spdx-expression-parse": "1.0.4"
+ },
+ "dependencies": {
+ "spdx-correct": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
+ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
+ "dev": true,
+ "requires": {
+ "spdx-license-ids": "1.2.2"
+ },
+ "dependencies": {
+ "spdx-license-ids": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
+ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
+ "dev": true
+ }
+ }
+ },
+ "spdx-expression-parse": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
+ "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "object-assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
+ "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=",
+ "dev": true
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "1.1.2",
+ "read-pkg": "1.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "2.1.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "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.4"
+ },
+ "dependencies": {
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "1.1.0",
+ "normalize-package-data": "2.3.5",
+ "path-type": "1.1.0"
+ },
+ "dependencies": {
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.9",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "strip-bom": "2.0.0"
+ },
+ "dependencies": {
+ "graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha1-uqy6N9GdEfnRRtNXi8mZWMN4fik=",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "1.3.0"
+ },
+ "dependencies": {
+ "error-ex": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz",
+ "integrity": "sha1-5ntD8+gsluo6WE/+4Ln8MyXYAtk=",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "0.2.1"
+ },
+ "dependencies": {
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "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.4"
+ },
+ "dependencies": {
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ }
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ },
+ "dependencies": {
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.9",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha1-uqy6N9GdEfnRRtNXi8mZWMN4fik=",
+ "dev": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "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.4"
+ },
+ "dependencies": {
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "2.1.0",
+ "strip-indent": "1.0.1"
+ },
+ "dependencies": {
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "2.0.1"
+ },
+ "dependencies": {
+ "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.2"
+ },
+ "dependencies": {
+ "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.1"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1"
+ }
+ }
+ }
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "fancy-log": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.2.0.tgz",
+ "integrity": "sha1-1aUbU+mrIsoH1VjytnrlX9tfy9g=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "time-stamp": "1.0.1"
+ },
+ "dependencies": {
+ "time-stamp": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.0.1.tgz",
+ "integrity": "sha1-n0vSNVnJNllm8zAtu6KwfGuZsVE=",
+ "dev": true
+ }
+ }
+ },
+ "gulplog": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
+ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=",
+ "dev": true,
+ "requires": {
+ "glogg": "1.0.0"
+ },
+ "dependencies": {
+ "glogg": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz",
+ "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=",
+ "dev": true,
+ "requires": {
+ "sparkles": "1.0.0"
+ },
+ "dependencies": {
+ "sparkles": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz",
+ "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "has-gulplog": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz",
+ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=",
+ "dev": true,
+ "requires": {
+ "sparkles": "1.0.0"
+ },
+ "dependencies": {
+ "sparkles": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz",
+ "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=",
+ "dev": true
+ }
+ }
+ },
+ "lodash._reescape": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz",
+ "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=",
+ "dev": true
+ },
+ "lodash._reevaluate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz",
+ "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=",
+ "dev": true
+ },
+ "lodash._reinterpolate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
+ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
+ "dev": true
+ },
+ "lodash.template": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz",
+ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=",
+ "dev": true,
+ "requires": {
+ "lodash._basecopy": "3.0.1",
+ "lodash._basetostring": "3.0.1",
+ "lodash._basevalues": "3.0.0",
+ "lodash._isiterateecall": "3.0.9",
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.escape": "3.2.0",
+ "lodash.keys": "3.1.2",
+ "lodash.restparam": "3.6.1",
+ "lodash.templatesettings": "3.1.1"
+ },
+ "dependencies": {
+ "lodash._basecopy": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
+ "dev": true
+ },
+ "lodash._basetostring": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz",
+ "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=",
+ "dev": true
+ },
+ "lodash._basevalues": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz",
+ "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=",
+ "dev": true
+ },
+ "lodash._isiterateecall": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
+ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
+ "dev": true
+ },
+ "lodash.escape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz",
+ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=",
+ "dev": true,
+ "requires": {
+ "lodash._root": "3.0.1"
+ },
+ "dependencies": {
+ "lodash._root": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
+ "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=",
+ "dev": true
+ }
+ }
+ },
+ "lodash.keys": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+ "dev": true,
+ "requires": {
+ "lodash._getnative": "3.9.1",
+ "lodash.isarguments": "3.1.0",
+ "lodash.isarray": "3.0.4"
+ },
+ "dependencies": {
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+ "dev": true
+ },
+ "lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+ "dev": true
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+ "dev": true
+ }
+ }
+ },
+ "lodash.restparam": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
+ "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=",
+ "dev": true
+ },
+ "lodash.templatesettings": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz",
+ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=",
+ "dev": true,
+ "requires": {
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.escape": "3.2.0"
+ }
+ }
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "multipipe": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
+ "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=",
+ "dev": true,
+ "requires": {
+ "duplexer2": "0.0.2"
+ },
+ "dependencies": {
+ "duplexer2": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
+ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.1.14"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ },
+ "dependencies": {
+ "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
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "object-assign": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
+ "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
+ "dev": true
+ },
+ "replace-ext": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
+ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
+ "dev": true
+ },
+ "vinyl": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz",
+ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.2",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz",
+ "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=",
+ "dev": true
+ },
+ "clone-stats": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
+ "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "js-yaml": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz",
+ "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=",
+ "dev": true,
+ "requires": {
+ "argparse": "1.0.9",
+ "esprima": "2.7.3"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "1.0.3"
+ },
+ "dependencies": {
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ }
+ }
+ },
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+ "dev": true
+ }
+ }
+ },
+ "lodash": {
+ "version": "4.16.4",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.4.tgz",
+ "integrity": "sha1-Ac4wa5utExnypVKGdPiCl663ASc=",
+ "dev": true
+ },
+ "node.extend": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz",
+ "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=",
+ "dev": true,
+ "requires": {
+ "is": "3.1.0"
+ },
+ "dependencies": {
+ "is": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is/-/is-3.1.0.tgz",
+ "integrity": "sha1-KUXSBdaRy/5IM+P4oRyK6UZz8qc=",
+ "dev": true
+ }
+ }
+ },
+ "through2": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz",
+ "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.0.6",
+ "xtend": "4.0.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "0.10.31",
+ "util-deprecate": "1.0.2"
+ },
+ "dependencies": {
+ "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
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "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
+ }
+ }
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ }
+ }
+ },
+ "tryit": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.2.tgz",
+ "integrity": "sha1-wZawBz5rHFldk8nIMIVbeswypFM=",
+ "dev": true
+ },
+ "vinyl-bufferstream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz",
+ "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=",
+ "dev": true,
+ "requires": {
+ "bufferstreams": "1.0.1"
+ },
+ "dependencies": {
+ "bufferstreams": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz",
+ "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.1.14"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ },
+ "dependencies": {
+ "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
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "gulp-yaml": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gulp-yaml/-/gulp-yaml-1.0.1.tgz",
+ "integrity": "sha1-AIHJMhOCe66xJzD5P97on9a+Ey0=",
+ "dev": true,
+ "requires": {
+ "bufferstreams": "1.1.0",
+ "gulp-util": "3.0.7",
+ "js-yaml": "3.10.0",
+ "through2": "2.0.1",
+ "xtend": "4.0.1"
+ }
+ },
+ "gulplog": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
+ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=",
+ "dev": true,
+ "requires": {
+ "glogg": "1.0.0"
+ }
+ },
+ "handle-thing": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
+ "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
+ "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "commander": "2.9.0",
+ "is-my-json-valid": "2.15.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "has": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz",
+ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
+ "dev": true,
+ "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-binary": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz",
+ "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=",
+ "dev": true,
+ "requires": {
+ "isarray": "0.0.1"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "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": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "has-gulplog": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz",
+ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=",
+ "dev": true,
+ "requires": {
+ "sparkles": "1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+ "dev": true
+ },
+ "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.1"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "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-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "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.6"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
+ "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "hash.js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
+ "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
+ "dev": true,
+ "requires": {
+ "boom": "2.10.1",
+ "cryptiles": "2.0.5",
+ "hoek": "2.16.3",
+ "sntp": "1.0.9"
+ }
+ },
+ "he": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.1.0.tgz",
+ "integrity": "sha1-KTGdSb7sE6mx88T5sqbd5IWbsqc=",
+ "dev": true
+ },
+ "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.1.3",
+ "minimalistic-assert": "1.0.0",
+ "minimalistic-crypto-utils": "1.0.1"
+ }
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+ "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
+ "dev": true
+ },
+ "home-or-tmp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
+ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
+ "dev": true,
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "home-path": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/home-path/-/home-path-1.0.5.tgz",
+ "integrity": "sha1-eIspgVsS1Tus9XVkhHbm+QQdEz8=",
+ "dev": true
+ },
+ "homedir-polyfill": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz",
+ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=",
+ "dev": true,
+ "requires": {
+ "parse-passwd": "1.0.0"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz",
+ "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=",
+ "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.3",
+ "obuf": "1.1.1",
+ "readable-stream": "2.1.5",
+ "wbuf": "1.7.2"
+ }
+ },
+ "html-entities": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
+ "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+ "dev": true
+ },
+ "html-loader": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.4.4.tgz",
+ "integrity": "sha1-8rW5rNXgNf86tf02nBPJenuwFNo=",
+ "dev": true,
+ "requires": {
+ "es6-templates": "0.2.3",
+ "fastparse": "1.1.1",
+ "html-minifier": "3.2.3",
+ "loader-utils": "0.2.16",
+ "object-assign": "4.1.0"
+ }
+ },
+ "html-minifier": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.2.3.tgz",
+ "integrity": "sha1-0v9TbiTZVybDMkk9j3fYTb7YU3I=",
+ "dev": true,
+ "requires": {
+ "camel-case": "3.0.0",
+ "clean-css": "3.4.21",
+ "commander": "2.9.0",
+ "he": "1.1.0",
+ "ncname": "1.0.0",
+ "param-case": "2.1.0",
+ "relateurl": "0.2.7",
+ "uglify-js": "2.7.4"
+ }
+ },
+ "htmlparser2": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
+ "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+ "requires": {
+ "domelementtype": "1.3.0",
+ "domhandler": "2.4.1",
+ "domutils": "1.7.0",
+ "entities": "1.1.1",
+ "inherits": "2.0.3",
+ "readable-stream": "2.1.5"
+ }
+ },
+ "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.6.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
+ "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
+ "dev": true,
+ "requires": {
+ "depd": "1.1.1",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.0.3",
+ "statuses": "1.3.1"
+ },
+ "dependencies": {
+ "depd": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+ "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
+ "dev": true
+ },
+ "setprototypeof": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
+ "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.16.2",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz",
+ "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "1.2.0",
+ "requires-port": "1.0.0"
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "0.17.4",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz",
+ "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=",
+ "dev": true,
+ "requires": {
+ "http-proxy": "1.16.2",
+ "is-glob": "3.1.0",
+ "lodash": "4.17.5",
+ "micromatch": "2.3.11"
+ },
+ "dependencies": {
+ "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-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.1"
+ }
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ }
+ }
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "0.2.0",
+ "jsprim": "1.3.1",
+ "sshpk": "1.10.1"
+ }
+ },
+ "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
+ },
+ "iconv-lite": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+ "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs="
+ },
+ "ieee754": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
+ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=",
+ "dev": true
+ },
+ "ignore": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz",
+ "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA=="
+ },
+ "ignore-by-default": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
+ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=",
+ "dev": true
+ },
+ "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": "1.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz",
+ "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "2.0.0",
+ "resolve-cwd": "2.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "dev": true,
+ "requires": {
+ "find-up": "2.1.0"
+ }
+ }
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+ },
+ "in-publish": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
+ "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "2.0.1"
+ }
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ini": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
+ "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
+ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
+ "requires": {
+ "ansi-escapes": "3.0.0",
+ "chalk": "2.3.1",
+ "cli-cursor": "2.1.0",
+ "cli-width": "2.2.0",
+ "external-editor": "2.1.0",
+ "figures": "2.0.0",
+ "lodash": "4.16.6",
+ "mute-stream": "0.0.7",
+ "run-async": "2.3.0",
+ "rx-lite": "4.0.8",
+ "rx-lite-aggregates": "4.0.8",
+ "string-width": "2.1.1",
+ "strip-ansi": "4.0.0",
+ "through": "2.3.8"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz",
+ "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "5.2.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+ },
+ "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="
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "3.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz",
+ "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==",
+ "requires": {
+ "has-flag": "3.0.0"
+ }
+ }
+ }
+ },
+ "internal-ip": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz",
+ "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=",
+ "dev": true,
+ "requires": {
+ "meow": "3.7.0"
+ }
+ },
+ "interpret": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.1.tgz",
+ "integrity": "sha1-1Xn7f2k7hYAElHrzn6DbSfeVYCw=",
+ "dev": true
+ },
+ "invariant": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz",
+ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=",
+ "dev": true,
+ "requires": {
+ "loose-envify": "1.3.1"
+ }
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
+ "dev": true
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz",
+ "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=",
+ "dev": true
+ },
+ "is": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/is/-/is-0.3.0.tgz",
+ "integrity": "sha1-qPcd/IpuKDcWJ/JskpCYxvTV1dc=",
+ "dev": true
+ },
+ "is-absolute": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
+ "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=",
+ "dev": true,
+ "requires": {
+ "is-relative": "1.0.0",
+ "is-windows": "1.0.1"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "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
+ }
+ }
+ },
+ "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": "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.8.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz",
+ "integrity": "sha1-z8hszV3FpS+oBIkRHGkgxFfi2Ys=",
+ "dev": true
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "1.1.1"
+ }
+ },
+ "is-callable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
+ "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=",
+ "dev": true
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "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
+ }
+ }
+ },
+ "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=",
+ "dev": true
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "1.0.0",
+ "is-data-descriptor": "1.0.0",
+ "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
+ }
+ }
+ },
+ "is-dotfile": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz",
+ "integrity": "sha1-LBMjg/ORmfjtwmjKAbmwB9IFzE0=",
+ "dev": true
+ },
+ "is-equal-shallow": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+ "dev": true,
+ "requires": {
+ "is-primitive": "2.0.0"
+ }
+ },
+ "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": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "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.1"
+ }
+ },
+ "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.1"
+ }
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "is-my-json-valid": {
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz",
+ "integrity": "sha1-k27do8o8IR/ZjzstPgjaQ/eykVs=",
+ "dev": true,
+ "requires": {
+ "generate-function": "2.0.0",
+ "generate-object-property": "1.2.0",
+ "jsonpointer": "4.0.0",
+ "xtend": "4.0.1"
+ }
+ },
+ "is-npm": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
+ "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=",
+ "dev": true
+ },
+ "is-number": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.0.4"
+ }
+ },
+ "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-odd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz",
+ "integrity": "sha1-O4qTLrAos3dcObsJ6RdnrM22kIg=",
+ "dev": true,
+ "requires": {
+ "is-number": "3.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.4"
+ }
+ }
+ }
+ },
+ "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="
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
+ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=",
+ "requires": {
+ "is-path-inside": "1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz",
+ "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=",
+ "requires": {
+ "path-is-inside": "1.0.2"
+ }
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=",
+ "dev": true,
+ "requires": {
+ "isobject": "3.0.1"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "is-posix-bracket": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+ "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+ "dev": true
+ },
+ "is-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+ "dev": true
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
+ },
+ "is-property": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+ "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
+ "dev": true
+ },
+ "is-redirect": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
+ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "1.0.1"
+ }
+ },
+ "is-relative": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
+ "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=",
+ "dev": true,
+ "requires": {
+ "is-unc-path": "1.0.0"
+ }
+ },
+ "is-resolvable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
+ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg=="
+ },
+ "is-retry-allowed": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz",
+ "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=",
+ "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.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
+ "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=",
+ "dev": true
+ },
+ "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-unc-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
+ "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=",
+ "dev": true,
+ "requires": {
+ "unc-path-regex": "0.1.2"
+ }
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "is-windows": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz",
+ "integrity": "sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk=",
+ "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
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "isbinaryfile": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz",
+ "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz",
+ "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA="
+ },
+ "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"
+ }
+ },
+ "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
+ },
+ "jasmine": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.9.0.tgz",
+ "integrity": "sha1-dlcfklyHg0CefGFTVy5aY0HPk+s=",
+ "dev": true,
+ "requires": {
+ "exit": "0.1.2",
+ "glob": "7.1.1",
+ "jasmine-core": "2.9.1"
+ }
+ },
+ "jasmine-core": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.9.1.tgz",
+ "integrity": "sha1-trvB2OZSUNVvWIhGFwXr7uuI8i8=",
+ "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": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=",
+ "dev": true,
+ "requires": {
+ "colors": "1.1.2"
+ }
+ },
+ "jasmine-terminal-reporter": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/jasmine-terminal-reporter/-/jasmine-terminal-reporter-1.0.3.tgz",
+ "integrity": "sha1-iW8eyP30v2rs3UHFA+2nNH9hUms=",
+ "dev": true,
+ "requires": {
+ "indent-string": "2.1.0",
+ "pluralize": "1.2.1"
+ }
+ },
+ "jodid25519": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz",
+ "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.0"
+ }
+ },
+ "js-base64": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz",
+ "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz",
+ "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
+ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
+ "requires": {
+ "argparse": "1.0.9",
+ "esprima": "4.0.0"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw=="
+ }
+ }
+ },
+ "jsbn": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz",
+ "integrity": "sha1-ZQmH2g3XT06/WhE3eiqi0nPpff0=",
+ "dev": true,
+ "optional": true
+ },
+ "jsesc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+ "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
+ "dev": true
+ },
+ "json-loader": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
+ "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==",
+ "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.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
+ },
+ "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
+ },
+ "json3": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
+ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
+ "dev": true
+ },
+ "json5": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.0.tgz",
+ "integrity": "sha1-myBxWwJsvjd4/Xae3M2CLYMypbI=",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "requires": {
+ "graceful-fs": "4.1.10"
+ }
+ },
+ "jsonpointer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz",
+ "integrity": "sha1-ZmHhYdL8RF8Z+YQwIxNDci4fy9U=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz",
+ "integrity": "sha1-KnJW9wQSop7jZwqspiWZTE3P8lI=",
+ "dev": true,
+ "requires": {
+ "extsprintf": "1.0.2",
+ "json-schema": "0.2.3",
+ "verror": "1.3.6"
+ }
+ },
+ "karma": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz",
+ "integrity": "sha1-hcwI6eCiLXzpzKN8ShvoJPaisa4=",
+ "dev": true,
+ "requires": {
+ "bluebird": "3.5.1",
+ "body-parser": "1.18.2",
+ "chokidar": "1.6.1",
+ "colors": "1.1.2",
+ "combine-lists": "1.0.1",
+ "connect": "3.6.5",
+ "core-js": "2.4.1",
+ "di": "0.0.1",
+ "dom-serialize": "2.2.1",
+ "expand-braces": "0.1.2",
+ "glob": "7.1.1",
+ "graceful-fs": "4.1.10",
+ "http-proxy": "1.16.2",
+ "isbinaryfile": "3.0.2",
+ "lodash": "3.10.1",
+ "log4js": "0.6.38",
+ "mime": "1.3.4",
+ "minimatch": "3.0.3",
+ "optimist": "0.6.1",
+ "qjobs": "1.1.5",
+ "range-parser": "1.2.0",
+ "rimraf": "2.6.2",
+ "safe-buffer": "5.1.1",
+ "socket.io": "1.7.3",
+ "source-map": "0.5.6",
+ "tmp": "0.0.31",
+ "useragent": "2.3.0"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.1"
+ }
+ }
+ }
+ },
+ "karma-chrome-launcher": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
+ "integrity": "sha1-zxudBxNswY/iOTJ9JGVMPbw2is8=",
+ "dev": true,
+ "requires": {
+ "fs-access": "1.0.1",
+ "which": "1.2.11"
+ }
+ },
+ "karma-firefox-launcher": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz",
+ "integrity": "sha1-LEcDBFLwRTHrfRPU/HZpYwu5Mzk=",
+ "dev": true
+ },
+ "karma-jasmine": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.1.tgz",
+ "integrity": "sha1-b+hA51oRYAydkehLM8RY4cRqNSk=",
+ "dev": true
+ },
+ "karma-sourcemap-loader": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz",
+ "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10"
+ }
+ },
+ "karma-webpack": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.9.tgz",
+ "integrity": "sha1-YciAkffdkQY1E0wDKyZqRlr/tX8=",
+ "dev": true,
+ "requires": {
+ "async": "0.9.2",
+ "loader-utils": "0.2.16",
+ "lodash": "3.10.1",
+ "source-map": "0.5.6",
+ "webpack-dev-middleware": "1.12.2"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
+ "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
+ "dev": true
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true
+ },
+ "time-stamp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz",
+ "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=",
+ "dev": true
+ },
+ "webpack-dev-middleware": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz",
+ "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==",
+ "dev": true,
+ "requires": {
+ "memory-fs": "0.4.1",
+ "mime": "1.6.0",
+ "path-is-absolute": "1.0.1",
+ "range-parser": "1.2.0",
+ "time-stamp": "2.0.0"
+ }
+ }
+ }
+ },
+ "keypress": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz",
+ "integrity": "sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=",
+ "dev": true
+ },
+ "killable": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz",
+ "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz",
+ "integrity": "sha1-e47PGKThf4Jp1ztQHJ8jLJaIenQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.4"
+ }
+ },
+ "klaw": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10"
+ }
+ },
+ "latest-version": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
+ "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
+ "dev": true,
+ "requires": {
+ "package-json": "4.0.1"
+ }
+ },
+ "lazy-cache": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
+ "dev": true
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+ "dev": true,
+ "requires": {
+ "invert-kv": "1.0.0"
+ }
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "requires": {
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2"
+ }
+ },
+ "liftoff": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz",
+ "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=",
+ "dev": true,
+ "requires": {
+ "extend": "3.0.0",
+ "findup-sync": "2.0.0",
+ "fined": "1.1.0",
+ "flagged-respawn": "1.0.0",
+ "is-plain-object": "2.0.4",
+ "object.map": "1.0.1",
+ "rechoir": "0.6.2",
+ "resolve": "1.4.0"
+ }
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "strip-bom": "2.0.0"
+ }
+ },
+ "loader-runner": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz",
+ "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.16.tgz",
+ "integrity": "sha1-8IYyBm7YKCg13/iN+1JwR2Wt7m0=",
+ "dev": true,
+ "requires": {
+ "big.js": "3.1.3",
+ "emojis-list": "2.1.0",
+ "json5": "0.5.0",
+ "object-assign": "4.1.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "2.0.0",
+ "path-exists": "3.0.0"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ },
+ "lodash": {
+ "version": "4.16.6",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.6.tgz",
+ "integrity": "sha1-0iyaxmAojzhD4Wun0rXQbMon13c="
+ },
+ "lodash._arraycopy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz",
+ "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=",
+ "dev": true
+ },
+ "lodash._arrayeach": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz",
+ "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=",
+ "dev": true
+ },
+ "lodash._baseassign": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
+ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
+ "dev": true,
+ "requires": {
+ "lodash._basecopy": "3.0.1",
+ "lodash.keys": "3.1.2"
+ }
+ },
+ "lodash._basecopy": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
+ "dev": true
+ },
+ "lodash._basefor": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz",
+ "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=",
+ "dev": true
+ },
+ "lodash._basetostring": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz",
+ "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=",
+ "dev": true
+ },
+ "lodash._basevalues": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz",
+ "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=",
+ "dev": true
+ },
+ "lodash._bindcallback": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz",
+ "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=",
+ "dev": true
+ },
+ "lodash._createassigner": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz",
+ "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=",
+ "dev": true,
+ "requires": {
+ "lodash._bindcallback": "3.0.1",
+ "lodash._isiterateecall": "3.0.9",
+ "lodash.restparam": "3.6.1"
+ }
+ },
+ "lodash._escapehtmlchar": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz",
+ "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=",
+ "dev": true,
+ "requires": {
+ "lodash._htmlescapes": "2.4.1"
+ }
+ },
+ "lodash._escapestringchar": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz",
+ "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=",
+ "dev": true
+ },
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+ "dev": true
+ },
+ "lodash._htmlescapes": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz",
+ "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=",
+ "dev": true
+ },
+ "lodash._isiterateecall": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
+ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
+ "dev": true
+ },
+ "lodash._isnative": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz",
+ "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=",
+ "dev": true
+ },
+ "lodash._objecttypes": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz",
+ "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=",
+ "dev": true
+ },
+ "lodash._reescape": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz",
+ "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=",
+ "dev": true
+ },
+ "lodash._reevaluate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz",
+ "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=",
+ "dev": true
+ },
+ "lodash._reinterpolate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
+ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
+ "dev": true
+ },
+ "lodash._reunescapedhtml": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz",
+ "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=",
+ "dev": true,
+ "requires": {
+ "lodash._htmlescapes": "2.4.1",
+ "lodash.keys": "2.4.1"
+ },
+ "dependencies": {
+ "lodash.keys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz",
+ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=",
+ "dev": true,
+ "requires": {
+ "lodash._isnative": "2.4.1",
+ "lodash._shimkeys": "2.4.1",
+ "lodash.isobject": "2.4.1"
+ }
+ }
+ }
+ },
+ "lodash._root": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
+ "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=",
+ "dev": true
+ },
+ "lodash._shimkeys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz",
+ "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=",
+ "dev": true,
+ "requires": {
+ "lodash._objecttypes": "2.4.1"
+ }
+ },
+ "lodash.assign": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
+ "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
+ "dev": true
+ },
+ "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
+ },
+ "lodash.defaults": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz",
+ "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=",
+ "dev": true,
+ "requires": {
+ "lodash._objecttypes": "2.4.1",
+ "lodash.keys": "2.4.1"
+ },
+ "dependencies": {
+ "lodash.keys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz",
+ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=",
+ "dev": true,
+ "requires": {
+ "lodash._isnative": "2.4.1",
+ "lodash._shimkeys": "2.4.1",
+ "lodash.isobject": "2.4.1"
+ }
+ }
+ }
+ },
+ "lodash.escape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz",
+ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=",
+ "dev": true,
+ "requires": {
+ "lodash._root": "3.0.1"
+ }
+ },
+ "lodash.groupby": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz",
+ "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=",
+ "dev": true
+ },
+ "lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+ "dev": true
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+ "dev": true
+ },
+ "lodash.isobject": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz",
+ "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=",
+ "dev": true,
+ "requires": {
+ "lodash._objecttypes": "2.4.1"
+ }
+ },
+ "lodash.isplainobject": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz",
+ "integrity": "sha1-moI4rhayAEMpYM1zRlEtASP79MU=",
+ "dev": true,
+ "requires": {
+ "lodash._basefor": "3.0.3",
+ "lodash.isarguments": "3.1.0",
+ "lodash.keysin": "3.0.8"
+ }
+ },
+ "lodash.istypedarray": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz",
+ "integrity": "sha1-yaR3SYYHUB2OhJTSg7h8OSgc72I=",
+ "dev": true
+ },
+ "lodash.keys": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+ "dev": true,
+ "requires": {
+ "lodash._getnative": "3.9.1",
+ "lodash.isarguments": "3.1.0",
+ "lodash.isarray": "3.0.4"
+ }
+ },
+ "lodash.keysin": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-3.0.8.tgz",
+ "integrity": "sha1-IsRJPrvtsUJ5YqVLRFssinZ/tH8=",
+ "dev": true,
+ "requires": {
+ "lodash.isarguments": "3.1.0",
+ "lodash.isarray": "3.0.4"
+ }
+ },
+ "lodash.merge": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-3.3.2.tgz",
+ "integrity": "sha1-DZDZPtY3sYeEN7s+IWASYNev6ZQ=",
+ "dev": true,
+ "requires": {
+ "lodash._arraycopy": "3.0.0",
+ "lodash._arrayeach": "3.0.0",
+ "lodash._createassigner": "3.1.1",
+ "lodash._getnative": "3.9.1",
+ "lodash.isarguments": "3.1.0",
+ "lodash.isarray": "3.0.4",
+ "lodash.isplainobject": "3.2.0",
+ "lodash.istypedarray": "3.0.6",
+ "lodash.keys": "3.1.2",
+ "lodash.keysin": "3.0.8",
+ "lodash.toplainobject": "3.0.0"
+ }
+ },
+ "lodash.mergewith": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz",
+ "integrity": "sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU=",
+ "dev": true
+ },
+ "lodash.restparam": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
+ "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=",
+ "dev": true
+ },
+ "lodash.tail": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
+ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=",
+ "dev": true
+ },
+ "lodash.template": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz",
+ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=",
+ "dev": true,
+ "requires": {
+ "lodash._basecopy": "3.0.1",
+ "lodash._basetostring": "3.0.1",
+ "lodash._basevalues": "3.0.0",
+ "lodash._isiterateecall": "3.0.9",
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.escape": "3.2.0",
+ "lodash.keys": "3.1.2",
+ "lodash.restparam": "3.6.1",
+ "lodash.templatesettings": "3.1.1"
+ }
+ },
+ "lodash.templatesettings": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz",
+ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=",
+ "dev": true,
+ "requires": {
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.escape": "3.2.0"
+ }
+ },
+ "lodash.toplainobject": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lodash.toplainobject/-/lodash.toplainobject-3.0.0.tgz",
+ "integrity": "sha1-KHkK2ULSk9eKpmOgfs9/UsoEGY0=",
+ "dev": true,
+ "requires": {
+ "lodash._basecopy": "3.0.1",
+ "lodash.keysin": "3.0.8"
+ }
+ },
+ "lodash.values": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz",
+ "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=",
+ "dev": true,
+ "requires": {
+ "lodash.keys": "2.4.1"
+ },
+ "dependencies": {
+ "lodash.keys": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz",
+ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=",
+ "dev": true,
+ "requires": {
+ "lodash._isnative": "2.4.1",
+ "lodash._shimkeys": "2.4.1",
+ "lodash.isobject": "2.4.1"
+ }
+ }
+ }
+ },
+ "log4js": {
+ "version": "0.6.38",
+ "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz",
+ "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "semver": "4.3.6"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "semver": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz",
+ "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=",
+ "dev": true
+ }
+ }
+ },
+ "loglevel": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz",
+ "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=",
+ "dev": true
+ },
+ "long": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
+ "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==",
+ "dev": true
+ },
+ "longest": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+ "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
+ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=",
+ "dev": true,
+ "requires": {
+ "js-tokens": "3.0.1"
+ }
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "0.4.1",
+ "signal-exit": "3.0.1"
+ }
+ },
+ "lower-case": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz",
+ "integrity": "sha1-ySOT2XZ5Pu5bpO21g8+OrjW9m/s=",
+ "dev": true
+ },
+ "lowercase-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz",
+ "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz",
+ "integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=",
+ "requires": {
+ "pseudomap": "1.0.2",
+ "yallist": "2.0.0"
+ }
+ },
+ "make-dir": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz",
+ "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=",
+ "dev": true,
+ "requires": {
+ "pify": "2.3.0"
+ }
+ },
+ "make-iterator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz",
+ "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.6"
+ }
+ }
+ }
+ },
+ "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-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "map-stream": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
+ "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
+ "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.1"
+ }
+ },
+ "material-design-lite": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/material-design-lite/-/material-design-lite-1.3.0.tgz",
+ "integrity": "sha1-0ATOP+6Zoe63Sni4oyUTSl8RcdM="
+ },
+ "md5.js": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
+ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+ "dev": true,
+ "requires": {
+ "hash-base": "3.0.4",
+ "inherits": "2.0.3"
+ },
+ "dependencies": {
+ "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.3",
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "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": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "1.2.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.4",
+ "readable-stream": "2.1.5"
+ }
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "2.1.0",
+ "decamelize": "1.2.0",
+ "loud-rejection": "1.6.0",
+ "map-obj": "1.0.1",
+ "minimist": "1.2.0",
+ "normalize-package-data": "2.3.5",
+ "object-assign": "4.1.0",
+ "read-pkg-up": "1.0.1",
+ "redent": "1.0.0",
+ "trim-newlines": "1.0.0"
+ }
+ },
+ "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": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
+ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.1.5"
+ }
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "dev": true
+ },
+ "mg-crud": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz",
+ "integrity": "sha1-p6AWGzWSPK7/8ZpIBpS2V1vDggw=",
+ "requires": {
+ "angular": "1.6.8"
+ }
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": true,
+ "requires": {
+ "arr-diff": "2.0.0",
+ "array-unique": "0.2.1",
+ "braces": "1.8.5",
+ "expand-brackets": "0.1.5",
+ "extglob": "0.3.2",
+ "filename-regex": "2.0.0",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1",
+ "kind-of": "3.0.4",
+ "normalize-path": "2.0.1",
+ "object.omit": "2.0.1",
+ "parse-glob": "3.0.4",
+ "regex-cache": "0.4.3"
+ }
+ },
+ "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.11.8",
+ "brorand": "1.1.0"
+ }
+ },
+ "mime": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz",
+ "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.24.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz",
+ "integrity": "sha1-4tE/k58AFsbk6a0lqGUvEmxGfww=",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.12",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz",
+ "integrity": "sha1-FSuiVndwIN1GY/VMLnvCY4HnFyk=",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.24.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=="
+ },
+ "minimalistic-assert": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
+ "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=",
+ "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.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
+ "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=",
+ "requires": {
+ "brace-expansion": "1.1.6"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "minstache": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minstache/-/minstache-1.2.0.tgz",
+ "integrity": "sha1-/xzEA6woRPaNvxjGYhKb5+sO/EE=",
+ "dev": true,
+ "requires": {
+ "commander": "1.0.4"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-1.0.4.tgz",
+ "integrity": "sha1-Xt6xruI8T7VBprcNaSq+8ZZpotM=",
+ "dev": true,
+ "requires": {
+ "keypress": "0.1.0"
+ }
+ }
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.0.tgz",
+ "integrity": "sha1-R6hzK6l3mUV8jB7KKPlRMtfoFQo=",
+ "dev": true,
+ "requires": {
+ "for-in": "1.0.2",
+ "is-extendable": "1.0.1"
+ },
+ "dependencies": {
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "2.0.4"
+ }
+ }
+ }
+ },
+ "mixin-object": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
+ "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=",
+ "dev": true,
+ "requires": {
+ "for-in": "0.1.6",
+ "is-extendable": "0.1.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "requires": {
+ "minimist": "0.0.8"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ }
+ }
+ },
+ "ms": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+ "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
+ "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
+ },
+ "multipipe": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
+ "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=",
+ "dev": true,
+ "requires": {
+ "duplexer2": "0.0.2"
+ }
+ },
+ "mustache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz",
+ "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA=",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
+ },
+ "mysql2": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.5.2.tgz",
+ "integrity": "sha512-976p3FxXdNMRRiF6Qe/FCOwaUYw3KXVJiIYu5iE5shM7ggIASgF6G/9gd9rhpBqP8V6MVa3KQJ6Ao1xBeGBljw==",
+ "dev": true,
+ "requires": {
+ "cardinal": "1.0.0",
+ "denque": "1.2.3",
+ "generate-function": "2.0.0",
+ "iconv-lite": "0.4.19",
+ "long": "4.0.0",
+ "lru-cache": "4.1.1",
+ "named-placeholders": "1.1.1",
+ "object-assign": "4.1.1",
+ "readable-stream": "2.3.2",
+ "safe-buffer": "5.1.1",
+ "seq-queue": "0.0.5",
+ "sqlstring": "2.3.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
+ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "1.0.2",
+ "yallist": "2.1.2"
+ }
+ },
+ "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
+ },
+ "readable-stream": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.2.tgz",
+ "integrity": "sha1-WgTfBeT1f+Pw3Gj90R3FyXx+b00=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+ },
+ "named-placeholders": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.1.tgz",
+ "integrity": "sha1-O3oNJiA910s6nfTJz7gnsvuQfmQ=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "2.5.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz",
+ "integrity": "sha1-2COIrpyWC+y+oMc7uet5tsbOmus=",
+ "dev": true
+ }
+ }
+ },
+ "nan": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
+ "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=",
+ "dev": true
+ },
+ "nanomatch": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.7.tgz",
+ "integrity": "sha1-U81KoQn/aLf4aVkf3J0Q2u7qPnk=",
+ "dev": true,
+ "requires": {
+ "arr-diff": "4.0.0",
+ "array-unique": "0.3.2",
+ "define-property": "1.0.0",
+ "extend-shallow": "2.0.1",
+ "fragment-cache": "0.2.1",
+ "is-odd": "1.0.0",
+ "kind-of": "5.1.0",
+ "object.pick": "1.3.0",
+ "regex-not": "1.0.0",
+ "snapdragon": "0.8.1",
+ "to-regex": "3.0.1"
+ },
+ "dependencies": {
+ "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
+ },
+ "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
+ },
+ "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.1"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
+ "dev": true
+ }
+ }
+ },
+ "natives": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz",
+ "integrity": "sha1-ARrM4ffL2H97prMJPWzZOSvhxXQ=",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
+ },
+ "ncname": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz",
+ "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=",
+ "dev": true,
+ "requires": {
+ "xml-char-classes": "1.0.0"
+ }
+ },
+ "negotiator": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
+ "dev": true
+ },
+ "nightmare": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/nightmare/-/nightmare-2.10.0.tgz",
+ "integrity": "sha1-6cXVkLspb1loX9SCGML7rER2eyE=",
+ "dev": true,
+ "requires": {
+ "debug": "2.2.0",
+ "deep-defaults": "1.0.4",
+ "defaults": "1.0.3",
+ "electron": "1.7.9",
+ "enqueue": "1.0.2",
+ "function-source": "0.1.0",
+ "jsesc": "0.5.0",
+ "minstache": "1.2.0",
+ "mkdirp": "0.5.1",
+ "once": "1.4.0",
+ "rimraf": "2.5.4",
+ "sliced": "1.0.1",
+ "split2": "2.2.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ }
+ }
+ },
+ "no-case": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.0.tgz",
+ "integrity": "sha1-yiglzLdrGOb3nVc9z78erOM90WQ=",
+ "dev": true,
+ "requires": {
+ "lower-case": "1.1.3"
+ }
+ },
+ "node-forge": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz",
+ "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=",
+ "dev": true
+ },
+ "node-gyp": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz",
+ "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=",
+ "dev": true,
+ "requires": {
+ "fstream": "1.0.11",
+ "glob": "7.1.1",
+ "graceful-fs": "4.1.10",
+ "minimatch": "3.0.3",
+ "mkdirp": "0.5.1",
+ "nopt": "3.0.6",
+ "npmlog": "4.1.2",
+ "osenv": "0.1.4",
+ "request": "2.77.0",
+ "rimraf": "2.5.4",
+ "semver": "5.3.0",
+ "tar": "2.2.1",
+ "which": "1.2.11"
+ }
+ },
+ "node-libs-browser": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
+ "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==",
+ "dev": true,
+ "requires": {
+ "assert": "1.4.1",
+ "browserify-zlib": "0.2.0",
+ "buffer": "4.9.1",
+ "console-browserify": "1.1.0",
+ "constants-browserify": "1.0.0",
+ "crypto-browserify": "3.12.0",
+ "domain-browser": "1.2.0",
+ "events": "1.1.1",
+ "https-browserify": "1.0.0",
+ "os-browserify": "0.3.0",
+ "path-browserify": "0.0.0",
+ "process": "0.11.10",
+ "punycode": "1.4.1",
+ "querystring-es3": "0.2.1",
+ "readable-stream": "2.3.3",
+ "stream-browserify": "2.0.1",
+ "stream-http": "2.8.0",
+ "string_decoder": "1.0.3",
+ "timers-browserify": "2.0.6",
+ "tty-browserify": "0.0.0",
+ "url": "0.11.0",
+ "util": "0.10.3",
+ "vm-browserify": "0.0.4"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "node-sass": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.7.2.tgz",
+ "integrity": "sha512-CaV+wLqZ7//Jdom5aUFCpGNoECd7BbNhjuwdsX/LkXBrHl8eb1Wjw4HvWqcFvhr5KuNgAk8i/myf/MQ1YYeroA==",
+ "dev": true,
+ "requires": {
+ "async-foreach": "0.1.3",
+ "chalk": "1.1.3",
+ "cross-spawn": "3.0.1",
+ "gaze": "1.1.2",
+ "get-stdin": "4.0.1",
+ "glob": "7.1.1",
+ "in-publish": "2.0.0",
+ "lodash.assign": "4.2.0",
+ "lodash.clonedeep": "4.5.0",
+ "lodash.mergewith": "4.6.0",
+ "meow": "3.7.0",
+ "mkdirp": "0.5.1",
+ "nan": "2.8.0",
+ "node-gyp": "3.6.2",
+ "npmlog": "4.1.2",
+ "request": "2.79.0",
+ "sass-graph": "2.2.4",
+ "stdout-stream": "1.4.0",
+ "true-case-path": "1.0.2"
+ },
+ "dependencies": {
+ "request": {
+ "version": "2.79.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz",
+ "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "0.6.0",
+ "aws4": "1.5.0",
+ "caseless": "0.11.0",
+ "combined-stream": "1.0.5",
+ "extend": "3.0.0",
+ "forever-agent": "0.6.1",
+ "form-data": "2.1.1",
+ "har-validator": "2.0.6",
+ "hawk": "3.1.3",
+ "http-signature": "1.1.1",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.12",
+ "oauth-sign": "0.8.2",
+ "qs": "6.3.0",
+ "stringstream": "0.0.5",
+ "tough-cookie": "2.3.2",
+ "tunnel-agent": "0.4.3",
+ "uuid": "3.2.1"
+ }
+ },
+ "uuid": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
+ "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
+ "dev": true
+ }
+ }
+ },
+ "node-uuid": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz",
+ "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=",
+ "dev": true
+ },
+ "node.extend": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.0.10.tgz",
+ "integrity": "sha1-Mmm934HFRTX0CKvHhMMrDSvVX28=",
+ "dev": true,
+ "requires": {
+ "is": "0.3.0"
+ }
+ },
+ "nodemon": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.12.1.tgz",
+ "integrity": "sha1-mWpW3EnZ8Wu/G3ik3gjxNjSzh40=",
+ "dev": true,
+ "requires": {
+ "chokidar": "1.7.0",
+ "debug": "2.6.9",
+ "es6-promise": "3.3.1",
+ "ignore-by-default": "1.0.1",
+ "lodash.defaults": "3.1.2",
+ "minimatch": "3.0.4",
+ "ps-tree": "1.1.0",
+ "touch": "3.1.0",
+ "undefsafe": "0.0.3",
+ "update-notifier": "2.2.0"
+ },
+ "dependencies": {
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "dev": true,
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chokidar": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+ "dev": true,
+ "requires": {
+ "anymatch": "1.3.0",
+ "async-each": "1.0.1",
+ "fsevents": "1.1.3",
+ "glob-parent": "2.0.0",
+ "inherits": "2.0.3",
+ "is-binary-path": "1.0.1",
+ "is-glob": "2.0.1",
+ "path-is-absolute": "1.0.1",
+ "readdirp": "2.1.0"
+ }
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "es6-promise": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
+ "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
+ "dev": true
+ },
+ "lodash.assign": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz",
+ "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=",
+ "dev": true,
+ "requires": {
+ "lodash._baseassign": "3.2.0",
+ "lodash._createassigner": "3.1.1",
+ "lodash.keys": "3.1.2"
+ }
+ },
+ "lodash.defaults": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz",
+ "integrity": "sha1-xzCLGNv4vJNy1wGnNJPGEZK9Liw=",
+ "dev": true,
+ "requires": {
+ "lodash.assign": "3.2.0",
+ "lodash.restparam": "3.6.1"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "dev": true,
+ "requires": {
+ "abbrev": "1.0.9"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz",
+ "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "2.1.5",
+ "is-builtin-module": "1.0.0",
+ "semver": "5.3.0",
+ "validate-npm-package-license": "3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz",
+ "integrity": "sha1-R4hqwWYnYNQmG32XnSQXCdPOP3o=",
+ "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.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "dev": true,
+ "requires": {
+ "are-we-there-yet": "1.1.4",
+ "console-control-strings": "1.1.0",
+ "gauge": "2.7.4",
+ "set-blocking": "2.0.0"
+ }
+ },
+ "nugget": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz",
+ "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=",
+ "dev": true,
+ "requires": {
+ "debug": "2.2.0",
+ "minimist": "1.2.0",
+ "pretty-bytes": "1.0.4",
+ "progress-stream": "1.2.0",
+ "request": "2.77.0",
+ "single-line-log": "1.1.2",
+ "throttleit": "0.0.2"
+ }
+ },
+ "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
+ },
+ "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.8.2",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+ "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
+ "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A="
+ },
+ "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.1",
+ "define-property": "0.2.5",
+ "kind-of": "3.0.4"
+ },
+ "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.6"
+ }
+ },
+ "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.4"
+ }
+ },
+ "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.4"
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "0.1.6",
+ "is-data-descriptor": "0.1.4",
+ "kind-of": "5.1.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "object-keys": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
+ "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
+ "dev": true
+ },
+ "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.1"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "object.defaults": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
+ "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=",
+ "dev": true,
+ "requires": {
+ "array-each": "1.0.1",
+ "array-slice": "1.1.0",
+ "for-own": "1.0.0",
+ "isobject": "3.0.1"
+ },
+ "dependencies": {
+ "array-slice": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz",
+ "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==",
+ "dev": true
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+ "dev": true,
+ "requires": {
+ "for-in": "1.0.2"
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "object.map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz",
+ "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=",
+ "dev": true,
+ "requires": {
+ "for-own": "1.0.0",
+ "make-iterator": "1.0.0"
+ },
+ "dependencies": {
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+ "dev": true,
+ "requires": {
+ "for-in": "1.0.2"
+ }
+ }
+ }
+ },
+ "object.omit": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+ "dev": true,
+ "requires": {
+ "for-own": "0.1.4",
+ "is-extendable": "0.1.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"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "obuf": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz",
+ "integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4=",
+ "dev": true
+ },
+ "oclazyload": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",
+ "integrity": "sha1-Kjirv/QJDAihEBZxkZRbWfLoJ5w="
+ },
+ "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.1",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
+ "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "requires": {
+ "mimic-fn": "1.2.0"
+ }
+ },
+ "opn": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.2.0.tgz",
+ "integrity": "sha512-Jd/GpzPyHF4P2/aNOVmS3lfMSWV9J7cOhCG1s08XCEAsPkB7lp6ddiU0J7XzyQRDUh8BqJ7PchfINjR8jyofRQ==",
+ "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.10",
+ "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
+ }
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "requires": {
+ "deep-is": "0.1.3",
+ "fast-levenshtein": "2.0.6",
+ "levn": "0.3.0",
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2",
+ "wordwrap": "1.0.0"
+ },
+ "dependencies": {
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
+ }
+ }
+ },
+ "options": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
+ "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=",
+ "dev": true
+ },
+ "orchestrator": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz",
+ "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "0.1.5",
+ "sequencify": "0.0.7",
+ "stream-consume": "0.1.0"
+ }
+ },
+ "ordered-read-streams": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz",
+ "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=",
+ "dev": true
+ },
+ "original": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz",
+ "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=",
+ "dev": true,
+ "requires": {
+ "url-parse": "1.0.5"
+ },
+ "dependencies": {
+ "url-parse": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz",
+ "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=",
+ "dev": true,
+ "requires": {
+ "querystringify": "0.0.4",
+ "requires-port": "1.0.0"
+ }
+ }
+ }
+ },
+ "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": "1.4.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+ "dev": true,
+ "requires": {
+ "lcid": "1.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="
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
+ "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
+ "dev": true,
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "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-limit": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz",
+ "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==",
+ "dev": true,
+ "requires": {
+ "p-try": "1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "1.2.0"
+ }
+ },
+ "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
+ },
+ "p-queue": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-1.2.0.tgz",
+ "integrity": "sha1-Y5y4sHJwwVtx16ZEao4wQU88ltE=",
+ "dev": true
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "package-json": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
+ "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
+ "dev": true,
+ "requires": {
+ "got": "6.7.1",
+ "registry-auth-token": "3.3.1",
+ "registry-url": "3.1.0",
+ "semver": "5.3.0"
+ }
+ },
+ "pako": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
+ "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==",
+ "dev": true
+ },
+ "param-case": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.0.tgz",
+ "integrity": "sha1-Jhn5D9bIKe0LlY8chO0Dp0Wm1wo=",
+ "dev": true,
+ "requires": {
+ "no-case": "2.3.0"
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz",
+ "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=",
+ "dev": true,
+ "requires": {
+ "asn1.js": "4.9.2",
+ "browserify-aes": "1.1.1",
+ "create-hash": "1.1.3",
+ "evp_bytestokey": "1.0.3",
+ "pbkdf2": "3.0.14"
+ }
+ },
+ "parse-filepath": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
+ "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=",
+ "dev": true,
+ "requires": {
+ "is-absolute": "1.0.0",
+ "map-cache": "0.2.2",
+ "path-root": "0.1.1"
+ }
+ },
+ "parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+ "dev": true,
+ "requires": {
+ "glob-base": "0.3.0",
+ "is-dotfile": "1.0.2",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1"
+ }
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "1.3.0"
+ }
+ },
+ "parse-passwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
+ "dev": true
+ },
+ "parsejson": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz",
+ "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=",
+ "dev": true,
+ "requires": {
+ "better-assert": "1.0.2"
+ }
+ },
+ "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.2"
+ }
+ },
+ "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.2"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+ "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=",
+ "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.0",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
+ "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": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
+ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
+ "dev": true
+ },
+ "path-root": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz",
+ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=",
+ "dev": true,
+ "requires": {
+ "path-root-regex": "0.1.2"
+ }
+ },
+ "path-root-regex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz",
+ "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=",
+ "dev": true
+ },
+ "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": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "pause-stream": {
+ "version": "0.0.11",
+ "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
+ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
+ "dev": true,
+ "requires": {
+ "through": "2.3.8"
+ }
+ },
+ "pbkdf2": {
+ "version": "3.0.14",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
+ "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
+ "dev": true,
+ "requires": {
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "ripemd160": "2.0.1",
+ "safe-buffer": "5.1.1",
+ "sha.js": "2.4.10"
+ }
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
+ "dev": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "requires": {
+ "pinkie": "2.0.4"
+ }
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "dev": true,
+ "requires": {
+ "find-up": "2.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "2.0.0"
+ }
+ }
+ }
+ },
+ "plugin-error": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz",
+ "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "1.0.1",
+ "arr-diff": "4.0.0",
+ "arr-union": "3.1.0",
+ "extend-shallow": "3.0.2"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ },
+ "pluralize": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz",
+ "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=",
+ "dev": true
+ },
+ "portfinder": {
+ "version": "1.0.13",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz",
+ "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=",
+ "dev": true,
+ "requires": {
+ "async": "1.5.2",
+ "debug": "2.2.0",
+ "mkdirp": "0.5.1"
+ },
+ "dependencies": {
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ }
+ }
+ },
+ "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
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
+ },
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
+ "dev": true
+ },
+ "preserve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+ "dev": true
+ },
+ "pretty-bytes": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
+ "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1",
+ "meow": "3.7.0"
+ }
+ },
+ "pretty-hrtime": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
+ "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
+ "dev": true
+ },
+ "private": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.6.tgz",
+ "integrity": "sha1-VcapdtD5uvuZJIUTUP5HubX7t8E=",
+ "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": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+ },
+ "progress": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
+ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8="
+ },
+ "progress-stream": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz",
+ "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=",
+ "dev": true,
+ "requires": {
+ "speedometer": "0.1.4",
+ "through2": "0.2.3"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "through2": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
+ "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.1.14",
+ "xtend": "2.1.2"
+ }
+ },
+ "xtend": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
+ "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
+ "dev": true,
+ "requires": {
+ "object-keys": "0.4.0"
+ }
+ }
+ }
+ },
+ "proxy-addr": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz",
+ "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=",
+ "dev": true,
+ "requires": {
+ "forwarded": "0.1.2",
+ "ipaddr.js": "1.5.2"
+ }
+ },
+ "prr": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz",
+ "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=",
+ "dev": true
+ },
+ "ps-tree": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz",
+ "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=",
+ "dev": true,
+ "requires": {
+ "event-stream": "3.3.4"
+ }
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ },
+ "public-encrypt": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
+ "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=",
+ "dev": true,
+ "requires": {
+ "bn.js": "4.11.8",
+ "browserify-rsa": "4.0.1",
+ "create-hash": "1.1.3",
+ "parse-asn1": "5.1.0",
+ "randombytes": "2.0.6"
+ }
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ },
+ "qjobs": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.1.5.tgz",
+ "integrity": "sha1-ZZ3p8s+NzCehSBJ28gU3cnI4LnM=",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.0.tgz",
+ "integrity": "sha1-9AOyZPI7wBIox0ExtAfxjV6l1EI=",
+ "dev": true
+ },
+ "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": "0.0.4",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz",
+ "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=",
+ "dev": true
+ },
+ "randomatic": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz",
+ "integrity": "sha1-EQ3Kv/OX6dz/fAeJzMCkmt8exbs=",
+ "dev": true,
+ "requires": {
+ "is-number": "2.1.0",
+ "kind-of": "3.0.4"
+ }
+ },
+ "randombytes": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
+ "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz",
+ "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==",
+ "dev": true,
+ "requires": {
+ "randombytes": "2.0.6",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
+ "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
+ "dev": true,
+ "requires": {
+ "bytes": "3.0.0",
+ "http-errors": "1.6.2",
+ "iconv-lite": "0.4.19",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+ "dev": true
+ },
+ "depd": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+ "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
+ "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
+ "dev": true,
+ "requires": {
+ "depd": "1.1.1",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.0.3",
+ "statuses": "1.3.1"
+ }
+ },
+ "setprototypeof": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
+ "dev": true
+ }
+ }
+ },
+ "raw-loader": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
+ "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=",
+ "dev": true
+ },
+ "rc": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz",
+ "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=",
+ "dev": true,
+ "requires": {
+ "deep-extend": "0.4.2",
+ "ini": "1.3.4",
+ "minimist": "1.2.0",
+ "strip-json-comments": "2.0.1"
+ }
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "1.1.0",
+ "normalize-package-data": "2.3.5",
+ "path-type": "1.1.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "1.1.2",
+ "read-pkg": "1.1.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz",
+ "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=",
+ "requires": {
+ "buffer-shims": "1.0.0",
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "0.10.31",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "readdirp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
+ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10",
+ "minimatch": "3.0.3",
+ "readable-stream": "2.1.5",
+ "set-immediate-shim": "1.0.1"
+ }
+ },
+ "recast": {
+ "version": "0.11.18",
+ "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.18.tgz",
+ "integrity": "sha1-B69iV8p2mGiBUglAHU1g7vG1uUc=",
+ "dev": true,
+ "requires": {
+ "ast-types": "0.9.2",
+ "esprima": "3.1.2",
+ "private": "0.1.6",
+ "source-map": "0.5.6"
+ }
+ },
+ "rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+ "dev": true,
+ "requires": {
+ "resolve": "1.4.0"
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "2.1.0",
+ "strip-indent": "1.0.1"
+ }
+ },
+ "redeyed": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz",
+ "integrity": "sha1-6WwZO0DAgWsArshCaY5hGF5VSYo=",
+ "dev": true,
+ "requires": {
+ "esprima": "3.0.0"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz",
+ "integrity": "sha1-U88kes2ncxPlUcOqLnM0LT+099k=",
+ "dev": true
+ }
+ }
+ },
+ "regenerate": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz",
+ "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==",
+ "dev": true
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+ "dev": true
+ },
+ "regenerator-transform": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
+ "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "6.26.0",
+ "babel-types": "6.26.0",
+ "private": "0.1.6"
+ }
+ },
+ "regex-cache": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz",
+ "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=",
+ "dev": true,
+ "requires": {
+ "is-equal-shallow": "0.1.3",
+ "is-primitive": "2.0.0"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz",
+ "integrity": "sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "2.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.1"
+ }
+ }
+ }
+ },
+ "regexpu-core": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+ "dev": true,
+ "requires": {
+ "regenerate": "1.3.3",
+ "regjsgen": "0.2.0",
+ "regjsparser": "0.1.5"
+ }
+ },
+ "registry-auth-token": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.1.tgz",
+ "integrity": "sha1-+w0yie4Nmtosu1KvXf5mywcNMAY=",
+ "dev": true,
+ "requires": {
+ "rc": "1.2.1",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "registry-url": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
+ "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
+ "dev": true,
+ "requires": {
+ "rc": "1.2.1"
+ }
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "requires": {
+ "jsesc": "0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ }
+ }
+ },
+ "relateurl": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
+ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
+ "dev": true
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+ "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
+ "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=",
+ "dev": true
+ },
+ "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.2"
+ }
+ },
+ "replace-ext": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
+ "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
+ "dev": true
+ },
+ "request": {
+ "version": "2.77.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.77.0.tgz",
+ "integrity": "sha1-KwDYIDDt7cyXCJ/6XYgQqcKqMUs=",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "0.6.0",
+ "aws4": "1.5.0",
+ "caseless": "0.11.0",
+ "combined-stream": "1.0.5",
+ "extend": "3.0.0",
+ "forever-agent": "0.6.1",
+ "form-data": "2.1.1",
+ "har-validator": "2.0.6",
+ "hawk": "3.1.3",
+ "http-signature": "1.1.1",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.12",
+ "node-uuid": "1.4.7",
+ "oauth-sign": "0.8.2",
+ "qs": "6.3.0",
+ "stringstream": "0.0.5",
+ "tough-cookie": "2.3.2",
+ "tunnel-agent": "0.4.3"
+ }
+ },
+ "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
+ },
+ "require-uncached": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+ "requires": {
+ "caller-path": "0.1.0",
+ "resolve-from": "1.0.1"
+ }
+ },
+ "require-yaml": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
+ "integrity": "sha1-LhsY2RPDuqcqWk03O28Tjd0sMr0=",
+ "requires": {
+ "js-yaml": "3.10.0"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw=="
+ },
+ "js-yaml": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
+ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
+ "requires": {
+ "argparse": "1.0.9",
+ "esprima": "4.0.0"
+ }
+ }
+ }
+ },
+ "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.4.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz",
+ "integrity": "sha1-p1vgHFPaJdk0qY69DkxKcxL5KoY=",
+ "dev": true,
+ "requires": {
+ "path-parse": "1.0.5"
+ }
+ },
+ "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"
+ },
+ "dependencies": {
+ "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-dir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
+ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
+ "dev": true,
+ "requires": {
+ "expand-tilde": "2.0.2",
+ "global-modules": "1.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
+ "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY="
+ },
+ "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
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "requires": {
+ "onetime": "2.0.1",
+ "signal-exit": "3.0.2"
+ },
+ "dependencies": {
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ }
+ }
+ },
+ "right-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+ "dev": true,
+ "requires": {
+ "align-text": "0.1.4"
+ }
+ },
+ "rimraf": {
+ "version": "2.5.4",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz",
+ "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=",
+ "requires": {
+ "glob": "7.1.1"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
+ "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
+ "dev": true,
+ "requires": {
+ "hash-base": "2.0.2",
+ "inherits": "2.0.3"
+ }
+ },
+ "run-async": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+ "requires": {
+ "is-promise": "2.1.0"
+ }
+ },
+ "run-sequence": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.0.tgz",
+ "integrity": "sha1-s/jUKDbbidCLL+cE6vDJPf2DNeI=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "gulp-util": "3.0.8"
+ },
+ "dependencies": {
+ "dateformat": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
+ "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=",
+ "dev": true
+ },
+ "gulp-util": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz",
+ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=",
+ "dev": true,
+ "requires": {
+ "array-differ": "1.0.0",
+ "array-uniq": "1.0.3",
+ "beeper": "1.1.1",
+ "chalk": "1.1.3",
+ "dateformat": "2.2.0",
+ "fancy-log": "1.3.2",
+ "gulplog": "1.0.0",
+ "has-gulplog": "0.1.0",
+ "lodash._reescape": "3.0.0",
+ "lodash._reevaluate": "3.0.0",
+ "lodash._reinterpolate": "3.0.0",
+ "lodash.template": "3.6.2",
+ "minimist": "1.2.0",
+ "multipipe": "0.1.2",
+ "object-assign": "3.0.0",
+ "replace-ext": "0.0.1",
+ "through2": "2.0.1",
+ "vinyl": "0.5.3"
+ }
+ },
+ "object-assign": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
+ "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=",
+ "dev": true
+ }
+ }
+ },
+ "rx-lite": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
+ "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ="
+ },
+ "rx-lite-aggregates": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
+ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+ "requires": {
+ "rx-lite": "4.0.8"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
+ },
+ "sass-graph": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
+ "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.1",
+ "lodash": "4.16.6",
+ "scss-tokenizer": "0.2.3",
+ "yargs": "7.1.0"
+ }
+ },
+ "sass-loader": {
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.6.tgz",
+ "integrity": "sha512-c3/Zc+iW+qqDip6kXPYLEgsAu2lf4xz0EZDplB7EmSUMda12U1sGJPetH55B/j9eu0bTtKzKlNPWWyYC7wFNyQ==",
+ "dev": true,
+ "requires": {
+ "async": "2.6.0",
+ "clone-deep": "0.3.0",
+ "loader-utils": "1.1.0",
+ "lodash.tail": "4.1.1",
+ "pify": "3.0.0"
+ },
+ "dependencies": {
+ "async": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
+ "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
+ "dev": true,
+ "requires": {
+ "lodash": "4.16.6"
+ }
+ },
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "dev": true,
+ "requires": {
+ "big.js": "3.1.3",
+ "emojis-list": "2.1.0",
+ "json5": "0.5.0"
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "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.5.2"
+ },
+ "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.1"
+ }
+ }
+ }
+ },
+ "scss-tokenizer": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
+ "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
+ "dev": true,
+ "requires": {
+ "js-base64": "2.4.3",
+ "source-map": "0.4.4"
+ },
+ "dependencies": {
+ "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": "1.0.1"
+ }
+ }
+ }
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+ "dev": true
+ },
+ "selfsigned": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.2.tgz",
+ "integrity": "sha1-tESVgNmZKbZbEKSDiTAaZZIIh1g=",
+ "dev": true,
+ "requires": {
+ "node-forge": "0.7.1"
+ }
+ },
+ "semver": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
+ },
+ "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.3.0"
+ }
+ },
+ "send": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz",
+ "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "1.1.2",
+ "destroy": "1.0.4",
+ "encodeurl": "1.0.1",
+ "escape-html": "1.0.3",
+ "etag": "1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "1.6.2",
+ "mime": "1.4.1",
+ "ms": "2.0.0",
+ "on-finished": "2.3.0",
+ "range-parser": "1.2.0",
+ "statuses": "1.3.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"
+ }
+ },
+ "mime": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
+ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "seq-queue": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
+ "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=",
+ "dev": true
+ },
+ "sequencify": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz",
+ "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=",
+ "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": {
+ "accepts": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
+ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=",
+ "dev": true,
+ "requires": {
+ "mime-types": "2.1.17",
+ "negotiator": "0.6.1"
+ }
+ },
+ "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"
+ }
+ },
+ "mime-db": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
+ "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
+ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.30.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz",
+ "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==",
+ "dev": true,
+ "requires": {
+ "encodeurl": "1.0.1",
+ "escape-html": "1.0.3",
+ "parseurl": "1.3.2",
+ "send": "0.16.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-getter": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz",
+ "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=",
+ "dev": true,
+ "requires": {
+ "to-object-path": "0.3.0"
+ }
+ },
+ "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.0",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
+ "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "2.0.1",
+ "is-extendable": "0.1.1",
+ "is-plain-object": "2.0.4",
+ "split-string": "3.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.1"
+ }
+ }
+ }
+ },
+ "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.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ },
+ "sha.js": {
+ "version": "2.4.10",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz",
+ "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "shallow-clone": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz",
+ "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "0.1.1",
+ "kind-of": "2.0.1",
+ "lazy-cache": "0.2.7",
+ "mixin-object": "2.0.1"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz",
+ "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "1.1.4"
+ }
+ },
+ "lazy-cache": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz",
+ "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=",
+ "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=",
+ "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="
+ },
+ "sigmund": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
+ "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.1.tgz",
+ "integrity": "sha1-WkyISZK2OnrNm623iUw+6c/MrYE=",
+ "dev": true
+ },
+ "single-line-log": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz",
+ "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=",
+ "dev": true,
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
+ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0"
+ },
+ "dependencies": {
+ "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="
+ }
+ }
+ },
+ "sliced": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
+ "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=",
+ "dev": true
+ },
+ "snapdragon": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz",
+ "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=",
+ "dev": true,
+ "requires": {
+ "base": "0.11.2",
+ "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.1",
+ "use": "2.0.2"
+ },
+ "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.6"
+ }
+ },
+ "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.1"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "0.1.6",
+ "is-data-descriptor": "0.1.4",
+ "kind-of": "5.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
+ "dev": true
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=",
+ "dev": true,
+ "requires": {
+ "define-property": "1.0.0",
+ "isobject": "3.0.1",
+ "snapdragon-util": "3.0.1"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.6"
+ }
+ }
+ }
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
+ "dev": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "socket.io": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.3.tgz",
+ "integrity": "sha1-uK+cq6AJSeVo42nxMn6pvp6iRhs=",
+ "dev": true,
+ "requires": {
+ "debug": "2.3.3",
+ "engine.io": "1.8.3",
+ "has-binary": "0.1.7",
+ "object-assign": "4.1.0",
+ "socket.io-adapter": "0.5.0",
+ "socket.io-client": "1.7.3",
+ "socket.io-parser": "2.3.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
+ "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
+ "dev": true,
+ "requires": {
+ "ms": "0.7.2"
+ }
+ },
+ "ms": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+ "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
+ "dev": true
+ }
+ }
+ },
+ "socket.io-adapter": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz",
+ "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=",
+ "dev": true,
+ "requires": {
+ "debug": "2.3.3",
+ "socket.io-parser": "2.3.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
+ "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
+ "dev": true,
+ "requires": {
+ "ms": "0.7.2"
+ }
+ },
+ "ms": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+ "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
+ "dev": true
+ }
+ }
+ },
+ "socket.io-client": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.3.tgz",
+ "integrity": "sha1-sw6GqhDV7zVGYBwJzeR2Xjgdo3c=",
+ "dev": true,
+ "requires": {
+ "backo2": "1.0.2",
+ "component-bind": "1.0.0",
+ "component-emitter": "1.2.1",
+ "debug": "2.3.3",
+ "engine.io-client": "1.8.3",
+ "has-binary": "0.1.7",
+ "indexof": "0.0.1",
+ "object-component": "0.0.3",
+ "parseuri": "0.0.5",
+ "socket.io-parser": "2.3.1",
+ "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": "2.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
+ "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
+ "dev": true,
+ "requires": {
+ "ms": "0.7.2"
+ }
+ },
+ "ms": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+ "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
+ "dev": true
+ }
+ }
+ },
+ "socket.io-parser": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz",
+ "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=",
+ "dev": true,
+ "requires": {
+ "component-emitter": "1.1.2",
+ "debug": "2.2.0",
+ "isarray": "0.0.1",
+ "json3": "3.3.2"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "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.2.1"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
+ "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
+ "dev": true
+ }
+ }
+ },
+ "sockjs-client": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz",
+ "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "eventsource": "0.1.6",
+ "faye-websocket": "0.11.1",
+ "inherits": "2.0.3",
+ "json3": "3.3.2",
+ "url-parse": "1.2.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"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz",
+ "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": "0.7.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
+ "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=",
+ "dev": true
+ },
+ "source-map-resolve": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz",
+ "integrity": "sha1-etD1k/IoFZjoVN+A8ZquS5LXoRo=",
+ "dev": true,
+ "requires": {
+ "atob": "2.0.3",
+ "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.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"
+ }
+ },
+ "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
+ },
+ "sparkles": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz",
+ "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
+ "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=",
+ "dev": true,
+ "requires": {
+ "spdx-license-ids": "1.2.2"
+ }
+ },
+ "spdx-expression-parse": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz",
+ "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=",
+ "dev": true
+ },
+ "spdx-license-ids": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz",
+ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=",
+ "dev": true
+ },
+ "spdy": {
+ "version": "3.4.7",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
+ "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "handle-thing": "1.2.5",
+ "http-deceiver": "1.2.7",
+ "safe-buffer": "5.1.1",
+ "select-hose": "2.0.0",
+ "spdy-transport": "2.0.20"
+ },
+ "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
+ }
+ }
+ },
+ "spdy-transport": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz",
+ "integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "detect-node": "2.0.3",
+ "hpack.js": "2.1.6",
+ "obuf": "1.1.1",
+ "readable-stream": "2.3.3",
+ "safe-buffer": "5.1.1",
+ "wbuf": "1.7.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
+ },
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "speedometer": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz",
+ "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=",
+ "dev": true
+ },
+ "split": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
+ "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+ "dev": true,
+ "requires": {
+ "through": "2.3.8"
+ }
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "3.0.2"
+ },
+ "dependencies": {
+ "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"
+ }
+ },
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "2.0.4"
+ }
+ }
+ }
+ },
+ "split2": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz",
+ "integrity": "sha1-GGsldbz4PoW30YRldWI47k7kJJM=",
+ "dev": true,
+ "requires": {
+ "through2": "2.0.3"
+ },
+ "dependencies": {
+ "through2": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.1.5",
+ "xtend": "4.0.1"
+ }
+ }
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
+ "sqlstring": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz",
+ "integrity": "sha1-UluKT9Jtb3GqYegipsr5dtMa0qg=",
+ "dev": true
+ },
+ "sshpk": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.1.tgz",
+ "integrity": "sha1-MOGl0ykkSXShr2FREznVla9mOLA=",
+ "dev": true,
+ "requires": {
+ "asn1": "0.2.3",
+ "assert-plus": "1.0.0",
+ "bcrypt-pbkdf": "1.0.0",
+ "dashdash": "1.14.0",
+ "ecc-jsbn": "0.1.1",
+ "getpass": "0.1.6",
+ "jodid25519": "1.0.2",
+ "jsbn": "0.1.0",
+ "tweetnacl": "0.14.3"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "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.6"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "0.1.6",
+ "is-data-descriptor": "0.1.4",
+ "kind-of": "5.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
+ "dev": true
+ }
+ }
+ },
+ "statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
+ "dev": true
+ },
+ "stdout-stream": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz",
+ "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.1.5"
+ }
+ },
+ "stream-browserify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.1.5"
+ }
+ },
+ "stream-combiner": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
+ "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
+ "dev": true,
+ "requires": {
+ "duplexer": "0.1.1"
+ }
+ },
+ "stream-consume": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz",
+ "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=",
+ "dev": true
+ },
+ "stream-http": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz",
+ "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==",
+ "dev": true,
+ "requires": {
+ "builtin-status-codes": "3.0.0",
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3",
+ "to-arraybuffer": "1.0.1",
+ "xtend": "4.0.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "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.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
+ "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
+ "dev": true
+ },
+ "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": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "0.2.1"
+ }
+ },
+ "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-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "4.0.1"
+ }
+ },
+ "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="
+ },
+ "style-loader": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.20.1.tgz",
+ "integrity": "sha512-NtlwQOHQvUgEKuPs4JoUMQUkML8UNMxLbXM2JAZerIQVVVMgO5VVRjYQA8zzkpBu/X2OnTt+5ZKe8IbGk5TjRA==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "1.1.0",
+ "schema-utils": "0.4.3"
+ },
+ "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.1"
+ }
+ },
+ "ajv-keywords": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "dev": true,
+ "requires": {
+ "big.js": "3.1.3",
+ "emojis-list": "2.1.0",
+ "json5": "0.5.0"
+ }
+ },
+ "schema-utils": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.3.tgz",
+ "integrity": "sha512-sgv/iF/T4/SewJkaVpldKC4WjSkz0JsOh2eKtxCPpCO1oR05+7MOF+H476HVRbLArkgA7j5TRJJ4p2jdFkUGQQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "5.5.2",
+ "ajv-keywords": "2.1.1"
+ }
+ }
+ }
+ },
+ "sumchecker": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz",
+ "integrity": "sha1-ebs7RFbdBPGOvbwNcDodHa7FEF0=",
+ "dev": true,
+ "requires": {
+ "debug": "2.2.0",
+ "es6-promise": "4.1.1"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ },
+ "table": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
+ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
+ "requires": {
+ "ajv": "5.5.2",
+ "ajv-keywords": "2.1.1",
+ "chalk": "2.3.1",
+ "lodash": "4.17.5",
+ "slice-ansi": "1.0.0",
+ "string-width": "2.1.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "requires": {
+ "color-convert": "1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz",
+ "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==",
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "5.2.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+ },
+ "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="
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "3.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz",
+ "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==",
+ "requires": {
+ "has-flag": "3.0.0"
+ }
+ }
+ }
+ },
+ "tapable": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz",
+ "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=",
+ "dev": true
+ },
+ "tar": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
+ "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
+ "dev": true,
+ "requires": {
+ "block-stream": "0.0.9",
+ "fstream": "1.0.11",
+ "inherits": "2.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"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
+ },
+ "throttleit": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz",
+ "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=",
+ "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.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz",
+ "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "2.0.6",
+ "xtend": "4.0.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "0.10.31",
+ "util-deprecate": "1.0.2"
+ }
+ }
+ }
+ },
+ "thunky": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz",
+ "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=",
+ "dev": true
+ },
+ "tildify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz",
+ "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=",
+ "dev": true,
+ "requires": {
+ "os-homedir": "1.0.2"
+ }
+ },
+ "time-stamp": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
+ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=",
+ "dev": true
+ },
+ "timed-out": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+ "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
+ "dev": true
+ },
+ "timers-browserify": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz",
+ "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==",
+ "dev": true,
+ "requires": {
+ "setimmediate": "1.0.5"
+ }
+ },
+ "tmp": {
+ "version": "0.0.31",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz",
+ "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=",
+ "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": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
+ "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.4"
+ }
+ },
+ "to-regex": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz",
+ "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=",
+ "dev": true,
+ "requires": {
+ "define-property": "0.2.5",
+ "extend-shallow": "2.0.1",
+ "regex-not": "1.0.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.6"
+ }
+ },
+ "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.1"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "0.1.6",
+ "is-data-descriptor": "0.1.4",
+ "kind-of": "5.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
+ "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"
+ },
+ "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.4"
+ }
+ }
+ }
+ },
+ "touch": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
+ "integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=",
+ "dev": true,
+ "requires": {
+ "nopt": "1.0.10"
+ },
+ "dependencies": {
+ "nopt": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
+ "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
+ "dev": true,
+ "requires": {
+ "abbrev": "1.0.9"
+ }
+ }
+ }
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
+ "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=",
+ "dev": true,
+ "requires": {
+ "punycode": "1.4.1"
+ }
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "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
+ },
+ "true-case-path": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz",
+ "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=",
+ "dev": true,
+ "requires": {
+ "glob": "6.0.4"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
+ "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
+ "dev": true,
+ "requires": {
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.3",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.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.4.3",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
+ "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=",
+ "dev": true
+ },
+ "tweetnacl": {
+ "version": "0.14.3",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz",
+ "integrity": "sha1-PaOC9nDyXe1417PReSEZvKC3Ey0=",
+ "dev": true,
+ "optional": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "requires": {
+ "prelude-ls": "1.1.2"
+ }
+ },
+ "type-is": {
+ "version": "1.6.15",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
+ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "2.1.17"
+ },
+ "dependencies": {
+ "mime-db": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
+ "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
+ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.30.0"
+ }
+ }
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+ },
+ "uglify-js": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.4.tgz",
+ "integrity": "sha1-opWg3hK2plDAMcQN6w3ECxRWi9I=",
+ "dev": true,
+ "requires": {
+ "async": "0.2.10",
+ "source-map": "0.5.6",
+ "uglify-to-browserify": "1.0.2",
+ "yargs": "3.10.0"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "dev": true,
+ "requires": {
+ "center-align": "0.1.3",
+ "right-align": "0.1.3",
+ "wordwrap": "0.0.2"
+ }
+ },
+ "window-size": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "dev": true,
+ "requires": {
+ "camelcase": "1.2.1",
+ "cliui": "2.1.0",
+ "decamelize": "1.2.0",
+ "window-size": "0.1.0"
+ }
+ }
+ }
+ },
+ "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=",
+ "dev": true
+ },
+ "uglifyjs-webpack-plugin": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz",
+ "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=",
+ "dev": true,
+ "requires": {
+ "source-map": "0.5.6",
+ "uglify-js": "2.8.29",
+ "webpack-sources": "1.1.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "dev": true,
+ "requires": {
+ "center-align": "0.1.3",
+ "right-align": "0.1.3",
+ "wordwrap": "0.0.2"
+ }
+ },
+ "uglify-js": {
+ "version": "2.8.29",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
+ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+ "dev": true,
+ "requires": {
+ "source-map": "0.5.6",
+ "uglify-to-browserify": "1.0.2",
+ "yargs": "3.10.0"
+ }
+ },
+ "yargs": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "dev": true,
+ "requires": {
+ "camelcase": "1.2.1",
+ "cliui": "2.1.0",
+ "decamelize": "1.2.0",
+ "window-size": "0.1.0"
+ }
+ }
+ }
+ },
+ "ultron": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
+ "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=",
+ "dev": true
+ },
+ "unc-path-regex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
+ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=",
+ "dev": true
+ },
+ "undefsafe": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-0.0.3.tgz",
+ "integrity": "sha1-7Mo6A+VrmvFzhbqsgSrIO5lKli8=",
+ "dev": true
+ },
+ "union-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
+ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
+ "dev": true,
+ "requires": {
+ "arr-union": "3.1.0",
+ "get-value": "2.0.6",
+ "is-extendable": "0.1.1",
+ "set-value": "0.4.3"
+ },
+ "dependencies": {
+ "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
+ },
+ "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.1"
+ }
+ },
+ "set-value": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
+ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "2.0.1",
+ "is-extendable": "0.1.1",
+ "is-plain-object": "2.0.4",
+ "to-object-path": "0.3.0"
+ }
+ }
+ }
+ },
+ "unique-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz",
+ "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=",
+ "dev": true
+ },
+ "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"
+ }
+ },
+ "universalify": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
+ "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc="
+ },
+ "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.1"
+ },
+ "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.6",
+ "has-values": "0.1.4",
+ "isobject": "2.1.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
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ }
+ }
+ },
+ "unzip-response": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
+ "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=",
+ "dev": true
+ },
+ "update-notifier": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.2.0.tgz",
+ "integrity": "sha1-G1g3z5DAc22IYncytmHBOPht5y8=",
+ "dev": true,
+ "requires": {
+ "boxen": "1.2.1",
+ "chalk": "1.1.3",
+ "configstore": "3.1.1",
+ "import-lazy": "2.1.0",
+ "is-npm": "1.0.0",
+ "latest-version": "3.1.0",
+ "semver-diff": "2.1.0",
+ "xdg-basedir": "3.0.0"
+ }
+ },
+ "upper-case": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
+ "dev": true
+ },
+ "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.2.0",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz",
+ "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==",
+ "dev": true,
+ "requires": {
+ "querystringify": "1.0.0",
+ "requires-port": "1.0.0"
+ },
+ "dependencies": {
+ "querystringify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz",
+ "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=",
+ "dev": true
+ }
+ }
+ },
+ "url-parse-lax": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
+ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "1.0.4"
+ }
+ },
+ "use": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz",
+ "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=",
+ "dev": true,
+ "requires": {
+ "define-property": "0.2.5",
+ "isobject": "3.0.1",
+ "lazy-cache": "2.0.2"
+ },
+ "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.6"
+ }
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "0.1.6",
+ "is-data-descriptor": "0.1.4",
+ "kind-of": "5.1.0"
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
+ "dev": true
+ },
+ "lazy-cache": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz",
+ "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=",
+ "dev": true,
+ "requires": {
+ "set-getter": "0.1.0"
+ }
+ }
+ }
+ },
+ "useragent": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
+ "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "4.1.1",
+ "tmp": "0.0.31"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
+ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
+ "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.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"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+ "dev": true
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true
+ },
+ "v8flags": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz",
+ "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=",
+ "dev": true,
+ "requires": {
+ "user-home": "1.1.1"
+ },
+ "dependencies": {
+ "user-home": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz",
+ "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=",
+ "dev": true
+ }
+ }
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
+ "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "1.0.2",
+ "spdx-expression-parse": "1.0.4"
+ }
+ },
+ "validator": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-6.2.1.tgz",
+ "integrity": "sha1-vFdbeNFb6y4zimZbqVMMf0Ce9mc="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz",
+ "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=",
+ "dev": true,
+ "requires": {
+ "extsprintf": "1.0.2"
+ }
+ },
+ "vinyl": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz",
+ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=",
+ "dev": true,
+ "requires": {
+ "clone": "1.0.2",
+ "clone-stats": "0.0.1",
+ "replace-ext": "0.0.1"
+ }
+ },
+ "vinyl-fs": {
+ "version": "0.3.14",
+ "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz",
+ "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=",
+ "dev": true,
+ "requires": {
+ "defaults": "1.0.3",
+ "glob-stream": "3.1.18",
+ "glob-watcher": "0.0.6",
+ "graceful-fs": "3.0.11",
+ "mkdirp": "0.5.1",
+ "strip-bom": "1.0.0",
+ "through2": "0.6.5",
+ "vinyl": "0.4.6"
+ },
+ "dependencies": {
+ "clone": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
+ "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=",
+ "dev": true
+ },
+ "graceful-fs": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz",
+ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=",
+ "dev": true,
+ "requires": {
+ "natives": "1.1.1"
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "0.0.1",
+ "string_decoder": "0.10.31"
+ }
+ },
+ "strip-bom": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz",
+ "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=",
+ "dev": true,
+ "requires": {
+ "first-chunk-stream": "1.0.0",
+ "is-utf8": "0.2.1"
+ }
+ },
+ "through2": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
+ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "1.0.34",
+ "xtend": "4.0.1"
+ }
+ },
+ "vinyl": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
+ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=",
+ "dev": true,
+ "requires": {
+ "clone": "0.2.0",
+ "clone-stats": "0.0.1"
+ }
+ }
+ }
+ },
+ "vm-browserify": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+ "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+ "dev": true,
+ "requires": {
+ "indexof": "0.0.1"
+ }
+ },
+ "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.4.0",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz",
+ "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=",
+ "dev": true,
+ "requires": {
+ "async": "2.1.2",
+ "chokidar": "1.7.0",
+ "graceful-fs": "4.1.10"
+ },
+ "dependencies": {
+ "chokidar": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+ "dev": true,
+ "requires": {
+ "anymatch": "1.3.0",
+ "async-each": "1.0.1",
+ "fsevents": "1.1.3",
+ "glob-parent": "2.0.0",
+ "inherits": "2.0.3",
+ "is-binary-path": "1.0.1",
+ "is-glob": "2.0.1",
+ "path-is-absolute": "1.0.1",
+ "readdirp": "2.1.0"
+ }
+ }
+ }
+ },
+ "wbuf": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz",
+ "integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=",
+ "dev": true,
+ "requires": {
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "webpack": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz",
+ "integrity": "sha512-fxxKXoicjdXNUMY7LIdY89tkJJJ0m1Oo8PQutZ5rLgWbV5QVKI15Cn7+/IHnRTd3vfKfiwBx6SBqlorAuNA8LA==",
+ "dev": true,
+ "requires": {
+ "acorn": "5.4.1",
+ "acorn-dynamic-import": "2.0.2",
+ "ajv": "5.5.2",
+ "ajv-keywords": "2.1.1",
+ "async": "2.1.2",
+ "enhanced-resolve": "3.4.1",
+ "escope": "3.6.0",
+ "interpret": "1.0.1",
+ "json-loader": "0.5.7",
+ "json5": "0.5.1",
+ "loader-runner": "2.3.0",
+ "loader-utils": "1.1.0",
+ "memory-fs": "0.4.1",
+ "mkdirp": "0.5.1",
+ "node-libs-browser": "2.1.0",
+ "source-map": "0.5.6",
+ "supports-color": "4.5.0",
+ "tapable": "0.2.8",
+ "uglifyjs-webpack-plugin": "0.4.6",
+ "watchpack": "1.4.0",
+ "webpack-sources": "1.1.0",
+ "yargs": "8.0.2"
+ },
+ "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.1"
+ }
+ },
+ "ajv-keywords": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+ "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
+ },
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "dev": true
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "2.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
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
+ "dev": true
+ },
+ "load-json-file": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.10",
+ "parse-json": "2.2.0",
+ "pify": "2.3.0",
+ "strip-bom": "3.0.0"
+ }
+ },
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "dev": true,
+ "requires": {
+ "big.js": "3.1.3",
+ "emojis-list": "2.1.0",
+ "json5": "0.5.1"
+ }
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "dev": true,
+ "requires": {
+ "execa": "0.7.0",
+ "lcid": "1.0.0",
+ "mem": "1.1.0"
+ }
+ },
+ "path-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+ "dev": true,
+ "requires": {
+ "pify": "2.3.0"
+ }
+ },
+ "read-pkg": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "2.0.0",
+ "normalize-package-data": "2.3.5",
+ "path-type": "2.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
+ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+ "dev": true,
+ "requires": {
+ "find-up": "2.1.0",
+ "read-pkg": "2.0.0"
+ }
+ },
+ "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"
+ }
+ },
+ "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"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "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
+ },
+ "yargs": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz",
+ "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=",
+ "dev": true,
+ "requires": {
+ "camelcase": "4.1.0",
+ "cliui": "3.2.0",
+ "decamelize": "1.2.0",
+ "get-caller-file": "1.0.2",
+ "os-locale": "2.1.0",
+ "read-pkg-up": "2.0.0",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "2.1.1",
+ "which-module": "2.0.0",
+ "y18n": "3.2.1",
+ "yargs-parser": "7.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
+ "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
+ "dev": true,
+ "requires": {
+ "camelcase": "4.1.0"
+ }
+ }
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz",
+ "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==",
+ "dev": true,
+ "requires": {
+ "memory-fs": "0.4.1",
+ "mime": "1.6.0",
+ "path-is-absolute": "1.0.1",
+ "range-parser": "1.2.0",
+ "time-stamp": "2.0.0"
+ },
+ "dependencies": {
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true
+ },
+ "time-stamp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz",
+ "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=",
+ "dev": true
+ }
+ }
+ },
+ "webpack-dev-server": {
+ "version": "2.11.1",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.1.tgz",
+ "integrity": "sha512-ombhu5KsO/85sVshIDTyQ5HF3xjZR3N0sf5Ao6h3vFwpNyzInEzA1GV3QPVjTMLTNckp8PjfG1PFGznzBwS5lg==",
+ "dev": true,
+ "requires": {
+ "ansi-html": "0.0.7",
+ "array-includes": "3.0.3",
+ "bonjour": "3.5.0",
+ "chokidar": "2.0.0",
+ "compression": "1.7.1",
+ "connect-history-api-fallback": "1.5.0",
+ "debug": "3.1.0",
+ "del": "3.0.0",
+ "express": "4.16.2",
+ "html-entities": "1.2.1",
+ "http-proxy-middleware": "0.17.4",
+ "import-local": "1.0.0",
+ "internal-ip": "1.2.0",
+ "ip": "1.1.5",
+ "killable": "1.0.0",
+ "loglevel": "1.6.1",
+ "opn": "5.2.0",
+ "portfinder": "1.0.13",
+ "selfsigned": "1.10.2",
+ "serve-index": "1.9.1",
+ "sockjs": "0.3.19",
+ "sockjs-client": "1.1.4",
+ "spdy": "3.4.7",
+ "strip-ansi": "3.0.1",
+ "supports-color": "5.1.0",
+ "webpack-dev-middleware": "1.12.2",
+ "yargs": "6.6.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.5",
+ "normalize-path": "2.1.1"
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "braces": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz",
+ "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "1.1.0",
+ "array-unique": "0.3.2",
+ "define-property": "1.0.0",
+ "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.1.1",
+ "split-string": "3.1.0",
+ "to-regex": "3.0.1"
+ }
+ },
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.0.tgz",
+ "integrity": "sha512-OgXCNv2U6TnG04D3tth0gsvdbV4zdbxFG3sYUqcoQMoEFVd1j1pZR6TZ8iknC45o9IJ6PeQI/J6wT/+cHcniAw==",
+ "dev": true,
+ "requires": {
+ "anymatch": "2.0.0",
+ "async-each": "1.0.1",
+ "braces": "2.3.0",
+ "fsevents": "1.1.3",
+ "glob-parent": "3.1.0",
+ "inherits": "2.0.3",
+ "is-binary-path": "1.0.1",
+ "is-glob": "4.0.0",
+ "normalize-path": "2.1.1",
+ "path-is-absolute": "1.0.1",
+ "readdirp": "2.1.0"
+ }
+ },
+ "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"
+ }
+ },
+ "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.2.0",
+ "pify": "3.0.0",
+ "rimraf": "2.5.4"
+ }
+ },
+ "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.6.9",
+ "define-property": "0.2.5",
+ "extend-shallow": "2.0.1",
+ "posix-character-classes": "0.1.1",
+ "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.6"
+ }
+ }
+ }
+ },
+ "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.1"
+ }
+ },
+ "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"
+ }
+ },
+ "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.1"
+ }
+ },
+ "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.2"
+ },
+ "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.1"
+ }
+ }
+ }
+ },
+ "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.2",
+ "glob": "7.1.1",
+ "object-assign": "4.1.0",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "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.2.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.6"
+ }
+ }
+ }
+ },
+ "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.1.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-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-glob": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
+ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "3.2.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.6"
+ }
+ }
+ }
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "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
+ },
+ "micromatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.5.tgz",
+ "integrity": "sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "4.0.0",
+ "array-unique": "0.3.2",
+ "braces": "2.3.0",
+ "define-property": "1.0.0",
+ "extend-shallow": "2.0.1",
+ "extglob": "2.0.4",
+ "fragment-cache": "0.2.1",
+ "kind-of": "6.0.2",
+ "nanomatch": "1.2.7",
+ "object.pick": "1.3.0",
+ "regex-not": "1.0.0",
+ "snapdragon": "0.8.1",
+ "to-regex": "3.0.1"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "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.1.0"
+ }
+ },
+ "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.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz",
+ "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ },
+ "yargs": {
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
+ "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=",
+ "dev": true,
+ "requires": {
+ "camelcase": "3.0.0",
+ "cliui": "3.2.0",
+ "decamelize": "1.2.0",
+ "get-caller-file": "1.0.2",
+ "os-locale": "1.4.0",
+ "read-pkg-up": "1.0.1",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "1.0.2",
+ "which-module": "1.0.0",
+ "y18n": "3.2.1",
+ "yargs-parser": "4.2.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
+ "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=",
+ "dev": true,
+ "requires": {
+ "camelcase": "3.0.0"
+ }
+ }
+ }
+ },
+ "webpack-merge": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.1.tgz",
+ "integrity": "sha512-geQsZ86YkXOVOjvPC5yv3JSNnL6/X3Kzh935AQ/gJNEYXEfJDQFu/sdFuktS9OW2JcH/SJec8TGfRdrpHshH7A==",
+ "dev": true,
+ "requires": {
+ "lodash": "4.17.5"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ }
+ }
+ },
+ "webpack-sources": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
+ "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==",
+ "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
+ }
+ }
+ },
+ "websocket-driver": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz",
+ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=",
+ "dev": true,
+ "requires": {
+ "http-parser-js": "0.4.10",
+ "websocket-extensions": "0.1.3"
+ }
+ },
+ "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
+ },
+ "which": {
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.2.11.tgz",
+ "integrity": "sha1-yLLu6muMFln6fB3U/aq+lTPcXos=",
+ "requires": {
+ "isexe": "1.1.2"
+ }
+ },
+ "which-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
+ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
+ "dev": true
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
+ "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
+ "dev": true,
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "widest-line": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz",
+ "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=",
+ "dev": true,
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "window-size": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
+ "dev": true
+ },
+ "wordwrap": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.0.0.tgz",
+ "integrity": "sha1-fTD4+HP5pbvDpk2ryNF34HGuQm8=",
+ "dev": true,
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "write": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+ "requires": {
+ "mkdirp": "0.5.1"
+ }
+ },
+ "write-file-atomic": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz",
+ "integrity": "sha1-H/YVdcLipOjlENb6TiQ8zhg5mas=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "imurmurhash": "0.1.4",
+ "signal-exit": "3.0.2"
+ },
+ "dependencies": {
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "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
+ }
+ }
+ },
+ "ws": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.2.tgz",
+ "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=",
+ "dev": true,
+ "requires": {
+ "options": "0.0.6",
+ "ultron": "1.0.2"
+ }
+ },
+ "wtf-8": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz",
+ "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=",
+ "dev": true
+ },
+ "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
+ },
+ "xml-char-classes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz",
+ "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=",
+ "dev": true
+ },
+ "xmlhttprequest-ssl": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz",
+ "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=",
+ "dev": true
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+ "dev": true
+ },
+ "yallist": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz",
+ "integrity": "sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ="
+ },
+ "yaml-loader": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/yaml-loader/-/yaml-loader-0.5.0.tgz",
+ "integrity": "sha512-p9QIzcFSNm4mCw/m5NdyMfN4RE4aFZJWRRb01ERVNGCym8VNbKtw3OYZXnvUIkim6U/EjqE/2yIh9F/msShH9A==",
+ "dev": true,
+ "requires": {
+ "js-yaml": "3.10.0"
+ }
+ },
+ "yargs": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
+ "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
+ "dev": true,
+ "requires": {
+ "camelcase": "3.0.0",
+ "cliui": "3.2.0",
+ "decamelize": "1.2.0",
+ "get-caller-file": "1.0.2",
+ "os-locale": "1.4.0",
+ "read-pkg-up": "1.0.1",
+ "require-directory": "2.1.1",
+ "require-main-filename": "1.0.1",
+ "set-blocking": "2.0.0",
+ "string-width": "1.0.2",
+ "which-module": "1.0.0",
+ "y18n": "3.2.1",
+ "yargs-parser": "5.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+ "dev": true
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
+ "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
+ "dev": true,
+ "requires": {
+ "camelcase": "3.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+ "dev": true
+ }
+ }
+ },
+ "yauzl": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
+ "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
+ "dev": true,
+ "requires": {
+ "fd-slicer": "1.0.1"
+ }
+ },
+ "yeast": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
+ "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
index d68b33f9a..7b4c19023 100644
--- a/package.json
+++ b/package.json
@@ -3,55 +3,83 @@
"version": "1.0.0",
"author": "Verdnatura Levante SL",
"description": "Salix application",
- "license": "ISC",
+ "license": "GPL-3.0",
"repository": {
"type": "git",
- "url": "http://git.verdnatura.es:/salix"
+ "url": "https://git.verdnatura.es/salix"
},
"dependencies": {
- "angular": "^1.6.1",
+ "@uirouter/angularjs": "^1.0.3",
+ "angular": "^1.6.8",
+ "angular-cookies": "^1.6.4",
"angular-paging": "^2.2.2",
- "angular-translate": "^2.13.1",
- "angular-translate-loader-partial": "^2.13.1",
- "angular-ui-router": "^1.0.0-beta.3",
+ "angular-translate": "^2.17.0",
+ "angular-translate-loader-partial": "^2.17.0",
+ "flatpickr": "^2.6.3",
+ "fs-extra": "^5.0.0",
"material-design-lite": "^1.3.0",
"mg-crud": "^1.1.2",
"oclazyload": "^0.6.3",
+ "require-yaml": "0.0.1",
"validator": "^6.2.1"
},
"devDependencies": {
- "babel": "^6.5.2",
- "babel-core": "^6.22.1",
- "babel-loader": "^6.2.10",
- "babel-preset-es2015": "^6.22.0",
+ "angular-mocks": "^1.6.6",
+ "assets-webpack-plugin": "^3.5.1",
+ "babel": "^6.23.0",
+ "babel-core": "^6.26.0",
+ "babel-loader": "^7.1.2",
+ "babel-preset-es2015": "^6.24.1",
"cors": "^2.8.1",
"css-loader": "^0.25.0",
"del": "^2.2.2",
- "eslint": "^3.16.1",
+ "electron": "^1.7.9",
+ "eslint": "^3.19.0",
"eslint-config-angular": "^0.5.0",
"eslint-config-google": "^0.6.0",
+ "eslint-config-loopback": "^4.0.0",
"eslint-config-xo": "^0.17.0",
- "eslint-plugin-angular": "^1.4.1",
- "file-loader": "^0.9.0",
+ "eslint-plugin-jasmine": "^2.8.4",
+ "fancy-log": "^1.3.2",
+ "file-loader": "^1.1.6",
"gulp": "^3.9.1",
"gulp-concat": "^2.6.0",
+ "gulp-env": "^0.4.0",
"gulp-extend": "^0.2.0",
- "gulp-util": "^3.0.7",
+ "gulp-install": "^1.1.0",
+ "gulp-jasmine": "^3.0.0",
+ "gulp-print": "^2.0.1",
"gulp-wrap": "^0.13.0",
"gulp-yaml": "^1.0.1",
"html-loader": "^0.4.4",
+ "jasmine": "^2.9.0",
+ "jasmine-spec-reporter": "^4.2.1",
+ "js-yaml": "^3.10.0",
+ "karma": "^1.7.1",
+ "karma-chrome-launcher": "^2.2.0",
+ "karma-firefox-launcher": "^1.1.0",
+ "karma-jasmine": "^1.1.1",
+ "karma-sourcemap-loader": "^0.3.7",
+ "karma-webpack": "^2.0.9",
"merge-stream": "^1.0.1",
- "node-sass": "^3.11.0",
- "pre-commit": "^1.1.3",
+ "minimist": "^1.2.0",
+ "mustache": "^2.3.0",
+ "mysql2": "^1.5.2",
+ "nightmare": "^2.10.0",
+ "node-sass": "^4.7.2",
+ "nodemon": "^1.12.1",
+ "plugin-error": "^1.0.1",
"raw-loader": "*",
- "sass-loader": "^4.0.2",
- "style-loader": "^0.13.1",
- "webpack": "^2.2.0",
- "webpack-dev-server": "^2.2.0"
+ "run-sequence": "^2.2.0",
+ "sass-loader": "^6.0.6",
+ "style-loader": "^0.20.1",
+ "webpack": "^3.10.0",
+ "webpack-dev-server": "^2.11.1",
+ "webpack-merge": "^4.1.1",
+ "yaml-loader": "^0.5.0"
},
"scripts": {
- "build": "webpack --progress --colors",
- "dev": "webpack-dev-server --progress --colors",
+ "test": "nodemon -q services_tests.js -w services",
"lint": "eslint ./ --cache --ignore-pattern .gitignore"
}
}
diff --git a/services/.gitignore b/services/.gitignore
new file mode 100644
index 000000000..9792c4ca5
--- /dev/null
+++ b/services/.gitignore
@@ -0,0 +1,3 @@
+datasources.test.json
+datasources.development.json
+db.json
diff --git a/services/auth/.yo-rc.json b/services/.yo-rc.json
similarity index 100%
rename from services/auth/.yo-rc.json
rename to services/.yo-rc.json
diff --git a/services/auth/.gitignore b/services/auth/.gitignore
deleted file mode 100644
index ebbd90ea9..000000000
--- a/services/auth/.gitignore
+++ /dev/null
@@ -1,20 +0,0 @@
-*.csv
-*.dat
-*.iml
-*.log
-*.out
-*.pid
-*.seed
-*.sublime-*
-*.swo
-*.swp
-*.tgz
-*.xml
-.DS_Store
-.idea
-.project
-.strong-pm
-coverage
-node_modules
-npm-debug.log
-db.json
diff --git a/services/auth/Dockerfile b/services/auth/Dockerfile
index 9c8022953..3a151e289 100644
--- a/services/auth/Dockerfile
+++ b/services/auth/Dockerfile
@@ -1,9 +1,12 @@
-FROM node:6.9.1
+FROM node:8.9.4
-COPY . /app
+COPY auth /app
+COPY loopback /loopback
+COPY nginx/static/webpack-assets.json /loopback/client/
WORKDIR /app
RUN npm install
+RUN npm -g install pm2
-CMD ["npm", "start"]
\ No newline at end of file
+CMD ["pm2-docker", "./server/server.js"]
diff --git a/services/auth/client/index.ejs b/services/auth/client/index.ejs
index 3e3cd7205..83e71146f 100644
--- a/services/auth/client/index.ejs
+++ b/services/auth/client/index.ejs
@@ -6,14 +6,8 @@
-
-
-
+ <% for (let jsFile of assets('auth', ['vendor'])) { %>
+
+ <% } %>