diff --git a/.buckconfig b/.buckconfig new file mode 100644 index 000000000..934256cb2 --- /dev/null +++ b/.buckconfig @@ -0,0 +1,6 @@ + +[android] + target = Google Inc.:Google APIs:23 + +[maven_repositories] + central = https://repo1.maven.org/maven2 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..522278199 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +tab_width = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +end_of_line = lf +max_line_length = 100 diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 000000000..4afc766a2 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,75 @@ +[ignore] +; We fork some components by platform +.*/*[.]android.js + +; Ignore "BUCK" generated dirs +/\.buckd/ + +; Ignore polyfills +node_modules/react-native/Libraries/polyfills/.* + +; These should not be required directly +; require from fbjs/lib instead: require('fbjs/lib/warning') +node_modules/warning/.* + +; Flow doesn't support platforms +.*/Libraries/Utilities/LoadingView.js + +[untyped] +.*/node_modules/@react-native-community/cli/.*/.* + +[include] + +[libs] +node_modules/react-native/Libraries/react-native/react-native-interface.js +node_modules/react-native/flow/ + +[options] +emoji=true + +esproposal.optional_chaining=enable +esproposal.nullish_coalescing=enable + +module.file_ext=.js +module.file_ext=.json +module.file_ext=.ios.js + +munge_underscores=true + +module.name_mapper='^react-native$' -> '/node_modules/react-native/Libraries/react-native/react-native-implementation' +module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' +module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' + +suppress_type=$FlowIssue +suppress_type=$FlowFixMe +suppress_type=$FlowFixMeProps +suppress_type=$FlowFixMeState + +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError + +[lints] +sketchy-null-number=warn +sketchy-null-mixed=warn +sketchy-number=warn +untyped-type-import=warn +nonstrict-import=warn +deprecated-type=warn +unsafe-getters-setters=warn +inexact-spread=warn +unnecessary-invariant=warn +signature-verification-failure=warn +deprecated-utility=error + +[strict] +deprecated-type +nonstrict-import +sketchy-null +unclear-type +unsafe-getters-setters +untyped-import +untyped-type-import + +[version] +^0.105.0 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..e9dd62663 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +package-lock.json lockable +* text=auto eol=lf +*.pbxproj -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..e74b76f72 --- /dev/null +++ b/.gitignore @@ -0,0 +1,100 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +# Android/IntelliJ +# +build/ +.idea +.gradle +android/release.gradle +local.properties +*.iml + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# BUCK +buck-out/ +\.buckd/ +android/app/*.keystore +!android/app/debug.keystore + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +*/fastlane/report.xml +*/fastlane/Preview.html +*/fastlane/screenshots + +# Bundle artifact +*.jsbundle + +# CocoaPods +/ios/Pods/ +/ios/Podfile.lock + +# Jest +.jest/ + +# Legacy Eclipse project files +.classpath +.project +.cproject +.se + +# VisualStudioCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# Vim +# Persistent undo +[._]*.un~ +# Temporary +.netrwhist +*~ + +### Eclipse ### +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# +production/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..ab29b45cf --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + arrowParens: "always", + printWidth: 140, + trailingComma: "none", + jsxBracketSameLine: true, + requirePragma: false +} + diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..c3b98edda --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "codezombiech.gitignore", + // "dbaeumer.vscode-eslint", + "ms-vscode.vscode-typescript-tslint-plugin", + "eamodio.gitlens", + "EditorConfig.EditorConfig", + "msjsdiag.vscode-react-native", + "streetsidesoftware.code-spell-checker" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..dc9308ddc --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Utilisez IntelliSense pour en savoir plus sur les attributs possibles. + // Pointez pour afficher la description des attributs existants. + // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} diff --git a/.watchmanconfig b/.watchmanconfig new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/.watchmanconfig @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/App.tsx b/App.tsx new file mode 100644 index 000000000..db40433db --- /dev/null +++ b/App.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import SplashScreen from 'react-native-splash-screen'; +import Setup from './src/boot/Setup'; + +export default class App extends React.Component { + public componentDidMount() { + // Do stuff while splash screen is shown + // After having done stuff (such as async tasks) hide the splash screen + SplashScreen.hide(); + } + public render() { + return ; + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 000000000..d3119b238 --- /dev/null +++ b/NOTICE @@ -0,0 +1 @@ +Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved. diff --git a/README.md b/README.md new file mode 100644 index 000000000..2c016ea33 --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +# eMobility React Native Mobile App + +## Summary + +This application is the Electric Vehicle Charging Station (EVSE) mobile application for Android and iOS. + +## Installation + +* Install NodeJS: https://nodejs.org/ (install the LTS version) +* Install Python version 2.7 (not the version 3.7!) +* Install Java SE Development Kit 8 +* Install React Native: https://facebook.github.io/react-native/ + ``` + npm install -g react-native-cli + ``` +* Install Android Studio: https://developer.android.com/studio/ + * Ensure Android SDK Platform 28 and Intel x86 Atom_64 System Image are checked in the SDK manager. + * Windows: + * Add user environment variable: + **ANDROID_HOME=C:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk** + * Add **C:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk\platform-tools** to user paths + * OSX/*nix: + * Add to your shell profile: + ``` + export ANDROID_HOME=$HOME/Library/Android/sdk + export PATH=$PATH:$ANDROID_HOME/emulator + export PATH=$PATH:$ANDROID_HOME/tools + export PATH=$PATH:$ANDROID_HOME/tools/bin + export PATH=$PATH:$ANDROID_HOME/platform-tools + ``` +* Install Xcode: https://developer.apple.com/xcode/ +* Clone this GitHub project +* Go into the **ev-mobile** directory and run **npm install** or **yarn install** + +**NOTE**: On Windows with **chocolatey** (https://chocolatey.org/), +do as an administrator: +``` +choco install -y nodejs-lts python2 jdk8 androidstudio +``` +to install some of the needed dependencies + +## Running the application on a virtual device + +Open a terminal in the **ev-mobile** directory + +* Install CocoaPods on Mac OSX: + + ``` + npm run pod:install + ``` + +* Run on Android: + Setup and start an Android virtual device in Android Studio + + ``` + npm run android + ``` + +* Run on iOS: + + ``` + npm run ios + ``` + +## License + +This file and all other files in this repository are licensed under the Apache Software License, v.2 and copyrighted under the copyright in [NOTICE file](NOTICE), except as noted otherwise in the [LICENSE file](LICENSE). + +Please note that the mobile application can contain other software which may be licensed under different licenses. diff --git a/__tests__/App-test.tsx b/__tests__/App-test.tsx new file mode 100644 index 000000000..25ff076ac --- /dev/null +++ b/__tests__/App-test.tsx @@ -0,0 +1,14 @@ +/** + * @format + */ + +import React from 'react'; +import 'react-native'; +import App from '../App'; + +// Note: test renderer must be required after react-native. +import renderer from 'react-test-renderer'; + +it('renders correctly', () => { + renderer.create(); +}); diff --git a/android/app/_BUCK b/android/app/_BUCK new file mode 100644 index 000000000..be3bbc556 --- /dev/null +++ b/android/app/_BUCK @@ -0,0 +1,55 @@ +# To learn about Buck see [Docs](https://buckbuild.com/). +# To run your application with Buck: +# - install Buck +# - `npm start` - to start the packager +# - `cd android` +# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` +# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck +# - `buck install -r android/app` - compile, install and run application +# + +load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") + +lib_deps = [] + +create_aar_targets(glob(["libs/*.aar"])) + +create_jar_targets(glob(["libs/*.jar"])) + +android_library( + name = "all-libs", + exported_deps = lib_deps, +) + +android_library( + name = "app-code", + srcs = glob([ + "src/main/java/**/*.java", + ]), + deps = [ + ":all-libs", + ":build_config", + ":res", + ], +) + +android_build_config( + name = "build_config", + package = "com.emobility", +) + +android_resource( + name = "res", + package = "com.emobility", + res = "src/main/res", +) + +android_binary( + name = "app", + keystore = "//android/keystores:debug", + manifest = "src/main/AndroidManifest.xml", + package_type = "debug", + deps = [ + ":app-code", + ], +) diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 000000000..f849824f2 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,220 @@ +apply plugin: "com.android.application" + +apply from: file("../release.gradle") + +import com.android.build.OutputFile + +/** + * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets + * and bundleReleaseJsAndAssets). + * These basically call `react-native bundle` with the correct arguments during the Android build + * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the + * bundle directly from the development server. Below you can see all the possible configurations + * and their defaults. If you decide to add a configuration block, make sure to add it before the + * `apply from: "../../node_modules/react-native/react.gradle"` line. + * + * project.ext.react = [ + * // the name of the generated asset file containing your JS bundle + * bundleAssetName: "index.android.bundle", + * + * // the entry file for bundle generation + * entryFile: "index.android.js", + * + * // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format + * bundleCommand: "ram-bundle", + * + * // whether to bundle JS and assets in debug mode + * bundleInDebug: false, + * + * // whether to bundle JS and assets in release mode + * bundleInRelease: true, + * + * // whether to bundle JS and assets in another build variant (if configured). + * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants + * // The configuration property can be in the following formats + * // 'bundleIn${productFlavor}${buildType}' + * // 'bundleIn${buildType}' + * // bundleInFreeDebug: true, + * // bundleInPaidRelease: true, + * // bundleInBeta: true, + * + * // whether to disable dev mode in custom build variants (by default only disabled in release) + * // for example: to disable dev mode in the staging build type (if configured) + * devDisabledInStaging: true, + * // The configuration property can be in the following formats + * // 'devDisabledIn${productFlavor}${buildType}' + * // 'devDisabledIn${buildType}' + * + * // the root of your project, i.e. where "package.json" lives + * root: "../../", + * + * // where to put the JS bundle asset in debug mode + * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", + * + * // where to put the JS bundle asset in release mode + * jsBundleDirRelease: "$buildDir/intermediates/assets/release", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in debug mode + * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in release mode + * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", + * + * // by default the gradle tasks are skipped if none of the JS files or assets change; this means + * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to + * // date; if you have any other folders that you want to ignore for performance reasons (gradle + * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ + * // for example, you might want to remove it from here. + * inputExcludes: ["android/**", "ios/**"], + * + * // override which node gets called and with what additional arguments + * nodeExecutableAndArgs: ["node"], + * + * // supply additional arguments to the packager + * extraPackagerArgs: [] + * ] + */ + +project.ext.react = [ + entryFile: "index.js", + enableHermes: false, // clean and rebuild if changing +] + +apply from: "../../node_modules/react-native/react.gradle" + +/** + * Set this to true to create two separate APKs instead of one: + * - An APK that only works on ARM devices + * - An APK that only works on x86 devices + * The advantage is the size of the APK is reduced by about 4MB. + * Upload all the APKs to the Play Store and people will download + * the correct one based on the CPU architecture of their device. + */ +def enableSeparateBuildPerCPUArchitecture = false + +/** + * Run Proguard to shrink the Java bytecode in release builds. + */ +def enableProguardInReleaseBuilds = true + +/** + * The preferred build flavor of JavaScriptCore. + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +// def jscFlavor = 'org.webkit:android-jsc:+' +def jscFlavor = 'org.webkit:android-jsc-intl:+' + +/** + * Whether to enable the Hermes VM. + * + * This should be set on project.ext.react and mirrored here. If it is not set + * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode + * and the benefits of using Hermes will therefore be sharply reduced. + */ +def enableHermes = project.ext.react.get("enableHermes", false); + +android { + compileSdkVersion rootProject.ext.compileSdkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + defaultConfig { + applicationId "com.emobility" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 128 + versionName "1.3.1" + } + splits { + abi { + reset() + enable enableSeparateBuildPerCPUArchitecture + universalApk false // If true, also generate a universal APK + include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" + } + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + release { + if (EMOBILITY_UPLOAD_STORE_FILE) { + storeFile file(EMOBILITY_UPLOAD_STORE_FILE) + storePassword EMOBILITY_UPLOAD_STORE_PASSWORD + keyAlias EMOBILITY_UPLOAD_KEY_ALIAS + keyPassword EMOBILITY_UPLOAD_KEY_PASSWORD + } + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://facebook.github.io/react-native/docs/signed-apk-android. + signingConfig signingConfigs.release + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } + // applicationVariants are e.g. debug, release + applicationVariants.all { variant -> + variant.outputs.each { output -> + // For each separate APK per architecture, set a unique version code as described here: + // https://developer.android.com/studio/build/configure-apk-splits.html + def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] + def abi = output.getFilter(OutputFile.ABI) + if (abi != null) { // null for the universal-debug, universal-release variants + output.versionCodeOverride = + versionCodes.get(abi) * 1048576 + defaultConfig.versionCode + } + } + } +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation "com.facebook.react:react-native:+" // From node_modules + implementation 'androidx.appcompat:appcompat:1.1.0-rc01' + implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02' + implementation "com.google.android.gms:play-services-base:16.1.0" + implementation "com.google.firebase:firebase-core:16.0.9" + implementation 'com.google.firebase:firebase-analytics:17.2.0' + implementation 'com.google.firebase:firebase-messaging:20.0.0' + implementation 'me.leolin:ShortcutBadger:1.1.21@aar' // <-- Add this line if you wish to use badge on Android + + if (enableHermes) { + def hermesPath = "../../node_modules/hermes-engine/android/"; + debugImplementation files(hermesPath + "hermes-debug.aar") + releaseImplementation files(hermesPath + "hermes-release.aar") + } else { + implementation jscFlavor + } +} + +// Run this once to be able to run the application with BUCK +// puts all compile dependencies into folder libs for BUCK to use +task copyDownloadableDepsToLibs(type: Copy) { + from configurations.compile + into 'libs' +} + +apply plugin: 'com.google.gms.google-services' +apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) + diff --git a/android/app/build_defs.bzl b/android/app/build_defs.bzl new file mode 100644 index 000000000..fff270f8d --- /dev/null +++ b/android/app/build_defs.bzl @@ -0,0 +1,19 @@ +"""Helper definitions to glob .aar and .jar targets""" + +def create_aar_targets(aarfiles): + for aarfile in aarfiles: + name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] + lib_deps.append(":" + name) + android_prebuilt_aar( + name = name, + aar = aarfile, + ) + +def create_jar_targets(jarfiles): + for jarfile in jarfiles: + name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] + lib_deps.append(":" + name) + prebuilt_jar( + name = name, + binary_jar = jarfile, + ) diff --git a/android/app/debug.keystore b/android/app/debug.keystore new file mode 100644 index 000000000..364e105ed Binary files /dev/null and b/android/app/debug.keystore differ diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 000000000..df7bdabd4 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,47 @@ +{ + "project_info": { + "project_number": "49073993741", + "firebase_url": "https://emobility-9d380.firebaseio.com", + "project_id": "emobility-9d380", + "storage_bucket": "emobility-9d380.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:49073993741:android:196f784c80ad6d30", + "android_client_info": { + "package_name": "com.emobility" + } + }, + "oauth_client": [ + { + "client_id": "49073993741-kn3s29vjv53cdunhflfc8jschmtis1hn.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAkTPaxSFLk2UJEf0IJd3exWzoAgd3DZPk" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "49073993741-kn3s29vjv53cdunhflfc8jschmtis1hn.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "49073993741-eqd431narshe8vonisdb3vdp5a3a33k6.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.e-Mobility" + } + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro new file mode 100644 index 000000000..c79a4f74f --- /dev/null +++ b/android/app/proguard-rules.pro @@ -0,0 +1,14 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +-keep class io.invertase.firebase.** { *; } +-dontwarn io.invertase.firebase.** +-keep public class com.horcrux.svg.** {*;} \ No newline at end of file diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..fa26aa56e --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..7904d45bf --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/assets/fonts/AntDesign.ttf b/android/app/src/main/assets/fonts/AntDesign.ttf new file mode 100644 index 000000000..2abf03542 Binary files /dev/null and b/android/app/src/main/assets/fonts/AntDesign.ttf differ diff --git a/android/app/src/main/assets/fonts/Entypo.ttf b/android/app/src/main/assets/fonts/Entypo.ttf new file mode 100644 index 000000000..1c8f5e910 Binary files /dev/null and b/android/app/src/main/assets/fonts/Entypo.ttf differ diff --git a/android/app/src/main/assets/fonts/EvilIcons.ttf b/android/app/src/main/assets/fonts/EvilIcons.ttf new file mode 100644 index 000000000..b270f9851 Binary files /dev/null and b/android/app/src/main/assets/fonts/EvilIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Feather.ttf b/android/app/src/main/assets/fonts/Feather.ttf new file mode 100644 index 000000000..244854c54 Binary files /dev/null and b/android/app/src/main/assets/fonts/Feather.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome.ttf b/android/app/src/main/assets/fonts/FontAwesome.ttf new file mode 100644 index 000000000..35acda2fa Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf new file mode 100644 index 000000000..953d567b2 Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf new file mode 100644 index 000000000..235101c2d Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf differ diff --git a/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf b/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf new file mode 100644 index 000000000..7c92e986f Binary files /dev/null and b/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf differ diff --git a/android/app/src/main/assets/fonts/Fontisto.ttf b/android/app/src/main/assets/fonts/Fontisto.ttf new file mode 100644 index 000000000..96e2e81a3 Binary files /dev/null and b/android/app/src/main/assets/fonts/Fontisto.ttf differ diff --git a/android/app/src/main/assets/fonts/Foundation.ttf b/android/app/src/main/assets/fonts/Foundation.ttf new file mode 100644 index 000000000..6cce217dd Binary files /dev/null and b/android/app/src/main/assets/fonts/Foundation.ttf differ diff --git a/android/app/src/main/assets/fonts/Ionicons.ttf b/android/app/src/main/assets/fonts/Ionicons.ttf new file mode 100644 index 000000000..307ad889a Binary files /dev/null and b/android/app/src/main/assets/fonts/Ionicons.ttf differ diff --git a/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf new file mode 100644 index 000000000..82524a0c1 Binary files /dev/null and b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/MaterialIcons.ttf b/android/app/src/main/assets/fonts/MaterialIcons.ttf new file mode 100644 index 000000000..7015564ad Binary files /dev/null and b/android/app/src/main/assets/fonts/MaterialIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Octicons.ttf b/android/app/src/main/assets/fonts/Octicons.ttf new file mode 100644 index 000000000..09f5a96c0 Binary files /dev/null and b/android/app/src/main/assets/fonts/Octicons.ttf differ diff --git a/android/app/src/main/assets/fonts/Roboto.ttf b/android/app/src/main/assets/fonts/Roboto.ttf new file mode 100644 index 000000000..3e6e2e761 Binary files /dev/null and b/android/app/src/main/assets/fonts/Roboto.ttf differ diff --git a/android/app/src/main/assets/fonts/Roboto_medium.ttf b/android/app/src/main/assets/fonts/Roboto_medium.ttf new file mode 100644 index 000000000..aa00de0ef Binary files /dev/null and b/android/app/src/main/assets/fonts/Roboto_medium.ttf differ diff --git a/android/app/src/main/assets/fonts/SimpleLineIcons.ttf b/android/app/src/main/assets/fonts/SimpleLineIcons.ttf new file mode 100644 index 000000000..6ecb68683 Binary files /dev/null and b/android/app/src/main/assets/fonts/SimpleLineIcons.ttf differ diff --git a/android/app/src/main/assets/fonts/Zocial.ttf b/android/app/src/main/assets/fonts/Zocial.ttf new file mode 100644 index 000000000..e4ae46c62 Binary files /dev/null and b/android/app/src/main/assets/fonts/Zocial.ttf differ diff --git a/android/app/src/main/assets/fonts/rubicon-icon-font.ttf b/android/app/src/main/assets/fonts/rubicon-icon-font.ttf new file mode 100644 index 000000000..25e7d92e3 Binary files /dev/null and b/android/app/src/main/assets/fonts/rubicon-icon-font.ttf differ diff --git a/android/app/src/main/ic_launcher-web.png b/android/app/src/main/ic_launcher-web.png new file mode 100644 index 000000000..ab7cfb484 Binary files /dev/null and b/android/app/src/main/ic_launcher-web.png differ diff --git a/android/app/src/main/java/com/emobility/MainActivity.java b/android/app/src/main/java/com/emobility/MainActivity.java new file mode 100644 index 000000000..e58d47dca --- /dev/null +++ b/android/app/src/main/java/com/emobility/MainActivity.java @@ -0,0 +1,46 @@ +package com.emobility; + +import android.os.Bundle; +import android.content.Intent; +import android.content.res.Configuration; +import com.facebook.react.ReactActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.ReactRootView; +import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; +import org.devio.rn.splashscreen.SplashScreen; + +public class MainActivity extends ReactActivity { + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + Intent intent = new Intent("onConfigurationChanged"); + intent.putExtra("newConfig", newConfig); + this.sendBroadcast(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + SplashScreen.show(this, R.style.SplashScreenTheme); + super.onCreate(savedInstanceState); + } + + /** + * Returns the name of the main component registered from JavaScript. + * This is used to schedule rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "eMobility"; + } + + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new ReactActivityDelegate(this, getMainComponentName()) { + @Override + protected ReactRootView createRootView() { + return new RNGestureHandlerEnabledRootView(MainActivity.this); + } + }; + } +} diff --git a/android/app/src/main/java/com/emobility/MainApplication.java b/android/app/src/main/java/com/emobility/MainApplication.java new file mode 100644 index 000000000..78fa1aac8 --- /dev/null +++ b/android/app/src/main/java/com/emobility/MainApplication.java @@ -0,0 +1,52 @@ +package com.emobility; + +import android.content.Context; +import android.app.Application; + +import com.facebook.react.PackageList; +import com.facebook.react.ReactApplication; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.shell.MainReactPackage; +import com.facebook.soloader.SoLoader; +import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage; +import io.invertase.firebase.messaging.RNFirebaseMessagingPackage; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + @SuppressWarnings("UnnecessaryLocalVariable") + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + packages.add(new RNFirebaseMessagingPackage()); + packages.add(new RNFirebaseNotificationsPackage()); + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + } +} diff --git a/android/app/src/main/res/drawable/ic_stat_ic_notification.png b/android/app/src/main/res/drawable/ic_stat_ic_notification.png new file mode 100644 index 000000000..44ce3ed3c Binary files /dev/null and b/android/app/src/main/res/drawable/ic_stat_ic_notification.png differ diff --git a/android/app/src/main/res/layout/launch_screen.xml b/android/app/src/main/res/layout/launch_screen.xml new file mode 100644 index 000000000..b6832d220 --- /dev/null +++ b/android/app/src/main/res/layout/launch_screen.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..4ae7d1237 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..4ae7d1237 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..33e0f8a29 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png new file mode 100644 index 000000000..e9e89ee4d Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..f168374df Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..882be6186 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..b42875f98 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png new file mode 100644 index 000000000..e9e89ee4d Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..71b40998e Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..0a86f623c Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..af2f76432 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png new file mode 100644 index 000000000..e9e89ee4d Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..5580a4642 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..7fddbcac5 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..112899042 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png new file mode 100644 index 000000000..e9e89ee4d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..2505b8f0d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..ce0afedb9 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..c438d26d2 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png new file mode 100644 index 000000000..e9e89ee4d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 000000000..936fe2c68 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..b9722ff55 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml new file mode 100644 index 000000000..92e16fed8 --- /dev/null +++ b/android/app/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + #00376C + #00376C + #FFF + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..423f0db9c --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + e-Mobility + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..d092e0016 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 000000000..9c323ca85 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,39 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext { + buildToolsVersion = "28.0.3" + minSdkVersion = 16 + compileSdkVersion = 28 + targetSdkVersion = 28 + supportLibVersion = "28.0.0" + } + repositories { + google() + jcenter() + } + dependencies { + classpath("com.android.tools.build:gradle:3.4.2") + classpath("com.google.gms:google-services:4.3.2") + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + mavenLocal() + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url("$rootDir/../node_modules/react-native/android") + } + maven { + // Android JSC is installed from npm + url("$rootDir/../node_modules/jsc-android/dist") + } + maven { url "https://jitpack.io" } + + google() + jcenter() + } +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 000000000..e09ab02ef --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,23 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +android.enableJetifier=true +android.useAndroidX=true + +android.disableResourceValidation=true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..5c2d1cf01 Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..e0c4de36d --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 000000000..b0d6d0ab5 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,188 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 000000000..1e2f2ad67 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,101 @@ +@if "%DEBUG%" == "" @echo off + +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem http://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/release-template.gradle b/android/release-template.gradle new file mode 100644 index 000000000..6d9203743 --- /dev/null +++ b/android/release-template.gradle @@ -0,0 +1,9 @@ + +ext { + EMOBILITY_UPLOAD_STORE_FILE="release.keystore" + EMOBILITY_UPLOAD_KEY_ALIAS="" + EMOBILITY_UPLOAD_STORE_PASSWORD="" + EMOBILITY_UPLOAD_KEY_PASSWORD="" +} + + diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 000000000..2f4aa1737 --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,3 @@ +rootProject.name = 'eMobility' +apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) +include ':app' diff --git a/app.json b/app.json new file mode 100644 index 000000000..4410958cc --- /dev/null +++ b/app.json @@ -0,0 +1,4 @@ +{ + "name": "eMobility", + "displayName": "e-Mobility" +} diff --git a/assets/bg.png b/assets/bg.png new file mode 100644 index 000000000..81999cd33 Binary files /dev/null and b/assets/bg.png differ diff --git a/assets/connectorType/chademo.gif b/assets/connectorType/chademo.gif new file mode 100644 index 000000000..b0309b9c3 Binary files /dev/null and b/assets/connectorType/chademo.gif differ diff --git a/assets/connectorType/chademo.svg b/assets/connectorType/chademo.svg new file mode 100755 index 000000000..799fd0d8f --- /dev/null +++ b/assets/connectorType/chademo.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/connectorType/combo-ccs.svg b/assets/connectorType/combo-ccs.svg new file mode 100755 index 000000000..799a5a4e2 --- /dev/null +++ b/assets/connectorType/combo-ccs.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/connectorType/combo_ccs.gif b/assets/connectorType/combo_ccs.gif new file mode 100644 index 000000000..6b61d513e Binary files /dev/null and b/assets/connectorType/combo_ccs.gif differ diff --git a/assets/connectorType/domestic-ue.gif b/assets/connectorType/domestic-ue.gif new file mode 100644 index 000000000..4d1ea5d43 Binary files /dev/null and b/assets/connectorType/domestic-ue.gif differ diff --git a/assets/connectorType/domestic-ue.svg b/assets/connectorType/domestic-ue.svg new file mode 100755 index 000000000..5ec3694fa --- /dev/null +++ b/assets/connectorType/domestic-ue.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/assets/connectorType/no-connector.gif b/assets/connectorType/no-connector.gif new file mode 100644 index 000000000..44052988e Binary files /dev/null and b/assets/connectorType/no-connector.gif differ diff --git a/assets/connectorType/no-connector.svg b/assets/connectorType/no-connector.svg new file mode 100755 index 000000000..cc3f87ee6 --- /dev/null +++ b/assets/connectorType/no-connector.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/connectorType/type1-ccs.svg b/assets/connectorType/type1-ccs.svg new file mode 100755 index 000000000..fe4714d1d --- /dev/null +++ b/assets/connectorType/type1-ccs.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/connectorType/type1.svg b/assets/connectorType/type1.svg new file mode 100755 index 000000000..47e09fbb6 --- /dev/null +++ b/assets/connectorType/type1.svg @@ -0,0 +1,13 @@ + + + + + diff --git a/assets/connectorType/type2.gif b/assets/connectorType/type2.gif new file mode 100644 index 000000000..5a6b23e83 Binary files /dev/null and b/assets/connectorType/type2.gif differ diff --git a/assets/connectorType/type2.svg b/assets/connectorType/type2.svg new file mode 100755 index 000000000..8c50df37f --- /dev/null +++ b/assets/connectorType/type2.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/assets/connectorType/type3c.svg b/assets/connectorType/type3c.svg new file mode 100755 index 000000000..f85bee23c --- /dev/null +++ b/assets/connectorType/type3c.svg @@ -0,0 +1,13 @@ + + + + + diff --git a/assets/logo-low.png b/assets/logo-low.png new file mode 100644 index 000000000..65bc43775 Binary files /dev/null and b/assets/logo-low.png differ diff --git a/assets/no-photo-active.png b/assets/no-photo-active.png new file mode 100644 index 000000000..1da19ca2b Binary files /dev/null and b/assets/no-photo-active.png differ diff --git a/assets/no-photo-inverse.png b/assets/no-photo-inverse.png new file mode 100644 index 000000000..e9a0d276c Binary files /dev/null and b/assets/no-photo-inverse.png differ diff --git a/assets/no-photo.png b/assets/no-photo.png new file mode 100755 index 000000000..c617e2f34 Binary files /dev/null and b/assets/no-photo.png differ diff --git a/assets/no-site.png b/assets/no-site.png new file mode 100644 index 000000000..73b7f61c8 Binary files /dev/null and b/assets/no-site.png differ diff --git a/assets/sidebar-transparent.png b/assets/sidebar-transparent.png new file mode 100644 index 000000000..890d0f1cc Binary files /dev/null and b/assets/sidebar-transparent.png differ diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 000000000..f842b77fc --- /dev/null +++ b/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:metro-react-native-babel-preset'], +}; diff --git a/index.js b/index.js new file mode 100644 index 000000000..881337a9d --- /dev/null +++ b/index.js @@ -0,0 +1,9 @@ +/** + * @format + */ + +import { AppRegistry } from "react-native"; +import App from "./App"; +import { name as appName } from "./app.json"; + +AppRegistry.registerComponent(appName, () => App); diff --git a/ios/PodFile b/ios/PodFile new file mode 100644 index 000000000..7b727340e --- /dev/null +++ b/ios/PodFile @@ -0,0 +1,52 @@ +platform :ios, '9.1' +require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' + +target 'eMobility' do + # Pods for eMobility + pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" + pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" + pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" + pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" + pod 'React', :path => '../node_modules/react-native/' + pod 'React-Core', :path => '../node_modules/react-native/' + pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' + pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' + pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' + pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' + pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' + pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' + pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' + pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' + pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' + pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' + pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' + pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' + + pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' + pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' + pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' + pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' + pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon" + pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" + pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga' + + pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' + pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' + pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' + + # Required by RNCharts + pod 'SwiftyJSON', '5.0' + pod 'Charts', '3.3.0' + + # Add Firebase + pod 'Firebase/Core' + pod 'Firebase/Messaging' + pod 'Firebase/Analytics' + + target 'eMobilityTests' do + inherit! :search_paths + # Pods for testing + end + + use_native_modules! +end diff --git a/ios/RNCharts/eMobility-Bridging-Header.h b/ios/RNCharts/eMobility-Bridging-Header.h new file mode 100644 index 000000000..391f7367a --- /dev/null +++ b/ios/RNCharts/eMobility-Bridging-Header.h @@ -0,0 +1,12 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "React/RCTBridge.h" +#import "React/RCTViewManager.h" +#import "React/RCTUIManager.h" +#import "React/UIView+React.h" +#import "React/RCTBridgeModule.h" +#import "React/RCTEventDispatcher.h" +#import "React/RCTEventEmitter.h" +#import "React/RCTFont.h" diff --git a/ios/assets/assets/bg-signup.png b/ios/assets/assets/bg-signup.png new file mode 100644 index 000000000..4f3469f79 Binary files /dev/null and b/ios/assets/assets/bg-signup.png differ diff --git a/ios/assets/assets/bg.png b/ios/assets/assets/bg.png new file mode 100644 index 000000000..81999cd33 Binary files /dev/null and b/ios/assets/assets/bg.png differ diff --git a/ios/assets/assets/connectorType/chademo.gif b/ios/assets/assets/connectorType/chademo.gif new file mode 100644 index 000000000..b0309b9c3 Binary files /dev/null and b/ios/assets/assets/connectorType/chademo.gif differ diff --git a/ios/assets/assets/connectorType/combo_ccs.gif b/ios/assets/assets/connectorType/combo_ccs.gif new file mode 100644 index 000000000..6b61d513e Binary files /dev/null and b/ios/assets/assets/connectorType/combo_ccs.gif differ diff --git a/ios/assets/assets/connectorType/no-connector.gif b/ios/assets/assets/connectorType/no-connector.gif new file mode 100644 index 000000000..44052988e Binary files /dev/null and b/ios/assets/assets/connectorType/no-connector.gif differ diff --git a/ios/assets/assets/connectorType/type2.gif b/ios/assets/assets/connectorType/type2.gif new file mode 100644 index 000000000..5a6b23e83 Binary files /dev/null and b/ios/assets/assets/connectorType/type2.gif differ diff --git a/ios/assets/assets/logo-low.gif b/ios/assets/assets/logo-low.gif new file mode 100644 index 000000000..fd2b52696 Binary files /dev/null and b/ios/assets/assets/logo-low.gif differ diff --git a/ios/assets/assets/logo-low.png b/ios/assets/assets/logo-low.png new file mode 100644 index 000000000..65bc43775 Binary files /dev/null and b/ios/assets/assets/logo-low.png differ diff --git a/ios/assets/assets/no-photo.png b/ios/assets/assets/no-photo.png new file mode 100644 index 000000000..1da19ca2b Binary files /dev/null and b/ios/assets/assets/no-photo.png differ diff --git a/ios/assets/assets/no-site.gif b/ios/assets/assets/no-site.gif new file mode 100644 index 000000000..c790d6dda Binary files /dev/null and b/ios/assets/assets/no-site.gif differ diff --git a/ios/assets/assets/no-site.png b/ios/assets/assets/no-site.png new file mode 100644 index 000000000..73b7f61c8 Binary files /dev/null and b/ios/assets/assets/no-site.png differ diff --git a/ios/assets/assets/sidebar-transparent.png b/ios/assets/assets/sidebar-transparent.png new file mode 100644 index 000000000..890d0f1cc Binary files /dev/null and b/ios/assets/assets/sidebar-transparent.png differ diff --git a/ios/eMobility-tvOS/Info.plist b/ios/eMobility-tvOS/Info.plist new file mode 100644 index 000000000..ecbd496be --- /dev/null +++ b/ios/eMobility-tvOS/Info.plist @@ -0,0 +1,53 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSExceptionDomains + + localhost + + NSExceptionAllowsInsecureHTTPLoads + + + + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/eMobility-tvOSTests/Info.plist b/ios/eMobility-tvOSTests/Info.plist new file mode 100644 index 000000000..886825ccc --- /dev/null +++ b/ios/eMobility-tvOSTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/ios/eMobility.plist b/ios/eMobility.plist new file mode 100644 index 000000000..8670c80c5 --- /dev/null +++ b/ios/eMobility.plist @@ -0,0 +1,99 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + $(BUNDLE_NAME) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + eMobility + CFBundleURLSchemes + + eMobility + + + + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSExceptionDomains + + localhost + + NSExceptionAllowsInsecureHTTPLoads + + + + + NSLocationAlwaysUsageDescription + Discover charging stations + NSLocationWhenInUseUsageDescription + Discover charging stations + UIAppFonts + + AntDesign.ttf + Entypo.ttf + EvilIcons.ttf + Feather.ttf + FontAwesome.ttf + FontAwesome5_Brands.ttf + FontAwesome5_Regular.ttf + FontAwesome5_Solid.ttf + Foundation.ttf + Ionicons.ttf + MaterialCommunityIcons.ttf + MaterialIcons.ttf + Octicons.ttf + Roboto_medium.ttf + Roboto.ttf + rubicon-icon-font.ttf + SimpleLineIcons.ttf + Zocial.ttf + Fontisto.ttf + + UIBackgroundModes + + remote-notification + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/eMobility.xcodeproj/project.pbxproj b/ios/eMobility.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a145a5047 --- /dev/null +++ b/ios/eMobility.xcodeproj/project.pbxproj @@ -0,0 +1,1004 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 00E356F31AD99517003FC87E /* eMobilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* eMobilityTests.m */; }; + 342B70AC2F012B25B1A8509B /* libPods-eMobilityTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDE3817D5E96932F0F2E1E36 /* libPods-eMobilityTests.a */; }; + D204E9D723869B3600D788EF /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = D204E9D623869B3600D788EF /* GoogleService-Info.plist */; }; + D2336F5B23510E6F00A1BCB0 /* CustomChartDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074D0230782CA00116552 /* CustomChartDateFormatter.swift */; }; + D2336F5C23510E6F00A1BCB0 /* ScatterDataExtract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074A2230782C500116552 /* ScatterDataExtract.swift */; }; + D2336F5D23510E6F00A1BCB0 /* RNLineChartManagerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 531074CF230782CA00116552 /* RNLineChartManagerBridge.m */; }; + D2336F5E23510E6F00A1BCB0 /* IndexValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074B2230782C700116552 /* IndexValueFormatter.swift */; }; + D2336F5F23510E6F00A1BCB0 /* RNBubbleChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074D6230782CB00116552 /* RNBubbleChartManager.swift */; }; + D2336F6023510E6F00A1BCB0 /* RNScatterChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074CA230782CA00116552 /* RNScatterChartView.swift */; }; + D2336F6123510E6F00A1BCB0 /* PieDataExtract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074D9230782CB00116552 /* PieDataExtract.swift */; }; + D2336F6223510E6F00A1BCB0 /* RNScatterChartManagerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 531074A0230782C500116552 /* RNScatterChartManagerBridge.m */; }; + D2336F6323510E6F00A1BCB0 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; + D2336F6423510E6F00A1BCB0 /* RNPieChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074D5230782CB00116552 /* RNPieChartManager.swift */; }; + D2336F6523510E6F00A1BCB0 /* RNCombinedChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5310749A230782C500116552 /* RNCombinedChartManager.swift */; }; + D2336F6623510E6F00A1BCB0 /* RNHorizontalBarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074C2230782C900116552 /* RNHorizontalBarChartView.swift */; }; + D2336F6723510E6F00A1BCB0 /* RNBarChartManagerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 531074D3230782CB00116552 /* RNBarChartManagerBridge.m */; }; + D2336F6823510E6F00A1BCB0 /* DataExtract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074CD230782CA00116552 /* DataExtract.swift */; }; + D2336F6923510E6F00A1BCB0 /* RNBarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074BD230782C800116552 /* RNBarChartView.swift */; }; + D2336F6A23510E6F00A1BCB0 /* LineDataExtract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074AE230782C600116552 /* LineDataExtract.swift */; }; + D2336F6B23510E6F00A1BCB0 /* RNLineChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074BB230782C800116552 /* RNLineChartManager.swift */; }; + D2336F6C23510E6F00A1BCB0 /* BalloonMarker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074B6230782C700116552 /* BalloonMarker.swift */; }; + D2336F6D23510E6F00A1BCB0 /* BridgeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5310749C230782C500116552 /* BridgeUtils.swift */; }; + D2336F6E23510E6F00A1BCB0 /* HighlightUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074BE230782C800116552 /* HighlightUtils.swift */; }; + D2336F6F23510E6F00A1BCB0 /* RNBarChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074C5230782C900116552 /* RNBarChartViewBase.swift */; }; + D2336F7023510E6F00A1BCB0 /* ChartDataSetConfigUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074BA230782C800116552 /* ChartDataSetConfigUtils.swift */; }; + D2336F7123510E6F00A1BCB0 /* RadarDataExtract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074D7230782CB00116552 /* RadarDataExtract.swift */; }; + D2336F7223510E6F00A1BCB0 /* FontUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074CE230782CA00116552 /* FontUtils.swift */; }; + D2336F7323510E6F00A1BCB0 /* RNRadarChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074C0230782C800116552 /* RNRadarChartView.swift */; }; + D2336F7423510E6F00A1BCB0 /* RNCombinedChartManagerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 531074C8230782C900116552 /* RNCombinedChartManagerBridge.m */; }; + D2336F7523510E6F00A1BCB0 /* CandleDataExtract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074BF230782C800116552 /* CandleDataExtract.swift */; }; + D2336F7623510E6F00A1BCB0 /* RNLineChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074C9230782C900116552 /* RNLineChartView.swift */; }; + D2336F7723510E6F00A1BCB0 /* ChartGroupHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074AF230782C600116552 /* ChartGroupHolder.swift */; }; + D2336F7823510E6F00A1BCB0 /* BarDataExtract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074B9230782C700116552 /* BarDataExtract.swift */; }; + D2336F7923510E6F00A1BCB0 /* RNHorizontalBarChartManagerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 531074DA230782CB00116552 /* RNHorizontalBarChartManagerBridge.m */; }; + D2336F7A23510E6F00A1BCB0 /* RNCandleStickChartManagerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 531074A6230782C600116552 /* RNCandleStickChartManagerBridge.m */; }; + D2336F7B23510E6F00A1BCB0 /* RNRadarChartManagerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 531074D1230782CA00116552 /* RNRadarChartManagerBridge.m */; }; + D2336F7C23510E6F00A1BCB0 /* RNBarLineChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074D4230782CB00116552 /* RNBarLineChartViewBase.swift */; }; + D2336F7D23510E6F00A1BCB0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + D2336F7E23510E6F00A1BCB0 /* RNBubbleChartManagerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 531074A5230782C600116552 /* RNBubbleChartManagerBridge.m */; }; + D2336F7F23510E6F00A1BCB0 /* RNBarLineChartBaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074B1230782C700116552 /* RNBarLineChartBaseManager.swift */; }; + D2336F8023510E6F00A1BCB0 /* RNCombinedChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5310749D230782C500116552 /* RNCombinedChartView.swift */; }; + D2336F8123510E6F00A1BCB0 /* RNPieChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074CC230782CA00116552 /* RNPieChartView.swift */; }; + D2336F8223510E6F00A1BCB0 /* LargeValueFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074C3230782C900116552 /* LargeValueFormatter.swift */; }; + D2336F8323510E6F00A1BCB0 /* RNChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5310749F230782C500116552 /* RNChartViewBase.swift */; }; + D2336F8423510E6F00A1BCB0 /* CombinedDataExtract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074AC230782C600116552 /* CombinedDataExtract.swift */; }; + D2336F8523510E6F00A1BCB0 /* RNHorizontalBarChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074BC230782C800116552 /* RNHorizontalBarChartManager.swift */; }; + D2336F8623510E6F00A1BCB0 /* ChartDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074C6230782C900116552 /* ChartDateFormatter.swift */; }; + D2336F8723510E6F00A1BCB0 /* BubbleDataExtract.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074B8230782C700116552 /* BubbleDataExtract.swift */; }; + D2336F8823510E6F00A1BCB0 /* EntryToDictionaryUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074A9230782C600116552 /* EntryToDictionaryUtils.swift */; }; + D2336F8923510E6F00A1BCB0 /* RNCandleStickChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074A3230782C500116552 /* RNCandleStickChartManager.swift */; }; + D2336F8A23510E6F00A1BCB0 /* RNCandleStickChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074C4230782C900116552 /* RNCandleStickChartView.swift */; }; + D2336F8B23510E6F00A1BCB0 /* RNBarChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074B7230782C700116552 /* RNBarChartManager.swift */; }; + D2336F8C23510E6F00A1BCB0 /* RNYAxisChartViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074A8230782C600116552 /* RNYAxisChartViewBase.swift */; }; + D2336F8D23510E6F00A1BCB0 /* RNRadarChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074D2230782CA00116552 /* RNRadarChartManager.swift */; }; + D2336F8E23510E6F00A1BCB0 /* RNScatterChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5310749E230782C500116552 /* RNScatterChartManager.swift */; }; + D2336F8F23510E6F00A1BCB0 /* RNPieChartManagerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 531074A7230782C600116552 /* RNPieChartManagerBridge.m */; }; + D2336F9023510E6F00A1BCB0 /* RNBubbleChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531074DB230782CC00116552 /* RNBubbleChartView.swift */; }; + D2336F9523510E6F00A1BCB0 /* bar in Resources */ = {isa = PBXBuildFile; fileRef = 531074B4230782C700116552 /* bar */; }; + D2336F9623510E6F00A1BCB0 /* line in Resources */ = {isa = PBXBuildFile; fileRef = 531074AA230782C600116552 /* line */; }; + D2336F9723510E6F00A1BCB0 /* formatters in Resources */ = {isa = PBXBuildFile; fileRef = 531074B5230782C700116552 /* formatters */; }; + D2336F9823510E6F00A1BCB0 /* radar in Resources */ = {isa = PBXBuildFile; fileRef = 531074D8230782CB00116552 /* radar */; }; + D2336F9923510E6F00A1BCB0 /* scatter in Resources */ = {isa = PBXBuildFile; fileRef = 531074B3230782C700116552 /* scatter */; }; + D2336F9A23510E6F00A1BCB0 /* combine in Resources */ = {isa = PBXBuildFile; fileRef = 5310749B230782C500116552 /* combine */; }; + D2336F9B23510E6F00A1BCB0 /* candlestick in Resources */ = {isa = PBXBuildFile; fileRef = 531074AD230782C600116552 /* candlestick */; }; + D2336F9C23510E6F00A1BCB0 /* pie in Resources */ = {isa = PBXBuildFile; fileRef = 531074CB230782CA00116552 /* pie */; }; + D2336F9D23510E6F00A1BCB0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + D2336F9E23510E6F00A1BCB0 /* bubble in Resources */ = {isa = PBXBuildFile; fileRef = 531074A4230782C600116552 /* bubble */; }; + D2336F9F23510E6F00A1BCB0 /* utils in Resources */ = {isa = PBXBuildFile; fileRef = 531074C7230782C900116552 /* utils */; }; + D2336FA023510E6F00A1BCB0 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; + E34D840E15C81B71348CFD07 /* libPods-eMobility.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E3F56D2AA43D6CD6572F5BE0 /* libPods-eMobility.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; + 00E356EE1AD99517003FC87E /* eMobilityTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = eMobilityTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 00E356F21AD99517003FC87E /* eMobilityTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = eMobilityTests.m; sourceTree = ""; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = eMobility/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = eMobility/AppDelegate.m; sourceTree = ""; }; + 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = eMobility/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = eMobility/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = eMobility/main.m; sourceTree = ""; }; + 18950198593461215DDF4A96 /* Pods-eMobilityTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-eMobilityTests.debug.xcconfig"; path = "Target Support Files/Pods-eMobilityTests/Pods-eMobilityTests.debug.xcconfig"; sourceTree = ""; }; + 39B6D1EE842B47C4C5767484 /* Pods-eMobility.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-eMobility.release.xcconfig"; path = "Target Support Files/Pods-eMobility/Pods-eMobility.release.xcconfig"; sourceTree = ""; }; + 5310749A230782C500116552 /* RNCombinedChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNCombinedChartManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/combine/RNCombinedChartManager.swift"; sourceTree = ""; }; + 5310749B230782C500116552 /* combine */ = {isa = PBXFileReference; lastKnownFileType = folder; name = combine; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/combine"; sourceTree = ""; }; + 5310749C230782C500116552 /* BridgeUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BridgeUtils.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/utils/BridgeUtils.swift"; sourceTree = ""; }; + 5310749D230782C500116552 /* RNCombinedChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNCombinedChartView.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/combine/RNCombinedChartView.swift"; sourceTree = ""; }; + 5310749E230782C500116552 /* RNScatterChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNScatterChartManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/scatter/RNScatterChartManager.swift"; sourceTree = ""; }; + 5310749F230782C500116552 /* RNChartViewBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNChartViewBase.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/RNChartViewBase.swift"; sourceTree = ""; }; + 531074A0230782C500116552 /* RNScatterChartManagerBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNScatterChartManagerBridge.m; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/scatter/RNScatterChartManagerBridge.m"; sourceTree = ""; }; + 531074A1230782C500116552 /* RNBarLineChartManagerBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNBarLineChartManagerBridge.h; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/RNBarLineChartManagerBridge.h"; sourceTree = ""; }; + 531074A2230782C500116552 /* ScatterDataExtract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ScatterDataExtract.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/scatter/ScatterDataExtract.swift"; sourceTree = ""; }; + 531074A3230782C500116552 /* RNCandleStickChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNCandleStickChartManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/candlestick/RNCandleStickChartManager.swift"; sourceTree = ""; }; + 531074A4230782C600116552 /* bubble */ = {isa = PBXFileReference; lastKnownFileType = folder; name = bubble; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bubble"; sourceTree = ""; }; + 531074A5230782C600116552 /* RNBubbleChartManagerBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNBubbleChartManagerBridge.m; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bubble/RNBubbleChartManagerBridge.m"; sourceTree = ""; }; + 531074A6230782C600116552 /* RNCandleStickChartManagerBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNCandleStickChartManagerBridge.m; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/candlestick/RNCandleStickChartManagerBridge.m"; sourceTree = ""; }; + 531074A7230782C600116552 /* RNPieChartManagerBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNPieChartManagerBridge.m; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/pie/RNPieChartManagerBridge.m"; sourceTree = ""; }; + 531074A8230782C600116552 /* RNYAxisChartViewBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNYAxisChartViewBase.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/RNYAxisChartViewBase.swift"; sourceTree = ""; }; + 531074A9230782C600116552 /* EntryToDictionaryUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EntryToDictionaryUtils.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/utils/EntryToDictionaryUtils.swift"; sourceTree = ""; }; + 531074AA230782C600116552 /* line */ = {isa = PBXFileReference; lastKnownFileType = folder; name = line; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/line"; sourceTree = ""; }; + 531074AB230782C600116552 /* RNChartManagerBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNChartManagerBridge.h; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/RNChartManagerBridge.h"; sourceTree = ""; }; + 531074AC230782C600116552 /* CombinedDataExtract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CombinedDataExtract.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/combine/CombinedDataExtract.swift"; sourceTree = ""; }; + 531074AD230782C600116552 /* candlestick */ = {isa = PBXFileReference; lastKnownFileType = folder; name = candlestick; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/candlestick"; sourceTree = ""; }; + 531074AE230782C600116552 /* LineDataExtract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LineDataExtract.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/line/LineDataExtract.swift"; sourceTree = ""; }; + 531074AF230782C600116552 /* ChartGroupHolder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChartGroupHolder.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/ChartGroupHolder.swift"; sourceTree = ""; }; + 531074B0230782C600116552 /* RNYAxisChartManagerBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNYAxisChartManagerBridge.h; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/RNYAxisChartManagerBridge.h"; sourceTree = ""; }; + 531074B1230782C700116552 /* RNBarLineChartBaseManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNBarLineChartBaseManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/RNBarLineChartBaseManager.swift"; sourceTree = ""; }; + 531074B2230782C700116552 /* IndexValueFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IndexValueFormatter.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/IndexValueFormatter.swift"; sourceTree = ""; }; + 531074B3230782C700116552 /* scatter */ = {isa = PBXFileReference; lastKnownFileType = folder; name = scatter; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/scatter"; sourceTree = ""; }; + 531074B4230782C700116552 /* bar */ = {isa = PBXFileReference; lastKnownFileType = folder; name = bar; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bar"; sourceTree = ""; }; + 531074B5230782C700116552 /* formatters */ = {isa = PBXFileReference; lastKnownFileType = folder; name = formatters; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/formatters"; sourceTree = ""; }; + 531074B6230782C700116552 /* BalloonMarker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BalloonMarker.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/BalloonMarker.swift"; sourceTree = ""; }; + 531074B7230782C700116552 /* RNBarChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNBarChartManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bar/RNBarChartManager.swift"; sourceTree = ""; }; + 531074B8230782C700116552 /* BubbleDataExtract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BubbleDataExtract.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bubble/BubbleDataExtract.swift"; sourceTree = ""; }; + 531074B9230782C700116552 /* BarDataExtract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BarDataExtract.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bar/BarDataExtract.swift"; sourceTree = ""; }; + 531074BA230782C800116552 /* ChartDataSetConfigUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChartDataSetConfigUtils.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/utils/ChartDataSetConfigUtils.swift"; sourceTree = ""; }; + 531074BB230782C800116552 /* RNLineChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNLineChartManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/line/RNLineChartManager.swift"; sourceTree = ""; }; + 531074BC230782C800116552 /* RNHorizontalBarChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNHorizontalBarChartManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bar/RNHorizontalBarChartManager.swift"; sourceTree = ""; }; + 531074BD230782C800116552 /* RNBarChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNBarChartView.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bar/RNBarChartView.swift"; sourceTree = ""; }; + 531074BE230782C800116552 /* HighlightUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HighlightUtils.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/utils/HighlightUtils.swift"; sourceTree = ""; }; + 531074BF230782C800116552 /* CandleDataExtract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CandleDataExtract.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/candlestick/CandleDataExtract.swift"; sourceTree = ""; }; + 531074C0230782C800116552 /* RNRadarChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNRadarChartView.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/radar/RNRadarChartView.swift"; sourceTree = ""; }; + 531074C1230782C800116552 /* RNCharts-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RNCharts-Bridging-Header.h"; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/RNCharts-Bridging-Header.h"; sourceTree = ""; }; + 531074C2230782C900116552 /* RNHorizontalBarChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNHorizontalBarChartView.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bar/RNHorizontalBarChartView.swift"; sourceTree = ""; }; + 531074C3230782C900116552 /* LargeValueFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LargeValueFormatter.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/formatters/LargeValueFormatter.swift"; sourceTree = ""; }; + 531074C4230782C900116552 /* RNCandleStickChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNCandleStickChartView.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/candlestick/RNCandleStickChartView.swift"; sourceTree = ""; }; + 531074C5230782C900116552 /* RNBarChartViewBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNBarChartViewBase.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bar/RNBarChartViewBase.swift"; sourceTree = ""; }; + 531074C6230782C900116552 /* ChartDateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChartDateFormatter.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/formatters/ChartDateFormatter.swift"; sourceTree = ""; }; + 531074C7230782C900116552 /* utils */ = {isa = PBXFileReference; lastKnownFileType = folder; name = utils; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/utils"; sourceTree = ""; }; + 531074C8230782C900116552 /* RNCombinedChartManagerBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNCombinedChartManagerBridge.m; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/combine/RNCombinedChartManagerBridge.m"; sourceTree = ""; }; + 531074C9230782C900116552 /* RNLineChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNLineChartView.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/line/RNLineChartView.swift"; sourceTree = ""; }; + 531074CA230782CA00116552 /* RNScatterChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNScatterChartView.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/scatter/RNScatterChartView.swift"; sourceTree = ""; }; + 531074CB230782CA00116552 /* pie */ = {isa = PBXFileReference; lastKnownFileType = folder; name = pie; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/pie"; sourceTree = ""; }; + 531074CC230782CA00116552 /* RNPieChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNPieChartView.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/pie/RNPieChartView.swift"; sourceTree = ""; }; + 531074CD230782CA00116552 /* DataExtract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DataExtract.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/DataExtract.swift"; sourceTree = ""; }; + 531074CE230782CA00116552 /* FontUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FontUtils.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/utils/FontUtils.swift"; sourceTree = ""; }; + 531074CF230782CA00116552 /* RNLineChartManagerBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNLineChartManagerBridge.m; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/line/RNLineChartManagerBridge.m"; sourceTree = ""; }; + 531074D0230782CA00116552 /* CustomChartDateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CustomChartDateFormatter.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/CustomChartDateFormatter.swift"; sourceTree = ""; }; + 531074D1230782CA00116552 /* RNRadarChartManagerBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNRadarChartManagerBridge.m; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/radar/RNRadarChartManagerBridge.m"; sourceTree = ""; }; + 531074D2230782CA00116552 /* RNRadarChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNRadarChartManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/radar/RNRadarChartManager.swift"; sourceTree = ""; }; + 531074D3230782CB00116552 /* RNBarChartManagerBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNBarChartManagerBridge.m; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bar/RNBarChartManagerBridge.m"; sourceTree = ""; }; + 531074D4230782CB00116552 /* RNBarLineChartViewBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNBarLineChartViewBase.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/RNBarLineChartViewBase.swift"; sourceTree = ""; }; + 531074D5230782CB00116552 /* RNPieChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNPieChartManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/pie/RNPieChartManager.swift"; sourceTree = ""; }; + 531074D6230782CB00116552 /* RNBubbleChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNBubbleChartManager.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bubble/RNBubbleChartManager.swift"; sourceTree = ""; }; + 531074D7230782CB00116552 /* RadarDataExtract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RadarDataExtract.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/radar/RadarDataExtract.swift"; sourceTree = ""; }; + 531074D8230782CB00116552 /* radar */ = {isa = PBXFileReference; lastKnownFileType = folder; name = radar; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/radar"; sourceTree = ""; }; + 531074D9230782CB00116552 /* PieDataExtract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PieDataExtract.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/pie/PieDataExtract.swift"; sourceTree = ""; }; + 531074DA230782CB00116552 /* RNHorizontalBarChartManagerBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNHorizontalBarChartManagerBridge.m; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bar/RNHorizontalBarChartManagerBridge.m"; sourceTree = ""; }; + 531074DB230782CC00116552 /* RNBubbleChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RNBubbleChartView.swift; path = "../../node_modules/react-native-charts-wrapper/ios/ReactNativeCharts/bubble/RNBubbleChartView.swift"; sourceTree = ""; }; + 53F9531B2307230D00520246 /* eMobility-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "eMobility-Bridging-Header.h"; sourceTree = ""; }; + 9CC3BC0FEA8501024ED9567F /* Pods-eMobilityTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-eMobilityTests.release.xcconfig"; path = "Target Support Files/Pods-eMobilityTests/Pods-eMobilityTests.release.xcconfig"; sourceTree = ""; }; + ABD5B9B6F98EDD8E45471AE4 /* Pods-eMobility.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-eMobility.debug.xcconfig"; path = "Target Support Files/Pods-eMobility/Pods-eMobility.debug.xcconfig"; sourceTree = ""; }; + CDE3817D5E96932F0F2E1E36 /* libPods-eMobilityTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-eMobilityTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + D204E9D623869B3600D788EF /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "eMobility/GoogleService-Info.plist"; sourceTree = ""; }; + D2336FA623510E6F00A1BCB0 /* eMobility.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = eMobility.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D2336FA723510E6F00A1BCB0 /* eMobility.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = eMobility.plist; path = "/Users/i030367/Documents/charge-angels/ev-mobile/ios/eMobility.plist"; sourceTree = ""; }; + E3F56D2AA43D6CD6572F5BE0 /* libPods-eMobility.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-eMobility.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 00E356EB1AD99517003FC87E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 342B70AC2F012B25B1A8509B /* libPods-eMobilityTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D2336F9123510E6F00A1BCB0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E34D840E15C81B71348CFD07 /* libPods-eMobility.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00E356EF1AD99517003FC87E /* eMobilityTests */ = { + isa = PBXGroup; + children = ( + 00E356F21AD99517003FC87E /* eMobilityTests.m */, + 00E356F01AD99517003FC87E /* Supporting Files */, + ); + path = eMobilityTests; + sourceTree = ""; + }; + 00E356F01AD99517003FC87E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 00E356F11AD99517003FC87E /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* eMobility */ = { + isa = PBXGroup; + children = ( + D204E9D623869B3600D788EF /* GoogleService-Info.plist */, + 008F07F21AC5B25A0029DE68 /* main.jsbundle */, + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.m */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = eMobility; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + ED2971642150620600B7C4FE /* JavaScriptCore.framework */, + E3F56D2AA43D6CD6572F5BE0 /* libPods-eMobility.a */, + CDE3817D5E96932F0F2E1E36 /* libPods-eMobilityTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 53DD4F672305FDBB00044E75 /* RNCharts */ = { + isa = PBXGroup; + children = ( + 531074B6230782C700116552 /* BalloonMarker.swift */, + 531074B4230782C700116552 /* bar */, + 531074B9230782C700116552 /* BarDataExtract.swift */, + 5310749C230782C500116552 /* BridgeUtils.swift */, + 531074A4230782C600116552 /* bubble */, + 531074B8230782C700116552 /* BubbleDataExtract.swift */, + 531074BF230782C800116552 /* CandleDataExtract.swift */, + 531074AD230782C600116552 /* candlestick */, + 531074BA230782C800116552 /* ChartDataSetConfigUtils.swift */, + 531074C6230782C900116552 /* ChartDateFormatter.swift */, + 531074AF230782C600116552 /* ChartGroupHolder.swift */, + 5310749B230782C500116552 /* combine */, + 531074AC230782C600116552 /* CombinedDataExtract.swift */, + 531074D0230782CA00116552 /* CustomChartDateFormatter.swift */, + 531074CD230782CA00116552 /* DataExtract.swift */, + 531074A9230782C600116552 /* EntryToDictionaryUtils.swift */, + 531074CE230782CA00116552 /* FontUtils.swift */, + 531074B5230782C700116552 /* formatters */, + 531074BE230782C800116552 /* HighlightUtils.swift */, + 531074B2230782C700116552 /* IndexValueFormatter.swift */, + 531074C3230782C900116552 /* LargeValueFormatter.swift */, + 531074AA230782C600116552 /* line */, + 531074AE230782C600116552 /* LineDataExtract.swift */, + 531074CB230782CA00116552 /* pie */, + 531074D9230782CB00116552 /* PieDataExtract.swift */, + 531074D8230782CB00116552 /* radar */, + 531074D7230782CB00116552 /* RadarDataExtract.swift */, + 531074B7230782C700116552 /* RNBarChartManager.swift */, + 531074D3230782CB00116552 /* RNBarChartManagerBridge.m */, + 531074BD230782C800116552 /* RNBarChartView.swift */, + 531074C5230782C900116552 /* RNBarChartViewBase.swift */, + 531074B1230782C700116552 /* RNBarLineChartBaseManager.swift */, + 531074A1230782C500116552 /* RNBarLineChartManagerBridge.h */, + 531074D4230782CB00116552 /* RNBarLineChartViewBase.swift */, + 531074D6230782CB00116552 /* RNBubbleChartManager.swift */, + 531074A5230782C600116552 /* RNBubbleChartManagerBridge.m */, + 531074DB230782CC00116552 /* RNBubbleChartView.swift */, + 531074A3230782C500116552 /* RNCandleStickChartManager.swift */, + 531074A6230782C600116552 /* RNCandleStickChartManagerBridge.m */, + 531074C4230782C900116552 /* RNCandleStickChartView.swift */, + 531074AB230782C600116552 /* RNChartManagerBridge.h */, + 531074C1230782C800116552 /* RNCharts-Bridging-Header.h */, + 5310749F230782C500116552 /* RNChartViewBase.swift */, + 5310749A230782C500116552 /* RNCombinedChartManager.swift */, + 531074C8230782C900116552 /* RNCombinedChartManagerBridge.m */, + 5310749D230782C500116552 /* RNCombinedChartView.swift */, + 531074BC230782C800116552 /* RNHorizontalBarChartManager.swift */, + 531074DA230782CB00116552 /* RNHorizontalBarChartManagerBridge.m */, + 531074C2230782C900116552 /* RNHorizontalBarChartView.swift */, + 531074BB230782C800116552 /* RNLineChartManager.swift */, + 531074CF230782CA00116552 /* RNLineChartManagerBridge.m */, + 531074C9230782C900116552 /* RNLineChartView.swift */, + 531074D5230782CB00116552 /* RNPieChartManager.swift */, + 531074A7230782C600116552 /* RNPieChartManagerBridge.m */, + 531074CC230782CA00116552 /* RNPieChartView.swift */, + 531074D2230782CA00116552 /* RNRadarChartManager.swift */, + 531074D1230782CA00116552 /* RNRadarChartManagerBridge.m */, + 531074C0230782C800116552 /* RNRadarChartView.swift */, + 5310749E230782C500116552 /* RNScatterChartManager.swift */, + 531074A0230782C500116552 /* RNScatterChartManagerBridge.m */, + 531074CA230782CA00116552 /* RNScatterChartView.swift */, + 531074B0230782C600116552 /* RNYAxisChartManagerBridge.h */, + 531074A8230782C600116552 /* RNYAxisChartViewBase.swift */, + 531074B3230782C700116552 /* scatter */, + 531074A2230782C500116552 /* ScatterDataExtract.swift */, + 531074C7230782C900116552 /* utils */, + 53F9531B2307230D00520246 /* eMobility-Bridging-Header.h */, + ); + path = RNCharts; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 53DD4F672305FDBB00044E75 /* RNCharts */, + 13B07FAE1A68108700A75B9A /* eMobility */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 00E356EF1AD99517003FC87E /* eMobilityTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + C4E99EF1EB30928FD26DDEBC /* Pods */, + D2336FA723510E6F00A1BCB0 /* eMobility.plist */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 00E356EE1AD99517003FC87E /* eMobilityTests.xctest */, + D2336FA623510E6F00A1BCB0 /* eMobility.app */, + ); + name = Products; + sourceTree = ""; + }; + C4E99EF1EB30928FD26DDEBC /* Pods */ = { + isa = PBXGroup; + children = ( + ABD5B9B6F98EDD8E45471AE4 /* Pods-eMobility.debug.xcconfig */, + 39B6D1EE842B47C4C5767484 /* Pods-eMobility.release.xcconfig */, + 18950198593461215DDF4A96 /* Pods-eMobilityTests.debug.xcconfig */, + 9CC3BC0FEA8501024ED9567F /* Pods-eMobilityTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 00E356ED1AD99517003FC87E /* eMobilityTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "eMobilityTests" */; + buildPhases = ( + F361B7933BD396E2A462DD01 /* [CP] Check Pods Manifest.lock */, + 00E356EA1AD99517003FC87E /* Sources */, + 00E356EB1AD99517003FC87E /* Frameworks */, + 00E356EC1AD99517003FC87E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = eMobilityTests; + productName = eMobilityTests; + productReference = 00E356EE1AD99517003FC87E /* eMobilityTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + D2336F5723510E6F00A1BCB0 /* eMobility */ = { + isa = PBXNativeTarget; + buildConfigurationList = D2336FA323510E6F00A1BCB0 /* Build configuration list for PBXNativeTarget "eMobility" */; + buildPhases = ( + 2C465FF04F5CF035662CCA89 /* [CP] Check Pods Manifest.lock */, + D2336F5923510E6F00A1BCB0 /* Start Packager */, + D2336F5A23510E6F00A1BCB0 /* Sources */, + D2336F9123510E6F00A1BCB0 /* Frameworks */, + D2336F9323510E6F00A1BCB0 /* Resources */, + D2336FA123510E6F00A1BCB0 /* Bundle React Native code and images */, + 9B10D69CB29A3D6EF1977CDA /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = eMobility; + productName = eMobility; + productReference = D2336FA623510E6F00A1BCB0 /* eMobility.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1030; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 00E356ED1AD99517003FC87E = { + CreatedOnToolsVersion = 6.2; + DevelopmentTeam = SG7N28T3A2; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + D2336F5723510E6F00A1BCB0 = { + DevelopmentTeam = SG7N28T3A2; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "eMobility" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D2336F5723510E6F00A1BCB0 /* eMobility */, + 00E356ED1AD99517003FC87E /* eMobilityTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 00E356EC1AD99517003FC87E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D2336F9323510E6F00A1BCB0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D204E9D723869B3600D788EF /* GoogleService-Info.plist in Resources */, + D2336F9523510E6F00A1BCB0 /* bar in Resources */, + D2336F9623510E6F00A1BCB0 /* line in Resources */, + D2336F9723510E6F00A1BCB0 /* formatters in Resources */, + D2336F9823510E6F00A1BCB0 /* radar in Resources */, + D2336F9923510E6F00A1BCB0 /* scatter in Resources */, + D2336F9A23510E6F00A1BCB0 /* combine in Resources */, + D2336F9B23510E6F00A1BCB0 /* candlestick in Resources */, + D2336F9C23510E6F00A1BCB0 /* pie in Resources */, + D2336F9D23510E6F00A1BCB0 /* Images.xcassets in Resources */, + D2336F9E23510E6F00A1BCB0 /* bubble in Resources */, + D2336F9F23510E6F00A1BCB0 /* utils in Resources */, + D2336FA023510E6F00A1BCB0 /* LaunchScreen.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2C465FF04F5CF035662CCA89 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-eMobility-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9B10D69CB29A3D6EF1977CDA /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-eMobility/Pods-eMobility-resources.sh", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-eMobility/Pods-eMobility-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + D2336F5923510E6F00A1BCB0 /* Start Packager */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Start Packager"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n"; + showEnvVarsInLog = 0; + }; + D2336FA123510E6F00A1BCB0 /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; + }; + F361B7933BD396E2A462DD01 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-eMobilityTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 00E356EA1AD99517003FC87E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 00E356F31AD99517003FC87E /* eMobilityTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D2336F5A23510E6F00A1BCB0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D2336F5B23510E6F00A1BCB0 /* CustomChartDateFormatter.swift in Sources */, + D2336F5C23510E6F00A1BCB0 /* ScatterDataExtract.swift in Sources */, + D2336F5D23510E6F00A1BCB0 /* RNLineChartManagerBridge.m in Sources */, + D2336F5E23510E6F00A1BCB0 /* IndexValueFormatter.swift in Sources */, + D2336F5F23510E6F00A1BCB0 /* RNBubbleChartManager.swift in Sources */, + D2336F6023510E6F00A1BCB0 /* RNScatterChartView.swift in Sources */, + D2336F6123510E6F00A1BCB0 /* PieDataExtract.swift in Sources */, + D2336F6223510E6F00A1BCB0 /* RNScatterChartManagerBridge.m in Sources */, + D2336F6323510E6F00A1BCB0 /* AppDelegate.m in Sources */, + D2336F6423510E6F00A1BCB0 /* RNPieChartManager.swift in Sources */, + D2336F6523510E6F00A1BCB0 /* RNCombinedChartManager.swift in Sources */, + D2336F6623510E6F00A1BCB0 /* RNHorizontalBarChartView.swift in Sources */, + D2336F6723510E6F00A1BCB0 /* RNBarChartManagerBridge.m in Sources */, + D2336F6823510E6F00A1BCB0 /* DataExtract.swift in Sources */, + D2336F6923510E6F00A1BCB0 /* RNBarChartView.swift in Sources */, + D2336F6A23510E6F00A1BCB0 /* LineDataExtract.swift in Sources */, + D2336F6B23510E6F00A1BCB0 /* RNLineChartManager.swift in Sources */, + D2336F6C23510E6F00A1BCB0 /* BalloonMarker.swift in Sources */, + D2336F6D23510E6F00A1BCB0 /* BridgeUtils.swift in Sources */, + D2336F6E23510E6F00A1BCB0 /* HighlightUtils.swift in Sources */, + D2336F6F23510E6F00A1BCB0 /* RNBarChartViewBase.swift in Sources */, + D2336F7023510E6F00A1BCB0 /* ChartDataSetConfigUtils.swift in Sources */, + D2336F7123510E6F00A1BCB0 /* RadarDataExtract.swift in Sources */, + D2336F7223510E6F00A1BCB0 /* FontUtils.swift in Sources */, + D2336F7323510E6F00A1BCB0 /* RNRadarChartView.swift in Sources */, + D2336F7423510E6F00A1BCB0 /* RNCombinedChartManagerBridge.m in Sources */, + D2336F7523510E6F00A1BCB0 /* CandleDataExtract.swift in Sources */, + D2336F7623510E6F00A1BCB0 /* RNLineChartView.swift in Sources */, + D2336F7723510E6F00A1BCB0 /* ChartGroupHolder.swift in Sources */, + D2336F7823510E6F00A1BCB0 /* BarDataExtract.swift in Sources */, + D2336F7923510E6F00A1BCB0 /* RNHorizontalBarChartManagerBridge.m in Sources */, + D2336F7A23510E6F00A1BCB0 /* RNCandleStickChartManagerBridge.m in Sources */, + D2336F7B23510E6F00A1BCB0 /* RNRadarChartManagerBridge.m in Sources */, + D2336F7C23510E6F00A1BCB0 /* RNBarLineChartViewBase.swift in Sources */, + D2336F7D23510E6F00A1BCB0 /* main.m in Sources */, + D2336F7E23510E6F00A1BCB0 /* RNBubbleChartManagerBridge.m in Sources */, + D2336F7F23510E6F00A1BCB0 /* RNBarLineChartBaseManager.swift in Sources */, + D2336F8023510E6F00A1BCB0 /* RNCombinedChartView.swift in Sources */, + D2336F8123510E6F00A1BCB0 /* RNPieChartView.swift in Sources */, + D2336F8223510E6F00A1BCB0 /* LargeValueFormatter.swift in Sources */, + D2336F8323510E6F00A1BCB0 /* RNChartViewBase.swift in Sources */, + D2336F8423510E6F00A1BCB0 /* CombinedDataExtract.swift in Sources */, + D2336F8523510E6F00A1BCB0 /* RNHorizontalBarChartManager.swift in Sources */, + D2336F8623510E6F00A1BCB0 /* ChartDateFormatter.swift in Sources */, + D2336F8723510E6F00A1BCB0 /* BubbleDataExtract.swift in Sources */, + D2336F8823510E6F00A1BCB0 /* EntryToDictionaryUtils.swift in Sources */, + D2336F8923510E6F00A1BCB0 /* RNCandleStickChartManager.swift in Sources */, + D2336F8A23510E6F00A1BCB0 /* RNCandleStickChartView.swift in Sources */, + D2336F8B23510E6F00A1BCB0 /* RNBarChartManager.swift in Sources */, + D2336F8C23510E6F00A1BCB0 /* RNYAxisChartViewBase.swift in Sources */, + D2336F8D23510E6F00A1BCB0 /* RNRadarChartManager.swift in Sources */, + D2336F8E23510E6F00A1BCB0 /* RNScatterChartManager.swift in Sources */, + D2336F8F23510E6F00A1BCB0 /* RNPieChartManagerBridge.m in Sources */, + D2336F9023510E6F00A1BCB0 /* RNBubbleChartView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 13B07FB21A68108700A75B9A /* Base */, + ); + name = LaunchScreen.xib; + path = eMobility; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 00E356F61AD99517003FC87E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 18950198593461215DDF4A96 /* Pods-eMobilityTests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_TEAM = SG7N28T3A2; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = eMobilityTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(BUNDLE_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/eMobility.app/eMobility"; + }; + name = Debug; + }; + 00E356F71AD99517003FC87E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9CC3BC0FEA8501024ED9567F /* Pods-eMobilityTests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = SG7N28T3A2; + INFOPLIST_FILE = eMobilityTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(BUNDLE_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/eMobility.app/eMobility"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + D2336FA423510E6F00A1BCB0 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ABD5B9B6F98EDD8E45471AE4 /* Pods-eMobility.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + BUNDLE_NAME = "e-Mobility"; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = eMobility/eMobility.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = NO; + DEVELOPMENT_TEAM = SG7N28T3A2; + INFOPLIST_FILE = eMobility.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/Charts\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/Folly\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/Protobuf\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNI18n\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNSecureStorage\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNVectorIcons\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Core\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-DevSupport\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTActionSheet\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTWebSocket\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-fishhook\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsi\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/glog\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/nanopb\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-orientation-locker\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-sensitive-info\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-splash-screen\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/yoga\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + ); + MARKETING_VERSION = 1.3.1; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.$(BUNDLE_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "RNCharts/eMobility-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + D2336FA523510E6F00A1BCB0 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 39B6D1EE842B47C4C5767484 /* Pods-eMobility.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + BUNDLE_NAME = "e-Mobility"; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = eMobility/eMobility.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = SG7N28T3A2; + INFOPLIST_FILE = eMobility.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"${PODS_CONFIGURATION_BUILD_DIR}/Charts\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/Folly\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/Protobuf\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNI18n\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNSecureStorage\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/RNVectorIcons\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Core\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-DevSupport\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTActionSheet\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTWebSocket\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-fishhook\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsi\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/glog\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/nanopb\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-orientation-locker\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-sensitive-info\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/react-native-splash-screen\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/yoga\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + ); + MARKETING_VERSION = 1.3.1; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.$(BUNDLE_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "RNCharts/eMobility-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "eMobilityTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00E356F61AD99517003FC87E /* Debug */, + 00E356F71AD99517003FC87E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "eMobility" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D2336FA323510E6F00A1BCB0 /* Build configuration list for PBXNativeTarget "eMobility" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D2336FA423510E6F00A1BCB0 /* Debug */, + D2336FA523510E6F00A1BCB0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/ios/eMobility.xcodeproj/xcshareddata/xcschemes/eMobility-tvOS.xcscheme b/ios/eMobility.xcodeproj/xcshareddata/xcschemes/eMobility-tvOS.xcscheme new file mode 100644 index 000000000..5beca9568 --- /dev/null +++ b/ios/eMobility.xcodeproj/xcshareddata/xcschemes/eMobility-tvOS.xcscheme @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/eMobility.xcodeproj/xcshareddata/xcschemes/eMobility.xcscheme b/ios/eMobility.xcodeproj/xcshareddata/xcschemes/eMobility.xcscheme new file mode 100644 index 000000000..433006053 --- /dev/null +++ b/ios/eMobility.xcodeproj/xcshareddata/xcschemes/eMobility.xcscheme @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/eMobility.xcworkspace/contents.xcworkspacedata b/ios/eMobility.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6612d7d9b --- /dev/null +++ b/ios/eMobility.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/eMobility.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/eMobility.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/ios/eMobility.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/eMobility.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/eMobility.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..f9b0d7c5e --- /dev/null +++ b/ios/eMobility.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/eMobility/AppDelegate.h b/ios/eMobility/AppDelegate.h new file mode 100644 index 000000000..2726d5e13 --- /dev/null +++ b/ios/eMobility/AppDelegate.h @@ -0,0 +1,15 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +@interface AppDelegate : UIResponder + +@property (nonatomic, strong) UIWindow *window; + +@end diff --git a/ios/eMobility/AppDelegate.m b/ios/eMobility/AppDelegate.m new file mode 100644 index 000000000..263a7cf9c --- /dev/null +++ b/ios/eMobility/AppDelegate.m @@ -0,0 +1,135 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "AppDelegate.h" + +#import +#import +#import +#import "RNSplashScreen.h" +#import "Orientation.h" +#import +#import +#import +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + [FIRApp configure]; + [RNFirebaseNotifications configure]; + [FIRMessaging messaging].delegate = self; + if ([UNUserNotificationCenter class] != nil) { + // iOS 10 or later + // For iOS 10 display notification (sent via APNS) + [UNUserNotificationCenter currentNotificationCenter].delegate = self; + UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | + UNAuthorizationOptionSound | UNAuthorizationOptionBadge; + [[UNUserNotificationCenter currentNotificationCenter] + requestAuthorizationWithOptions:authOptions + completionHandler:^(BOOL granted, NSError * _Nullable error) { + // ... + }]; + } else { + // iOS 10 notifications aren't available; fall back to iOS 8-9 notifications. + UIUserNotificationType allNotificationTypes = + (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge); + UIUserNotificationSettings *settings = + [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil]; + [application registerUserNotificationSettings:settings]; + } + + [application registerForRemoteNotifications]; + + [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result, NSError * _Nullable error) { + if (error != nil) { + NSLog(@"Error fetching remote instance ID: %@", error); + } else { + NSLog(@"Remote instance ID token: %@", result.token); + } + }]; + + RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; + RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"eMobility" initialProperties:nil]; + + rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; + + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + UIViewController *rootViewController = [UIViewController new]; + rootViewController.view = rootView; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + [RNSplashScreen show]; + return YES; +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken { + NSLog(@"FCM registration token: %@", fcmToken); + // Notify about received token. + NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"]; + [[NSNotificationCenter defaultCenter] postNotificationName: + @"FCMToken" object:nil userInfo:dataDict]; + // TODO: If necessary send token to application server. + // Note: This callback is fired at each app startup and whenever a new token is generated. +} + +- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { + [[RNFirebaseNotifications instance] didReceiveLocalNotification:notification]; +} + +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + NSLog(@"Oh no! Failed to register for remote notifications with error \(error)"); +} + +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + NSLog(@"Received an APNs device token:"); + NSUInteger dataLength = deviceToken.length; + if (dataLength == 0) { + NSLog(@"Oh no! No Token found!!!"); + return; + } + const unsigned char *dataBuffer = (const unsigned char *)deviceToken.bytes; + NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)]; + for (int i = 0; i < dataLength; ++i) { + [hexString appendFormat:@"%02x", dataBuffer[i]]; + } + NSLog(@"%@", [hexString copy]); +} + +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{ + [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; +} + +- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { + [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings]; +} + +- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window +{ + return [Orientation getOrientation]; +} + +- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *)options +{ + return [RCTLinkingManager application:application openURL:url options:options]; +} + +- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler +{ + return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; +} +@end diff --git a/ios/eMobility/Base.lproj/LaunchScreen.xib b/ios/eMobility/Base.lproj/LaunchScreen.xib new file mode 100644 index 000000000..7163a0ea9 --- /dev/null +++ b/ios/eMobility/Base.lproj/LaunchScreen.xib @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/eMobility/GoogleService-Info.plist b/ios/eMobility/GoogleService-Info.plist new file mode 100644 index 000000000..0aa0ca715 --- /dev/null +++ b/ios/eMobility/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 49073993741-eqd431narshe8vonisdb3vdp5a3a33k6.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.49073993741-eqd431narshe8vonisdb3vdp5a3a33k6 + API_KEY + AIzaSyBGw2GDzE6YdOZrbC3X6SeGz-rQbpb6Mfc + GCM_SENDER_ID + 49073993741 + PLIST_VERSION + 1 + BUNDLE_ID + com.e-Mobility + PROJECT_ID + emobility-9d380 + STORAGE_BUCKET + emobility-9d380.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:49073993741:ios:aaf5445e10e25ae3 + DATABASE_URL + https://emobility-9d380.firebaseio.com + + \ No newline at end of file diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/Contents.json b/ios/eMobility/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..dfc04ff2c --- /dev/null +++ b/ios/eMobility/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "ios-e-mobility-20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "ios-e-mobility-20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "ios-e-mobility-29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "ios-e-mobility-29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "ios-e-mobility-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "ios-e-mobility-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "ios-e-mobility-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "ios-e-mobility-60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "ios-e-mobility-20.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "ios-e-mobility-20@2x-1.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "ios-e-mobility-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "ios-e-mobility-29@2x-1.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "ios-e-mobility-40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "ios-e-mobility-40@2x-1.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "ios-e-mobility-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "ios-e-mobility-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "ios-e-mobility-83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "ios-e-mobility-1024x1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-1024x1024.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-1024x1024.png new file mode 100644 index 000000000..4df955a06 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-1024x1024.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20.png new file mode 100644 index 000000000..35edf3598 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20@2x-1.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20@2x-1.png new file mode 100644 index 000000000..2734840e8 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20@2x-1.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20@2x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20@2x.png new file mode 100644 index 000000000..2734840e8 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20@2x.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20@3x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20@3x.png new file mode 100644 index 000000000..d02f310f9 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-20@3x.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29.png new file mode 100644 index 000000000..552c0b39d Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29@2x-1.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29@2x-1.png new file mode 100644 index 000000000..437feb36e Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29@2x-1.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29@2x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29@2x.png new file mode 100644 index 000000000..437feb36e Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29@2x.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29@3x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29@3x.png new file mode 100644 index 000000000..37500e0d8 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-29@3x.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40.png new file mode 100644 index 000000000..2734840e8 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40@2x-1.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40@2x-1.png new file mode 100644 index 000000000..2bba80e15 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40@2x-1.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40@2x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40@2x.png new file mode 100644 index 000000000..2bba80e15 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40@2x.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40@3x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40@3x.png new file mode 100644 index 000000000..1a96df800 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-40@3x.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-60@2x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-60@2x.png new file mode 100644 index 000000000..1a96df800 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-60@2x.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-60@3x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-60@3x.png new file mode 100644 index 000000000..3f8a39832 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-60@3x.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-76.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-76.png new file mode 100644 index 000000000..9d3291176 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-76.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-76@2x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-76@2x.png new file mode 100644 index 000000000..10faecda6 Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-76@2x.png differ diff --git a/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-83.5@2x.png b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-83.5@2x.png new file mode 100644 index 000000000..d26ee3b2c Binary files /dev/null and b/ios/eMobility/Images.xcassets/AppIcon.appiconset/ios-e-mobility-83.5@2x.png differ diff --git a/ios/eMobility/Images.xcassets/Contents.json b/ios/eMobility/Images.xcassets/Contents.json new file mode 100644 index 000000000..da4a164c9 --- /dev/null +++ b/ios/eMobility/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/eMobility/Images.xcassets/splash-screen.imageset/Contents.json b/ios/eMobility/Images.xcassets/splash-screen.imageset/Contents.json new file mode 100644 index 000000000..dabc97713 --- /dev/null +++ b/ios/eMobility/Images.xcassets/splash-screen.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "splash-screen-2048x2048.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/eMobility/Images.xcassets/splash-screen.imageset/splash-screen-2048x2048.png b/ios/eMobility/Images.xcassets/splash-screen.imageset/splash-screen-2048x2048.png new file mode 100644 index 000000000..e9e89ee4d Binary files /dev/null and b/ios/eMobility/Images.xcassets/splash-screen.imageset/splash-screen-2048x2048.png differ diff --git a/ios/eMobility/Info.plist b/ios/eMobility/Info.plist new file mode 100644 index 000000000..8670c80c5 --- /dev/null +++ b/ios/eMobility/Info.plist @@ -0,0 +1,99 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + $(BUNDLE_NAME) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + eMobility + CFBundleURLSchemes + + eMobility + + + + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSExceptionDomains + + localhost + + NSExceptionAllowsInsecureHTTPLoads + + + + + NSLocationAlwaysUsageDescription + Discover charging stations + NSLocationWhenInUseUsageDescription + Discover charging stations + UIAppFonts + + AntDesign.ttf + Entypo.ttf + EvilIcons.ttf + Feather.ttf + FontAwesome.ttf + FontAwesome5_Brands.ttf + FontAwesome5_Regular.ttf + FontAwesome5_Solid.ttf + Foundation.ttf + Ionicons.ttf + MaterialCommunityIcons.ttf + MaterialIcons.ttf + Octicons.ttf + Roboto_medium.ttf + Roboto.ttf + rubicon-icon-font.ttf + SimpleLineIcons.ttf + Zocial.ttf + Fontisto.ttf + + UIBackgroundModes + + remote-notification + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/eMobility/eMobility.entitlements b/ios/eMobility/eMobility.entitlements new file mode 100644 index 000000000..903def2af --- /dev/null +++ b/ios/eMobility/eMobility.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + diff --git a/ios/eMobility/main.m b/ios/eMobility/main.m new file mode 100644 index 000000000..c316cf816 --- /dev/null +++ b/ios/eMobility/main.m @@ -0,0 +1,16 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/ios/eMobilityTests/Info.plist b/ios/eMobilityTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/ios/eMobilityTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/ios/eMobilityTests/eMobilityTests.m b/ios/eMobilityTests/eMobilityTests.m new file mode 100644 index 000000000..75a0a4cda --- /dev/null +++ b/ios/eMobilityTests/eMobilityTests.m @@ -0,0 +1,72 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +#import +#import + +#define TIMEOUT_SECONDS 600 +#define TEXT_TO_LOOK_FOR @"Welcome to React" + +@interface eMobilityTests : XCTestCase + +@end + +@implementation eMobilityTests + +- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test +{ + if (test(view)) { + return YES; + } + for (UIView *subview in [view subviews]) { + if ([self findSubviewInView:subview matching:test]) { + return YES; + } + } + return NO; +} + +- (void)testRendersWelcomeScreen +{ + UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; + BOOL foundElement = NO; + + __block NSString *redboxError = nil; +#ifdef DEBUG + RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { + if (level >= RCTLogLevelError) { + redboxError = message; + } + }); +#endif + + while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + + foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { + if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { + return YES; + } + return NO; + }]; + } + +#ifdef DEBUG + RCTSetLogFunction(RCTDefaultLogFunction); +#endif + + XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); + XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); +} + + +@end diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 000000000..2e0df3dd2 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,4 @@ +module.exports = { + preset: 'react-native', + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], +} diff --git a/metro.config.js b/metro.config.js new file mode 100644 index 000000000..6c3c20b5d --- /dev/null +++ b/metro.config.js @@ -0,0 +1,16 @@ +const { getDefaultConfig } = require("metro-config"); + +module.exports = (async () => { + const { + resolver: { sourceExts, assetExts } + } = await getDefaultConfig(); + return { + transformer: { + babelTransformerPath: require.resolve("react-native-svg-transformer") + }, + resolver: { + assetExts: assetExts.filter(ext => ext !== "svg"), + sourceExts: [...sourceExts, "svg"] + } + }; +})(); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..867b1d76f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,12921 @@ +{ + "name": "eMobility", + "version": "1.2.4", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/core": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", + "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helpers": "^7.8.4", + "@babel/parser": "^7.8.4", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", + "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", + "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", + "requires": { + "@babel/helper-explode-assignable-expression": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-builder-react-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz", + "integrity": "sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ==", + "requires": { + "@babel/types": "^7.8.3", + "esutils": "^2.0.0" + } + }, + "@babel/helper-call-delegate": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz", + "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==", + "requires": { + "@babel/helper-hoist-variables": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", + "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.8.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz", + "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-regex": "^7.8.3", + "regexpu-core": "^4.7.0" + } + }, + "@babel/helper-define-map": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", + "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", + "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", + "requires": { + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", + "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-imports": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", + "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-transforms": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz", + "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==", + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==" + }, + "@babel/helper-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", + "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", + "requires": { + "lodash": "^4.17.13" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", + "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-wrap-function": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-replace-supers": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", + "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-simple-access": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", + "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "requires": { + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-wrap-function": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", + "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helpers": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", + "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==" + }, + "@babel/plugin-external-helpers": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-external-helpers/-/plugin-external-helpers-7.8.3.tgz", + "integrity": "sha512-mx0WXDDiIl5DwzMtzWGRSPugXi9BxROS05GQrhLNbEamhBiicgn994ibwkyiBH+6png7bm/yA7AUsvHyCXi4Vw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-default-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.8.3.tgz", + "integrity": "sha512-PYtv2S2OdCdp7GSPDg5ndGZFm9DmWFvuLoS5nBxZCgOBggluLnhTScspJxng96alHQzPyrrHxvC9/w4bFuspeA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz", + "integrity": "sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.8.3.tgz", + "integrity": "sha512-UcAyQWg2bAN647Q+O811tG9MrJ38Z10jjhQdKNAL8fsyPzE3cCN/uT+f55cFVY4aGO4jqJAvmqsuY3GQDwAoXg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-default-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.8.3.tgz", + "integrity": "sha512-a1qnnsr73KLNIQcQlcQ4ZHxqqfBKM6iNQZW2OMTyxNbA2WC7SHWHtGVpFzWtQAuS2pspkWVzdEBXXx8Ik0Za4w==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz", + "integrity": "sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", + "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz", + "integrity": "sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", + "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", + "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-remap-async-to-generator": "^7.8.3" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", + "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", + "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "lodash": "^4.17.13" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz", + "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-define-map": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", + "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz", + "integrity": "sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", + "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz", + "integrity": "sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-flow": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz", + "integrity": "sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", + "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", + "requires": { + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", + "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz", + "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", + "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==", + "requires": { + "@babel/helper-module-transforms": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-simple-access": "^7.8.3", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/plugin-transform-object-assign": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.8.3.tgz", + "integrity": "sha512-i3LuN8tPDqUCRFu3dkzF2r1Nx0jp4scxtm7JxtIqI9he9Vk20YD+/zshdzR9JLsoBMlJlNR82a62vQExNEVx/Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", + "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz", + "integrity": "sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==", + "requires": { + "@babel/helper-call-delegate": "^7.8.3", + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", + "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz", + "integrity": "sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz", + "integrity": "sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g==", + "requires": { + "@babel/helper-builder-react-jsx": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz", + "integrity": "sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.8.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz", + "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==", + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz", + "integrity": "sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ==", + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "resolve": "^1.8.1", + "semver": "^5.5.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", + "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", + "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", + "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-regex": "^7.8.3" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", + "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.8.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.7.tgz", + "integrity": "sha512-7O0UsPQVNKqpHeHLpfvOG4uXmlw+MOxYvUv6Otc9uH5SYMIxvF6eBdjkWvC3f9G+VXe0RsNExyAQBeTRug/wqQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-typescript": "^7.8.3" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", + "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/register": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.8.3.tgz", + "integrity": "sha512-t7UqebaWwo9nXWClIPLPloa5pN33A2leVs8Hf0e9g9YwUP8/H9NeR7DJU+4CXo23QtjChQv5a3DjEtT83ih1rg==", + "requires": { + "find-cache-dir": "^2.0.0", + "lodash": "^4.17.13", + "make-dir": "^2.1.0", + "pirates": "^4.0.0", + "source-map-support": "^0.5.16" + } + }, + "@babel/runtime": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", + "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@callstack/react-theme-provider": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.5.tgz", + "integrity": "sha512-Iec+ybWN0FvNj87sD3oWo/49edGUP0UOSdMnzCJEFJIDYr992ECIuOV89burAAh2/ibPCxgLiK6dmgv2mO/8Tg==", + "requires": { + "deepmerge": "^3.2.0", + "hoist-non-react-statics": "^3.3.0" + }, + "dependencies": { + "deepmerge": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz", + "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA==" + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + } + } + }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "requires": { + "@types/hammerjs": "^2.0.36" + } + }, + "@hapi/address": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", + "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==" + }, + "@hapi/bourne": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz", + "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==" + }, + "@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==" + }, + "@hapi/topo": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz", + "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==", + "requires": { + "@hapi/hoek": "^8.3.0" + } + }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/core": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", + "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.9.0", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-resolve-dependencies": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "jest-watcher": "^24.9.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "slash": "^2.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", + "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.2.6", + "jest-haste-map": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.4.2", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@react-native-community/cli-platform-android": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-3.0.3.tgz", + "integrity": "sha512-rNO9DmRiVhB6aP2DVUjEJv7ecriTARDZND88ny3xNVUkrD1Y+zwF6aZu3eoT52VXOxLCSLiJzz19OiyGmfqxYg==", + "requires": { + "@react-native-community/cli-tools": "^3.0.0", + "chalk": "^2.4.2", + "execa": "^1.0.0", + "jetifier": "^1.6.2", + "logkitty": "^0.6.0", + "slash": "^3.0.0", + "xmldoc": "^1.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@react-native-community/cli-platform-ios": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-3.0.0.tgz", + "integrity": "sha512-QoNVlDj8eMXRZk9uktPFsctHurQpv9jKmiu6mQii4NEtT2npE7g1hbWpRNojutBsfgmCdQGDHd9uB54eeCnYgg==", + "requires": { + "@react-native-community/cli-tools": "^3.0.0", + "chalk": "^2.4.2", + "js-yaml": "^3.13.1", + "xcode": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@react-native-community/cli-tools": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-3.0.0.tgz", + "integrity": "sha512-8IhQKZdf3E4CR8T7HhkPGgorot/cLkRDgneJFDSWk/wCYZAuUh4NEAdumQV7N0jLSMWX7xxiWUPi94lOBxVY9g==", + "requires": { + "chalk": "^2.4.2", + "lodash": "^4.17.5", + "mime": "^2.4.1", + "node-fetch": "^2.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" + }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@react-navigation/core": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-3.5.2.tgz", + "integrity": "sha512-HgKXci1h74aETgm5CXMBoIWG8R7VZG1eUUHYb3BdxwekdiZjW1P/srjiXzsCqFGlsESnVIOIkzT4DqI9J752Bw==", + "requires": { + "hoist-non-react-statics": "^3.3.0", + "path-to-regexp": "^1.7.0", + "query-string": "^6.4.2", + "react-is": "^16.8.6" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + } + } + }, + "@react-navigation/native": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-3.6.5.tgz", + "integrity": "sha512-ttEmnokFVf09CvrkzlPIdfA693KfYcRxTYf9OZwp0Ll6El27UYjJD4arwGc+zvlohjTErCdba6CAKV702Wv28w==", + "requires": { + "hoist-non-react-statics": "^3.3.2", + "react-native-safe-area-view": "^0.14.8" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + } + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz", + "integrity": "sha512-j7KnilGyZzYr/jhcrSYS3FGWMZVaqyCG0vzMCwzvei0coIkczuYMcniK07nI0aHJINciujjH11T72ICW5eL5Ig==", + "dev": true + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-4.2.0.tgz", + "integrity": "sha512-3XHLtJ+HbRCH4n28S7y/yZoEQnRpl0tvTZQsHqvaeNXPra+6vE5tbRliH3ox1yZYPCxrlqaJT/Mg+75GpDKlvQ==", + "dev": true + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-4.2.0.tgz", + "integrity": "sha512-yTr2iLdf6oEuUE9MsRdvt0NmdpMBAkgK8Bjhl6epb+eQWk6abBaX3d65UZ3E3FWaOwePyUgNyNCMVG61gGCQ7w==", + "dev": true + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.2.0.tgz", + "integrity": "sha512-U9m870Kqm0ko8beHawRXLGLvSi/ZMrl89gJ5BNcT452fAjtF2p4uRzXkdzvGJJJYBgx7BmqlDjBN/eCp5AAX2w==", + "dev": true + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.3.3.tgz", + "integrity": "sha512-w3Be6xUNdwgParsvxkkeZb545VhXEwjGMwExMVBIdPQJeyMQHqm9Msnb2a1teHBqUYL66qtwfhNkbj1iarCG7w==", + "dev": true + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-4.2.0.tgz", + "integrity": "sha512-C0Uy+BHolCHGOZ8Dnr1zXy/KgpBOkEUYY9kI/HseHVPeMbluaX3CijJr7D4C5uR8zrc1T64nnq/k63ydQuGt4w==", + "dev": true + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-4.2.0.tgz", + "integrity": "sha512-7YvynOpZDpCOUoIVlaaOUU87J4Z6RdD6spYN4eUb5tfPoKGSF9OG2NuhgYnq4jSkAxcpMaXWPf1cePkzmqTPNw==", + "dev": true + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.2.0.tgz", + "integrity": "sha512-hYfYuZhQPCBVotABsXKSCfel2slf/yvJY8heTVX1PCTaq/IgASq1IyxPPKJ0chWREEKewIU/JMSsIGBtK1KKxw==", + "dev": true + }, + "@svgr/babel-preset": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-4.3.3.tgz", + "integrity": "sha512-6PG80tdz4eAlYUN3g5GZiUjg2FMcp+Wn6rtnz5WJG9ITGEF1pmFdzq02597Hn0OmnQuCVaBYQE1OVFAnwOl+0A==", + "dev": true, + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^4.2.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^4.2.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^4.2.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^4.2.0", + "@svgr/babel-plugin-svg-dynamic-title": "^4.3.3", + "@svgr/babel-plugin-svg-em-dimensions": "^4.2.0", + "@svgr/babel-plugin-transform-react-native-svg": "^4.2.0", + "@svgr/babel-plugin-transform-svg-component": "^4.2.0" + } + }, + "@svgr/core": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-4.3.3.tgz", + "integrity": "sha512-qNuGF1QON1626UCaZamWt5yedpgOytvLj5BQZe2j1k1B8DUG4OyugZyfEwBeXozCUwhLEpsrgPrE+eCu4fY17w==", + "dev": true, + "requires": { + "@svgr/plugin-jsx": "^4.3.3", + "camelcase": "^5.3.1", + "cosmiconfig": "^5.2.1" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.3.2.tgz", + "integrity": "sha512-JioXclZGhFIDL3ddn4Kiq8qEqYM2PyDKV0aYno8+IXTLuYt6TOgHUbUAAFvqtb0Xn37NwP0BTHglejFoYr8RZg==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@svgr/plugin-jsx": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-4.3.3.tgz", + "integrity": "sha512-cLOCSpNWQnDB1/v+SUENHH7a0XY09bfuMKdq9+gYvtuwzC2rU4I0wKGFEp1i24holdQdwodCtDQdFtJiTCWc+w==", + "dev": true, + "requires": { + "@babel/core": "^7.4.5", + "@svgr/babel-preset": "^4.3.3", + "@svgr/hast-util-to-babel-ast": "^4.3.2", + "svg-parser": "^2.0.0" + } + }, + "@svgr/plugin-svgo": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-4.3.1.tgz", + "integrity": "sha512-PrMtEDUWjX3Ea65JsVCwTIXuSqa3CG9px+DluF1/eo9mlDrgrtFE7NE/DjdhjJgSM9wenlVBzkzneSIUgfUI/w==", + "dev": true, + "requires": { + "cosmiconfig": "^5.2.1", + "merge-deep": "^3.0.2", + "svgo": "^1.2.2" + } + }, + "@types/babel__core": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", + "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz", + "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz", + "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/color": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.1.tgz", + "integrity": "sha512-oeUWVaAwI+xINDUx+3F2vJkl/vVB03VChFF/Gl3iQCdbcakjuoJyMOba+3BXRtnBhxZ7uBYqQBi9EpLnvSoztA==", + "dev": true, + "requires": { + "@types/color-convert": "*" + } + }, + "@types/color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha512-OKGEfULrvSL2VRbkl/gnjjgbbF7ycIlpSsX7Nkab4MOWi5XxmgBYvuiQ7lcCFY5cPDz7MUNaKgxte2VRmtr4Fg==", + "dev": true, + "requires": { + "@types/color-name": "*" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "@types/hammerjs": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz", + "integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ==" + }, + "@types/i18n-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/i18n-js/-/i18n-js-3.0.1.tgz", + "integrity": "sha512-m7tWPh9zKpQoYenIpkmeREb2oMaZiZB8qfGv+2ucDg1LgFnETAxYIXkT8dASGyVRWZyEhNEPlfODP4+QfXI3KQ==", + "dev": true + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==" + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.9.1.tgz", + "integrity": "sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q==", + "dev": true, + "requires": { + "jest-diff": "^24.3.0" + } + }, + "@types/jwt-decode": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/jwt-decode/-/jwt-decode-2.2.1.tgz", + "integrity": "sha512-aWw2YTtAdT7CskFyxEX2K21/zSDStuf/ikI3yBqmwpwJF0pS+/IX5DWv+1UFffZIbruP6cnT9/LAJV1gFwAT1A==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", + "dev": true + }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" + }, + "@types/q": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", + "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", + "dev": true + }, + "@types/react": { + "version": "16.9.22", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.22.tgz", + "integrity": "sha512-7OSt4EGiLvy0h5R7X+r0c7S739TCU/LvWbkNOrm10lUwNHe7XPz5OLhLOSZeCkqO9JSCly1NkYJ7ODTUqVnHJQ==", + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "@types/react-dom": { + "version": "16.9.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.5.tgz", + "integrity": "sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/react-native": { + "version": "0.60.31", + "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.60.31.tgz", + "integrity": "sha512-Y0Q+nv50KHnLL+jM0UH68gQQv7Wt6v2KuNepiHKwK1DoWGVd1oYun/GJCnvUje+/V8pMQQWW6QuBvHZz1pV7tQ==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/react": "*" + } + }, + "@types/react-native-htmlview": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/react-native-htmlview/-/react-native-htmlview-0.12.2.tgz", + "integrity": "sha512-r5lWdZcZmcxLrfhIAAzBCEpDUuDFRiB5V9d0QvCqhTRh9vorlEjXgyZ5K8/HzbIOuvGb9/mQJPK0rItEAQk0dw==", + "dev": true, + "requires": { + "@types/react": "*", + "@types/react-native": "*" + } + }, + "@types/react-native-vector-icons": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.5.tgz", + "integrity": "sha512-JBpcjWQE4n0GlE0p6HpDDclT+uXpFC453T5k4h+B38q0utlGJhvgNr8899BoJGc1xOktA2cgqFKmFMJd0h7YaA==", + "requires": { + "@types/react": "*", + "@types/react-native": "*" + }, + "dependencies": { + "@types/react-native": { + "version": "0.61.12", + "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.61.12.tgz", + "integrity": "sha512-9Do0pTN9H3hnon0LUCTqIC5fCmFpKU5V8rJEH2iAAsCRm8+2Q7zPUMKuCaSRbO5zhXMW5oC8IE0nCfg1kqyXvw==", + "requires": { + "@types/react": "*" + } + } + } + }, + "@types/react-test-renderer": { + "version": "16.9.2", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.2.tgz", + "integrity": "sha512-4eJr1JFLIAlWhzDkBCkhrOIWOvOxcCAfQh+jiKg7l/nNZcCIL2MHl2dZhogIFKyHzedVWHaVP1Yydq/Ruu4agw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==" + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==" + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "abab": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", + "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", + "dev": true + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "absolute-path": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/absolute-path/-/absolute-path-0.0.0.tgz", + "integrity": "sha1-p4di+9rftSl76ZsV01p4Wy8JW/c=" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true + }, + "add": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/add/-/add-2.0.6.tgz", + "integrity": "sha1-JI8Kn25aUo7yKV2+7DBTITCuIjU=" + }, + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "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.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 + }, + "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" + } + } + } + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "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=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + }, + "ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "requires": { + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=" + }, + "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-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=" + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=" + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "art": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/art/-/art-0.10.3.tgz", + "integrity": "sha512-HXwbdofRTiJT6qZX/FnchtldzJjS3vkLJxQilc3Xj+ma2MXjY4UAyQ0ls1XZYVnDvVIBiFZbC6QsvtW86TD6tQ==" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "dev": true + }, + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "requires": { + "follow-redirects": "1.5.10" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + } + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } + }, + "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.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "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.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "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.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "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.22.0", + "babel-types": "^6.24.1" + } + }, + "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.22.0", + "babel-types": "^6.24.1" + } + }, + "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.22.0", + "babel-types": "^6.24.1" + } + }, + "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.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", + "dev": true, + "requires": { + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-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.22.0" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-plugin-react-transform": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-react-transform/-/babel-plugin-react-transform-2.0.2.tgz", + "integrity": "sha1-UVu/qZaJOYEULZCx+bFjXeKZUQk=", + "dev": true, + "requires": { + "lodash": "^4.6.1" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", + "dev": true + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", + "dev": true + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", + "dev": true + }, + "babel-plugin-syntax-do-expressions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", + "dev": true + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true + }, + "babel-plugin-syntax-function-bind": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", + "dev": true + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "7.0.0-beta.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", + "integrity": "sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==" + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "dev": true, + "requires": { + "babel-plugin-syntax-class-constructor-call": "^6.18.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-decorators-legacy": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz", + "integrity": "sha512-jYHwjzRXRelYQ1uGm353zNzf3QmtdCfvJbuYTZ4gKveK7M9H1fs3a5AKdY1JUDl0z97E30ukORW1dzhWvsabtA==", + "dev": true, + "requires": { + "babel-plugin-syntax-decorators": "^6.1.18", + "babel-runtime": "^6.2.0", + "babel-template": "^6.3.0" + } + }, + "babel-plugin-transform-do-expressions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", + "dev": true, + "requires": { + "babel-plugin-syntax-do-expressions": "^6.8.0", + "babel-runtime": "^6.22.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.22.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.4" + } + }, + "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.24.1", + "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.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "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.22.0", + "babel-template": "^6.24.1" + } + }, + "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.22.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.22.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.22.0", + "babel-types": "^6.24.1" + } + }, + "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.22.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "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-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.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "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.22.0", + "babel-types": "^6.24.1" + } + }, + "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.22.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.22.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "dev": true, + "requires": { + "babel-plugin-syntax-export-extensions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "^6.18.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-function-bind": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", + "dev": true, + "requires": { + "babel-plugin-syntax-function-bind": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-object-assign": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz", + "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.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.0" + }, + "dependencies": { + "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.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + } + } + }, + "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.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-preset-fbjs": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.3.0.tgz", + "integrity": "sha512-7QTLTCd2gwB2qGoi5epSULMHugSVgpcVt5YAeiFO9ABLrutDQzKfGwzxgZHLpugq8qMdg/DhRZDZ5CLKxBkEbw==", + "requires": { + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-class-properties": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-block-scoped-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-member-expression-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-property-literals": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "babel-plugin-syntax-trailing-function-commas": "^7.0.0-beta.0" + } + }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, + "babel-preset-react-native": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/babel-preset-react-native/-/babel-preset-react-native-1.9.2.tgz", + "integrity": "sha1-sird0uNV/zs5Zxt5voB+Ut+hRfI=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.5.0", + "babel-plugin-react-transform": "2.0.2", + "babel-plugin-syntax-async-functions": "^6.5.0", + "babel-plugin-syntax-class-properties": "^6.5.0", + "babel-plugin-syntax-flow": "^6.5.0", + "babel-plugin-syntax-jsx": "^6.5.0", + "babel-plugin-syntax-trailing-function-commas": "^6.5.0", + "babel-plugin-transform-class-properties": "^6.5.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.5.0", + "babel-plugin-transform-es2015-block-scoping": "^6.5.0", + "babel-plugin-transform-es2015-classes": "^6.5.0", + "babel-plugin-transform-es2015-computed-properties": "^6.5.0", + "babel-plugin-transform-es2015-destructuring": "^6.5.0", + "babel-plugin-transform-es2015-for-of": "^6.5.0", + "babel-plugin-transform-es2015-function-name": "^6.5.0", + "babel-plugin-transform-es2015-literals": "^6.5.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.5.0", + "babel-plugin-transform-es2015-parameters": "^6.5.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.5.0", + "babel-plugin-transform-es2015-spread": "^6.5.0", + "babel-plugin-transform-es2015-template-literals": "^6.5.0", + "babel-plugin-transform-flow-strip-types": "^6.5.0", + "babel-plugin-transform-object-assign": "^6.5.0", + "babel-plugin-transform-object-rest-spread": "^6.5.0", + "babel-plugin-transform-react-display-name": "^6.5.0", + "babel-plugin-transform-react-jsx": "^6.5.0", + "babel-plugin-transform-react-jsx-source": "^6.5.0", + "babel-plugin-transform-regenerator": "^6.5.0", + "react-transform-hmr": "^1.0.4" + }, + "dependencies": { + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + } + } + }, + "babel-preset-react-native-stage-0": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-native-stage-0/-/babel-preset-react-native-stage-0-1.0.1.tgz", + "integrity": "sha1-1fX2hVdUce91aknxkbGTJp90MG4=", + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "^6.5.0", + "babel-plugin-transform-class-constructor-call": "^6.6.5", + "babel-plugin-transform-decorators-legacy": "^1.3.4", + "babel-plugin-transform-do-expressions": "^6.5.0", + "babel-plugin-transform-exponentiation-operator": "^6.5.0", + "babel-plugin-transform-export-extensions": "^6.5.0", + "babel-plugin-transform-function-bind": "^6.5.2", + "babel-preset-react-native": "^1.5.6" + }, + "dependencies": { + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "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.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "blueimp-md5": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.12.0.tgz", + "integrity": "sha512-zo+HIdIhzojv6F1siQPqPFROyVy7C50KzHv/k/Iz+BtvtVzSHXiMXOpq2wCfNkeBqdCv+V8XOV96tsEt2W/3rQ==" + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "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.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "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" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "bplist-creator": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz", + "integrity": "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==", + "requires": { + "stream-buffers": "~2.2.0" + } + }, + "bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "requires": { + "big-integer": "^1.6.44" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "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 + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-id": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-id/-/caller-id-0.1.0.tgz", + "integrity": "sha1-Wb2sCJPRLDhxQIJ5Ix+XRYNk8Hs=", + "requires": { + "stack-trace": "~0.0.7" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsite-record": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/callsite-record/-/callsite-record-3.2.2.tgz", + "integrity": "sha1-mgOQZC5D/ou4I5ReUUZPafQWQ94=", + "dev": true, + "requires": { + "callsite": "^1.0.0", + "chalk": "^1.1.1", + "error-stack-parser": "^1.3.3", + "highlight-es": "^1.0.0", + "lodash": "4.6.1 || ^4.16.1", + "pinkie-promise": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "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.0.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "requires": { + "rsvp": "^4.8.4" + } + }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz", + "integrity": "sha1-UJr7ZwZudJn36zU1x3RFdyri0Bk=", + "requires": { + "ansi-styles": "^2.1.0", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "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=" + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "clamp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", + "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ=" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "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-spinners": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.2.0.tgz", + "integrity": "sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ==" + }, + "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": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "clone-deep": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", + "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", + "dev": true, + "requires": { + "for-own": "^0.1.3", + "is-plain-object": "^2.0.1", + "kind-of": "^3.0.2", + "lazy-cache": "^1.0.3", + "shallow-clone": "^0.1.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "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=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", + "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "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==" + }, + "colorette": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.1.0.tgz", + "integrity": "sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "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-react-class": { + "version": "15.6.3", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", + "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", + "requires": { + "fbjs": "^0.8.9", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, + "cross-env": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-6.0.3.tgz", + "integrity": "sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "cross-spawn-async": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", + "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", + "dev": true, + "requires": { + "lru-cache": "^4.0.0", + "which": "^1.2.8" + } + }, + "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-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", + "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", + "requires": { + "mdn-data": "2.0.6", + "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==" + } + } + }, + "css-what": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", + "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==" + }, + "csso": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.2.tgz", + "integrity": "sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg==", + "dev": true, + "requires": { + "css-tree": "1.0.0-alpha.37" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "csstype": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz", + "integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==" + }, + "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.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "dayjs": { + "version": "1.8.20", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.20.tgz", + "integrity": "sha512-mH0MCDxw6UCGJYxVN78h8ugWycZAO8thkj3bW6vApL5tS0hQplIDdAQcmbvl7n35H0AKdCJQaArTrIQw2xt4Qg==" + }, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", + "dev": true + }, + "debounce": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", + "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==" + }, + "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" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "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=", + "dev": true + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "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 + }, + "denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=" + }, + "depcheck": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-0.8.3.tgz", + "integrity": "sha512-xcLTnaovCFFTts5Ge7mUUhMGHSu6eRfftvVvOjN7gXO5EFUhJfX6UQa1b08a0SIwKfzG9eKNn5mzZlXp0mZARA==", + "dev": true, + "requires": { + "@babel/parser": "^7.3.1", + "@babel/traverse": "^7.2.3", + "builtin-modules": "^3.0.0", + "deprecate": "^1.0.0", + "deps-regex": "^0.1.4", + "js-yaml": "^3.4.2", + "lodash": "^4.17.11", + "minimatch": "^3.0.2", + "node-sass-tilde-importer": "^1.0.2", + "please-upgrade-node": "^3.1.1", + "require-package-name": "^2.0.1", + "resolve": "^1.10.0", + "vue-template-compiler": "^2.6.10", + "walkdir": "^0.3.2", + "yargs": "^13.2.2" + }, + "dependencies": { + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + } + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "deprecate": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deprecate/-/deprecate-1.1.1.tgz", + "integrity": "sha512-ZGDXefq1xknT292LnorMY5s8UVU08/WKdzDZCUT6t9JzsiMSP4uzUhgpqugffNVcT5WC6wMBiSQ+LFjlv3v7iQ==", + "dev": true + }, + "deps-regex": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.1.4.tgz", + "integrity": "sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "didyoumean": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.1.tgz", + "integrity": "sha1-6S7f2tplN9SE1zwBcv0eugxJdv8=" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==" + }, + "entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==" + } + } + }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "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", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "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.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + } + } + }, + "error-stack-parser": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-1.3.6.tgz", + "integrity": "sha1-4Oc7k+QXE40c18C3RrGkoUhUwpI=", + "dev": true, + "requires": { + "stackframe": "^0.3.1" + } + }, + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-template": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/es6-template/-/es6-template-1.0.4.tgz", + "integrity": "sha1-Vq9CtXox9RddP1Z9RLHvwS0vJjY=", + "dev": true, + "requires": { + "es6-template-regex": "^0.1.1", + "extend-shallow": "^2.0.1", + "get-value": "^2.0.2", + "lazy-cache": "^1.0.3", + "mkdirp": "^0.5.1", + "sliced": "^1.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "es6-template-regex": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/es6-template-regex/-/es6-template-regex-0.1.1.tgz", + "integrity": "sha1-5Re54PdCvuuNMECDRUT9oORlFGc=", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", + "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "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, + "optional": true + } + } + }, + "eslint-config-prettier": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.10.0.tgz", + "integrity": "sha512-AtndijGte1rPILInUdHjvKEGbIV06NuvPrqlIEaEaWtbtvJh464mDeyGMdZEQMsGvC0ZVkiex1fSNcC4HAbRGg==", + "requires": { + "get-stdin": "^6.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "eventemitter2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-1.0.5.tgz", + "integrity": "sha1-+YNhBRexc3wLncZDvsqTiTwE3xg=" + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" + }, + "exec-sh": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", + "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==" + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "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" + } + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "requires": { + "bser": "2.1.1" + } + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + }, + "fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + }, + "fbjs-scripts": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fbjs-scripts/-/fbjs-scripts-1.2.0.tgz", + "integrity": "sha512-5krZ8T0Bf8uky0abPoCLrfa7Orxd8UH4Qq8hRUF2RZYNMu+FmEOrBc7Ib3YVONmxTXTlLAvyrrdrVmksDb2OqQ==", + "requires": { + "@babel/core": "^7.0.0", + "ansi-colors": "^1.0.1", + "babel-preset-fbjs": "^3.2.0", + "core-js": "^2.4.1", + "cross-spawn": "^5.1.0", + "fancy-log": "^1.3.2", + "object-assign": "^4.0.1", + "plugin-error": "^0.1.2", + "semver": "^5.1.0", + "through2": "^2.0.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + }, + "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.9" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "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-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "find-yarn-workspace-root": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", + "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", + "dev": true, + "requires": { + "fs-extra": "^4.0.3", + "micromatch": "^3.1.4" + }, + "dependencies": { + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + } + } + }, + "flow-bin": { + "version": "0.105.2", + "resolved": "https://registry.npmjs.org/flow-bin/-/flow-bin-0.105.2.tgz", + "integrity": "sha512-VCHt0SCjFPviv/Ze/W7AgkcE0uH4TocypSFA8wR3ZH1P7BSjny4l3uhHyOjzU3Qo1i0jO4NyaU6q3Y5IaQ6xng==", + "dev": true + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "optional": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.7.1", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "giturl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/giturl/-/giturl-1.0.1.tgz", + "integrity": "sha512-wQourBdI13n8tbjcZTDl6k+ZrCRMU6p9vfp9jknZq+zfWc8xXNztpZFM4XkPHVzHcMSUZxEMYYKZjIGkPlei6Q==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dev": true, + "requires": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "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.2.14" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "globby": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-4.1.0.tgz", + "integrity": "sha1-CA9UVJ7BuCpsYOYx/ILhIR2+lfg=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^6.0.1", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "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.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "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-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hermes-engine": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/hermes-engine/-/hermes-engine-0.2.1.tgz", + "integrity": "sha512-eNHUQHuadDMJARpaqvlCZoK/Nitpj6oywq3vQ3wCwEsww5morX34mW5PmKWQTO7aU0ck0hgulxR+EVDlXygGxQ==" + }, + "highlight-es": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/highlight-es/-/highlight-es-1.0.3.tgz", + "integrity": "sha512-s/SIX6yp/5S1p8aC/NRDC1fwEb+myGIfp8/TzZz0rtAv8fzsdX7vGl3Q1TrXCsczFq8DI3CBFBCySPClfBSdbg==", + "dev": true, + "requires": { + "chalk": "^2.4.0", + "is-es2016-keyword": "^1.0.0", + "js-tokens": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "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 + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "hoist-non-react-statics": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", + "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=" + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==" + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "html-escaper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", + "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", + "dev": true + }, + "htmlparser2-without-node-native": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2-without-node-native/-/htmlparser2-without-node-native-3.9.2.tgz", + "integrity": "sha1-s+0FDYd9D/NGWWnjOYd7f59mMfY=", + "requires": { + "domelementtype": "^1.3.0", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "eventemitter2": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "i18n-js": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.5.1.tgz", + "integrity": "sha512-nJgbE5Vj9qzOQfjdVd/uoMoO8ppVaB/3LB6KOmMfD8IQ1vNNh307iHyQLK8ZnLYWkAszfPvVpYmUt1Le/RuHMQ==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "image-size": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", + "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==" + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "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.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + }, + "is-es2016-keyword": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-es2016-keyword/-/is-es2016-keyword-1.0.0.tgz", + "integrity": "sha1-9uVOEQxeT40mXmnS7Q6vjPX0dxg=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "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=" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "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": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "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.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "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.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.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 + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0" + } + }, + "jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", + "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.9.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "jest-cli": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", + "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", + "dev": true, + "requires": { + "@jest/core": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^13.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-changed-files": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", + "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==" + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", + "dev": true, + "requires": { + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "requires": { + "@jest/types": "^24.9.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "dev": true + }, + "jest-react-native": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/jest-react-native/-/jest-react-native-18.0.0.tgz", + "integrity": "sha1-d92QnwaTJFmfInxYxhwuYhaHJro=" + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", + "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.9.0" + } + }, + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==" + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "requires": { + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "requires": { + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-watcher": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", + "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.9.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jetifier": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/jetifier/-/jetifier-1.6.5.tgz", + "integrity": "sha512-T7yzBSu9PR+DqjYt+I0KVO1XTb1QhAfHnXV5Nd3xpbXM6Xg4e3vP60Q4qkNU8Fh6PHC2PivPUNN3rY7G2MxcDQ==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsc-android": { + "version": "245459.0.0", + "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-245459.0.0.tgz", + "integrity": "sha512-wkjURqwaB1daNkDi2OYYbsLnIdC/lUM2nPXQKRs5pqEU9chDg435bjvo+LSaHotDENygHQDHe+ntUkkw2gwMtg==" + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "~0.0.0" + } + }, + "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 + }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jwt-decode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", + "integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "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.0" + } + }, + "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=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "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=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "load-yaml-file": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.1.1.tgz", + "integrity": "sha512-G910TofXH7u0NfslAzqv6c9pHpvBzObNOo2hMG0/KUDpdHeFY0wE/fTBMExt0Gb12gg5bXS7Hj6pb0e+xbBXLA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.5", + "js-yaml": "^3.13.0", + "pify": "^2.3.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "^2.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "logkitty": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.6.1.tgz", + "integrity": "sha512-cHuXN8qUZuzX/7kB6VyS7kB4xyD24e8gyHXIFNhIv+fjW3P+jEXNUhj0o/7qWJtv7UZpbnPgUqzu/AZQ8RAqxQ==", + "requires": { + "ansi-fragments": "^0.2.1", + "dayjs": "^1.8.15", + "yargs": "^12.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "requires": { + "invert-kv": "^2.0.0" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "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=" + }, + "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" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "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" + } + } + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "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.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "requires": { + "tmpl": "1.0.x" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "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=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", + "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==" + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "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.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.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.0.0", + "pinkie-promise": "^2.0.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.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "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.2.0" + } + }, + "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.0" + } + }, + "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.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "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.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.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.0.0", + "read-pkg": "^1.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.0" + } + } + } + }, + "merge-deep": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.2.tgz", + "integrity": "sha512-T7qC8kg4Zoti1cFd8Cr0M+qaZfOwjlPDEdZIIPPB2JZctjaPM4fX+i7HOId69tAti2fvO6X5ldfYUONDODsrkA==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "clone-deep": "^0.2.4", + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "requires": { + "readable-stream": "^2.0.1" + } + }, + "metro-babel-register": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-babel-register/-/metro-babel-register-0.56.4.tgz", + "integrity": "sha512-Phm6hMluOWYqfykftjJ1jsTpWvbgb49AC/1taxEctxUdRCZlFgZwBleJZAhQYxJD5J+ikFkEbHDzePEXb29KVA==", + "requires": { + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/register": "^7.0.0", + "core-js": "^2.2.2", + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + } + } + }, + "metro-babel-transformer": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.56.4.tgz", + "integrity": "sha512-IOi4ILgZvaX7GCGHBJp79paNVOq5QxhhbyqAdEJgDP8bHfl/OVHoVKSypfrsMSKSiBrqxhIjyc4XjkXsQtkx5g==", + "requires": { + "@babel/core": "^7.0.0", + "metro-source-map": "^0.56.4" + } + }, + "metro-cache": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.56.4.tgz", + "integrity": "sha512-d1hiUSKwtRsuMxUhHVJ3tjK2BbpUlJGvTyMWohK8Wxx+0GbnWRWWFcI4vlCzlZfoK0VtZK2MJEl5t7Du1mIniQ==", + "requires": { + "jest-serializer": "^24.4.0", + "metro-core": "^0.56.4", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4" + } + }, + "metro-core": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.56.4.tgz", + "integrity": "sha512-hMzkBdgPt5Zm9nr/1KtIT+A6H7TNiLVCEGG5OiAXj8gTRsA2yy7wAdQpwy0xbE+zi88t/pLOzXpd3ClG/YxyWg==", + "requires": { + "jest-haste-map": "^24.7.1", + "lodash.throttle": "^4.1.1", + "metro-resolver": "^0.56.4", + "wordwrap": "^1.0.0" + } + }, + "metro-inspector-proxy": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-inspector-proxy/-/metro-inspector-proxy-0.56.4.tgz", + "integrity": "sha512-E1S3MO25mWKmcLn1UQuCDiS0hf9P2Fwq8sEAX5lBLoZbehepNH+4xJ3xXSY51JX4dozBrE8GGoKL4ll3II40LA==", + "requires": { + "connect": "^3.6.5", + "debug": "^2.2.0", + "rxjs": "^5.4.3", + "ws": "^1.1.5", + "yargs": "^9.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=" + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "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=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "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=" + }, + "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" + } + } + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.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.0.0", + "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=", + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "metro-minify-uglify": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-minify-uglify/-/metro-minify-uglify-0.56.4.tgz", + "integrity": "sha512-BHgj7+BKEK2pHvWHUR730bIrsZwl8DPtr49x9L0j2grPZ5/UROWXzEr8VZgIss7fl64t845uu1HXNNyuSj2EhA==", + "requires": { + "uglify-es": "^3.1.9" + } + }, + "metro-react-native-babel-preset": { + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.56.0.tgz", + "integrity": "sha512-MAo1fm0dNn6MVZmylaz6k2HC1MINHLTLfE7O3a9Xz3fAtbGbApisp06rBUfK5uUqIJDmAaKgbiT34lHJSIiE6Q==", + "dev": true, + "requires": { + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-assign": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.0.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "react-refresh": "^0.4.0" + } + }, + "metro-react-native-babel-transformer": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.56.4.tgz", + "integrity": "sha512-ng74eutuy1nyGI9+TDzzVAVfEmNPDlapV4msTQMKPi4EFqo/fBn7Ct33ME9l5E51pQBBnxt/UwcpTvd13b29kQ==", + "requires": { + "@babel/core": "^7.0.0", + "babel-preset-fbjs": "^3.1.2", + "metro-babel-transformer": "^0.56.4", + "metro-react-native-babel-preset": "^0.56.4", + "metro-source-map": "^0.56.4" + }, + "dependencies": { + "metro-react-native-babel-preset": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.56.4.tgz", + "integrity": "sha512-CzbBDM9Rh6w8s1fq+ZqihAh7DDqUAcfo9pPww25+N/eJ7UK436Q7JdfxwdIPpBwLFn6o6MyYn+uwL9OEWBJarA==", + "requires": { + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-assign": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.0.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "react-refresh": "^0.4.0" + } + } + } + }, + "metro-resolver": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.56.4.tgz", + "integrity": "sha512-Ug4ulVfpkKZ1Wu7mdYj9XLGuOqZTuWCqEhyx3siKTc/2eBwKZQXmiNo5d/IxWNvmwL/87Abeb724I6CMzMfjiQ==", + "requires": { + "absolute-path": "^0.0.0" + } + }, + "metro-source-map": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.56.4.tgz", + "integrity": "sha512-f1P9/rpFmG3Z0Jatiw2zvLItx1TwR7mXTSDj4qLDCWeVMB3kEXAr3R0ucumTW8c6HfpJljeRBWzYFXF33fd81g==", + "requires": { + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "invariant": "^2.2.4", + "metro-symbolicate": "^0.56.4", + "ob1": "^0.56.4", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + } + }, + "metro-symbolicate": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.56.4.tgz", + "integrity": "sha512-8mCNNn6zV5FFKCIcRgI7736Xl+owgvYuy8qanPxZN36f7utiWRYeB+PirEBPcglBk4qQvoy2lT6oPULNXZQbbQ==", + "requires": { + "invariant": "^2.2.4", + "metro-source-map": "^0.56.4", + "source-map": "^0.5.6", + "through2": "^2.0.1", + "vlq": "^1.0.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "requires": { + "mime-db": "1.43.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "requires": { + "dom-walk": "^0.1.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "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.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } + } + }, + "mkdirp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", + "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", + "requires": { + "minimist": "^1.2.5" + } + }, + "mock-require": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-2.0.2.tgz", + "integrity": "sha1-HqpxqtIwE3c9En3H6Ro/u0g31g0=", + "requires": { + "caller-id": "^0.1.0" + } + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "native-base": { + "version": "2.13.8", + "resolved": "https://registry.npmjs.org/native-base/-/native-base-2.13.8.tgz", + "integrity": "sha512-47Wm7bjH5Dc99gBUeVvsURyADU97aiLMLPGX4ewPgR9kW47TD9slS/Y5vGMToBgz1bsku9anXgN2T1rpdQbpFA==", + "requires": { + "blueimp-md5": "^2.5.0", + "clamp": "^1.0.1", + "color": "~3.1.2", + "create-react-class": "^15.6.3", + "eslint-config-prettier": "^6.0.0", + "fs-extra": "^2.0.0", + "jest-react-native": "^18.0.0", + "lodash": "^4.17.14", + "native-base-shoutem-theme": "0.3.1", + "opencollective-postinstall": "^2.0.2", + "print-message": "^2.1.0", + "prop-types": "^15.5.10", + "react-native-drawer": "2.5.1", + "react-native-easy-grid": "0.2.2", + "react-native-keyboard-aware-scroll-view": "0.9.1", + "react-native-vector-icons": "^6.6.0", + "react-timer-mixin": "^0.13.4", + "react-tween-state": "^0.1.5", + "tween-functions": "^1.0.1" + } + }, + "native-base-shoutem-theme": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/native-base-shoutem-theme/-/native-base-shoutem-theme-0.3.1.tgz", + "integrity": "sha512-uwEGhg6gwDuJTHuhNXRKbHtNjni1UI9qfAsVchIqfK7mQAHSNPVU1QRs9Hw6O2K/qLZaP/aJmNoZGc2h2EGSwA==", + "requires": { + "hoist-non-react-statics": "^1.0.5", + "lodash": "^4.17.14", + "prop-types": "^15.5.10" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node-emoji": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", + "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", + "dev": true, + "requires": { + "lodash.toarray": "^4.4.0" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=" + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "node-sass-tilde-importer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/node-sass-tilde-importer/-/node-sass-tilde-importer-1.0.2.tgz", + "integrity": "sha512-Swcmr38Y7uB78itQeBm3mThjxBy9/Ah/ykPIaURY/L6Nec9AyRoL/jJ7ECfMR+oZeCTVQNxVMu/aHU+TLRVbdg==", + "dev": true, + "requires": { + "find-parent-dir": "^0.3.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-check": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/npm-check/-/npm-check-5.9.2.tgz", + "integrity": "sha512-YlTZGP1A8+Rad5wldGil9STYxgZpZl18X6GZI03f4Ch6qTI1TLHIYM0ISco19qgg8M3UHfooEqMfYOpOkF3AeA==", + "dev": true, + "requires": { + "babel-runtime": "^6.6.1", + "callsite-record": "^3.0.0", + "chalk": "^1.1.3", + "co": "^4.6.0", + "depcheck": "0.8.3", + "execa": "^0.2.2", + "giturl": "^1.0.0", + "global-modules": "^1.0.0", + "globby": "^4.0.0", + "inquirer": "^0.12.0", + "is-ci": "^1.0.8", + "lodash": "^4.17.15", + "meow": "^3.7.0", + "minimatch": "^3.0.2", + "node-emoji": "^1.0.3", + "ora": "^0.2.1", + "package-json": "^4.0.1", + "path-exists": "^2.1.0", + "pkg-dir": "^1.0.0", + "preferred-pm": "^1.0.1", + "semver": "^5.0.1", + "semver-diff": "^2.0.0", + "text-table": "^0.2.0", + "throat": "^2.0.2", + "update-notifier": "^2.1.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", + "dev": true + }, + "execa": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", + "integrity": "sha1-4urUcsLDGq1vc/GslW7vReEjIMs=", + "dev": true, + "requires": { + "cross-spawn-async": "^2.1.1", + "npm-run-path": "^1.0.0", + "object-assign": "^4.0.1", + "path-key": "^1.0.0", + "strip-eof": "^1.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "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.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=", + "dev": true, + "requires": { + "path-key": "^1.0.0" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "cli-cursor": "^1.0.2", + "cli-spinners": "^0.1.2", + "object-assign": "^4.0.1" + } + }, + "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.0" + } + }, + "path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=", + "dev": true + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "^1.0.0" + } + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "^1.3.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "throat": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-2.0.2.tgz", + "integrity": "sha1-qfzoCLaeEzpjJZB4DzQsMKYkmwI=", + "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=", + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, + "nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==" + }, + "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=" + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "ob1": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.56.4.tgz", + "integrity": "sha512-URgFof9z2wotiYFsqlydXtQfGV81gvBI2ODy64xfd3vPo+AYom5PVDX4t4zn23t/O+S2IxqApSQM8uJAybmz7w==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz", + "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==" + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "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", + "word-wrap": "~1.2.3" + } + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.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=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + } + } + }, + "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=" + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" + }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "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.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + }, + "dependencies": { + "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 + }, + "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.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "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.1" + } + } + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" + }, + "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 + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "patch-package": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.2.0.tgz", + "integrity": "sha512-HWlQflaBBMjLBfOWomfolF8aqsFDeNbSNro1JDUgYqnVvPM5OILJ9DQdwIRiKmGaOsmHvhkl1FYkvv1I9r2ZJw==", + "dev": true, + "requires": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^1.2.1", + "fs-extra": "^7.0.1", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.0", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "update-notifier": "^2.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "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=" + } + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "plist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", + "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", + "requires": { + "base64-js": "^1.2.3", + "xmlbuilder": "^9.0.7", + "xmldom": "0.1.x" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "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=" + }, + "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=", + "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=" + } + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "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=" + }, + "preferred-pm": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-1.0.1.tgz", + "integrity": "sha512-9Uxgin5Xnsl67DBvlNFsmDIlBuG9/XKK2cVBTj//7/7wW6ZY+IC9/GlLqxyHABpoasAsJ1MARFOdYPxMUtndxA==", + "dev": true, + "requires": { + "path-exists": "^3.0.0", + "which-pm": "^1.0.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, + "print-message": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/print-message/-/print-message-2.1.0.tgz", + "integrity": "sha1-tViO0IsOG/d6x7y1y3gASvr5qJE=", + "requires": { + "chalk": "1.1.1" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "prompts": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz", + "integrity": "sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.4" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "query-string": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.10.1.tgz", + "integrity": "sha512-SHTUV6gDlgMXg/AQUuLpTiBtW/etZ9JT6k6RCtCyqADquApLX0Aq5oK/s5UeTUAWBG50IExjIr587GqfXRfM4A==", + "requires": { + "decode-uri-component": "^0.2.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "requires": { + "performance-now": "^2.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "react": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.9.0.tgz", + "integrity": "sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-deep-force-update": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/react-deep-force-update/-/react-deep-force-update-1.1.2.tgz", + "integrity": "sha512-WUSQJ4P/wWcusaH+zZmbECOk7H5N2pOIl0vzheeornkIMhu+qrNdGFm0bDZLCb0hSF0jf/kH1SgkNGfBdTc4wA==", + "dev": true + }, + "react-devtools-core": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-3.6.3.tgz", + "integrity": "sha512-+P+eFy/yo8Z/UH9J0DqHZuUM5+RI2wl249TNvMx3J2jpUomLQa4Zxl56GEotGfw3PIP1eI+hVf1s53FlUONStQ==", + "requires": { + "shell-quote": "^1.6.1", + "ws": "^3.3.1" + }, + "dependencies": { + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-mixin": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/react-mixin/-/react-mixin-3.1.1.tgz", + "integrity": "sha512-z9fZ0aCRDjlgxLdMeWkJ9TwhmVLhQ09r8RFpin/cEPA2T6jsb7YHNWcIe0Oii+hhJNyMymdy91CSya5mRkuCkg==", + "requires": { + "object-assign": "^4.0.1", + "smart-mixin": "^2.0.0" + } + }, + "react-native": { + "version": "0.61.5", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.61.5.tgz", + "integrity": "sha512-MXqE3NoGO0T3dUKIKkIppijBhRRMpfN6ANbhMXHDuyfA+fSilRWgCwYgR/YNCC7ntECoJYikKaNTUBB0DeQy6Q==", + "requires": { + "@babel/runtime": "^7.0.0", + "@react-native-community/cli": "^3.0.0", + "@react-native-community/cli-platform-android": "^3.0.0", + "@react-native-community/cli-platform-ios": "^3.0.0", + "abort-controller": "^3.0.0", + "art": "^0.10.0", + "base64-js": "^1.1.2", + "connect": "^3.6.5", + "create-react-class": "^15.6.3", + "escape-string-regexp": "^1.0.5", + "event-target-shim": "^5.0.1", + "fbjs": "^1.0.0", + "fbjs-scripts": "^1.1.0", + "hermes-engine": "^0.2.1", + "invariant": "^2.2.4", + "jsc-android": "^245459.0.0", + "metro-babel-register": "^0.56.0", + "metro-react-native-babel-transformer": "^0.56.0", + "metro-source-map": "^0.56.0", + "nullthrows": "^1.1.0", + "pretty-format": "^24.7.0", + "promise": "^7.1.1", + "prop-types": "^15.7.2", + "react-devtools-core": "^3.6.3", + "react-refresh": "^0.4.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.15.0", + "stacktrace-parser": "^0.1.3", + "whatwg-fetch": "^3.0.0" + }, + "dependencies": { + "@react-native-community/cli": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-3.2.1.tgz", + "integrity": "sha512-bZ/bfZ+9r1gQSxp6t7+00DcpC6vmbVYSvzUCFM/yo5k8bhsDdcy8aocscIaXXVGG+v9Edri/Q7hH9ks7L18/Rg==", + "requires": { + "@hapi/joi": "^15.0.3", + "@react-native-community/cli-debugger-ui": "^3.0.0", + "@react-native-community/cli-tools": "^3.0.0", + "@react-native-community/cli-types": "^3.0.0", + "chalk": "^2.4.2", + "command-exists": "^1.2.8", + "commander": "^2.19.0", + "compression": "^1.7.1", + "connect": "^3.6.5", + "cosmiconfig": "^5.1.0", + "deepmerge": "^3.2.0", + "didyoumean": "^1.2.1", + "envinfo": "^7.1.0", + "errorhandler": "^1.5.0", + "execa": "^1.0.0", + "find-up": "^4.1.0", + "fs-extra": "^7.0.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.3", + "inquirer": "^3.0.6", + "lodash": "^4.17.5", + "metro": "^0.56.0", + "metro-config": "^0.56.0", + "metro-core": "^0.56.0", + "metro-react-native-babel-transformer": "^0.56.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "morgan": "^1.9.0", + "node-notifier": "^5.2.1", + "open": "^6.2.0", + "ora": "^3.4.0", + "plist": "^3.0.0", + "pretty-format": "^25.1.0", + "semver": "^6.3.0", + "serve-static": "^1.13.1", + "shell-quote": "1.6.1", + "strip-ansi": "^5.2.0", + "sudo-prompt": "^9.0.0", + "wcwidth": "^1.0.1", + "ws": "^1.1.0" + }, + "dependencies": { + "@hapi/joi": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.1.tgz", + "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==", + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "@react-native-community/cli-debugger-ui": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-3.0.0.tgz", + "integrity": "sha512-m3X+iWLsK/H7/b7PpbNO33eQayR/+M26la4ZbYe1KRke5Umg4PIWsvg21O8Tw4uJcY8LA5hsP+rBi/syBkBf0g==", + "requires": { + "serve-static": "^1.13.1" + } + }, + "@react-native-community/cli-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-3.0.0.tgz", + "integrity": "sha512-ng6Tm537E/M42GjE4TRUxQyL8sRfClcL7bQWblOCoxPZzJ2J3bdALsjeG3vDnVCIfI/R0AeFalN9KjMt0+Z/Zg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "command-exists": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", + "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==" + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + } + }, + "envinfo": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.5.0.tgz", + "integrity": "sha512-jDgnJaF/Btomk+m3PZDTTCb5XIIIX3zYItnCRfF73zVgvinLoRomuhi75Y4su0PtQxWz4v66XnLLckyvyJTOIQ==" + }, + "errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "requires": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "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.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "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" + } + } + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "metro": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.56.4.tgz", + "integrity": "sha512-Kt3OQJQtQdts0JrKnyGdLpKHDjqYBgIfzvYrvfhmFCkKuZ8aqRlVnvpfjQ4/OBm0Fmm9NyyxbNRD9VIbj7WjnA==", + "requires": { + "@babel/core": "^7.0.0", + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/plugin-external-helpers": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "absolute-path": "^0.0.0", + "async": "^2.4.0", + "babel-preset-fbjs": "^3.1.2", + "buffer-crc32": "^0.2.13", + "chalk": "^2.4.1", + "concat-stream": "^1.6.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "denodeify": "^1.2.1", + "eventemitter3": "^3.0.0", + "fbjs": "^1.0.0", + "fs-extra": "^1.0.0", + "graceful-fs": "^4.1.3", + "image-size": "^0.6.0", + "invariant": "^2.2.4", + "jest-haste-map": "^24.7.1", + "jest-worker": "^24.6.0", + "json-stable-stringify": "^1.0.1", + "lodash.throttle": "^4.1.1", + "merge-stream": "^1.0.1", + "metro-babel-register": "^0.56.4", + "metro-babel-transformer": "^0.56.4", + "metro-cache": "^0.56.4", + "metro-config": "^0.56.4", + "metro-core": "^0.56.4", + "metro-inspector-proxy": "^0.56.4", + "metro-minify-uglify": "^0.56.4", + "metro-react-native-babel-preset": "^0.56.4", + "metro-resolver": "^0.56.4", + "metro-source-map": "^0.56.4", + "metro-symbolicate": "^0.56.4", + "mime-types": "2.1.11", + "mkdirp": "^0.5.1", + "node-fetch": "^2.2.0", + "nullthrows": "^1.1.0", + "resolve": "^1.5.0", + "rimraf": "^2.5.4", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "temp": "0.8.3", + "throat": "^4.1.0", + "wordwrap": "^1.0.0", + "write-file-atomic": "^1.2.0", + "ws": "^1.1.5", + "xpipe": "^1.0.5", + "yargs": "^9.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" + } + } + } + }, + "metro-config": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.56.4.tgz", + "integrity": "sha512-O85QDHwWdMn/8ERe13y4a6vbZL0AHyO8atTvL+9BCulLEO+FQBi1iJjr3+ViLa8cf0m5dRftDsa7P47m5euk4A==", + "requires": { + "cosmiconfig": "^5.0.5", + "jest-validate": "^24.7.0", + "metro": "^0.56.4", + "metro-cache": "^0.56.4", + "metro-core": "^0.56.4", + "pretty-format": "^24.7.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + } + } + }, + "metro-core": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.56.4.tgz", + "integrity": "sha512-hMzkBdgPt5Zm9nr/1KtIT+A6H7TNiLVCEGG5OiAXj8gTRsA2yy7wAdQpwy0xbE+zi88t/pLOzXpd3ClG/YxyWg==", + "requires": { + "jest-haste-map": "^24.7.1", + "lodash.throttle": "^4.1.1", + "metro-resolver": "^0.56.4", + "wordwrap": "^1.0.0" + } + }, + "mkdirp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", + "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", + "requires": { + "minimist": "^1.2.5" + } + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + } + }, + "open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "requires": { + "is-wsl": "^1.1.0" + } + }, + "ora": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", + "requires": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + } + }, + "pretty-format": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.1.0.tgz", + "integrity": "sha512-46zLRSGLd02Rp+Lhad9zzuNZ+swunitn8zIpfD2B4OPCRLXbM87RJT2aBLBWYOznNUML/2l/ReMyWNC80PJBUQ==", + "requires": { + "@jest/types": "^25.1.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + }, + "dependencies": { + "@jest/types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.1.0.tgz", + "integrity": "sha512-VpOtt7tCrgvamWZh1reVsGADujKigBUFTi19mlRjqEGsE8qH4r3s+skY33dNdXOwyZIvuftZ5tqdF1IgsMejMA==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "sudo-prompt": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.1.1.tgz", + "integrity": "sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA==" + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + } + } + }, + "@types/yargs": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", + "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "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" + } + } + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "deepmerge": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz", + "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "fbjs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-1.0.0.tgz", + "integrity": "sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA==", + "requires": { + "core-js": "^2.4.1", + "fbjs-css-vars": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "metro-react-native-babel-preset": { + "version": "0.56.4", + "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.56.4.tgz", + "integrity": "sha512-CzbBDM9Rh6w8s1fq+ZqihAh7DDqUAcfo9pPww25+N/eJ7UK436Q7JdfxwdIPpBwLFn6o6MyYn+uwL9OEWBJarA==", + "requires": { + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.2.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-exponentiation-operator": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-assign": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-regenerator": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.0.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "react-refresh": "^0.4.0" + } + }, + "mime-db": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz", + "integrity": "sha1-oxtAcK2uon1zLqMzdApk0OyaZlk=" + }, + "mime-types": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", + "integrity": "sha1-wlnEcb2oCKhdbNGTtDCl+uRHOzw=", + "requires": { + "mime-db": "~1.23.0" + } + }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "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=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "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" + } + } + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.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.0.0", + "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=", + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "react-native-animatable": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz", + "integrity": "sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==", + "requires": { + "prop-types": "^15.7.2" + } + }, + "react-native-calendars": { + "version": "1.263.0", + "resolved": "https://registry.npmjs.org/react-native-calendars/-/react-native-calendars-1.263.0.tgz", + "integrity": "sha512-Xi1b/B/yKd7vnfREMCmN/MAaDD7uKmYxiwm4spFB/gbJv6naHc0vXX5Fxqr00jifzKoc9C6/LYE9YYaWnIL97A==", + "requires": { + "hoist-non-react-statics": "^3.3.1", + "lodash": "^4.0.0", + "prop-types": "^15.5.10", + "xdate": "^0.8.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + } + } + }, + "react-native-carousel-view": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/react-native-carousel-view/-/react-native-carousel-view-0.5.1.tgz", + "integrity": "sha1-Kw1k0y1xvgn/dVWqjBmx2smMWWk=", + "requires": { + "react-mixin": "^3.0.5", + "react-timer-mixin": "^0.13.3" + } + }, + "react-native-charts-wrapper": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/react-native-charts-wrapper/-/react-native-charts-wrapper-0.5.7.tgz", + "integrity": "sha512-d1lOSN47YRUqFGOht4uBP+P7N7OvtRrhgwTOdTNlXC+ZmoveBIIE+bl65uwGkS08kUUBudRBugsCRkf5MB/p2w==", + "requires": { + "prop-types": "^15.5.10", + "react": "16.8.3" + }, + "dependencies": { + "react": { + "version": "16.8.3", + "resolved": "https://registry.npmjs.org/react/-/react-16.8.3.tgz", + "integrity": "sha512-3UoSIsEq8yTJuSu0luO1QQWYbgGEILm+eJl2QN/VLDi7hL+EN18M3q3oVZwmVzzBJ3DkM7RMdRwBmZZ+b4IzSA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.13.3" + } + }, + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "react-native-clean-project": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/react-native-clean-project/-/react-native-clean-project-3.3.0.tgz", + "integrity": "sha512-IudFlNsaQd6QcgcbTZcNEXDlrJ9zzRspIUV7yvBX3bfB72Z9et9hIceH9+F+xYSlvwUSB4L/fvkIPosYKa+q9Q==", + "dev": true + }, + "react-native-debugger-open": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/react-native-debugger-open/-/react-native-debugger-open-0.3.24.tgz", + "integrity": "sha512-qiq9fApbS8j/Q3tjaUM/a1K++mhl7RvAAHgoqZ+oB6tbGWohiBOWfBgf9f1l5CYC2DMl2UZzKMqMjMRd0rJxdg==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "es6-template": "^1.0.4", + "minimist": "^1.2.0", + "semver": "^5.4.1" + }, + "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.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "react-native-deep-linking": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-native-deep-linking/-/react-native-deep-linking-2.2.0.tgz", + "integrity": "sha512-PKShbOsa/oxjSzZ/Bag98O/J+jaZOI6ic5YdanPirTpRAraAvKUzJWQUhE5Yy0Isl9yfIkSogOClE9BRfSyUbA==" + }, + "react-native-device-info": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-2.3.2.tgz", + "integrity": "sha512-ccpPuUbwhw5uYdVwN1UJp6ykMZz6U/u82HNM3oJ7O6MP8RIMlMDkHbqR4O0sDtUSuRMGiqqRzFtmOLFYeQ0ODw==" + }, + "react-native-drawer": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/react-native-drawer/-/react-native-drawer-2.5.1.tgz", + "integrity": "sha512-cxcQNbSWy5sbGi7anSVp6EDr6JarOBMY9lbFOeLFeVYbONiudoqRKbgEsSDgSw3/LFCLvUXK5zdjXCOedeytxQ==", + "requires": { + "prop-types": "^15.5.8", + "tween-functions": "^1.0.1" + } + }, + "react-native-easy-grid": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/react-native-easy-grid/-/react-native-easy-grid-0.2.2.tgz", + "integrity": "sha512-MlYrNIldnEMKn6TVatQN1P64GoVlwGIuz+8ncdfJ0Wq/xtzUkQwlil8Uksyp7MhKfENE09MQnGNcba6Mx3oSAA==", + "requires": { + "lodash": "^4.17.15" + } + }, + "react-native-elements": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/react-native-elements/-/react-native-elements-1.2.7.tgz", + "integrity": "sha512-0S+0R1cbItl15i64qrkWnyMztwpw60d0SUsZGVDKRAMf0Jvq9Clgyh/MzxJx2sr42mbedQP1sg5Et4fZM7Fp1w==", + "requires": { + "@types/react-native-vector-icons": "^6.4.4", + "color": "^3.1.0", + "deepmerge": "^3.1.0", + "hoist-non-react-statics": "^3.1.0", + "opencollective-postinstall": "^2.0.0", + "prop-types": "^15.7.2", + "react-native-ratings": "^6.3.0", + "react-native-status-bar-height": "^2.2.0" + }, + "dependencies": { + "deepmerge": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz", + "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA==" + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + } + } + }, + "react-native-firebase": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/react-native-firebase/-/react-native-firebase-5.6.0.tgz", + "integrity": "sha512-I+o3zNLdIz4pxWTCSZH70M1BcPl+SdqKQfurOT0sWcaMSL2ecDqVy0PCTmN7ORt7/Z879Er6PLgA/psjArQlmw==", + "requires": { + "opencollective-postinstall": "^2.0.0", + "prop-types": "^15.7.2" + } + }, + "react-native-gesture-handler": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.6.0.tgz", + "integrity": "sha512-KulGCWKTxa6xBpPP4LWEPmmLqBqOe2jbtdlILOVF/dR4EgImiaBVrKdOHeRMyMzJOYAWxs5uDZsyA8hgSsm+lw==", + "requires": { + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^2.3.1", + "invariant": "^2.2.4", + "prop-types": "^15.7.2" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", + "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" + } + } + }, + "react-native-google-maps-directions": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/react-native-google-maps-directions/-/react-native-google-maps-directions-2.1.1.tgz", + "integrity": "sha512-hsq2T3cJsZZ31akEq08nBCdRlYQ+o+07R7wTb9QclrTQHJRIKR78mI9lgizOpKm4NFSYUOxGtbL7LfhJw1OANQ==" + }, + "react-native-htmlview": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/react-native-htmlview/-/react-native-htmlview-0.15.0.tgz", + "integrity": "sha512-7PtmM5bIHB22Dv1Nv02YDxhBcngU5ulJznJmjW8rPGGYcF+2721TNPAVw7u44/p4kTKH/IGtyf//vCo2SAFYqA==", + "requires": { + "entities": "^1.1.1", + "htmlparser2-without-node-native": "^3.9.2" + } + }, + "react-native-iphone-x-helper": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.2.1.tgz", + "integrity": "sha512-/VbpIEp8tSNNHIvstuA3Swx610whci1Zpc9mqNkqn14DkMbw+ORviln2u0XyHG1kPvvwTNGZY6QpeFwxYaSdbQ==" + }, + "react-native-keyboard-aware-scroll-view": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/react-native-keyboard-aware-scroll-view/-/react-native-keyboard-aware-scroll-view-0.9.1.tgz", + "integrity": "sha512-tBZ8rmjELN0F6t5UBp5CW3NYmZXgVnJSzVCssv/OqG2t6kiB+OUTqxNvUP24K+HARX4H+XaW0aEJSFQkQCv6KA==", + "requires": { + "prop-types": "^15.6.2", + "react-native-iphone-x-helper": "^1.0.3" + } + }, + "react-native-localize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/react-native-localize/-/react-native-localize-1.3.3.tgz", + "integrity": "sha512-lpKx/iqDKQ7dC58fb/vGGERLT4ZYfk+H2AXMg6aaVkgv8eEIgApQAzB2Oaotx7FIM/RopJponUFyJ4PMIHi4Rw==" + }, + "react-native-modal": { + "version": "11.5.4", + "resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-11.5.4.tgz", + "integrity": "sha512-3wPBtba2maa4TczV1MeBv/M/8qcipxfOr+HG5pKF7qHmH5MlfaF22OmRhg1ioSN7+rkRkF/gvYIGQOufpI7emQ==", + "requires": { + "prop-types": "^15.6.2", + "react-native-animatable": "1.3.3" + } + }, + "react-native-modalbox": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/react-native-modalbox/-/react-native-modalbox-1.7.1.tgz", + "integrity": "sha512-Jqn12MKQaT5OSb1uMAEeDQF02xHS+WWdgKl55ecoIknrDy+FIoC3fXHMEoRZH6agADDg9eVBqx8w+P7+EwXTbQ==", + "requires": { + "create-react-class": "^15.6.0", + "prop-types": "^15.5.10" + } + }, + "react-native-open-maps": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/react-native-open-maps/-/react-native-open-maps-0.3.5.tgz", + "integrity": "sha512-JPRZVj8gYJDHqJZV90BQIemIvTmoxCE8T3CVD3w25ZNXjf822xAespJ+JRRCB8gZ58TnmcrzcRG8cst/tJeIhQ==", + "requires": { + "query-string": "^6.1.0" + } + }, + "react-native-orientation-locker": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/react-native-orientation-locker/-/react-native-orientation-locker-1.1.8.tgz", + "integrity": "sha512-+Vd7x6O/3zGqYIMXpeDlaw3ma074Dtnocm8ryT9v5SvaiEcWSzII4frPgXaUcc/MiCq4OWZ1JtVoyw75mdomQw==" + }, + "react-native-paper": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-3.6.0.tgz", + "integrity": "sha512-amsZpN8vUJIGBiHMf1sQm0dtJMUhNFAPkXkt/9XMR1mKneEUfWGIap1KBZdOHLIVp1iACigpV8g9R3j+MaxWOg==", + "requires": { + "@callstack/react-theme-provider": "^3.0.5", + "color": "^3.1.2", + "react-native-safe-area-view": "^0.14.6" + } + }, + "react-native-ratings": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/react-native-ratings/-/react-native-ratings-6.5.0.tgz", + "integrity": "sha512-YMcfQ7UQCmXGEc/WPlukHSHs5yvckTwjq5fTRk1FG8gaO7fZCNygEUGPuw4Dbvvp3IlsCUn0bOQd63RYsb7NDQ==", + "requires": { + "lodash": "^4.17.4", + "prop-types": "^15.5.10" + } + }, + "react-native-reanimated": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-1.7.0.tgz", + "integrity": "sha512-FQWSqP605eQVJumuK2HpR+7heF0ZI+qfy4jNguv3Xv8nPFHeIgZaRTXHCEQL2AcuSIj50zy8jGJf5l134QMQWQ==" + }, + "react-native-responsive-stylesheet": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-native-responsive-stylesheet/-/react-native-responsive-stylesheet-1.1.0.tgz", + "integrity": "sha1-9WRekIHoY/fSw0G350IKiMadFkw=", + "requires": { + "mock-require": "^2.0.1" + } + }, + "react-native-safe-area-view": { + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.14.8.tgz", + "integrity": "sha512-MtRSIcZNstxv87Jet+UsPhEd1tpGe8cVskDXlP657x6rHpSrbrc+y13ZNXrwAgGNNhqQNX7UJT68ZIq//ZRmvw==", + "requires": { + "hoist-non-react-statics": "^2.3.1" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", + "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" + } + } + }, + "react-native-screens": { + "version": "1.0.0-alpha.23", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-1.0.0-alpha.23.tgz", + "integrity": "sha512-tOxHGQUN83MTmQB4ghoQkibqOdGiX4JQEmeyEv96MKWO/x8T2PJv84ECUos9hD3blPRQwVwSpAid1PPPhrVEaw==", + "requires": { + "debounce": "^1.2.0" + } + }, + "react-native-sensitive-info": { + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/react-native-sensitive-info/-/react-native-sensitive-info-5.5.5.tgz", + "integrity": "sha512-ShRqvHTZnY4VYNEF+5pCBUu/2wslojY445FdA9nuH9nkVqOQRXxIGYqTRYXJ42mDLTt+KnW5hcvuAjpVVokafQ==" + }, + "react-native-size-matters": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/react-native-size-matters/-/react-native-size-matters-0.2.1.tgz", + "integrity": "sha512-u3XlYOt15SRjZtFdwiVIejp/X+gHj/uL6DcStNh4R8/7wGr2WkzpaG4C9YYPuZTJ0SwBJOCI4E1yCdQAOIi6fA==" + }, + "react-native-splash-screen": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-native-splash-screen/-/react-native-splash-screen-3.2.0.tgz", + "integrity": "sha512-Ls9qiNZzW/OLFoI25wfjjAcrf2DZ975hn2vr6U9gyuxi2nooVbzQeFoQS5vQcbCt9QX5NY8ASEEAtlLdIa6KVg==" + }, + "react-native-status-bar-height": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/react-native-status-bar-height/-/react-native-status-bar-height-2.4.0.tgz", + "integrity": "sha512-pWvZFlyIHiuxLugLioq97vXiaGSovFXEyxt76wQtbq0gxv4dGXMPqYow46UmpwOgeJpBhqL1E0EKxnfJRrFz5w==" + }, + "react-native-svg": { + "version": "9.13.6", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-9.13.6.tgz", + "integrity": "sha512-vjjuJhEhQCwWjqsgWyGy6/C/LIBM2REDxB40FU1PMhi8T3zQUwUHnA6M15pJKlQG8vaZyA+QnLyIVhjtujRgig==", + "requires": { + "css-select": "^2.0.2", + "css-tree": "^1.0.0-alpha.37" + } + }, + "react-native-svg-transformer": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/react-native-svg-transformer/-/react-native-svg-transformer-0.14.3.tgz", + "integrity": "sha512-agDGdMeeBAsWEgg/u7mjtR2Z3c8smGCLep/n3svwifut9dpswZCP+bSIrU8ekg6RNtxAJL+eGJbWjJ38vWxw6g==", + "dev": true, + "requires": { + "@svgr/core": "^4.3.3", + "@svgr/plugin-svgo": "^4.3.1", + "path-dirname": "^1.0.2", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "react-native-tab-view": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-2.13.0.tgz", + "integrity": "sha512-AeYbp/u91+D/C9+PmVEPBmFb3ixv8IkLMC3Sc5MajJ/fg0Zl3Of+BcEknBvTnKoe7Fj2y8+Qf9zorBbh5xzh4A==" + }, + "react-native-vector-icons": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-6.6.0.tgz", + "integrity": "sha512-MImKVx8JEvVVBnaShMr7/yTX4Y062JZMupht1T+IEgbqBj4aQeQ1z2SH4VHWKNtWtppk4kz9gYyUiMWqx6tNSw==", + "requires": { + "lodash": "^4.0.0", + "prop-types": "^15.6.2", + "yargs": "^13.2.2" + } + }, + "react-native-webview": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-7.6.0.tgz", + "integrity": "sha512-IQWtIpCTYb4dTshAJO3hMM9Ms5T6KRpk6qWqgBTGMdmgeEvSxWz9l7Og1ALhb7T7NoAnPy8w/dQmD9LlbGGs5g==", + "requires": { + "escape-string-regexp": "2.0.0", + "invariant": "2.2.4" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + } + } + }, + "react-navigation": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-4.1.1.tgz", + "integrity": "sha512-HEzPOsndrKnxTf0+gsi1N/0GKbwu8KSTOveL7ptJLG7XNXHBXVvp4lbaS3PVPe2IaiXbXCC+y3VJ8dH50wHR4g==", + "requires": { + "@react-navigation/core": "^3.5.2", + "@react-navigation/native": "^3.6.5" + } + }, + "react-navigation-drawer": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/react-navigation-drawer/-/react-navigation-drawer-2.3.4.tgz", + "integrity": "sha512-jPGFVsYB+Q51bMFoeXLO2sYXMQISu2b9fQWZ9QMTvRsA/9pqeBfW7AXM97qW+HdciiQJBdJ6DcttoybWjBSpWQ==" + }, + "react-navigation-material-bottom-tabs": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/react-navigation-material-bottom-tabs/-/react-navigation-material-bottom-tabs-2.1.5.tgz", + "integrity": "sha512-MGoVI63ekaU6MxL2FLF9q7n0R9dSGaMzp5PGE4PQCHB3XgN9zAL+gPOWNQFivhqSXHx45sL0oPuxnNOGt9IU3Q==" + }, + "react-navigation-stack": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/react-navigation-stack/-/react-navigation-stack-1.10.3.tgz", + "integrity": "sha512-1gksFi/g/Lg9sBhgLlD0OiEB5xnatHb4C0eNMA5tli9cTVlhq375XNPIqOiTyftibBmjdApAsZFj5srUCoOu/w==", + "requires": { + "prop-types": "^15.7.2" + } + }, + "react-navigation-tabs": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/react-navigation-tabs/-/react-navigation-tabs-2.7.0.tgz", + "integrity": "sha512-fQEHjFrIBi+89loLL521HjGS0Z9tl4Y89SSamRkDl8Of6bPS1Ep++an3ctl2j7c3veqBZBrj3H1qa7qjd3apBQ==", + "requires": { + "hoist-non-react-statics": "^3.3.0", + "react-lifecycles-compat": "^3.0.4", + "react-native-safe-area-view": "^0.14.6", + "react-native-tab-view": "^2.11.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + } + } + }, + "react-proxy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz", + "integrity": "sha1-nb/Z2SdSjDqp9ETkVYw3gwq4wmo=", + "dev": true, + "requires": { + "lodash": "^4.6.1", + "react-deep-force-update": "^1.0.0" + } + }, + "react-refresh": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.2.tgz", + "integrity": "sha512-kv5QlFFSZWo7OlJFNYbxRtY66JImuP2LcrFgyJfQaf85gSP+byzG21UbDQEYjU7f//ny8rwiEkO6py2Y+fEgAQ==" + }, + "react-test-renderer": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.8.6.tgz", + "integrity": "sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "react-is": "^16.8.6", + "scheduler": "^0.13.6" + }, + "dependencies": { + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "react-timer-mixin": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/react-timer-mixin/-/react-timer-mixin-0.13.4.tgz", + "integrity": "sha512-4+ow23tp/Tv7hBM5Az5/Be/eKKF7DIvJ09voz5LyHGQaqqz9WV8YMs31eFvcYQs7d451LSg7kDJV70XYN/Ug/Q==" + }, + "react-transform-hmr": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-transform-hmr/-/react-transform-hmr-1.0.4.tgz", + "integrity": "sha1-4aQL0Krvxy6N/Xp82gmvhQZjl7s=", + "dev": true, + "requires": { + "global": "^4.3.0", + "react-proxy": "^1.1.7" + } + }, + "react-tween-state": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/react-tween-state/-/react-tween-state-0.1.5.tgz", + "integrity": "sha1-6YsGZVHvuTy5LdG+FJlcLj3q4zk=", + "requires": { + "raf": "^3.1.0", + "tween-functions": "^1.0.1" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "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=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^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=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + } + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.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" + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" + }, + "regenerator-transform": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.3.tgz", + "integrity": "sha512-zXHNKJspmONxBViAb3ZUmFoFPnTBs3zFhCEZJiwp/gkNzxVbTqNJVjYKx6Qk1tQ1P4XLf4TbH9+KBB7wGoAaUw==", + "requires": { + "@babel/runtime": "^7.8.4", + "private": "^0.1.8" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", + "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "registry-auth-token": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.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.0.1" + } + }, + "regjsgen": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", + "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==" + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", + "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", + "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "dev": true, + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "require-package-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", + "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "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.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "rn-secure-storage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/rn-secure-storage/-/rn-secure-storage-2.0.4.tgz", + "integrity": "sha512-pDMLLHu2vXWTvEWdeYEP7g04sQQrTu6uc8STIf9ecbipV+N6fJ6nqM8+jMxBq1+u+8oa1L9hGmIwUYKixPpGSw==" + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==" + }, + "run-async": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", + "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", + "requires": { + "is-promise": "^2.1.0" + } + }, + "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": "*" + } + }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "requires": { + "symbol-observable": "1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "schedule": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/schedule/-/schedule-0.5.0.tgz", + "integrity": "sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw==", + "dev": true, + "requires": { + "object-assign": "^4.1.1" + } + }, + "scheduler": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz", + "integrity": "sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "^5.0.3" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "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.3", + "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.0.2" + } + }, + "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=" + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-plist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.1.0.tgz", + "integrity": "sha512-2i5Tc0BYAqppM7jVzmNrI+aEUntPolIq4fDgji6WuNNn1D/qYdn2KwoLhZdzQkE04lu9L5tUoeJsjuJAvd+lFg==", + "requires": { + "bplist-creator": "0.0.8", + "bplist-parser": "0.2.0", + "plist": "^3.0.1" + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=", + "dev": true + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + }, + "smart-mixin": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/smart-mixin/-/smart-mixin-2.0.0.tgz", + "integrity": "sha1-o0oQVeMqdbMNK048oyPcmctT9Dc=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==" + }, + "stackframe": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", + "integrity": "sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ=", + "dev": true + }, + "stacktrace-parser": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.8.tgz", + "integrity": "sha512-ig5rHJSdJrAsVqdb3oAI/8C6aQ7dEwJXoy/TIEIOTzdJHssmn12o6RsFoeQSLHoKjq0lX+kqhmnLDpyQTuWiJA==", + "requires": { + "type-fest": "^0.7.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=" + }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "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" + }, + "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 + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "svg-parser": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.3.tgz", + "integrity": "sha512-fnCWiifNhK8i2Z7b9R5tbNahpxrRdAaQbnoxKlT2KrSCj9Kq/yBSgulCRgBJRhy1dPnSY5slg5ehPUnzpEcHlg==", + "dev": true + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "^1.0.0", + "rimraf": "~2.2.6" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" + } + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" + }, + "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 + }, + "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" + } + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, + "tslint": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.1.tgz", + "integrity": "sha512-kd6AQ/IgPRpLn6g5TozqzPdGNZ0q0jtXW4//hRcj10qLYBaa3mTUU2y2MCG+RXZm8Zx+KZi0eA+YCrMyNlF4UA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.10.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "tslint-config-prettier": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", + "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", + "dev": true + }, + "tslint-react": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tslint-react/-/tslint-react-4.2.0.tgz", + "integrity": "sha512-lO22+FKr9ZZGueGiuALzvZE/8ANoDoCHGCknX1Ge3ALrfcLQHQ1VGdyb1scZXQFdEQEfwBTIU40r5BUlJpn0JA==", + "dev": true, + "requires": { + "tsutils": "^3.9.1" + }, + "dependencies": { + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tween-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", + "integrity": "sha1-GuOlDnxguz3vd06scHrLynO7w/8=" + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.21", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", + "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==" + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "requires": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==" + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==" + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==" + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-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.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "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=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, + "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.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate.js": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/validate.js/-/validate.js-0.13.1.tgz", + "integrity": "sha512-PnFM3xiZ+kYmLyTiMgTYmU7ZHkjBZz2/+F0DaALc/uUtVzdCt1wAosvYJ5hFQi/hz8O4zb52FQhHZRC+uVkJ+g==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==" + }, + "vue-template-compiler": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz", + "integrity": "sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==", + "dev": true, + "requires": { + "de-indent": "^1.0.2", + "he": "^1.1.0" + } + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "walkdir": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.3.2.tgz", + "integrity": "sha512-0Twghia4Z5wDGDYWURlhZmI47GvERMCsXIu0QZWVVZyW9ZjpbbZvD9Zy9M6cWiQQRRbAcYajIyKNavaZZDt1Uw==", + "dev": true + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "requires": { + "makeerror": "1.0.x" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "which-pm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-1.1.0.tgz", + "integrity": "sha512-7GHHJQpALk7BWMD8I+xSILSbHyngvBlfSXlwGpdRFY2voFwVCx+eJAybXTzTnUYmt7zio6B9SEdI81T0fBjxNA==", + "dev": true, + "requires": { + "load-yaml-file": "^0.1.0", + "path-exists": "^3.0.0" + } + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + }, + "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 + }, + "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" + } + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + }, + "xcode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-2.1.0.tgz", + "integrity": "sha512-uCrmPITrqTEzhn0TtT57fJaNaw8YJs1aCzs+P/QqxsDbvPZSv7XMPPwXrKvHtD6pLjBM/NaVwraWJm8q83Y4iQ==", + "requires": { + "simple-plist": "^1.0.0", + "uuid": "^3.3.2" + } + }, + "xdate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/xdate/-/xdate-0.8.2.tgz", + "integrity": "sha1-17AzwASF0CaVuvAET06s2j/JYaM=" + }, + "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-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xmldoc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-1.1.2.tgz", + "integrity": "sha512-ruPC/fyPNck2BD1dpz0AZZyrEwMOrWTO5lDdIXS91rs3wtm4j+T8Rp2o+zoOYkkAxJTZRPOSnOGei1egoRmKMQ==", + "requires": { + "sax": "^1.2.1" + } + }, + "xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" + }, + "xpipe": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/xpipe/-/xpipe-1.0.5.tgz", + "integrity": "sha1-jdi/Rfw/f1Xw4FS4ePQ6YmFNr98=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..7c49e36c5 --- /dev/null +++ b/package.json @@ -0,0 +1,137 @@ +{ + "name": "eMobility", + "version": "1.2.4", + "repository": { + "type": "git", + "url": "https://github.com/LucasBrazi06/ev-mobile.git" + }, + "author": "SAP E-Mobility Labs France ", + "license": "Apache-2.0", + "licenses": [ + { + "type": "Apache-2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + } + ], + "devDependencies": { + "@babel/core": "^7.6.4", + "@babel/runtime": "^7.6.3", + "@types/color": "^3.0.0", + "@types/i18n-js": "^3.0.1", + "@types/jest": "^24.0.19", + "@types/jwt-decode": "^2.2.1", + "@types/lodash": "^4.14.144", + "@types/react": "^16.9.22", + "@types/react-dom": "^16.9.2", + "@types/react-native": "^0.60.21", + "@types/react-native-htmlview": "^0.12.2", + "@types/react-test-renderer": "^16.9.1", + "babel-jest": "^24.9.0", + "babel-preset-react-native-stage-0": "^1.0.1", + "cross-env": "^6.0.3", + "flow-bin": "^0.105.0", + "jest": "^24.9.0", + "jetifier": "^1.6.4", + "metro-react-native-babel-preset": "^0.56.0", + "npm-check": "^5.9.2", + "patch-package": "^6.2.0", + "prettier": "^1.18.2", + "react-native-clean-project": "^3.3.0", + "react-native-debugger-open": "^0.3.24", + "react-native-svg-transformer": "^0.14.3", + "react-test-renderer": "16.8.6", + "schedule": "^0.5.0", + "tslint": "^6.1.1", + "tslint-config-prettier": "^1.18.0", + "tslint-react": "^4.2.0", + "typescript": "^3.8.3" + }, + "scripts": { + "postinstall": "patch-package", + "start": "react-native start", + "clean": "npm start -- --reset-cache", + "start:debug": "cross-env REACT_DEBUGGER=\"rndebugger-open --open --port 8081\" npm start", + "android": "cross-env TSC_WATCHFILE=UseFsEventsWithFallbackDynamicPolling react-native run-android", + "android:release": "react-native run-android --variant=release", + "android:assembleRelease": "npm run android:jetify && cd android && ./gradlew assembleRelease", + "android:bundleRelease": "npm run android:jetify && cd android && ./gradlew bundleRelease", + "android:jetify": "npx jetify", + "list-ios": "xcrun simctl list devices", + "ios": "cross-env TSC_WATCHFILE=UseFsEventsWithFallbackDynamicPolling react-native run-ios", + "ios-iphone-xs-max": "cross-env TSC_WATCHFILE=UseFsEventsWithFallbackDynamicPolling react-native run-ios --simulator='iPhone Xs Max'", + "ios-iphone-6s-plus": "cross-env TSC_WATCHFILE=UseFsEventsWithFallbackDynamicPolling react-native run-ios --simulator='iPhone 6s Plus'", + "ios-ipad-pro": "cross-env TSC_WATCHFILE=UseFsEventsWithFallbackDynamicPolling react-native run-ios --simulator='iPad Pro (12.9-inch) (2nd generation)'", + "ios:release": "react-native run-ios --configuration Release", + "pod:install": "cd ios && pod install", + "pod:deintegrate": "cd ios && pod deintegrate", + "test": "jest --passWithNoTests && npm run lint", + "precommit": "npm test", + "lint": "tslint '{src,__tests__}/**/*.ts{,x}' *.ts{,x}", + "lint:fix": "tslint --fix '{src,__tests__}/**/*.ts{,x}' *.ts{,x}", + "tsc": "tsc", + "tsc-stats": "tsc --diagnostics --listFiles", + "check-ts-circ-deps": "madge --extensions jsx src/**/* -c", + "clean-install-win": "rmdir node_modules /S /Q && del package-lock.json && npm cache clear --force && npm install", + "clean-install-lin": "rm -rf ./node_modules && rm -f ./package-lock.json && npm cache clear --force && npm install", + "ios:bundle": "react-native bundle --platform='ios' --dev=false --entry-file='index.js' --bundle-output='./ios/main.jsbundle' --assets-dest='./ios'", + "android:bundle": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/", + "android:clean": "cd android && ./gradlew clean", + "npm-check": "npm-check", + "react-native:upgrade": "react-native upgrade", + "react-native:link": "react-native link", + "react-native:unlink": "react-native unlink", + "react-native:uninstall": "react-native uninstall", + "react-native:log-ios": "react-native log-ios", + "react-native:log-android": "react-native log-android", + "react-native:clean-project-auto": "react-native clean-project-auto" + }, + "jest": { + "preset": "react-native" + }, + "dependencies": { + "add": "^2.0.6", + "axios": "^0.19.0", + "color": "^3.1.2", + "deepmerge": "^4.1.1", + "i18n-js": "^3.3.0", + "jwt-decode": "^2.2.0", + "lodash": "^4.17.15", + "moment": "^2.24.0", + "native-base": "^2.13.8", + "react": "16.9.0", + "react-native": "0.61.5", + "react-native-animatable": "^1.3.3", + "react-native-calendars": "^1.263.0", + "react-native-carousel-view": "^0.5.1", + "react-native-charts-wrapper": "^0.5.5", + "react-native-deep-linking": "^2.2.0", + "react-native-device-info": "^2.3.2", + "react-native-elements": "^1.2.6", + "react-native-firebase": "^5.5.6", + "react-native-gesture-handler": "^1.6.0", + "react-native-google-maps-directions": "^2.1.1", + "react-native-htmlview": "^0.15.0", + "react-native-localize": "^1.3.0", + "react-native-modal": "^11.5.4", + "react-native-modalbox": "^1.7.1", + "react-native-open-maps": "^0.3.4", + "react-native-orientation-locker": "^1.1.6", + "react-native-paper": "^3.2.1", + "react-native-reanimated": "^1.3.0", + "react-native-responsive-stylesheet": "^1.1.0", + "react-native-screens": "^1.0.0-alpha.23", + "react-native-sensitive-info": "^5.5.3", + "react-native-size-matters": "^0.2.1", + "react-native-splash-screen": "^3.2.0", + "react-native-svg": "^9.13.6", + "react-native-vector-icons": "^6.6.0", + "react-native-webview": "^7.4.2", + "react-navigation": "^4.1.1", + "react-navigation-drawer": "^2.3.4", + "react-navigation-material-bottom-tabs": "^2.1.5", + "react-navigation-stack": "^1.10.3", + "react-navigation-tabs": "^2.7.0", + "rn-secure-storage": "^2.0.2", + "validate.js": "^0.13.1" + } +} diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 000000000..a6f22a8b4 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,341 @@ +import I18n from 'i18n-js'; +import { Icon, Root } from 'native-base'; +import CentralServerProvider from 'provider/CentralServerProvider'; +import React from 'react'; +import { StatusBar } from 'react-native'; +import { createAppContainer, createSwitchNavigator, NavigationContainer, NavigationContainerComponent, NavigationState } from 'react-navigation'; +import { createDrawerNavigator } from 'react-navigation-drawer'; +import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs'; +import { createStackNavigator } from 'react-navigation-stack'; +import computeStyleSheet from './AppStyles'; +import DeepLinkingManager from './deeplinking/DeepLinkingManager'; +import I18nManager from './I18n/I18nManager'; +import NotificationManager from './notification/NotificationManager'; +import ProviderFactory from './provider/ProviderFactory'; +import Eula from './screens/auth/eula/Eula'; +import Login from './screens/auth/login/Login'; +import ResetPassword from './screens/auth/reset-password/ResetPassword'; +import RetrievePassword from './screens/auth/retrieve-password/RetrievePassword'; +import SignUp from './screens/auth/sign-up/SignUp'; +import ChargerActions from './screens/chargers/actions/ChargerActions'; +import ChargerConnectorDetails from './screens/chargers/connector-details/ChargerConnectorDetails'; +import Chargers from './screens/chargers/list/Chargers'; +import ChargerOcppParameters from './screens/chargers/ocpp/ChargerOcppParameters'; +import ChargerProperties from './screens/chargers/properties/ChargerProperties'; +import Home from './screens/home/Home'; +import Sidebar from './screens/sidebar/SideBar'; +import SiteAreas from './screens/site-areas/SiteAreas'; +import Sites from './screens/sites/Sites'; +import Statistics from './screens/statistics/Statistics'; +import TransactionChart from './screens/transactions/chart/TransactionChart'; +import TransactionDetails from './screens/transactions/details/TransactionDetails'; +import TransactionsInProgress from './screens/transactions/in-progress/TransactionsInProgress'; +import TransactionsHistory from './screens/transactions/list/TransactionsHistory'; +import commonColor from './theme/variables/commonColor'; +import SecuredStorage from './utils/SecuredStorage'; + +// Init i18n +I18nManager.initialize(); + +const appStyles = computeStyleSheet(); + +// Auth Stack Navigation +const authNavigator: NavigationContainer = createStackNavigator( + { + Login: { screen: Login }, + Eula: { screen: Eula }, + SignUp: { screen: SignUp }, + ResetPassword: { screen: ResetPassword }, + RetrievePassword: { screen: RetrievePassword } + }, + { + initialRouteName: 'Login', + headerMode: 'none' + } +); + +// Home Stack Navigation +const homeNavigator: NavigationContainer = createStackNavigator( + { + Home: { screen: Home } }, + { + initialRouteName: 'Home', + headerMode: 'none' + } +); + +// Stats Stack Navigation +const statisticsNavigator: NavigationContainer = createStackNavigator( + { + Statistics: { screen: Statistics } + }, + { + initialRouteName: 'Statistics', + headerMode: 'none' + } +); + +const chargerDetailsTabsNavigator = createMaterialBottomTabNavigator( + { + ChargerProperties: { + screen: ChargerProperties, + navigationOptions: { + title: I18n.t('chargers.properties'), + tabBarIcon: (props) => createTabBarIcon(props, 'MaterialIcons', 'info') + } + }, + ChargerActions: { + screen: ChargerActions, + navigationOptions: { + title: I18n.t('chargers.actions'), + tabBarIcon: (props) => createTabBarIcon(props, 'MaterialIcons', 'build') + } + }, + ChargerOcppParameters: { + screen: ChargerOcppParameters, + navigationOptions: { + title: I18n.t('chargers.ocpp'), + tabBarIcon: (props) => createTabBarIcon(props, 'MaterialIcons', 'format-list-bulleted') + } + } + }, + { + activeColor: commonColor.topTabBarActiveTextColor, + inactiveColor: commonColor.topTabBarTextColor, + barStyle: { backgroundColor: commonColor.brandPrimaryDark }, + labeled: true, + backBehavior: 'none', + initialRouteName: 'ChargerProperties', + } +); + +const chargerConnectorDetailsTabsNavigator = createMaterialBottomTabNavigator( + { + ChargerConnectorDetails: { + screen: ChargerConnectorDetails, + navigationOptions: { + title: I18n.t('sites.chargePoint'), + tabBarIcon: (props) => createTabBarIcon(props, 'FontAwesome', 'bolt') + }, + }, + TransactionChart: { + screen: TransactionChart, + navigationOptions: { + title: I18n.t('details.graph'), + tabBarIcon: (props) => createTabBarIcon(props, 'AntDesign', 'linechart') + } + }, + }, + { + activeColor: commonColor.topTabBarActiveTextColor, + inactiveColor: commonColor.topTabBarTextColor, + barStyle: { backgroundColor: commonColor.brandPrimaryDark }, + labeled: true, + backBehavior: 'none', + initialRouteName: 'ChargerConnectorDetails', + } +); + +const transactionDetailsTabsNavigator = createMaterialBottomTabNavigator( + { + TransactionDetails: { + screen: TransactionDetails, + navigationOptions: { + title: I18n.t('transactions.transaction'), + tabBarIcon: (props) => createTabBarIcon(props, 'FontAwesome', 'bolt') + }, + }, + TransactionChart: { + screen: TransactionChart, + navigationOptions: { + title: I18n.t('details.graph'), + tabBarIcon: (props) => createTabBarIcon(props, 'AntDesign', 'linechart') + } + } + }, + { + activeColor: commonColor.topTabBarActiveTextColor, + inactiveColor: commonColor.topTabBarTextColor, + barStyle: { backgroundColor: commonColor.brandPrimaryDark }, + labeled: true, + backBehavior: 'none', + initialRouteName: 'TransactionDetails', + } +); + +// Organizations Stack Navigation +const sitesNavigator: NavigationContainer = createStackNavigator( + { + Sites: { screen: Sites }, + SiteAreas: { screen: SiteAreas }, + Chargers: { screen: Chargers }, + ChargerDetailsTabs: { screen: chargerDetailsTabsNavigator }, + ChargerConnectorDetailsTabs: { screen: chargerConnectorDetailsTabsNavigator }, + TransactionDetailsTabs: { screen: transactionDetailsTabsNavigator } + }, + { + initialRouteName: 'Sites', + headerMode: 'none' + } +); + +// Chargers Stack Navigation +const chargersNavigator: NavigationContainer = createStackNavigator( + { + Chargers: { screen: Chargers }, + ChargerDetailsTabs: { screen: chargerDetailsTabsNavigator }, + ChargerConnectorDetailsTabs: { screen: chargerConnectorDetailsTabsNavigator }, + TransactionDetailsTabs: { screen: transactionDetailsTabsNavigator } + }, + { + initialRouteName: 'Chargers', + headerMode: 'none' + } +); + +const createTabBarIcon = (props: { focused: boolean; tintColor?: string; horizontal?: boolean;}, + type: 'AntDesign' | 'Entypo' | 'EvilIcons' | 'Feather' | 'FontAwesome' | 'FontAwesome5' | 'Foundation' | 'Ionicons' | 'MaterialCommunityIcons' | 'MaterialIcons' | 'Octicons' | 'SimpleLineIcons' | 'Zocial', + name: string): React.ReactNode => { + return +}; + +const transactionHistoryNavigator: NavigationContainer = createStackNavigator( + { + TransactionsHistory: { screen: TransactionsHistory }, + TransactionDetailsTabs: { screen: transactionDetailsTabsNavigator } + }, + { + initialRouteName: 'TransactionsHistory', + headerMode: 'none' + } +); + +const transactionInProgressNavigator: NavigationContainer = createStackNavigator( + { + TransactionsInProgress: { screen: TransactionsInProgress }, + ChargerDetailsTabs: { screen: chargerDetailsTabsNavigator }, + ChargerConnectorDetailsTabs: { screen: chargerConnectorDetailsTabsNavigator } + }, + { + initialRouteName: 'TransactionsInProgress', + headerMode: 'none' + } +); + +// Drawer Navigation +const appDrawerNavigator: NavigationContainer = createDrawerNavigator( + { + HomeNavigator: { screen: homeNavigator }, + SitesNavigator: { screen: sitesNavigator }, + ChargersNavigator: { screen: chargersNavigator }, + StatisticsNavigator: { screen: statisticsNavigator }, + TransactionHistoryNavigator: { screen: transactionHistoryNavigator }, + TransactionInProgressNavigator: { screen: transactionInProgressNavigator }, + }, + { + navigationOptions: { + swipeEnabled: true + }, + drawerWidth: appStyles.sideMenu.width, + initialRouteName: 'HomeNavigator', + unmountInactiveRoutes: true, + drawerPosition: 'right', + // @ts-ignore + contentComponent: (props) => + } +); + +const rootNavigator: any = createSwitchNavigator( + { + AuthNavigator: { screen: authNavigator }, + AppDrawerNavigator: { screen: appDrawerNavigator } + }, + { + initialRouteName: 'AuthNavigator' + } +); + +// Create a container to wrap the main navigator +const RootContainer: NavigationContainer = createAppContainer(rootNavigator); + +// Handle persistence of navigation +const persistNavigationState = async (navigationState: NavigationState) => { + try { + await SecuredStorage.saveNavigationState(navigationState); + } catch (error) { + // tslint:disable-next-line: no-console + console.log(error); + } +}; + +const loadNavigationState = async () => { + const navigationState = await SecuredStorage.getNavigationState(); + return navigationState; +}; + +export interface Props { +} + +interface State { +} + +export default class App extends React.Component { + public state: State; + public props: Props; + private notificationManager: NotificationManager; + private deepLinkingManager: DeepLinkingManager; + private centralServerProvider: CentralServerProvider; + private navigator: NavigationContainerComponent; + + constructor(props: Props) { + super(props); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + // eslint-disable-next-line class-methods-use-this + public async componentDidMount() { + // Get the central server + this.centralServerProvider = await ProviderFactory.getProvider(); + // Init Notification + this.notificationManager = NotificationManager.getInstance(); + this.notificationManager.setCentralServerProvider(this.centralServerProvider); + this.notificationManager.initialize(this.navigator); + await this.notificationManager.start(); + // Assign + this.centralServerProvider.setNotificationManager(this.notificationManager); + // Init Deep Linking + this.deepLinkingManager = DeepLinkingManager.getInstance(); + this.deepLinkingManager.initialize(this.navigator, this.centralServerProvider); + // Activate Deep links + this.deepLinkingManager.startListening(); + // Check on hold notification + this.notificationManager.checkOnHoldNotification(); + } + + public async componentWillUnmount() { + // Deactivate Deep links + this.deepLinkingManager.stopListening(); + // Stop Notifications + await this.notificationManager.stop(); + } + + // eslint-disable-next-line class-methods-use-this + public render() { + return ( + + + ); + } +} diff --git a/src/AppStyles.tsx b/src/AppStyles.tsx new file mode 100644 index 000000000..9a6074860 --- /dev/null +++ b/src/AppStyles.tsx @@ -0,0 +1,20 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet'; +import { ScaledSheet } from 'react-native-size-matters'; + +const commonStyles = ScaledSheet.create({ + sideMenu: { + width: '250@s', + }, +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/I18n/I18nManager.tsx b/src/I18n/I18nManager.tsx new file mode 100644 index 000000000..77fb1af0b --- /dev/null +++ b/src/I18n/I18nManager.tsx @@ -0,0 +1,91 @@ +import i18n from 'i18n-js'; +import moment from 'moment'; +import { I18nManager as I18nReactNativeManager } from 'react-native'; +import * as RNLocalize from 'react-native-localize'; +import Constants from '../utils/Constants'; +import Utils from '../utils/Utils'; +import deJsonLanguage from './languages/de.json'; +import enJsonLanguage from './languages/en.json'; +import frJsonLanguage from './languages/fr.json'; + +export default class I18nManager { + private static currency: string; + + public static async initialize() { + // Get the supported locales for moment + require('moment/locale/fr'); + require('moment/locale/de'); + require('moment/locale/en-gb'); + // Translation files + const translationGetters: any = { + en: () => enJsonLanguage, + fr: () => frJsonLanguage, + de: () => deJsonLanguage, + }; + // Fallback if no available language fits + const fallback = { languageTag: Constants.DEFAULT_LANGUAGE, isRTL: false }; + // Get current locale + const { languageTag, isRTL } = RNLocalize.findBestAvailableLanguage(Object.keys(translationGetters)) || fallback; + // Set translation files + i18n.translations.en = enJsonLanguage; + i18n.translations.fr = frJsonLanguage; + i18n.translations.de = deJsonLanguage; + // Update layout direction + I18nReactNativeManager.forceRTL(isRTL); + // Default + i18n.locale = languageTag; + moment.locale(languageTag); + } + + public static switchLocale(locale: string, currency: string) { + if (locale) { + return I18nManager.switchLanguage(Utils.getLanguageFromLocale(locale), currency); + } + } + + public static switchLanguage(language: string, currency: string) { + // Supported languages? + if (language && Constants.SUPPORTED_LANGUAGES.includes(language)) { + i18n.locale = language; + moment.locale(language); + } + // Keep the currency + I18nManager.currency = currency; + } + + public static formatNumber(value: number): string { + if (!isNaN(value)) { + return new Intl.NumberFormat(i18n.locale).format(value); + } + return '-'; + } + + public static formatCurrency(value: number): string { + if (!isNaN(value)) { + const currency = I18nManager.currency; + if (currency) { + return new Intl.NumberFormat(i18n.locale, { style: 'currency', currency }).format(value); + } + return I18nManager.formatNumber(Math.round(value * 100) / 100); + } + return '-'; + } + + public static formatPercentage(value: number): string { + if (!isNaN(value)) { + return new Intl.NumberFormat(i18n.locale, { style: 'percent' }).format(value); + } + return '-'; + } + + private static isValidDate(date: Date): boolean { + return !isNaN(new Date(date).getTime()); + } + + public static formatDateTime(value: Date, format: string = 'LLL') { + if (I18nManager.isValidDate(value)) { + return moment(value).format(format); + } + return '-'; + } +} diff --git a/src/I18n/languages/de.json b/src/I18n/languages/de.json new file mode 100644 index 000000000..1d5a76462 --- /dev/null +++ b/src/I18n/languages/de.json @@ -0,0 +1,286 @@ +{ + "general": { + "cannotConnectBackend": "Die Verbindung wurde unterbrochen", + "unexpectedErrorBackend": "Unexpected Backend Error", + "unexpectedError": "Unexpected Error", + "sessionExpired": "Sitzung abgelaufen", + "numbers": "Geben Sie eine gültige Zahl ein", + "email": "Geben Sie eine gültige E-Mail ein", + "mandatory": "ist notwendig", + "eulaUnexpectedError": "Cannot load the EULA", + "ok": "Ok", + "yes": "Ja", + "no": "Nein", + "clear": "Clear", + "close": "Close", + "apply": "Apply", + "cancel": "Abbrechen", + "version": "Version", + "search": "Suche", + "exitApp": "Beenden", + "exitAppConfirm": "Möchten Sie die Anwendung wirklich beenden?", + "noRecordFound": "Kein Eintrag gefunden", + "day": "d", + "hour": "h", + "minute": "m", + "second": "s", + "startDate": "Start Date", + "endDate": "End Date", + "onlyMyTransactions": "My Sessions", + "onlyAvailableChargers": "Available Chargers", + "wrongTenant": "You are connected to the wrong tenant", + "createdOn": "Created On", + "createdBy": "Created By", + "lastChangedOn": "Last Changed On", + "lastChangedBy": "Last Changed By" + }, + "sidebar": { + "home": "Home", + "sites": "Standorte", + "chargers": "Ladestationen", + "transactionsHistory": "Sessions History", + "transactionsInProgress": "Sessions In Progress", + "statistics": "Statistics" + }, + "authentication": { + "mandatoryTenant": "Die Organisation ist notwendig", + "unknownTenant": "Unbekannte Organisation!", + "mandatoryName": "Der Name ist notwendig", + "mandatoryFirstName": "Der Vorname ist notwendig", + "mandatoryEmail": "Die E-Mail ist notwendig", + "invalidEmail": "Die E-Mail ist ungültig", + "mandatoryPassword": "Das Passwort ist notwendig", + "logOut": "Ausloggen", + "mustSelectTenant": "Wählen Sie eine Organisation", + "wrongEmailOrPassword": "Falsche E-Mail oder Passwort", + "authenticationFailed": "Authentifizierung gescheitert", + "invalidCaptcha": "Ungültiges Captcha!", + "wrongEmail": "Ungültige E-Mail!", + "accountLocked": "Ihr Konto ist gesperrt.", + "registerUnexpectedError": "Cannot create account", + "emailAlreadyExists": "Email already exist", + "accountNotActive": "Ihr Konto ist nicht aktiv", + "accountAlreadyActive": "Your account is already active", + "accountVerifiedSuccess": "Your account has been activated with success!", + "accountPending": "Ihr Konto wurde noch nicht aktiviert, überprüfen Sie Ihre E-Mails!", + "activationTokenNotValid": "Your account's activation link is no longer valid", + "activationEmailNotValid": "This Email does not exist anymore", + "activationUnexpectedError": "Cannot activate account", + "loginUnexpectedError": "Cannot login", + "resetSuccess": "Anfrage angenommen, überprüfen Sie Ihre E-Mails!", + "eulaNotAccepted": "Sie müssen den Endnutzer-Lizenzvertrag annehmen", + "newUser": "Neuer Benutzer?", + "forgotYourPassword": "Passwort vergessen?", + "retrievePassword": "Passwort wieder auffinden", + "resetPassword": "Passwort zurücksetzen", + "backLogin": "Zurück zur Anmeldung", + "required": "Benötigt", + "acceptEula": "Ich bestätige den ", + "eula": "Endnutzer-Lizenzvertrag", + "login": "Anmelden", + "registerSuccess": "Konto erfolgreich erstellt, überprüfen Sie bitte Ihre E-Mails!", + "resetPasswordSuccess": "Passwort erfolgreich aktualisiert!", + "resetPasswordHashNotValid": "Anfrage nicht mehr gültig, fordern Sie erneut ein neues Passwort an", + "resetPasswordUnexpectedError": "Cannot reset password", + "verifyAccountTokenNotValid": "Request no longer valid, request a new account validation", + "haveAlreadyAccount": "Haben Sie bereits ein Konto?", + "name": "Name", + "firstName": "Vorname", + "email": "E-mail", + "password": "Passwort", + "repeatPassword": "Passwort wiederholen", + "signUp": "Konto erstellen", + "passwordRule": "Muss einen Kleinbuchstaben, einen Großbuchstaben, eine Zahl, ein Sonderzeichen und mindestens 8 Zeichen beinhalten.", + "passwordNotMatch": "Passwörter stimmen nicht miteinander überein", + "tenant": "Wählen Sie eine Organisation" + }, + "users": { + "userUnexpectedError": "Cannot read the user" + }, + "transactions": { + "transaction": "Session", + "transactions": "Session(s)", + "history": "History", + "in-progress": "In Progress", + "transactionsHistory": "Sitzungsverlauf", + "transactionsInProgress": "Laufende Sitzungen", + "transactionDoesNotExist": "Session does not exist", + "chargingCurve": "Sitzungsdiagramm", + "noTransactionsInProgress": "Es werden keine Sitzungen durchgeführt", + "noTransactionsHistory": "Kein Sitzungsverlauf", + "transactionUnexpectedError": "Cannot read the session", + "transactionStatsUnexpectedError": "Cannot read the statistics", + "transactionStartUnexpectedError": "Cannot start the session", + "transactionStopUnexpectedError": "Cannot stop the session" + }, + "home": { + "browseSites": "Sites", + "browseSitesNote": "Browse the Sites and Site Areas", + "browseChargers": "Charging Stations", + "browseChargersNote": "Browse the Charging Stations", + "browseSessions": "Sessions History", + "browseSessionsNote": "Browse the Sessions", + "browseStatistics": "Statistics", + "browseStatisticsNote": "Navigate to Statistics", + "ongoingSessions": "{{nbrSessions}} ongoing Session(s)", + "noOngoingSessions": "No Session In Progress", + "ongoingSessionsNote": "Navigate to Sessions in progress", + "statistics": "Statistics", + "numberOfSessions": "{{nbrSessions}} Sessions", + "noSessions": "No Session found", + "numberOfSessionsNote": "Total number of Sessions", + "totalConsumptiom": "{{totalConsumptiom}} kW.h", + "totalConsumptiomNote": "Total energy consumed", + "totalDuration": "{{totalDuration}}", + "totalDurationNote": "Total Sessions duration", + "totalInactivity": "{{totalInactivity}} ({{totalInactivityPercent}})", + "totalInactivityNote": "Total Inactivity duration", + "totalPrice": "{{totalPrice}}", + "totalPriceNote": "Total cost" + }, + "sites": { + "freeChargers": "Freie Ladestationen", + "chargePoint": "Ladepunkt", + "free": "Frei", + "occupied": "Besetzt", + "noSites": "Kein Standort gefunden", + "siteUnexpectedError": "Cannot read the site" + }, + "siteAreas": { + "title": "Standortbereiche", + "noChargers": "Dieser Standortbereich hat keine Ladestationen", + "noSiteAreas": "Kein Standortbereich gefunden", + "siteAreaUnexpectedError": "Cannot read the site area" + }, + "chargers": { + "title": "Ladestationen", + "heartBeat": "Herzschlag", + "chargers": "Charging Station(s)", + "noOCPPParameters": "No OCPP parameter", + "noChargerParameters": "No Charging Station parameter", + "chargerConfigurationUnexpectedError": "Cannot read the configuration of the charging station", + "chargerUnexpectedError": "Cannot read the charging station", + "chargerResetUnexpectedError": "Cannot reset the charging station", + "chargerRebootUnexpectedError": "Cannot reboot the charging station", + "chargerClearCacheUnexpectedError": "Cannot clear the cache of the charging station", + "chargerUnlockUnexpectedError": "Cannot unlock the connector", + "heartBeatOkMessage": "'{{chargeBoxID}}' funktioniert ordentlich und hat vor einer Minute einen Herzschlag gesendet", + "heartBeatKoMessage": "'{{chargeBoxID}}' ist fehlerhaft und hat zuletzt {{lastHeartBeat}} einen Herzschlag gesendet", + "resetHard": "Neubooten", + "resetHardMessage": "Möchten Sie wirklich die Ladestation '{{chargeBoxID}}' neu starten?", + "resetSoft": "Reset", + "resetSoftMessage": "Möchten Sie wirklich die Ladestation '{{chargeBoxID}}' zurücksetzen?", + "requestConfiguration": "Request Configuration", + "requestConfigurationMessage": "Do you really want to request the configuration of '{{chargeBoxID}}'?", + "unlockConnector": "Unlock Connector {{connectorId}}", + "unlockConnectorMessage": "Do you really want to unlock the connector {{connectorId}} of '{{chargeBoxID}}'?", + "clearCache": "Cache leeren", + "clearCacheMessage": "Möchten Sie wirklich den Cache der Ladestation '{{chargeBoxID}}' leeren?", + "noChargers": "Keine Ladestation gefunden", + "properties": "Properties", + "ocpp": "OCPP", + "actions": "Actions", + "noSession": "No Session", + "noSessionMessage": "No session has been done on that connector" + }, + "connector": { + "occupied": "Besetzt", + "charging": "Lädt", + "available": "Verfügbar", + "unavailable": "Unverfügbar", + "notCharging": "Inaktiv", + "suspendedEV": "EV angehalten", + "suspendedEVSE": "EVSE angehalten", + "faulted": "Fehlerhaft", + "reserved": "Gebucht", + "preparing": "Vorbereitung", + "finishing": "Vollendung", + "unknown": "Unbekannt", + "type2": "Type 2", + "comboCCS": "Kombo", + "chademo": "Chademo", + "domestic": "Hausanschluss" + }, + "details": { + "connector": "Anschluss", + "connectors": "Connectors", + "stoppedAt": "Stopped on", + "stoppedBy": "Stopped by", + "inactive": "Disconnected Charger", + "informations": "Informationen", + "graph": "Diagramm", + "notAuthorized": "You are not authorized to read this session", + "noTransaction": "Keine laufende Transaktion", + "startTransaction": "Transaktion starten", + "stopTransaction": "Transaktion stoppen", + "startTransactionMessage": "Wollen Sie wirklich eine neue Ladesitzung auf '{{chargeBoxID}}' starten?", + "stopTransactionMessage": "Wollen Sie die jetzige Ladesitzung auf '{{chargeBoxID}}' beenden?", + "notAuthorisedTitle": "Nicht zugelassen", + "notAuthorised": "Sie dürfen die Ladesitzung nicht beenden.", + "accepted": "Anfrage wurde angenommen", + "noBadgeID": "Kein Badge in Ihrem Profil!", + "denied": "Request has failed", + "duration": "(hh:mm)", + "total": "Summe", + "maximum": "Maximum", + "instant": "Momentan", + "battery": "Batterie", + "vendor": "Verkäufer", + "model": "Modell", + "ocppVersion": "OCPP Version", + "firmwareVersion": "Firmware Version", + "time": "Zeit (Minuten)", + "chargeInWatts": "Ladung (Watt)", + "instantPowerChartLabel": "Momentane Leistung (kW)", + "cumulatedChartLabel": "Kumuliert (kW.h)", + "batteryChartLabel": "Batterieladestand (%)", + "connectorMax": "Max. Leistung Anschluss (kW)", + "noData": "Nicht Daten", + "noSessionInProgress": "No Session in progress", + "serialNumber": "Serial Number", + "privateURL": "Private URL", + "publicURL": "Public URL", + "currentIP": "IP Route", + "lastReboot": "Last Reboot", + "capabilities": "Capabilities", + "ocppStandardParams": "OCPP Standard Params", + "ocppVendorParams": "OCPP Advanced Params", + "ocppAdvancedCommands": "OCPP Advanced Commands" + }, + "notifications": { + "mustLogin": "Sie müssen angemeldet sein", + "cannotNavigate": "Kann nicht zum Bildschirm navigieren", + "extraDataMissing": "Benachrichtigung nicht komplett", + "incorrectTenant": "Falsche Organisation", + "notifyEndOfTransaction": { + "message": "Ihre Ladesitzung auf '{{chargeBoxID}}' wurde beendet.", + "subMessage": "Ladesitzung beendet", + "longMessage": "Ihre Ladesitzung auf '{{chargeBoxID}}' wurde soeben beendet." + }, + "notifyEndOfCharge": { + "message": "Ladung auf '{{chargeBoxID}}' wurde beendet.", + "subMessage": "Ladeende", + "longMessage": "Ihr Fahrzeug an '{{chargeBoxID}}' wurde vollständig geladen. Sie können die Ladesitzung beenden und Ihr Fahrzeug wegfahren." + }, + "notifyOptimalChargeReached": { + "message": "Der optimale Ladestand auf '{{chargeBoxID}}' wurde erreicht.", + "subMessage": "Optimaler Ladestand", + "longMessage": "Der optimale Ladestand auf '{{chargeBoxID}}' wurde erreicht." + }, + "notifyChargingStationStatusError": { + "message": "Fehler auf '{{chargeBoxID}}'", + "subMessage": "Fehler auf Ladestation", + "longMessage": "Fehler auf '{{chargeBoxID}}' - Anschluss {{connectorId}}: {{error}}." + }, + "notifyChargingStationRegistered": { + "message": "'{{chargeBoxID}}' wurde auf dem zentralen Server registriert.", + "subMessage": "Ladestation registriert", + "longMessage": "'{{chargeBoxID}}' wurde auf dem zentralen Server registriert." + }, + "notifyUnknownUserBadged": { + "message": "Ein unbekannter Benutzer hat auf '{{chargeBoxID}}' gebadgt.", + "subMessage": "Unbekannter Benutzer", + "longMessage": "Ein unbekanner Benutzer hat auf '{{chargeBoxID}}' gebadgt." + } + } +} diff --git a/src/I18n/languages/en.json b/src/I18n/languages/en.json new file mode 100644 index 000000000..ddaac44eb --- /dev/null +++ b/src/I18n/languages/en.json @@ -0,0 +1,286 @@ +{ + "general": { + "cannotConnectBackend": "Connection has been lost", + "unexpectedErrorBackend": "Unexpected Backend Error", + "unexpectedError": "Unexpected Error", + "sessionExpired": "Session has expired", + "numbers": "Enter a valid number", + "email": "Enter a valid email address", + "mandatory": "is mandatory", + "eulaUnexpectedError": "Cannot load the EULA", + "ok": "Ok", + "yes": "Yes", + "no": "No", + "clear": "Clear", + "close": "Close", + "apply": "Apply", + "cancel": "Cancel", + "version": "Version", + "search": "Search", + "exitApp": "Exit App", + "exitAppConfirm": "Do you really want to exit the application?", + "noRecordFound": "No record found", + "day": "d", + "hour": "h", + "minute": "m", + "second": "s", + "startDate": "Start Date", + "endDate": "End Date", + "onlyMyTransactions": "My Sessions", + "onlyAvailableChargers": "Available Chargers", + "wrongTenant": "You are connected to the wrong tenant", + "createdOn": "Created On", + "createdBy": "Created By", + "lastChangedOn": "Last Changed On", + "lastChangedBy": "Last Changed By" + }, + "sidebar": { + "home": "Home", + "sites": "Sites", + "chargers": "Charging Stations", + "transactionsHistory": "Sessions History", + "transactionsInProgress": "Sessions In Progress", + "statistics": "Statistics" + }, + "authentication": { + "mandatoryTenant": "The Organization is mandatory", + "unknownTenant": "Unknown Organization!", + "mandatoryName": "The Name is mandatory", + "mandatoryFirstName": "The First Name is mandatory", + "mandatoryEmail": "The Email is mandatory", + "invalidEmail": "The Email is invalid", + "mandatoryPassword": "The Password is mandatory", + "logOut": "Log Out", + "mustSelectTenant": "Select an Organization", + "wrongEmailOrPassword": "Wrong email or password", + "authenticationFailed": "Authentication Failed", + "invalidCaptcha": "The Captcha has been refused (security)!", + "wrongEmail": "Wrong email!", + "emailAlreadyExists": "Email already exist", + "registerUnexpectedError": "Cannot create account", + "accountLocked": "Your account is locked", + "accountNotActive": "Your account is not active", + "accountAlreadyActive": "Your account is already active", + "accountVerifiedSuccess": "Your account has been activated with success!", + "accountPending": "Your account is pending! Check your e-mail", + "activationTokenNotValid": "Your account's activation link is no longer valid", + "activationEmailNotValid": "This Email does not exist anymore", + "activationUnexpectedError": "Cannot activate account", + "loginUnexpectedError": "Cannot login", + "resetSuccess": "Request accepted! Check your e-mail", + "eulaNotAccepted": "You must accept the End-User License Agreement", + "newUser": "New User?", + "forgotYourPassword": "Forgot Password?", + "retrievePassword": "Retrieve Password", + "resetPassword": "Reset Password", + "backLogin": "Back to Login", + "required": "Required", + "acceptEula": "I accept the ", + "eula": "End-User License Agreement", + "login": "Login", + "registerSuccess": "Account created with success! Check your email", + "resetPasswordSuccess": "Password updated with success!", + "resetPasswordUnexpectedError": "Cannot reset password", + "resetPasswordHashNotValid": "Request no longer valid, request a new password again", + "verifyAccountTokenNotValid": "Request no longer valid, request a new account validation", + "haveAlreadyAccount": "Already have an account?", + "name": "Name", + "firstName": "First Name", + "email": "Email", + "password": "Password", + "repeatPassword": "Repeat password", + "signUp": "Sign Up", + "passwordRule": "Must contain 1 letter lowercase and uppercase, 1 number, 1 special char and 8 chars long", + "passwordNotMatch": "Password does not match", + "tenant": "Choose an Organization" + }, + "users": { + "userUnexpectedError": "Cannot read the user" + }, + "transactions": { + "transaction": "Session", + "transactions": "Session(s)", + "history": "History", + "in-progress": "In Progress", + "transactionsHistory": "Sessions History", + "transactionsInProgress": "Sessions In Progress", + "transactionDoesNotExist": "Session does not exist", + "chargingCurve": "Session Chart", + "noTransactionsInProgress": "No Session in progress", + "noTransactionsHistory": "No Session history", + "transactionUnexpectedError": "Cannot read the session", + "transactionStatsUnexpectedError": "Cannot read the statistics", + "transactionStartUnexpectedError": "Cannot start the session", + "transactionStopUnexpectedError": "Cannot stop the session" + }, + "home": { + "browseSites": "Sites", + "browseSitesNote": "Navigate to Sites and Site Areas", + "browseChargers": "Charging Stations", + "browseChargersNote": "Navigate to Charging Stations", + "browseSessions": "Sessions History", + "browseSessionsNote": "Navigate to Sessions", + "browseStatistics": "Statistics", + "browseStatisticsNote": "Navigate to Statistics", + "ongoingSessions": "Sessions In Progress", + "noOngoingSessions": "No Session In Progress", + "ongoingSessionsNote": "Navigate to Sessions in progress", + "statistics": "Statistics", + "numberOfSessions": "{{nbrSessions}} Sessions", + "noSessions": "No Session found", + "numberOfSessionsNote": "Total number of Sessions", + "totalConsumptiom": "{{totalConsumptiom}} kW.h", + "totalConsumptiomNote": "Total energy consumed", + "totalDuration": "{{totalDuration}}", + "totalDurationNote": "Total Sessions duration", + "totalInactivity": "{{totalInactivity}} ({{totalInactivityPercent}})", + "totalInactivityNote": "Total Inactivity duration", + "totalPrice": "{{totalPrice}}", + "totalPriceNote": "Total cost" + }, + "sites": { + "freeChargers": "Free chargers", + "chargePoint": "Charge Point", + "free": "Free", + "occupied": "Occupied", + "noSites": "No Site found", + "siteUnexpectedError": "Cannot read the site" + }, + "siteAreas": { + "title": "Site Areas", + "noChargers": "This Site Area has no Charger", + "noSiteAreas": "No Site Area found", + "siteAreaUnexpectedError": "Cannot read the site area" + }, + "chargers": { + "title": "Charging Stations", + "heartBeat": "Heartbeat", + "chargers": "Charging Station(s)", + "noOCPPParameters": "No OCPP parameter", + "noChargerParameters": "No Charging Station parameter", + "chargerConfigurationUnexpectedError": "Cannot read the configuration of the charging station", + "chargerUnexpectedError": "Cannot read the charging station", + "chargerResetUnexpectedError": "Cannot reset the charging station", + "chargerRebootUnexpectedError": "Cannot reboot the charging station", + "chargerClearCacheUnexpectedError": "Cannot clear the cache of the charging station", + "chargerUnlockUnexpectedError": "Cannot unlock the connector", + "heartBeatOkMessage": "'{{chargeBoxID}}' is working properly and reported its status a minute ago", + "heartBeatKoMessage": "'{{chargeBoxID}}' is not working properly and hasn't reported its status since {{lastHeartBeat}}", + "resetHard": "Reboot", + "resetHardMessage": "Do you really want to reboot '{{chargeBoxID}}'?", + "resetSoft": "Reset", + "resetSoftMessage": "Do you really want to reset '{{chargeBoxID}}'?", + "requestConfiguration": "Request Configuration", + "requestConfigurationMessage": "Do you really want to request the configuration of '{{chargeBoxID}}'?", + "unlockConnector": "Unlock Connector {{connectorId}}", + "unlockConnectorMessage": "Do you really want to unlock the connector {{connectorId}} of '{{chargeBoxID}}'?", + "clearCache": "Clear Cache", + "clearCacheMessage": "Do you really want to clear the cache of '{{chargeBoxID}}'?", + "noChargers": "No Charging Station found", + "properties": "Properties", + "ocpp": "OCPP", + "actions": "Actions", + "noSession": "No Session", + "noSessionMessage": "No session has been done on that connector" + }, + "connector": { + "occupied": "Occupied", + "charging": "Charging", + "available": "Available", + "unavailable": "Unavailable", + "notCharging": "Inactive", + "suspendedEV": "Suspended EV", + "suspendedEVSE": "Suspended EVSE", + "faulted": "Faulted", + "reserved": "Reserved", + "preparing": "Preparing", + "finishing": "Finishing", + "unknown": "Unknown", + "type2": "Type 2", + "comboCCS": "Combo", + "chademo": "Chademo", + "domestic": "Domestic" + }, + "details": { + "connector": "Connector", + "connectors": "Connectors", + "stoppedAt": "Stopped on", + "stoppedBy": "Stopped by", + "inactive": "Disconnected Charger", + "informations": "Informations", + "graph": "Chart", + "notAuthorized": "You are not authorized to read this session", + "noTransaction": "No ongoing transaction", + "startTransaction": "Start transaction", + "stopTransaction": "Stop transaction", + "startTransactionMessage": "Do you really want to start a new session on the charging station '{{chargeBoxID}}'?", + "stopTransactionMessage": "Do you really want to stop the session of the charging station '{{chargeBoxID}}'?", + "notAuthorisedTitle": "Not Authorized", + "notAuthorised": "You are not authorized to stop the transaction.", + "accepted": "Request has been accepted", + "noBadgeID": "No badge in your profile", + "denied": "Request has failed", + "duration": "(hh:mm)", + "total": "Total", + "maximum": "Maximum", + "instant": "Instant", + "battery": "Battery", + "vendor": "Vendor", + "model": "Model", + "ocppVersion": "OCPP Version", + "firmwareVersion": "Firmware Version", + "time": "Time (mins)", + "chargeInWatts": "Charge (Watt)", + "instantPowerChartLabel": "Instant Power (kW)", + "cumulatedChartLabel": "Cumulated (kW.h)", + "batteryChartLabel": "Battery Level (%)", + "connectorMax": "Connector Max Power (kW)", + "noData": "No Data", + "noSessionInProgress": "No Session in progress", + "serialNumber": "Serial Number", + "privateURL": "Private URL", + "publicURL": "Public URL", + "currentIP": "IP Route", + "lastReboot": "Last Reboot", + "capabilities": "Capabilities", + "ocppStandardParams": "OCPP Standard Params", + "ocppVendorParams": "OCPP Advanced Params", + "ocppAdvancedCommands": "OCPP Advanced Commands" + }, + "notifications": { + "mustLogin": "You must be logged in", + "cannotNavigate": "Cannot navigate to the screen", + "extraDataMissing": "Notification is corrupted", + "incorrectTenant": "The organization is incorrect", + "notifyEndOfTransaction": { + "message": "Your session on '{{chargeBoxID}}' has just finished.", + "subMessage": "Session Finished", + "longMessage": "Your session on '{{chargeBoxID}}' has just finished." + }, + "notifyEndOfCharge": { + "message": "Your charge on '{{chargeBoxID}}' has finished.", + "subMessage": "End Of Charge", + "longMessage": "Your charge on '{{chargeBoxID}}' has finished. You can now stop the session and move your vehicle." + }, + "notifyOptimalChargeReached": { + "message": "Your optimal charge on '{{chargeBoxID}}' has been reached.", + "subMessage": "Optimal Charge", + "longMessage": "Your optimal charge on '{{chargeBoxID}}' has been reached." + }, + "notifyChargingStationStatusError": { + "message": "Error occurred on '{{chargeBoxID}}'", + "subMessage": "Charging Station Error", + "longMessage": "Error occurred on '{{chargeBoxID}}' - Connector {{connectorId}}: {{error}}." + }, + "notifyChargingStationRegistered": { + "message": "'{{chargeBoxID}}' just got registered to the central server.", + "subMessage": "Charger Registered", + "longMessage": "'{{chargeBoxID}}' just got registered to the central server." + }, + "notifyUnknownUserBadged": { + "message": "An unknown user has just badged on '{{chargeBoxID}}'.", + "subMessage": "Unknown User", + "longMessage": "An unknown user has just badged on '{{chargeBoxID}}'." + } + } +} diff --git a/src/I18n/languages/fr.json b/src/I18n/languages/fr.json new file mode 100644 index 000000000..0abd57cbd --- /dev/null +++ b/src/I18n/languages/fr.json @@ -0,0 +1,286 @@ +{ + "general": { + "cannotConnectBackend": "La connexion a été perdue", + "unexpectedErrorBackend": "Erreur Backend Inattendue", + "unexpectedError": "Erreur Applicative", + "sessionExpired": "La session a expirée", + "numbers": "Entrez un nombre valide", + "email": "Entrez une adresse email valide", + "mandatory": "est obligatoire", + "eulaUnexpectedError": "Impossible de charger les CGUs", + "ok": "Ok", + "yes": "Oui", + "no": "Non", + "clear": "Effacer", + "close": "Fermer", + "cancel": "Annuler", + "apply": "Appliquer", + "version": "Version", + "search": "Rechercher", + "exitApp": "Quitter", + "exitAppConfirm": "Voulez-vous vraiment quitter l'application ?", + "noRecordFound": "Pas d'enregistrement trouvé", + "day": "j", + "hour": "h", + "minute": "m", + "second": "s", + "startDate": "Date Début", + "endDate": "Date Fin", + "onlyMyTransactions": "Mes Sessions", + "onlyAvailableChargers": "Bornes Disponibles", + "wrongTenant": "Vous êtes connecté sur la mauvaise organisation", + "createdOn": "Créé le", + "createdBy": "Créé par", + "lastChangedOn": "Modifié le", + "lastChangedBy": "Modifié par" + }, + "sidebar": { + "home": "Home", + "sites": "Sites", + "chargers": "Bornes", + "transactionsHistory": "Historique Sessions", + "transactionsInProgress": "Sessions En Cours", + "statistics": "Statistiques" + }, + "authentication": { + "mandatoryTenant": "L'organisation est obligatoire", + "unknownTenant": "Organisation inconnue!", + "mandatoryName": "Le Nom est obligatoire", + "mandatoryFirstName": "Le Prénom est obligatoire", + "mandatoryEmail": "L'Email est obligatoire", + "invalidEmail": "L'Email est invalide", + "mandatoryPassword": "Le Mot de Passe est obligatoire", + "logOut": "Se déconnecter", + "mustSelectTenant": "Selectionnez une Organisation", + "wrongEmailOrPassword": "Mauvais email ou mot de passe", + "authenticationFailed": "Authentification Echouée", + "invalidCaptcha": "Le Captcha a été refusé (sécurité)!", + "wrongEmail": "Email inconnu !", + "emailAlreadyExists": "Cet Email existe déjà", + "registerUnexpectedError": "Impossible de créer le compte", + "accountLocked": "Votre compte est bloqué", + "accountNotActive": "Votre compte est inactif", + "accountAlreadyActive": "Votre compte a déjà été activé", + "accountVerifiedSuccess": "Votre compte a été activé avec succès!", + "accountPending": "Votre compte n'est pas activé! Vérifiez vos e-mails", + "activationTokenNotValid": "Le lien d'activation de votre compte n'est plus valide", + "activationEmailNotValid": "Cet Email n'existe plus", + "activationUnexpectedError": "Impossible d'activer le compte", + "loginUnexpectedError": "Connexion impossible", + "resetSuccess": "Requête acceptée ! Vérifiez vos e-mails", + "eulaNotAccepted": "Vous devez accepter les conditions d'utilisation", + "newUser": "Nouvel Utilisateur ?", + "forgotYourPassword": "Mot de passe oublié?", + "retrievePassword": "Récupérez Mot de Passe", + "resetPassword": "Réinitialiser Mot de Passe", + "backLogin": "Se Connecter", + "required": "Obligatoire", + "acceptEula": "J'accepte les ", + "eula": "Conditions d'utilisation", + "login": "S'identifier", + "registerSuccess": "Compte créé avec succès ! Vérifiez vos emails", + "resetPasswordSuccess": "Mot de passe mis à jour avec succès !", + "resetPasswordHashNotValid": "La requete n'est plus valide, refaites une demande de mot de passe", + "resetPasswordUnexpectedError": "Impossible de réinitialiser le mot de passe", + "verifyAccountTokenNotValid": "La requete n'est plus valide, refaites une demande d'activation de compte", + "haveAlreadyAccount": "Avez-vous déjà un compte?", + "name": "Nom", + "firstName": "Prénom", + "email": "Email", + "password": "Mot de passe", + "repeatPassword": "Répétez mot de passe", + "signUp": "S'enregistrer", + "passwordRule": "Doit contenir 1 char. minuscule et majuscule, 1 nombre, 1 char. spécial et une longueur minimum de 8", + "passwordNotMatch": "Les mots de passes ne correspondent pas", + "tenant": "Choisir une Organisation" + }, + "users": { + "userUnexpectedError": "Impossible de lire l'utilisateur" + }, + "transactions": { + "transaction": "Session", + "transactions": "Session(s)", + "history": "Historique", + "in-progress": "En Cours", + "transactionsHistory": "Historique Sessions", + "transactionsInProgress": "Sessions En Cours", + "transactionDoesNotExist": "Session inéxistante", + "chargingCurve": "Graphique Session", + "noTransactionsInProgress": "Pas de Session en cours", + "noTransactionsHistory": "Pas d'historique de Session", + "transactionUnexpectedError": "Impossible de lire la session", + "transactionStatsUnexpectedError": "Impossible de lire les statistiques", + "transactionStartUnexpectedError": "Impossible de démarrer la session", + "transactionStopUnexpectedError": "Impossible de stopper la session" + }, + "home": { + "browseSites": "Sites", + "browseSitesNote": "Naviguez vers les Sites et les Zones", + "browseChargers": "Bornes", + "browseChargersNote": "Naviguez vers les Bornes", + "browseSessions": "Historique Sessions", + "browseSessionsNote": "Naviguez vers les Sessions", + "browseStatistics": "Statistiques", + "browseStatisticsNote": "Naviguez vers les Statistiques", + "ongoingSessions": "Sessions En Cours", + "noOngoingSessions": "Pas de Session en cours", + "ongoingSessionsNote": "Naviguez vers les Session en cours", + "statistics": "Statistiques", + "numberOfSessions": "{{nbrSessions}} Sessions", + "noSessions": "Pas de Session trouvée", + "numberOfSessionsNote": "Nombre total de Sessions", + "totalConsumptiom": "{{totalConsumptiom}} kW.h", + "totalConsumptiomNote": "Energie totale consommée", + "totalDuration": "{{totalDuration}}", + "totalDurationNote": "Durée totale des Sessions", + "totalInactivity": "{{totalInactivity}} ({{totalInactivityPercent}})", + "totalInactivityNote": "Durée totale d'inactivité", + "totalPrice": "{{totalPrice}}", + "totalPriceNote": "Cout total" + }, + "sites": { + "freeChargers": "Chargeurs disponibles", + "chargePoint": "Point de Charge", + "free": "Libre(s)", + "occupied": "Occupé(s)", + "noSites": "Aucun Site trouvé", + "siteUnexpectedError": "Impossible de lire le site" + }, + "siteAreas": { + "title": "Zones", + "noChargers": "Cette Zone n'a pas de Borne", + "noSiteAreas": "Aucune Zone trouvée", + "siteAreaUnexpectedError": "Cannot read the site area" + }, + "chargers": { + "title": "Bornes", + "heartBeat": "Heartbeat", + "chargers": "Borne(s)", + "noOCPPParameters": "Pas de parametre OCPP", + "noChargerParameters": "Pas de parametre", + "chargerConfigurationUnexpectedError": "Impossible de lire la configuration de la borne", + "chargerUnexpectedError": "Impossible de lire la borne", + "chargerResetUnexpectedError": "Impossible de réinitialiser la borne", + "chargerRebootUnexpectedError": "Impossible de redémarrer la borne", + "chargerClearCacheUnexpectedError": "Impossible d'effacer le cache de la borne", + "chargerUnlockUnexpectedError": "Impossible de dévérouiller le connecteur", + "heartBeatOkMessage": "'{{chargeBoxID}}' fonctionne correctement et a reporté son statut il y a moins d'une minute", + "heartBeatKoMessage": "'{{chargeBoxID}}' ne fonctionne pas correctement et n'a pas reporté son statut depuis {{lastHeartBeat}}", + "resetHard": "Redémarrer", + "resetHardMessage": "Voulez-vous vraiment redémarrer '{{chargeBoxID}}'?", + "resetSoft": "Réinitialiser", + "resetSoftMessage": "Voulez-vous vraiment réinitialiser '{{chargeBoxID}}'?", + "requestConfiguration": "Récupérer la Configuration", + "requestConfigurationMessage": "Voulez-vous vraiment récupérer la configuration de la borne '{{chargeBoxID}}'?", + "unlockConnector": "Dévérouiller Connecteur {{connectorId}}", + "unlockConnectorMessage": "Voulez-vous vraiment dévérouiller le connecteur {{connectorId}} de '{{chargeBoxID}}'?", + "clearCache": "Effacer le Cache", + "clearCacheMessage": "Voulez-vous vraiment le cache de '{{chargeBoxID}}'?", + "noChargers": "Aucune Borne trouvée", + "properties": "Propriétées", + "ocpp": "OCPP", + "actions": "Actions", + "noSession": "Aucune Session", + "noSessionMessage": "Auncune session n'a été faite sur ce connecteur" + }, + "connector": { + "occupied": "Occupé", + "charging": "En charge", + "available": "Disponible", + "unavailable": "Indisponible", + "notCharging": "Inactif", + "suspendedEV": "EV Suspendu", + "suspendedEVSE": "EVSE Suspendu", + "faulted": "Erreur", + "reserved": "Réservé", + "preparing": "Préparation", + "finishing": "Finalisation", + "unknown": "Unknown", + "type2": "Type 2", + "comboCCS": "Combo", + "chademo": "Chademo", + "domestic": "Domestique" + }, + "details": { + "connector": "Connecteur", + "connectors": "Connecteurs", + "stoppedAt": "Stoppée le", + "stoppedBy": "Stoppée par", + "inactive": "Borne Déconnectée", + "informations": "Informations", + "graph": "Courbe", + "notAuthorized": "Vous n'êtes pas autorisé à lire cette session", + "noTransaction": "Pas de transaction en cours", + "startTransaction": "Démarrer transaction", + "stopTransaction": "Stopper transaction", + "startTransactionMessage": "Voulez-vous vraiment démarrer une nouvelle session sur la borne '{{chargeBoxID}}'", + "stopTransactionMessage": "Voulez-vous vraiment arrêter la session sur la borne '{{chargeBoxID}}'", + "notAuthorisedTitle": "Non autorisé", + "notAuthorised": "Vous n'êtes pas autorisé à arrêter la transaction.", + "accepted": "La requête a été acceptée", + "noBadgeID": "Pas de badge dans votre profile", + "denied": "La requête a échouée", + "duration": "(hh:mm)", + "total": "Total", + "maximum": "Maximum", + "instant": "Instant.", + "battery": "Battery", + "vendor": "Vendeur", + "model": "Modèle", + "ocppVersion": "Version OCPP", + "firmwareVersion": "Version Firmware", + "time": "Temps (mins)", + "chargeInWatts": "Charge (Watt)", + "instantPowerChartLabel": "Puissance Instantanée (kW)", + "cumulatedChartLabel": "Cumulé (kW.h)", + "batteryChartLabel": "Niveau Batterie (%)", + "connectorMax": "Connecteur Max Power (kW)", + "noData": "Pas de données", + "noSessionInProgress": "Pas de session en cours", + "serialNumber": "No Série", + "privateURL": "URL Privée", + "publicURL": "URL Public", + "currentIP": "Addressage IP", + "lastReboot": "Dernier Reboot", + "capabilities": "Capacitées", + "ocppStandardParams": "OCPP Params Standard", + "ocppVendorParams": "OCPP Params Avancés", + "ocppAdvancedCommands": "OCPP Commandes Avancées" + }, + "notifications": { + "mustLogin": "Vous devez etre connecté", + "cannotNavigate": "Impossible de naviger vers l'écran", + "extraDataMissing": "La notification est corrompue", + "incorrectTenant": "L'organisation est incorrecte", + "notifyEndOfSession": { + "message": "Votre session sur '{{chargeBoxID}}' est terminée.", + "subMessage": "Session Terminée", + "longMessage": "Votre session sur '{{chargeBoxID}}' est terminée." + }, + "notifyEndOfCharge": { + "message": "Votre charge maximale sur '{{chargeBoxID}}' a été atteinte.", + "subMessage": "Fin De Charge", + "longMessage": "Votre charge maximale sur '{{chargeBoxID}}' a été atteinte. Vous pouvez stopper la session et déplacer votre véhicule." + }, + "notifyOptimalChargeReached": { + "message": "Votre charge optimale sur '{{chargeBoxID}}' a été atteinte.", + "subMessage": "Charge Optimale", + "longMessage": "Votre charge optimale sur '{{chargeBoxID}}' a été atteinte." + }, + "notifyChargingStationStatusError": { + "message": "Une erreur est survenue sur '{{chargeBoxID}}'", + "subMessage": "Erreur Borne", + "longMessage": "Une erreur est survenue sur '{{chargeBoxID}}' - Connecteur {{connectorId}}: {{error}}." + }, + "notifyChargingStationRegistered": { + "message": "'{{chargeBoxID}}' vient de se connecter au serveur central.", + "subMessage": "Borne Connectée", + "longMessage": "'{{chargeBoxID}}' vient de se connecter au serveur central." + }, + "notifyUnknownUserBadged": { + "message": "Un utilisateur inconnu vient juste de badger sur '{{chargeBoxID}}'.", + "subMessage": "Utilisateur Inconnu", + "longMessage": "Un utilisateur inconnu vient juste de badger sur '{{chargeBoxID}}'." + } + } +} diff --git a/src/boot/Setup.tsx b/src/boot/Setup.tsx new file mode 100644 index 000000000..32cccf361 --- /dev/null +++ b/src/boot/Setup.tsx @@ -0,0 +1,16 @@ +import { StyleProvider } from 'native-base'; +import React from 'react'; +import { Component } from 'react'; +import App from '../App'; +import Theme from '../theme/components'; +import variables from '../theme/variables/commonColor'; + +export default class Setup extends Component { + public render() { + return ( + + + + ); + } +} diff --git a/src/components/charger/ChargerComponent.tsx b/src/components/charger/ChargerComponent.tsx new file mode 100644 index 000000000..9a8d505ec --- /dev/null +++ b/src/components/charger/ChargerComponent.tsx @@ -0,0 +1,96 @@ +import I18n from 'i18n-js'; +import moment from 'moment'; +import { Button, Icon, Text, View } from 'native-base'; +import React from 'react'; +import { Alert } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import BaseProps from '../../types/BaseProps'; +import ChargingStation from '../../types/ChargingStation'; +import Utils from '../../utils/Utils'; +import computeStyleSheet from './ChargerComponentStyles'; +import ChargerConnectorComponent from './connector/ChargerConnectorComponent'; + +export interface Props extends BaseProps { + charger: ChargingStation; + isAdmin: boolean; + isSiteAdmin: boolean; +} + +interface State { +} + +export default class ChargerComponent extends React.Component { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public showHeartbeatStatus = () => { + const { charger } = this.props; + let message = I18n.t('chargers.heartBeatOkMessage', { chargeBoxID: charger.id }); + if (charger.inactive) { + message = I18n.t('chargers.heartBeatKoMessage', { + chargeBoxID: charger.id, + lastHeartBeat: moment(new Date(charger.lastHeartBeat),null, true).fromNow(true) + }); + } + Alert.alert(I18n.t('chargers.heartBeat'), message, [{ text: I18n.t('general.ok') }]); + }; + + public render() { + const style = computeStyleSheet(); + const { charger, isAdmin, isSiteAdmin, navigation } = this.props; + return ( + + + {charger.id} + + {(isAdmin || isSiteAdmin) && + + } + + + + + {charger.connectors.map((connector) => ( + + ))} + + + ); + } +} diff --git a/src/components/charger/ChargerComponentStyles.tsx b/src/components/charger/ChargerComponentStyles.tsx new file mode 100644 index 000000000..93a1a20f0 --- /dev/null +++ b/src/components/charger/ChargerComponentStyles.tsx @@ -0,0 +1,68 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + flexDirection: 'column', + borderBottomWidth: 1, + borderBottomColor: commonColor.brandPrimaryDark + }, + headerContent: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingLeft: '5@s', + paddingRight: '5@s', + borderBottomColor: commonColor.listBorderColor, + borderBottomWidth: 1, + backgroundColor: commonColor.headerBgColor + }, + headerName: { + color: commonColor.headerTextColor, + fontSize: '20@s', + marginLeft: '5@s', + fontWeight: 'bold' + }, + buttonContainer: { + flexDirection: 'row', + justifyContent: 'flex-end', + }, + button: { + marginLeft: '10@s', + marginRight: '10@s' + }, + icon: { + fontSize: '20@s', + paddingLeft: '20@s', + }, + heartbeatIcon: { + color: commonColor.brandSuccess, + paddingLeft: '20@s', + fontSize: '18@s' + }, + deadHeartbeatIcon: { + color: commonColor.brandDanger, + paddingLeft: '20@s', + fontSize: '18@s' + }, + connectorsContainer: { + flexDirection: 'row', + justifyContent: 'flex-start', + alignItems: 'center', + flexWrap: 'wrap' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/charger/connector/ChargerConnectorComponent.tsx b/src/components/charger/connector/ChargerConnectorComponent.tsx new file mode 100644 index 000000000..7fa0de7e0 --- /dev/null +++ b/src/components/charger/connector/ChargerConnectorComponent.tsx @@ -0,0 +1,194 @@ +import I18n from 'i18n-js'; +import { Icon, Text, View } from 'native-base'; +import React from 'react'; +import { TouchableOpacity } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import Chademo from '../../../../assets/connectorType/chademo.svg'; +import ComboCCS from '../../../../assets/connectorType/combo-ccs.svg'; +import Domestic from '../../../../assets/connectorType/domestic-ue.svg'; +import NoConnector from '../../../../assets/connectorType/no-connector.svg'; +import Type1CCS from '../../../../assets/connectorType/type1-ccs.svg'; +import Type1 from '../../../../assets/connectorType/type1.svg'; +import Type2 from '../../../../assets/connectorType/type2.svg'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseProps from '../../../types/BaseProps'; +import ChargingStation, { Connector, ConnectorType } from '../../../types/ChargingStation'; +import Constants from '../../../utils/Constants'; +import Utils from '../../../utils/Utils'; +import ConnectorStatusComponent from '../../connector-status/ConnectorStatusComponent'; +import computeStyleSheet from './ChargerConnectorComponentStyles'; + +export interface Props extends BaseProps { + charger: ChargingStation; + connector: Connector; +} + +interface State { + showBatteryLevel?: boolean; +} + +export default class ChargerConnectorComponent extends React.Component { + public state: State; + public props: Props; + private timerAnimation: number; + + constructor(props: Props) { + super(props); + // Init State + this.state = { + showBatteryLevel: false + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + // Refresh every minutes + this.timerAnimation = setInterval(() => { + // Animate + this.animate(); + }, Constants.ANIMATION_PERIOD_MILLIS); + } + + public componentWillUnmount() { + // Stop the timer + if (this.timerAnimation) { + clearInterval(this.timerAnimation); + } + } + + public animate() { + const { connector } = this.props; + if (connector && connector.currentStateOfCharge === 0) { + // SoC not supported + return; + } + // Switch battery/Consumption + this.setState({ + showBatteryLevel: !this.state.showBatteryLevel + }); + } + + public renderFirstConnectorDetails = (connector: Connector) => ( + + ); + + private getConnectorTypeSVG = (connectorType: ConnectorType, style: any): Element => { + switch (connectorType) { + case ConnectorType.CHADEMO: + return ; + case ConnectorType.TYPE_2: + return ; + case ConnectorType.COMBO_CCS: + return ; + case ConnectorType.DOMESTIC: + return ; + case ConnectorType.TYPE_1: + return ; + case ConnectorType.TYPE_1_CCS: + return ; + } + return ; + } + + public renderSecondConnectorDetails = (connector: Connector, style: any) => { + return connector.activeTransactionID !== 0 ? ( + + + + {connector.currentConsumption / 1000 < 10 + ? connector.currentConsumption > 0 + ? (I18nManager.formatNumber(Math.round(connector.currentConsumption / 10) / 100)) + : 0 + : I18nManager.formatNumber(Math.trunc(connector.currentConsumption / 1000))} + + + {I18n.t('details.instant')} + + + (kW) + + + + {connector.currentStateOfCharge} + + {I18n.t('details.battery')} + + + (%) + + + + ) : ( + + {/* */} + {this.getConnectorTypeSVG(connector.type, style)} + {Utils.translateConnectorType(connector.type)} + + ); + } + + public renderThirdConnectorDetails = (connector: Connector, style: any) => + connector.activeTransactionID !== 0 ? ( + + {I18nManager.formatNumber(Math.round(connector.totalConsumption / 1000))} + + {I18n.t('details.total')} + + + (kW.h) + + + ) : ( + + {I18nManager.formatNumber(Math.trunc(connector.power / 1000))} + + {I18n.t('details.maximum')} + + + (kW) + + + ); + + public render() { + const style = computeStyleSheet(); + const { connector, navigation, charger } = this.props; + return ( + + navigation.navigate({ + routeName: 'ChargerConnectorDetailsTabs', + params: { + chargerID: charger.id, + connectorID: connector.connectorId + }, + key: `${Utils.randomNumber()}` + }) + }> + + + + {this.renderFirstConnectorDetails(connector)} + {this.renderSecondConnectorDetails(connector, style)} + {this.renderThirdConnectorDetails(connector, style)} + {!charger.inactive && + + } + + + + + ); + } +} diff --git a/src/components/charger/connector/ChargerConnectorComponentStyles.tsx b/src/components/charger/connector/ChargerConnectorComponentStyles.tsx new file mode 100644 index 000000000..fc5732aa0 --- /dev/null +++ b/src/components/charger/connector/ChargerConnectorComponentStyles.tsx @@ -0,0 +1,83 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + width: '100%', + justifyContent: 'center', + alignItems: 'stretch', + borderStyle: 'solid', + borderWidth: 1, + borderColor: 'transparent', + borderTopColor: commonColor.listBorderColor + }, + connectorContainer: { + flexDirection: 'column', + justifyContent: 'space-evenly', + alignItems: 'center', + width: '100%' + }, + connectorDetailContainer: { + flexDirection: 'row', + justifyContent: 'space-evenly', + alignItems: 'center', + width: '100%', + paddingLeft: '5@s', + paddingRight: '5@s', + paddingTop: '10@s', + paddingBottom: '10@s' + }, + connectorDetail: { + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + height: '60@s', + width: '80@s', + color: commonColor.textColor + }, + connectorDetailAnimated: { + position: 'absolute', + alignItems: 'center' + }, + connectorValues: { + color: commonColor.textColor, + marginTop: '-1@s', + fontSize: '30@s', + fontWeight: 'bold', + textAlign: 'center' + }, + connectorSVG: { + width: '40@s', + height: '40@s' + }, + labelImage: { + color: commonColor.textColor, + paddingTop: '2@s', + fontSize: '10@s' + }, + label: { + color: commonColor.textColor, + fontSize: '10@s', + marginTop: '-3@s' + }, + subLabel: { + color: commonColor.textColor, + fontSize: '9@s' + }, + icon: { + fontSize: '30@s' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/connector-status/ConnectorStatusComponent.tsx b/src/components/connector-status/ConnectorStatusComponent.tsx new file mode 100644 index 000000000..41365724b --- /dev/null +++ b/src/components/connector-status/ConnectorStatusComponent.tsx @@ -0,0 +1,173 @@ +import { Text, View } from 'native-base'; +import React from 'react'; +import { Animated, Easing, Platform } from 'react-native'; +import BaseProps from '../../types/BaseProps'; +import { ChargePointStatus, Connector } from '../../types/ChargingStation'; +import Utils from '../../utils/Utils'; +import computeStyleSheet from './ConnectorStatusComponentStyles'; + +export interface Props extends BaseProps { + connector?: Connector; + text: string; + value?: number; + type?: string; +} + +interface State { +} + +export default class ConnectorStatusComponent extends React.Component { + public state: State; + public props: Props; + private rotateClockwise: Animated.AnimatedInterpolation; + private rotateCounterClockwise: Animated.AnimatedInterpolation; + + constructor(props: Props) { + super(props); + this.state = {}; + // Create + const spinValue = new Animated.Value(0); + // First set up animation + Animated.loop( + Animated.timing(spinValue, { + toValue: 1, + duration: 4000, + easing: Easing.linear + }) + ).start(); + // Second interpolate beginning and end values (in this case 0 and 1) + this.rotateClockwise = spinValue.interpolate({ + inputRange: [0, 1], + outputRange: ['0deg', '360deg'] + }); + + this.rotateCounterClockwise = spinValue.interpolate({ + inputRange: [0, 1], + outputRange: ['360deg', '0deg'] + }); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public getConnectorStyles(style: any) { + const { type, connector } = this.props; + // Get the type + let connectorType; + let status; + if (connector) { + connectorType = connector.status; + } else if (type) { + connectorType = type; + } + // Default CSS + const connectorStyles = { + container: [style.commonConnector], + value: [style.commonConnectorValue], + description: [style.commonConnectorDescription] + }; + switch (connectorType) { + // Charging + case ChargePointStatus.CHARGING: + case ChargePointStatus.OCCUPIED: + status = 'charging'; + break; + // Preparing + case ChargePointStatus.PREPARING: + status = 'preparing'; + break; + // Preparing + case ChargePointStatus.FINISHING: + status = 'finishing'; + break; + // Reserved + case ChargePointStatus.RESERVED: + status = 'reserved'; + break; + // Faulted + case ChargePointStatus.FAULTED: + status = 'faulted'; + break; + // Unavailable + case ChargePointStatus.UNAVAILABLE: + status = 'unavailable'; + break; + // Suspending EV / EVSE + case ChargePointStatus.SUSPENDED_EVSE: + case ChargePointStatus.SUSPENDED_EV: + status = 'suspended'; + break; + // Available + case ChargePointStatus.AVAILABLE: + status = 'available'; + break; + // Default + default: + case ChargePointStatus.UNAVAILABLE: + status = 'unavailable'; + break; + } + if (status) { + connectorStyles.container.push(style[status + 'Connector']); + connectorStyles.value.push(style[status + 'ConnectorValue']); + connectorStyles.description.push(style[status + 'ConnectorDescription']); + } + return connectorStyles; + } + + public getConnectorValue(): string { + // Get value + const { value, connector } = this.props; + if (connector) { + return Utils.getConnectorLetterFromConnectorID(connector.connectorId); + } else if (value >= 0) { + return '' + value; + } else { + return '-'; + } + } + + public isAnimated(): boolean { + const { value, type, connector } = this.props; + if (connector) { + return connector.currentConsumption > 0; + } else { + return type === ChargePointStatus.CHARGING && value > 0; + } + } + + public render() { + const style = computeStyleSheet(); + // Get styling + const connectorStyles = this.getConnectorStyles(style); + // Get value + const value = this.getConnectorValue(); + // Animated + const isAnimated = this.isAnimated(); + const isAndroid = Platform.OS === 'android'; + return ( + + {isAndroid ? ( + + + {value} + + + ) : ( + + + + {value} + + + + )} + {this.props.text && {this.props.text}} + + ); + } +} diff --git a/src/components/connector-status/ConnectorStatusComponentStyles.tsx b/src/components/connector-status/ConnectorStatusComponentStyles.tsx new file mode 100644 index 000000000..0aa09d058 --- /dev/null +++ b/src/components/connector-status/ConnectorStatusComponentStyles.tsx @@ -0,0 +1,121 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + containerWithDescription: { + height: '60@s', + width: '100@s', + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'center' + }, + containerWithNoDescription: { + height: '55@s', + width: '60@s', + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'center' + }, + commonConnector: { + width: '44@s', + height: '44@s', + justifyContent: 'center', + borderStyle: 'solid', + alignItems: 'center', + borderWidth: '4@s', + borderRadius: '22@s', + borderColor: commonColor.textColor, + backgroundColor: 'transparent' + }, + commonConnectorValue: { + fontSize: '22@s', + fontWeight: 'bold', + color: commonColor.inverseTextColor + }, + commonConnectorDescription: { + position: 'absolute', + bottom: '-2@s', + fontSize: '12@s', + color: commonColor.textColor + }, + faultedConnector: { + backgroundColor: commonColor.brandDanger, + borderColor: commonColor.brandDangerDark + }, + faultedConnectorValue: {}, + faultedConnectorDescription: { + color: commonColor.brandDanger + }, + availableConnector: { + borderColor: commonColor.brandSuccess + }, + availableConnectorValue: { + color: commonColor.brandSuccess + }, + availableConnectorDescription: { + color: commonColor.brandSuccess + }, + suspendedConnector: { + backgroundColor: commonColor.brandPrimary, + borderColor: commonColor.brandPrimaryDark + }, + suspendedConnectorValue: {}, + suspendedConnectorDescription: { + color: commonColor.brandPrimaryDark + }, + preparingConnector: { + backgroundColor: commonColor.brandWarning, + borderColor: commonColor.brandWarningDark + }, + preparingConnectorValue: {}, + preparingConnectorDescription: { + color: commonColor.brandWarning + }, + finishingConnector: { + backgroundColor: commonColor.brandWarning, + borderColor: commonColor.brandWarningDark + }, + finishingConnectorValue: {}, + finishingConnectorDescription: { + color: commonColor.brandWarning + }, + unavailableConnector: { + backgroundColor: commonColor.brandDisabled, + borderColor: commonColor.brandDisabledDark + }, + unavailableConnectorValue: {}, + unavailableConnectorDescription: { + color: commonColor.brandDisabled + }, + reservedConnector: { + backgroundColor: commonColor.brandDisabled, + borderColor: commonColor.brandDisabledDark + }, + reservedConnectorValue: {}, + reservedConnectorDescription: { + color: commonColor.brandDisabled + }, + chargingConnector: { + backgroundColor: commonColor.brandPrimary, + borderColor: commonColor.brandInfoLight, + borderTopColor: commonColor.brandPrimary, + borderBottomColor: commonColor.brandPrimary + }, + chargingConnectorValue: {}, + chargingConnectorDescription: { + color: commonColor.brandPrimaryDark + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/connector-status/ConnectorStatusesContainerComponent.tsx b/src/components/connector-status/ConnectorStatusesContainerComponent.tsx new file mode 100644 index 000000000..69ca7a540 --- /dev/null +++ b/src/components/connector-status/ConnectorStatusesContainerComponent.tsx @@ -0,0 +1,61 @@ +import I18n from 'i18n-js'; +import { View } from 'native-base'; +import React from 'react'; +import BaseProps from '../../types/BaseProps'; +import { ChargePointStatus } from '../../types/ChargingStation'; +import ConnectorStats from '../../types/ConnectorStats'; +import Utils from '../../utils/Utils'; +import ConnectorStatusComponent from './ConnectorStatusComponent'; +import computeStyleSheet from './ConnectorStatusesContainerComponentStyles'; + +export interface Props extends BaseProps { + connectorStats: ConnectorStats; +} + +interface State { +} + +export default class ConnectorStatusesContainerComponent extends React.Component { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public render() { + const style = computeStyleSheet(); + const { connectorStats, navigation } = this.props; + return ( + + + + + + ); + } +} diff --git a/src/components/connector-status/ConnectorStatusesContainerComponentStyles.tsx b/src/components/connector-status/ConnectorStatusesContainerComponentStyles.tsx new file mode 100644 index 000000000..15c63c42e --- /dev/null +++ b/src/components/connector-status/ConnectorStatusesContainerComponentStyles.tsx @@ -0,0 +1,23 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + flexDirection: 'row', + justifyContent: 'space-evenly', + alignItems: 'center' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/header/HeaderComponent.tsx b/src/components/header/HeaderComponent.tsx new file mode 100644 index 000000000..3c0bf8113 --- /dev/null +++ b/src/components/header/HeaderComponent.tsx @@ -0,0 +1,130 @@ +import { Body, Button, Header, Icon, Left, Right, Subtitle, Title, View } from 'native-base'; +import React from 'react'; +import { BackHandler, Image } from 'react-native'; +import logo from '../../../assets/logo-low.png'; +import FilterModalContainerComponent from '../../components/search/filter/containers/FilterModalContainerComponent'; +import BaseProps from '../../types/BaseProps'; +import { IconType } from '../../types/Icon'; +import computeStyleSheet from './HeaderComponentStyles'; + +export interface Props extends BaseProps { + title: string; + subTitle?: string; + leftAction?: () => void; + leftActionIcon?: string; + leftActionIconType?: IconType; + rightAction?: () => void; + rightActionIcon?: string; + rightActionIconType?: IconType; + filters?: any; +} + +interface State { + hasFilter?: boolean; +} + +export default class HeaderComponent extends React.Component { + public state: State; + public props: Props; + private searchIsVisible: boolean; + private filterModalContainerComponent: FilterModalContainerComponent; + + public static defaultProps = { + leftActionIconType: 'MaterialIcons', + rightActionIconType: 'MaterialIcons', + }; + + constructor(props: Props) { + super(props); + this.state = { + hasFilter: false, + } + // Default values + this.searchIsVisible = false; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public getFilterModalContainerComponent(): FilterModalContainerComponent { + return this.filterModalContainerComponent; + } + + public setFilterModalContainerComponent(filterModalContainerComponent: FilterModalContainerComponent) { + this.filterModalContainerComponent = filterModalContainerComponent; + this.setState({ + hasFilter: true + }); + } + + public componentDidMount() { + const { leftAction } = this.props; + // Left Action is always Back + if (leftAction) { + BackHandler.addEventListener('hardwareBackPress', leftAction); + } + } + + public componentWillUnmount() { + const { leftAction } = this.props; + // Left Action is always Back + if (leftAction) { + BackHandler.removeEventListener('hardwareBackPress', leftAction); + } + } + + public render = () => { + const style = computeStyleSheet(); + const { hasFilter } = this.state; + const { title, subTitle, leftAction, leftActionIcon, leftActionIconType, + rightAction, rightActionIcon, rightActionIconType, navigation } = this.props; + return ( +
+ + {leftAction ? ( + + + + + ) : ( + + )} + + + {title} + {subTitle && {subTitle}} + + + {hasFilter && ( + + )} + {rightAction ? ( + + ) : ( + + )} + +
+ ); + } +} diff --git a/src/components/header/HeaderComponentStyles.tsx b/src/components/header/HeaderComponentStyles.tsx new file mode 100644 index 000000000..b65bb4180 --- /dev/null +++ b/src/components/header/HeaderComponentStyles.tsx @@ -0,0 +1,70 @@ +import deepmerge from 'deepmerge'; +import { Platform } from 'react-native'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + header: { + height: '55@s', + width: '100%', + padding: 0, + margin: 0, + paddingLeft: '10@s', + paddingRight: '10@s', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor, + backgroundColor: commonColor.brandPrimaryDark + }, + buttonRow: { + flexDirection: 'row', + }, + leftHeader: { + }, + leftButtonHeader: { + paddingLeft: 0 + }, + rightHeader: { + }, + rightButtonHeader: { + }, + rightFilterButtonHeader: { + marginRight: '15@s' + }, + bodyHeader: { + flex: 3, + paddingLeft: Platform.OS === 'ios' ? 0 : '50@s' + }, + titleHeader: { + color: commonColor.inverseTextColor, + fontSize: '18@s' + }, + titleHeaderWithSubTitle: { + fontSize: '18@s' + }, + subTitleHeader: { + color: commonColor.inverseTextColor, + fontWeight: 'bold', + fontSize: '12@s', + marginTop: Platform.OS === 'ios' ? 0 : '-3@s' + }, + logoHeader: { + width: '45@s', + resizeMode: 'contain' + }, + iconHeader: { + color: commonColor.inverseTextColor, + fontSize: '30@s' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/list/empty-text/ListEmptyTextComponent.tsx b/src/components/list/empty-text/ListEmptyTextComponent.tsx new file mode 100644 index 000000000..f21c3a40f --- /dev/null +++ b/src/components/list/empty-text/ListEmptyTextComponent.tsx @@ -0,0 +1,27 @@ +import I18n from 'i18n-js'; +import { Text } from 'native-base'; +import React from 'react'; +import BaseProps from '../../../types/BaseProps'; +import computeStyleSheet from './ListEmptyTextComponentStyles'; + +export interface Props extends BaseProps { + text?: string; +} + +interface State { +} + +export default class ListEmptyTextComponent extends React.Component { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + } + + public render() { + const style = computeStyleSheet(); + const { text } = this.props; + return {text || I18n.t('general.noRecordFound')}; + } +} diff --git a/src/components/list/empty-text/ListEmptyTextComponentStyles.tsx b/src/components/list/empty-text/ListEmptyTextComponentStyles.tsx new file mode 100644 index 000000000..2131e581d --- /dev/null +++ b/src/components/list/empty-text/ListEmptyTextComponentStyles.tsx @@ -0,0 +1,23 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; + +const commonStyles = ScaledSheet.create({ + noRecordFound: { + flex: 1, + paddingTop: '20@s', + fontSize: '14@s', + alignSelf: 'center' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/list/footer/ListFooterComponent.tsx b/src/components/list/footer/ListFooterComponent.tsx new file mode 100644 index 000000000..5f5d8fa66 --- /dev/null +++ b/src/components/list/footer/ListFooterComponent.tsx @@ -0,0 +1,39 @@ +import { Spinner, View } from 'native-base'; +import React from 'react'; +import BaseProps from '../../../types/BaseProps'; +import computeStyleSheet from './ListFooterComponentStyles'; + +export interface Props extends BaseProps { + skip: number; + limit: number; + count: number; +} + +interface State { +} + +export default class ListFooterComponent extends React.Component { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public render() { + const style = computeStyleSheet(); + const { skip, limit, count } = this.props; + if (skip + limit < count || count === -1) { + return ( + + + + ); + } + return null; + } +} diff --git a/src/components/list/footer/ListFooterComponentStyles.tsx b/src/components/list/footer/ListFooterComponentStyles.tsx new file mode 100644 index 000000000..0e81b01ca --- /dev/null +++ b/src/components/list/footer/ListFooterComponentStyles.tsx @@ -0,0 +1,21 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; + +const commonStyles = ScaledSheet.create({ + spinnerContainer: { + padding: '10@s', + alignSelf: 'center' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/search/filter/containers/FilterContainerComponent.tsx b/src/components/search/filter/containers/FilterContainerComponent.tsx new file mode 100644 index 000000000..b55f93033 --- /dev/null +++ b/src/components/search/filter/containers/FilterContainerComponent.tsx @@ -0,0 +1,135 @@ +import React from 'react'; +import SecuredStorage from '../../../../utils/SecuredStorage'; +import FilterControlComponent from '../controls/FilterControlComponent'; + +export interface FilterContainerComponentProps { + onFilterChanged?: (filters: any, applyFilters: boolean) => void; + visible?: boolean; + children?: React.ReactNode; +} + +export interface FilterContainerComponentState { + visible?: boolean; +} + +export default abstract class FilterContainerComponent extends React.Component { + public state: FilterContainerComponentState; + public props: FilterContainerComponentProps; + public static defaultProps = { + visible: false + }; + private filterControlComponents: FilterControlComponent[] = []; + + constructor(props: FilterContainerComponentProps) { + super(props); + this.state = { + visible: props.visible ? props.visible : false + }; + } + + public setState = (state: FilterContainerComponentState | ((prevState: Readonly, props: Readonly) => FilterContainerComponentState | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public setVisible = (visible: boolean) => { + this.setState({ visible }); + } + + public async notifyFilterChanged() { + const { onFilterChanged } = this.props; + // Save + await this.saveFilters(); + // Notify + onFilterChanged(this.getFilters(), true); + } + + public async setFilterControlComponents(filterControlComponents: FilterControlComponent[]) { + this.filterControlComponents = filterControlComponents; + } + + public setFilter = async (filterID: string, filterValue: any) => { + // Search + for (const filterControlComponent of this.filterControlComponents) { + // Set + if (filterControlComponent.getID() === filterID) { + filterControlComponent.setValue(filterValue); + this.notifyFilterChanged(); + break; + } + } + } + + public clearFilter = async (filterID: string) => { + // Search + for (const filterControlComponent of this.filterControlComponents) { + if (filterControlComponent.getID() === filterID) { + // Set + filterControlComponent.clearValue(); + this.notifyFilterChanged(); + break; + } + } + } + + public getFilter = (id: string): any => { + // Search + for (const filterControlComponent of this.filterControlComponents) { + if (filterControlComponent.getID() === id) { + return filterControlComponent.getValue(); + } + } + return null; + } + + public getFilters = (): any => { + const filters: any = {}; + // Build + for (const filterControlComponent of this.filterControlComponents) { + filters[filterControlComponent.getID()] = filterControlComponent.getValue(); + } + return filters; + } + + public async applyFiltersAndNotify() { + // Save + await this.saveFilters(); + // Trigger notif + this.notifyFilterChanged(); + } + + public clearFilters() { + // Clear + for (const filterControlComponent of this.filterControlComponents) { + filterControlComponent.clearValue(); + } + } + + public getNumberOfFilters(): number { + let numberOfFilter = 0 + for (const filterControlComponent of this.filterControlComponents) { + if (filterControlComponent.getValue()) { + numberOfFilter++; + } + } + return numberOfFilter; + } + + public async clearFiltersAndNotify() { + // Clear + await this.clearFilters(); + // Save + await this.saveFilters(); + // Trigger notif + this.notifyFilterChanged(); + } + + public saveFilters = async () => { + // Build + for (const filterControlComponent of this.filterControlComponents) { + // Save + if (filterControlComponent.canBeSaved()) { + await SecuredStorage.saveFilterValue(filterControlComponent.getInternalID(), filterControlComponent.getValue()); + } + } + } +} diff --git a/src/components/search/filter/containers/FilterContainerComponentStyles.tsx b/src/components/search/filter/containers/FilterContainerComponentStyles.tsx new file mode 100644 index 000000000..143e6145d --- /dev/null +++ b/src/components/search/filter/containers/FilterContainerComponentStyles.tsx @@ -0,0 +1,59 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet'; +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + modalContainer: { + }, + modalFiltersContainer: { + backgroundColor: 'white', + padding: '15@s', + justifyContent: 'flex-start', + borderColor: 'rgba(0, 0, 0, 0.1)', + }, + modalButtonsContainer: { + flexDirection: 'row', + width: '100%' + }, + modalButton: { + height: '40@s', + width: '50%', + justifyContent: 'center', + alignItems: 'center' + }, + modalTextButton: { + color: commonColor.inverseTextColor, + height: '100%', + marginTop: '12@s', + fontSize: '16@s' + }, + visibleContainer: { + paddingLeft: '10@s', + paddingRight: '10@s', + justifyContent: 'flex-start', + borderColor: 'rgba(0, 0, 0, 0.1)', + backgroundColor: commonColor.containerBgColor + }, + visibleExpandedContainer: { + flexDirection: 'row', + justifyContent: 'center', + borderTopWidth: 1, + borderTopColor: commonColor.listBorderColor, + backgroundColor: commonColor.containerBgColor + }, + visibleExpandedIcon: { + fontSize: '25@s' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/search/filter/containers/FilterModalContainerComponent.tsx b/src/components/search/filter/containers/FilterModalContainerComponent.tsx new file mode 100644 index 000000000..4e45aabe1 --- /dev/null +++ b/src/components/search/filter/containers/FilterModalContainerComponent.tsx @@ -0,0 +1,76 @@ +import I18n from 'i18n-js'; +import { Button, View } from 'native-base'; +import React from 'react'; +import { Text } from 'react-native'; +import Modal from 'react-native-modal'; +import FilterContainerComponent, { FilterContainerComponentProps, FilterContainerComponentState } from './FilterContainerComponent'; +import computeStyleSheet from './FilterContainerComponentStyles'; + +export interface Props extends FilterContainerComponentProps { +} + +interface State extends FilterContainerComponentState { +} + +export default class FilterModalContainerComponent extends FilterContainerComponent { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async notifyFilterChanged() { + const { onFilterChanged } = this.props; + // Notify + onFilterChanged(this.getFilters(), false); + } + + public applyFiltersAndNotify = async () => { + const { onFilterChanged } = this.props; + // Save + await this.saveFilters(); + // Notify + onFilterChanged(this.getFilters(), true); + // Close + this.setVisible(false); + } + + public clearFiltersAndNotify = async () => { + const { onFilterChanged } = this.props; + // Clear + this.clearFilters(); + // Save + await this.saveFilters(); + // Notify + onFilterChanged(this.getFilters(), true); + // Close + this.setVisible(false); + } + + public render = () => { + const style = computeStyleSheet(); + const { visible } = this.state; + return ( + this.setState({ visible: false })}> + + {this.props.children} + + + + + + + ); + } +} diff --git a/src/components/search/filter/containers/FilterVisibleContainerComponent.tsx b/src/components/search/filter/containers/FilterVisibleContainerComponent.tsx new file mode 100644 index 000000000..70c99948a --- /dev/null +++ b/src/components/search/filter/containers/FilterVisibleContainerComponent.tsx @@ -0,0 +1,66 @@ +import { View, Icon } from 'native-base'; +import React from 'react'; +import FilterContainerComponent, { FilterContainerComponentProps, FilterContainerComponentState } from './FilterContainerComponent'; +import computeStyleSheet from './FilterContainerComponentStyles'; +import { TouchableOpacity } from 'react-native-gesture-handler'; + +export interface Props extends FilterContainerComponentProps { + expanded?: boolean; + onExpand?: (expanded: boolean) => void +} + +interface State extends FilterContainerComponentState { + expanded: boolean; +} + +export default class FilterVisibleContainerComponent extends FilterContainerComponent { + public state: State; + public props: Props; + public static defaultProps = { + visible: false, + showExpandControl: false, + expanded: false + }; + + constructor(props: Props) { + super(props); + this.state = { + expanded: props.expanded ? props.expanded : false + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + private toggleExpanded = () => { + const { onExpand } = this.props; + this.setState({ + expanded: !this.state.expanded + }, ()=> { + if (onExpand) { + onExpand(this.state.expanded); + } + }); + } + + public render = () => { + const style = computeStyleSheet(); + const { onExpand } = this.props; + const { expanded } = this.state; + return ( + + {this.props.children} + {onExpand && + + {expanded ? + + : + + } + + } + + ); + } +} diff --git a/src/components/search/filter/controls/FilterControlComponent.tsx b/src/components/search/filter/controls/FilterControlComponent.tsx new file mode 100644 index 000000000..8af96b1d0 --- /dev/null +++ b/src/components/search/filter/controls/FilterControlComponent.tsx @@ -0,0 +1,60 @@ +import React from 'react'; + +export interface FilterControlComponentProps { + internalFilterID: string; + filterID: string; + label: string; + locale?: string; + initialValue?: T; + style?: object; + onFilterChanged: (id: string, value: T) => void; +} + +interface FilterControlComponentState { +} + +export default class FilterControlComponent extends React.Component, FilterControlComponentState> { + public state: FilterControlComponentState; + public props: FilterControlComponentProps; + public static defaultProps = { + style: {} + }; + private value: T = null; + + constructor(props: FilterControlComponentProps) { + super(props); + this.value = this.props.initialValue; + this.state = { + }; + } + + public setState = (state: FilterControlComponentState | ((prevState: Readonly, props: Readonly>) => FilterControlComponentState | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public canBeSaved() { + return false; + } + + public async setValue(value: any) { + this.value = value; + } + + public getValue(): any { + return this.value; + } + + public async clearValue() { + this.value = null; + } + + public getID(): string { + const { filterID } = this.props; + return filterID; + } + + public getInternalID(): string { + const { internalFilterID } = this.props; + return internalFilterID; + } +} diff --git a/src/components/search/filter/controls/FilterControlComponentStyles.tsx b/src/components/search/filter/controls/FilterControlComponentStyles.tsx new file mode 100644 index 000000000..44ca9d09c --- /dev/null +++ b/src/components/search/filter/controls/FilterControlComponentStyles.tsx @@ -0,0 +1,56 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet'; +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + rowFilterContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + height: '40@s', + alignItems: 'center', + }, + columnFilterContainer: { + flexDirection: 'column', + justifyContent: 'space-evenly', + height: '100@s', + alignItems: 'center', + }, + rowFilterWithBorder: { + borderTopWidth: 1, + borderTopColor: commonColor.listBorderColor + }, + textFilter: { + fontSize: '16@s', + }, + filterValue: { + fontSize: '16@s', + color: commonColor.textColor + }, + switchFilter: { + }, + connectorTypeFilterContainer: { + flexDirection: 'row', + justifyContent: 'space-evenly', + width: '100%' + }, + connectorTypeButton: { + width: '50@s', + height: '50@s', + }, + connectorTypeSVG: { + width: '40@s', + height: '40@s', + }, +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/search/filter/controls/connector-type/ConnectorTypeFilterControlComponent.tsx b/src/components/search/filter/controls/connector-type/ConnectorTypeFilterControlComponent.tsx new file mode 100644 index 000000000..bd9a652e4 --- /dev/null +++ b/src/components/search/filter/controls/connector-type/ConnectorTypeFilterControlComponent.tsx @@ -0,0 +1,102 @@ +import { Text, View } from 'native-base'; +import React from 'react'; +import { ToggleButton } from 'react-native-paper'; +import ComboCCS from '../../../../../../assets/connectorType/combo-ccs.svg'; +import Chademo from '../../../../../../assets/connectorType/chademo.svg'; +import Domestic from '../../../../../../assets/connectorType/domestic-ue.svg'; +import Type2 from '../../../../../../assets/connectorType/type2.svg'; +import { ConnectorType } from '../../../../../types/ChargingStation'; +import FilterControlComponent, { FilterControlComponentProps } from '../FilterControlComponent'; +import computeStyleSheet from '../FilterControlComponentStyles'; + +export interface Props extends FilterControlComponentProps { +} + +interface State { +} + +const connectorStyle = computeStyleSheet(); + +export default class ConnectorTypeFilterControlComponent extends FilterControlComponent { + public state: State; + public props: Props; + private connectors: {type: ConnectorType; element: Element; selected: boolean;}[] = [ + { type: ConnectorType.TYPE_2, element: , selected: false }, + { type: ConnectorType.COMBO_CCS, element: , selected: false }, + { type: ConnectorType.CHADEMO, element: , selected: false }, + { type: ConnectorType.DOMESTIC, element: , selected: false }, + ] + + constructor(props: Props) { + super(props); + const connectorTypes = this.getValue() as string; + if (connectorTypes) { + for (const connectorType of connectorTypes.split('|')) { + for (const connector of this.connectors) { + if (connector.type === connectorType) { + connector.selected = true; + break; + } + } + } + } + this.state = { + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public canBeSaved() { + return true; + } + + private onValueChanged = async () => { + const { onFilterChanged } = this.props; + // Build Filter + const connectorFilters: ConnectorType[] = []; + for (const connector of this.connectors) { + if (connector.selected) { + connectorFilters.push(connector.type); + } + } + if (onFilterChanged) { + if (connectorFilters.length) { + const filterValue = connectorFilters.join('|'); + this.setValue(filterValue); + onFilterChanged(this.getID(), filterValue); + } else { + this.clearValue(); + onFilterChanged(this.getID(), null); + } + } + // Update + this.forceUpdate(); + } + + public render = () => { + const internalStyle = computeStyleSheet(); + const { style, label } = this.props; + return ( + + {label} + + {this.connectors.map((connector) => + connector.element} + value='bluetooth' + status={connector.selected ? 'checked' : 'unchecked'} + onPress={() => { + connector.selected = !connector.selected; + this.onValueChanged(); + }} + /> + )} + + + ); + } +} diff --git a/src/components/search/filter/controls/date/DateFilterControlComponent.tsx b/src/components/search/filter/controls/date/DateFilterControlComponent.tsx new file mode 100644 index 000000000..080dd459d --- /dev/null +++ b/src/components/search/filter/controls/date/DateFilterControlComponent.tsx @@ -0,0 +1,72 @@ +import { DatePicker, Text, View } from 'native-base'; +import React from 'react'; +import I18nManager from '../../../../../I18n/I18nManager'; +import FilterControlComponent, { FilterControlComponentProps } from '../FilterControlComponent'; +import computeStyleSheet from '../FilterControlComponentStyles'; + +export interface Props extends FilterControlComponentProps { + defaultDate?: Date; + minimumDate?: Date; + maximumDate?: Date; +} + +interface State { +} + +export default class DateFilterControlComponent extends FilterControlComponent { + public state: State; + public props: Props; + public static defaultProps = { + style: {}, + defaultDate: new Date() + }; + + constructor(props: Props) { + super(props); + this.state = { + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + private onValueChanged = async (newValue: Date) => { + const { onFilterChanged } = this.props; + // Set Filter + if (onFilterChanged) { + if (newValue) { + this.setValue(newValue); + onFilterChanged(this.getID(), newValue); + } else { + this.clearValue(); + onFilterChanged(this.getID(), null); + } + } + } + + public render = () => { + const internalStyle = computeStyleSheet(); + const { label, style, defaultDate, minimumDate, maximumDate, locale } = this.props; + return ( + + {label} + I18nManager.formatDateTime(date, 'LL')} + /> + + ); + } +} diff --git a/src/components/search/filter/controls/my-user-switch/MyUserSwitchFilterControlComponent.tsx b/src/components/search/filter/controls/my-user-switch/MyUserSwitchFilterControlComponent.tsx new file mode 100644 index 000000000..e1ac2fb7c --- /dev/null +++ b/src/components/search/filter/controls/my-user-switch/MyUserSwitchFilterControlComponent.tsx @@ -0,0 +1,73 @@ +import { Switch, Text, View } from 'native-base'; +import React from 'react'; +import ProviderFactory from '../../../../../provider/ProviderFactory'; +import FilterControlComponent, { FilterControlComponentProps } from '../FilterControlComponent'; +import computeStyleSheet from '../FilterControlComponentStyles'; + +export interface Props extends FilterControlComponentProps { +} + +interface State { + switchValue?: boolean; +} + +export default class MyUserSwitchFilterControlComponent extends FilterControlComponent { + public state: State; + public props: Props; + private userID: string; + + constructor(props: Props) { + super(props); + this.state = { + switchValue: !!this.getValue() + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public canBeSaved() { + return true; + } + + public async componentDidMount() { + // Get corresponding + const centralServerProvider = await ProviderFactory.getProvider(); + if (centralServerProvider) { + this.userID = centralServerProvider.getUserInfo().id; + } + } + + private onValueChanged = async (newValue: boolean) => { + const { onFilterChanged } = this.props; + // Set Filter + if (onFilterChanged) { + if (newValue) { + this.setValue(this.userID); + onFilterChanged(this.getID(), this.userID); + } else { + this.clearValue(); + onFilterChanged(this.getID(), null); + } + } + // Update + this.setState({ switchValue: newValue }); + } + + public render = () => { + const internalStyle = computeStyleSheet(); + const { label, style } = this.props; + const { switchValue } = this.state; + return ( + + {label} + + + ); + } +} diff --git a/src/components/search/filter/controls/only-available-chargers/OnlyAvailableChargerSwitchFilterControlComponent.tsx b/src/components/search/filter/controls/only-available-chargers/OnlyAvailableChargerSwitchFilterControlComponent.tsx new file mode 100644 index 000000000..8bd705428 --- /dev/null +++ b/src/components/search/filter/controls/only-available-chargers/OnlyAvailableChargerSwitchFilterControlComponent.tsx @@ -0,0 +1,65 @@ +import { Switch, Text, View } from 'native-base'; +import React from 'react'; +import { ChargePointStatus } from '../../../../../types/ChargingStation'; +import FilterControlComponent, { FilterControlComponentProps } from '../FilterControlComponent'; +import computeStyleSheet from '../FilterControlComponentStyles'; + +export interface Props extends FilterControlComponentProps { +} + +interface State { + switchValue?: boolean; +} + +export default class OnlyAvailableChargerSwitchFilterControlComponent extends FilterControlComponent { + public state: State; + public props: Props; + private status: ChargePointStatus = ChargePointStatus.AVAILABLE; + + constructor(props: Props) { + super(props); + this.state = { + switchValue: !!this.getValue() + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public canBeSaved() { + return true; + } + + private onValueChanged = async (newValue: boolean) => { + const { onFilterChanged } = this.props; + // Set Filter + if (onFilterChanged) { + if (newValue) { + this.setValue(this.status); + onFilterChanged(this.getID(), this.status); + } else { + this.clearValue(); + onFilterChanged(this.getID(), null); + } + } + // Update + this.setState({ switchValue: newValue }); + } + + public render = () => { + const internalStyle = computeStyleSheet(); + const { label, style } = this.props; + const { switchValue } = this.state; + return ( + + {label} + + + ); + } +} diff --git a/src/components/search/filter/screen/ScreenFilters.tsx b/src/components/search/filter/screen/ScreenFilters.tsx new file mode 100644 index 000000000..b803b96fb --- /dev/null +++ b/src/components/search/filter/screen/ScreenFilters.tsx @@ -0,0 +1,132 @@ +import React from 'react'; +import CentralServerProvider from '../../../../provider/CentralServerProvider'; +import ProviderFactory from '../../../../provider/ProviderFactory'; +import SecurityProvider from '../../../../provider/SecurityProvider'; +import FilterModalContainerComponent from '../containers/FilterModalContainerComponent'; +import FilterVisibleContainerComponent from '../containers/FilterVisibleContainerComponent'; +import FilterControlComponent from '../controls/FilterControlComponent'; +import { View } from 'native-base'; +import * as Animatable from 'react-native-animatable'; + +export interface ScreenFiltersProps { +} + +export interface ScreenFiltersState { + isAdmin?: boolean; + hasSiteAdmin?: boolean; + locale?: string; + expanded?: boolean; +} + +export default class ScreenFilters extends React.Component { + public state: ScreenFiltersState; + public props: ScreenFiltersProps; + private filterVisibleContainerComponent: FilterVisibleContainerComponent; + private filterModalContainerComponent: FilterModalContainerComponent; + private centralServerProvider: CentralServerProvider; + private securityProvider: SecurityProvider; + private filterModalControlComponents: FilterControlComponent[] = []; + private filterVisibleControlComponents: FilterControlComponent[] = []; + private expandableView: any; + + constructor(props: ScreenFiltersProps) { + super(props); + this.state = { + isAdmin: false, + hasSiteAdmin: false, + locale: null, + expanded: false, + }; + } + + public async componentDidMount() { + let locale = null; + let isAdmin = false; + let hasSiteAdmin = false; + // Get Provider + this.centralServerProvider = await ProviderFactory.getProvider(); + if (this.centralServerProvider) { + locale = this.centralServerProvider.getUserLanguage(); + // Get Security + this.securityProvider = this.centralServerProvider.getSecurityProvider(); + if (this.securityProvider) { + isAdmin = this.securityProvider.isAdmin(); + hasSiteAdmin = this.securityProvider.hasSiteAdmin(); + } + } + this.setState({ + isAdmin, + hasSiteAdmin, + locale + }); + } + + public setViewExpanded = (expanded: boolean, styleFrom?: object, styleTo?: object) => { + if (expanded && styleFrom && styleTo) { + this.expandableView.animate({ from: styleFrom, to: styleTo }, 250); + } else { + this.expandableView.animate({ from: styleTo, to: styleFrom }, 250); + } + this.setState({expanded}); + } + + public setExpandableView = (expandableView: any) => { + if (expandableView) { + this.expandableView = expandableView; + } + } + + public setState = (state: ScreenFiltersState | ((prevState: Readonly, props: Readonly) => ScreenFiltersState | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public getFilterModalContainerComponent(): FilterModalContainerComponent { + return this.filterModalContainerComponent; + } + + public setFilterModalContainerComponent(filterModalContainerComponent: FilterModalContainerComponent) { + if (filterModalContainerComponent) { + this.filterModalContainerComponent = filterModalContainerComponent; + this.filterModalContainerComponent.setFilterControlComponents(this.filterModalControlComponents); + } + } + + public getFilterVisibleContainerComponent(): FilterVisibleContainerComponent { + return this.filterVisibleContainerComponent; + } + + public setFilterVisibleContainerComponent(filterVisibleContainerComponent: FilterVisibleContainerComponent) { + if (filterVisibleContainerComponent) { + this.filterVisibleContainerComponent = filterVisibleContainerComponent; + this.filterVisibleContainerComponent.setFilterControlComponents(this.filterVisibleControlComponents); + } + } + + public async addModalFilter(newFilterComponent: FilterControlComponent) { + if (newFilterComponent) { + this.addFilter(this.filterModalControlComponents, newFilterComponent); + } + } + + public async addVisibleFilter(newFilterComponent: FilterControlComponent) { + if (newFilterComponent) { + this.addFilter(this.filterVisibleControlComponents, newFilterComponent); + } + } + + private async addFilter(filterControlComponents: FilterControlComponent[], newFilterComponent: FilterControlComponent) { + // Search + if (filterControlComponents) { + for (let index = 0; index < filterControlComponents.length; index++) { + const filterControlComponent = filterControlComponents[index]; + if (filterControlComponent.getID() === newFilterComponent.getID()) { + // Replace + filterControlComponents.splice(index, 1, filterControlComponent); + return; + } + } + // Add new + filterControlComponents.push(newFilterComponent); + } + } +} diff --git a/src/components/search/simple/SimpleSearchComponent.tsx b/src/components/search/simple/SimpleSearchComponent.tsx new file mode 100644 index 000000000..670118919 --- /dev/null +++ b/src/components/search/simple/SimpleSearchComponent.tsx @@ -0,0 +1,68 @@ +import I18n from 'i18n-js'; +import { Button, Icon } from 'native-base'; +import React from 'react'; +import { TextInput, View } from 'react-native'; +import commonColor from '../../../theme/variables/commonColor'; +import BaseProps from '../../../types/BaseProps'; +import computeStyleSheet from './SimpleSearchComponentStyles'; + +export interface Props extends BaseProps { + onChange: (search: string) => void, +} + +interface State { +} + +export default class SimpleSearchComponent extends React.Component { + public state: State; + public props: Props; + private textInput: TextInput; + private currentSearchText: string; + public static defaultProps = { + visible: false + }; + + constructor(props: Props) { + super(props); + this.state = { + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public searchHasChanged(searchText: string) { + this.currentSearchText = searchText; + const { onChange } = this.props; + // Call the function + onChange(searchText); + } + + public clearSearch() { + this.textInput.clear(); + this.searchHasChanged(''); + } + + public render() { + const style = computeStyleSheet(); + return ( + + + { + this.textInput = ref; + }} + selectionColor={commonColor.textColor} + style={style.inputField} + placeholder={I18n.t('general.search')} + placeholderTextColor={commonColor.placeholderTextColor} + onChangeText={(searchText) => this.searchHasChanged(searchText)} + /> + + + ); + } +} diff --git a/src/components/search/simple/SimpleSearchComponentStyles.tsx b/src/components/search/simple/SimpleSearchComponentStyles.tsx new file mode 100644 index 000000000..c01655620 --- /dev/null +++ b/src/components/search/simple/SimpleSearchComponentStyles.tsx @@ -0,0 +1,38 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + height: '35@s', + paddingLeft: '5@s', + paddingRight: '5@s', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor, + backgroundColor: commonColor.containerBgColor + }, + inputField: { + flex: 1, + fontSize: '16@s' + }, + icon: { + paddingLeft: '5@s', + paddingRight: '5@s', + fontSize: '25@s' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/site-area/SiteAreaComponent.tsx b/src/components/site-area/SiteAreaComponent.tsx new file mode 100644 index 000000000..20c9b025e --- /dev/null +++ b/src/components/site-area/SiteAreaComponent.tsx @@ -0,0 +1,70 @@ +import I18n from 'i18n-js'; +import { Icon, Text, View } from 'native-base'; +import React from 'react'; +import { TouchableOpacity } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import BaseProps from '../../types/BaseProps'; +import SiteArea from '../../types/SiteArea'; +import Constants from '../../utils/Constants'; +import Message from '../../utils/Message'; +import Utils from '../../utils/Utils'; +import ConnectorStatusesContainerComponent from '../connector-status/ConnectorStatusesContainerComponent'; +import computeStyleSheet from './SiteAreaComponentStyles'; + +export interface Props extends BaseProps { + siteArea: SiteArea; +} + +interface State { +} + +export default class SiteAreaComponent extends React.Component { + public state: State; + public props: Props; + private counter: number = 0; + + constructor(props: Props) { + super(props); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public render() { + const style = computeStyleSheet(); + const { siteArea, navigation } = this.props; + // New backend? + return ( + + { + if (siteArea.connectorStats.totalConnectors > 0) { + navigation.navigate({ + routeName: 'Chargers', + params: { + siteAreaID: siteArea.id + }, + key: `${Utils.randomNumber()}` + }); + } else { + Message.showError(I18n.t('siteAreas.noChargers')); + } + }}> + + + {siteArea.name} + 0 ? style.icon : style.iconHidden} type='MaterialIcons' name='navigate-next' /> + + + + + + + + ); + } +} diff --git a/src/components/site-area/SiteAreaComponentStyles.tsx b/src/components/site-area/SiteAreaComponentStyles.tsx new file mode 100644 index 000000000..e2210048d --- /dev/null +++ b/src/components/site-area/SiteAreaComponentStyles.tsx @@ -0,0 +1,104 @@ +import deepmerge from 'deepmerge'; +import { Platform } from 'react-native'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + flexDirection: 'column', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor + }, + headerContent: { + flexDirection: 'row', + justifyContent: 'space-between', + paddingTop: '5@s', + paddingBottom: '5@s', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor, + backgroundColor: commonColor.headerBgColor + }, + headerName: { + paddingTop: Platform.OS === 'ios' ? '2@s' : 0, + paddingLeft: '10@s', + fontSize: '20@s', + fontWeight: 'bold', + color: commonColor.headerTextColor + }, + connectorContent: { + flexDirection: 'row', + justifyContent: 'center', + paddingTop: '12@s', + paddingBottom: '12@s', + borderBottomWidth: 1, + borderBottomColor: commonColor.brandPrimaryDark + }, + icon: { + fontSize: '30@s', + marginLeft: '10@s', + marginRight: '10@s', + color: commonColor.headerTextColor + }, + iconHidden: { + opacity: 0 + }, + detailedContent: { + flexDirection: 'row', + justifyContent: 'space-evenly', + alignItems: 'center' + }, + badgeContainer: { + paddingTop: '5@s', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }, + badgeSuccessContainer: {}, + badgeOccupiedContainer: {}, + connectorText: { + color: commonColor.textColor, + marginTop: '-15@s', + marginRight: '10@s', + fontSize: '20@s' + }, + connectorBadge: { + marginTop: '5@s' + }, + freeConnectorBadge: { + backgroundColor: commonColor.brandInfo + }, + occupiedConnectorBadge: { + backgroundColor: commonColor.brandDanger + }, + connectorBadgeTitle: { + minWidth: '35@s', + textAlign: 'center', + fontSize: '25@s', + paddingTop: Platform.OS === 'ios' ? '3@s' : 0, + paddingBottom: Platform.OS === 'ios' ? '3@s' : 0, + fontWeight: 'bold', + color: commonColor.textColor + }, + connectorSubTitle: { + fontSize: '15@s', + paddingBottom: '5@s', + marginTop: '5@s', + marginBottom: '5@s', + marginLeft: '10@s', + marginRight: '10@s', + color: commonColor.textColor + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/site/SiteComponent.tsx b/src/components/site/SiteComponent.tsx new file mode 100644 index 000000000..9a63ed8da --- /dev/null +++ b/src/components/site/SiteComponent.tsx @@ -0,0 +1,89 @@ +import { Icon, Text, View } from 'native-base'; +import React from 'react'; +import { TouchableOpacity } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import openMap from 'react-native-open-maps'; +import Address from '../../types/Address'; +import BaseProps from '../../types/BaseProps'; +import ConnectorStats from '../../types/ConnectorStats'; +import Site from '../../types/Site'; +import Constants from '../../utils/Constants'; +import Utils from '../../utils/Utils'; +import ConnectorStatusesContainerComponent from '../connector-status/ConnectorStatusesContainerComponent'; +import computeStyleSheet from './SiteComponentStyles'; + +export interface Props extends BaseProps { + site: Site; +} + +interface State { +} + +export default class SiteComponent extends React.Component { + public state: State; + public props: Props; + private counter: number = 0; + + constructor(props: Props) { + super(props); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public siteLocation(address: Address) { + openMap({ + latitude: address.latitude, + longitude: address.longitude, + zoom: 18 + }); + } + + public render() { + const style = computeStyleSheet(); + const { site, navigation } = this.props; + let connectorStats: ConnectorStats; + // New backend? + if (site.connectorStats) { + // Override + connectorStats = site.connectorStats; + } else { + connectorStats = { + totalConnectors: site.connectorStats.totalConnectors, + availableConnectors: site.connectorStats.availableConnectors + }; + } + return ( + + { + navigation.navigate({ + routeName: 'SiteAreas', + params: { + siteID: site.id + }, + key: `${Utils.randomNumber()}` + }) + }}> + + + + this.siteLocation(site.address)}> + + + {site.name} + + + + + + + + + + ); + } +} diff --git a/src/components/site/SiteComponentStyles.tsx b/src/components/site/SiteComponentStyles.tsx new file mode 100644 index 000000000..e41c91ce3 --- /dev/null +++ b/src/components/site/SiteComponentStyles.tsx @@ -0,0 +1,58 @@ +import deepmerge from 'deepmerge'; +import { Platform } from 'react-native'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + flexDirection: 'column', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor + }, + headerContent: { + flexDirection: 'row', + justifyContent: 'space-between', + paddingTop: '5@s', + paddingBottom: '5@s', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor, + backgroundColor: commonColor.headerBgColor + }, + headerName: { + paddingTop: Platform.OS === 'ios' ? '4@s' : 0, + fontSize: '20@s', + fontWeight: 'bold', + color: commonColor.headerTextColor + }, + subHeaderContent: { + flexDirection: 'row', + justifyContent: 'space-between' + }, + connectorContent: { + flexDirection: 'row', + justifyContent: 'center', + paddingTop: '12@s', + paddingBottom: '12@s', + borderBottomWidth: 1, + borderBottomColor: commonColor.brandPrimaryDark + }, + icon: { + fontSize: '30@s', + marginLeft: '10@s', + marginRight: '10@s', + color: commonColor.headerTextColor + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/transaction/TransactionComponentCommonStyles.tsx b/src/components/transaction/TransactionComponentCommonStyles.tsx new file mode 100644 index 000000000..0b0d6022a --- /dev/null +++ b/src/components/transaction/TransactionComponentCommonStyles.tsx @@ -0,0 +1,74 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + flexDirection: 'column', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor + }, + transactionContent: { + flex: 1, + flexDirection: 'row', + justifyContent: 'space-evenly', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor, + paddingLeft: '5@s', + paddingRight: '5@s', + height: '80@s', + width: '100%' + }, + label: { + color: commonColor.textColor, + fontSize: '10@s', + marginTop: '-3@s' + }, + info: { + color: commonColor.brandPrimaryDark + }, + success: { + color: commonColor.brandSuccess + }, + warning: { + color: commonColor.brandWarning + }, + danger: { + color: commonColor.brandDanger + }, + columnContainer: { + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '60@s' + }, + rowContainer: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center' + }, + icon: { + color: commonColor.textColor, + fontSize: '30@s', + justifyContent: 'flex-end' + }, + labelValue: { + fontSize: '15@s' + }, + subLabelValue: { + fontSize: '10@s' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/transaction/header/TransactionHeaderComponent.tsx b/src/components/transaction/header/TransactionHeaderComponent.tsx new file mode 100644 index 000000000..f9d07ed29 --- /dev/null +++ b/src/components/transaction/header/TransactionHeaderComponent.tsx @@ -0,0 +1,60 @@ +import { Icon, Text, View } from 'native-base'; +import React from 'react'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseScreen from '../../../screens/base-screen/BaseScreen'; +import BaseProps from '../../../types/BaseProps'; +import Transaction from '../../../types/Transaction'; +import Utils from '../../../utils/Utils'; +import computeStyleSheet from './TransactionHeaderComponentStyles'; + +export interface Props extends BaseProps { + transaction: Transaction; + isAdmin: boolean; + isSiteAdmin: boolean; + displayNavigationIcon?: boolean; + visible?: boolean; +} + +interface State { +} +export default class TransactionHeaderComponent extends BaseScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + props.displayNavigationIcon = true; + this.state = { + isVisible: this.props.visible + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public render() { + const style = computeStyleSheet(); + const { transaction, isAdmin, isSiteAdmin, displayNavigationIcon } = this.props; + return ( + + + + {I18nManager.formatDateTime(transaction.timestamp)} + + {displayNavigationIcon && } + + + + {transaction.chargeBoxID} - {Utils.getConnectorLetterFromConnectorID(transaction.connectorId)} + + {(isAdmin || isSiteAdmin) && ( + + {Utils.buildUserName(transaction.user)} + + )} + + + ); + } +} diff --git a/src/components/transaction/header/TransactionHeaderComponentStyles.tsx b/src/components/transaction/header/TransactionHeaderComponentStyles.tsx new file mode 100644 index 000000000..b30477680 --- /dev/null +++ b/src/components/transaction/header/TransactionHeaderComponentStyles.tsx @@ -0,0 +1,104 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + flexDirection: 'column', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor + }, + headerContent: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + padding: '5@s', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor, + backgroundColor: commonColor.headerBgColor + }, + headerName: { + color: commonColor.headerTextColor, + fontSize: '18@s', + marginLeft: '5@s', + marginRight: '5@s', + fontWeight: 'bold' + }, + subHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + padding: '5@s', + paddingLeft: '8@s', + paddingRight: '8@s', + backgroundColor: commonColor.headerBgColorLight + }, + subHeaderName: { + color: commonColor.headerTextColor, + fontSize: '15@s', + width: '49%' + }, + subHeaderNameLeft: {}, + subHeaderNameRight: { + textAlign: 'right' + }, + transactionContent: { + flex: 1, + flexDirection: 'row', + justifyContent: 'space-evenly', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor, + paddingLeft: '5@s', + paddingRight: '5@s', + height: '80@s', + width: '100%' + }, + label: { + color: commonColor.textColor, + fontSize: '10@s', + marginTop: '-3@s' + }, + info: { + color: commonColor.brandPrimaryDark + }, + success: { + color: commonColor.brandSuccess + }, + warning: { + color: commonColor.brandWarning + }, + danger: { + color: commonColor.brandDanger + }, + columnContainer: { + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }, + rowContainer: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center' + }, + icon: { + color: commonColor.textColor, + fontSize: '30@s', + justifyContent: 'flex-end' + }, + labelValue: { + fontSize: '15@s' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/components/transaction/history/TransactionHistoryComponent.tsx b/src/components/transaction/history/TransactionHistoryComponent.tsx new file mode 100644 index 000000000..8af4d38a6 --- /dev/null +++ b/src/components/transaction/history/TransactionHistoryComponent.tsx @@ -0,0 +1,93 @@ +import { Icon, Text, View } from 'native-base'; +import React from 'react'; +import { TouchableOpacity } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseProps from '../../../types/BaseProps'; +import Transaction from '../../../types/Transaction'; +import Constants from '../../../utils/Constants'; +import Utils from '../../../utils/Utils'; +import TransactionHeaderComponent from '../header/TransactionHeaderComponent'; +import computeStyleSheet from '../TransactionComponentCommonStyles'; + +export interface Props extends BaseProps { + transaction: Transaction; + isPricingActive: boolean; + isAdmin: boolean; + isSiteAdmin: boolean; + visible?: boolean; +} + +interface State { +} + +export default class TransactionHistoryComponent extends React.Component { + public state: State; + public props: Props; + private counter: number = 0; + + constructor(props: Props) { + super(props); + this.state = { + isVisible: this.props.visible + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public render() { + const style = computeStyleSheet(); + const { navigation } = this.props; + const { transaction, isAdmin, isSiteAdmin, isPricingActive } = this.props; + const consumption = Math.round(transaction.stop.totalConsumption / 10) / 100; + const price = transaction.stop.price ? Math.round(transaction.stop.price * 100) / 100 : 0; + const duration = Utils.formatDurationHHMMSS(transaction.stop.totalDurationSecs, false); + const inactivity = Utils.formatDurationHHMMSS(transaction.stop.totalInactivitySecs, false); + const inactivityStyle = Utils.computeInactivityStyle(transaction.stop.inactivityStatus); + return ( + + { + navigation.navigate({ + routeName: 'TransactionDetailsTabs', + params: { transactionID: transaction.id }, + key: `${Utils.randomNumber()}` + }); + }}> + + + + + + {I18nManager.formatNumber(consumption)} + (kW.h) + + + + {duration} + (hh:mm) + + + + {inactivity} + (hh:mm) + + {isPricingActive && ( + + + {I18nManager.formatCurrency(price)} + ({transaction.priceUnit}) + + )} + + + + + ); + } +} diff --git a/src/components/transaction/in-progress/TransactionInProgressComponent.tsx b/src/components/transaction/in-progress/TransactionInProgressComponent.tsx new file mode 100644 index 000000000..7726b02f3 --- /dev/null +++ b/src/components/transaction/in-progress/TransactionInProgressComponent.tsx @@ -0,0 +1,110 @@ +import { Icon, Text, View } from 'native-base'; +import React from 'react'; +import { TouchableOpacity } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseProps from '../../../types/BaseProps'; +import Transaction from '../../../types/Transaction'; +import Constants from '../../../utils/Constants'; +import Utils from '../../../utils/Utils'; +import TransactionHeaderComponent from '../header/TransactionHeaderComponent'; +import computeStyleSheet from '../TransactionComponentCommonStyles'; + +export interface Props extends BaseProps { + transaction: Transaction; + isPricingActive: boolean; + isAdmin: boolean; + isSiteAdmin: boolean; + visible?: boolean; +} + +interface State { +} + +export default class TransactionInProgressComponent extends React.Component { + public state: State; + public props: Props; + private counter: number = 0; + + constructor(props: Props) { + super(props); + this.state = { + isVisible: this.props.visible + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public render() { + const style = computeStyleSheet(); + const { transaction, isAdmin, isSiteAdmin, isPricingActive } = this.props; + const consumption = Math.round(transaction.currentConsumption / 10) / 100; + const totalConsumption = Math.round(transaction.currentTotalConsumption / 10) / 100; + const price = transaction.currentCumulatedPrice ? Math.round(transaction.currentCumulatedPrice * 100) / 100 : 0; + const duration = Utils.formatDurationHHMMSS(transaction.currentTotalDurationSecs, false); + const inactivity = Utils.formatDurationHHMMSS(transaction.currentTotalInactivitySecs, false); + const inactivityStyle = Utils.computeInactivityStyle(transaction.currentInactivityStatus); + const batteryLevel = transaction.stateOfCharge ? `${transaction.stateOfCharge} > ${transaction.currentStateOfCharge}` : '-'; + const navigation = this.props.navigation; + return ( + + { + navigation.navigate({ + routeName: 'ChargerConnectorDetailsTabs', + params: { + chargerID: transaction.chargeBoxID, + connectorID: transaction.connectorId + }, + key: `${Utils.randomNumber()}` + }); + }}> + + + + + + {I18nManager.formatNumber(consumption)} + (kW) + + + + {I18nManager.formatNumber(totalConsumption)} + (kW.h) + + + + {batteryLevel} + (%) + + + + + + {duration} + (hh:mm) + + + + {inactivity} + (hh:mm) + + {isPricingActive && ( + + + {price} + ({transaction.priceUnit}) + + )} + + + + + ); + } +} diff --git a/src/config/Configuration.tsx b/src/config/Configuration.tsx new file mode 100644 index 000000000..1a69a41cd --- /dev/null +++ b/src/config/Configuration.tsx @@ -0,0 +1 @@ +export default class Configuration {} diff --git a/src/deeplinking/DeepLinkingManager.tsx b/src/deeplinking/DeepLinkingManager.tsx new file mode 100644 index 000000000..7d318af20 --- /dev/null +++ b/src/deeplinking/DeepLinkingManager.tsx @@ -0,0 +1,160 @@ +import I18n from 'i18n-js'; +import { Linking } from 'react-native'; +import DeepLinking from 'react-native-deep-linking'; +import { NavigationActions, NavigationContainerComponent } from 'react-navigation'; +import CentralServerProvider from '../provider/CentralServerProvider'; +import Constants from '../utils/Constants'; +import Message from '../utils/Message'; +import Utils from '../utils/Utils'; + +export default class DeepLinkingManager { + private navigator: NavigationContainerComponent; + private centralServerProvider: CentralServerProvider; + + public static getInstance() { + return new DeepLinkingManager(); + } + + public initialize(navigator: NavigationContainerComponent, centralServerProvider: CentralServerProvider) { + // Keep + this.navigator = navigator; + this.centralServerProvider = centralServerProvider; + // Activate Deep Linking + DeepLinking.addScheme('eMobility://'); + DeepLinking.addScheme('emobility://'); + // Init Routes + this.addResetPasswordRoute(); + this.addVerifyAccountRoute(); + // Init URL + Linking.getInitialURL().then((url) => { + if (url) { + Linking.openURL(url); + } + }).catch((err) => { + // tslint:disable-next-line: no-console + console.error('An error occurred', err) + }); + } + + private addResetPasswordRoute = () => { + // Add Route + DeepLinking.addRoute('/resetPassword/:tenant/:hash', (response: {tenant: string, hash: string}) => { + // Check params + if (!response.tenant) { + Message.showError(I18n.t('authentication.mandatoryTenant')); + } + // Get the Tenant + const tenant = this.centralServerProvider.getTenant(response.tenant); + if (!tenant) { + Message.showError(I18n.t('authentication.unknownTenant')); + } + if (!response.hash) { + Message.showError(I18n.t('authentication.resetPasswordHashNotValid')); + } + // Disable + this.centralServerProvider.setAutoLoginDisabled(true); + // Navigate + this.navigator.dispatch( + NavigationActions.navigate({ + routeName: 'ResetPassword', + key: `${Utils.randomNumber()}`, + params: { tenantSubDomain: response.tenant, hash: response.hash } + }) + ); + }); + } + + private addVerifyAccountRoute = () => { + // Add Route + DeepLinking.addRoute('/verifyAccount/:tenant/:email/:token/:resetToken', + async (response: {tenant: string, email: string, token: string, resetToken: string}) => { + // Check params + if (!response.tenant) { + Message.showError(I18n.t('authentication.mandatoryTenant')); + } + if (!response.email) { + Message.showError(I18n.t('authentication.mandatoryEmail')); + } + // Get the Tenant + const tenant = this.centralServerProvider.getTenant(response.tenant); + if (!tenant) { + Message.showError(I18n.t('authentication.unknownTenant')); + } + if (!response.token) { + Message.showError(I18n.t('authentication.verifyAccountTokenNotValid')); + } + // Disable + this.centralServerProvider.setAutoLoginDisabled(true); + this.centralServerProvider.logoff(); + // Navigate to login page + this.navigator.dispatch( + NavigationActions.navigate({ + routeName: 'Login', + key: `${Utils.randomNumber()}`, + params: { tenantSubDomain: response.tenant, email: response.email } + }) + ); + // Call the backend + try { + // Validate Account + const result = await this.centralServerProvider.verifyEmail(response.tenant, response.email, response.token); + if (result.status === Constants.REST_RESPONSE_SUCCESS) { + // Ok + Message.showSuccess(I18n.t('authentication.accountVerifiedSuccess')); + // Check if user has to change his password + if (response.resetToken && response.resetToken !== 'null') { + // Change password + this.navigator.dispatch( + NavigationActions.navigate({ + routeName: 'ResetPassword', + key: `${Utils.randomNumber()}`, + params: { tenantSubDomain: response.tenant, hash: response.resetToken } + }) + ); + } + } + } catch (error) { + // Check request? + if (error.request) { + // Show error + switch (error.request.status) { + // Account already active + case 530: + Message.showError(I18n.t('authentication.accountAlreadyActive')); + break; + // VerificationToken no longer valid + case 540: + Message.showError(I18n.t('authentication.activationTokenNotValid')); + break; + // Email does not exist + case 550: + Message.showError(I18n.t('authentication.activationEmailNotValid')); + break; + // Other common Error + default: + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'authentication.activationUnexpectedError'); + } + } else { + Message.showError(I18n.t('authentication.activationUnexpectedError')); + } + } + }); + } + + public startListening() { + Linking.addEventListener('url', this.handleUrl); + } + + public stopListening() { + Linking.removeEventListener('url', this.handleUrl); + } + + public handleUrl = ({ url }: { url: string }) => { + Linking.canOpenURL(url).then((supported) => { + if (supported) { + DeepLinking.evaluateUrl(url); + } + }); + } +} diff --git a/src/migration/MigrationManager.tsx b/src/migration/MigrationManager.tsx new file mode 100644 index 000000000..d50202782 --- /dev/null +++ b/src/migration/MigrationManager.tsx @@ -0,0 +1,23 @@ +import { ChargePointStatus } from '../types/ChargingStation'; +import { GlobalFilters } from '../types/Filter'; +import SecuredStorage from '../utils/SecuredStorage'; + +export default class MigrationManager { + public static getInstance(): MigrationManager { + return new MigrationManager(); + } + + public migrate = async () => { + // Init filters + await this.checkInitialFilters(); + } + + private async checkInitialFilters() { + // Available chargers + const filterExists = await SecuredStorage.filterExists(GlobalFilters.ONLY_AVAILABLE_CHARGERS); + if (!filterExists) { + // Create initial default value + await SecuredStorage.saveFilterValue(GlobalFilters.ONLY_AVAILABLE_CHARGERS, ChargePointStatus.AVAILABLE); + } + } +} diff --git a/src/notification/NotificationManager.tsx b/src/notification/NotificationManager.tsx new file mode 100644 index 000000000..dab7a0722 --- /dev/null +++ b/src/notification/NotificationManager.tsx @@ -0,0 +1,261 @@ +import I18n from 'i18n-js'; +import { Platform } from 'react-native'; +import firebase from 'react-native-firebase'; +import { Notification, NotificationOpen } from 'react-native-firebase/notifications'; +import { NavigationActions, NavigationContainerComponent } from 'react-navigation'; +import CentralServerProvider from '../provider/CentralServerProvider'; +import { UserNotificationType } from '../types/UserNotifications'; +import Message from '../utils/Message'; +import Utils from '../utils/Utils'; + +export default class NotificationManager { + private static notificationManager: NotificationManager; + private token: string; + private navigator: NavigationContainerComponent; + private removeNotificationDisplayedListener: () => any; + private removeNotificationListener: () => any; + private removeNotificationOpenedListener: () => any; + private removeTokenRefreshListener: () => any; + private messageListener: () => any; + private centralServerProvider: CentralServerProvider; + private lastNotification: NotificationOpen + + public static getInstance(): NotificationManager { + if (!this.notificationManager) { + this.notificationManager = new NotificationManager(); + } + return this.notificationManager; + } + + public setCentralServerProvider(centralServerProvider: CentralServerProvider) { + this.centralServerProvider = centralServerProvider; + } + + public async initialize(navigator: NavigationContainerComponent) { + // Keep the nav + this.navigator = navigator; + // Check if user has given permission + let enabled = await firebase.messaging().hasPermission(); + if (!enabled) { + // Request permission + try { + await firebase.messaging().requestPermission(); + // User has authorized permissions + } catch (error) { + // User has rejected permissions + } + } + // Check again + enabled = await firebase.messaging().hasPermission(); + if (enabled) { + const fcmToken = await firebase.messaging().getToken(); + if (fcmToken) { + this.token = fcmToken; + } + } + } + + public async start() { + // Check Initial Notification + const initialNotificationOpen = await firebase.notifications().getInitialNotification(); + if (initialNotificationOpen) { + this.lastNotification = initialNotificationOpen; + } + // Notification Displayed + this.removeNotificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification: Notification) => { + // Do nothing + }); + // Notification Received + this.removeNotificationListener = firebase.notifications().onNotification(async (notification: Notification) => { + // App in foreground: Display the notification + notification.setSound('default'); + // Check if notification has to be displayed + if (notification.data) { + // Check + switch (notification.data.notificationType) { + // Do nothing + case UserNotificationType.END_OF_SESSION: + case UserNotificationType.SESSION_STARTED: + break; + + // Force display notif + default: + await firebase.notifications().displayNotification(notification); + break; + } + } else { + // Always display it + await firebase.notifications().displayNotification(notification); + } + }); + // Notification Received and User opened it + this.removeNotificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => { + this.processOpenedNotification(notificationOpen); + }); + // Get Firebase messages + this.messageListener = firebase.messaging().onMessage((message) => { + // Do nothing + }); + // Token has changed + this.removeTokenRefreshListener = firebase.messaging().onTokenRefresh(async (newFcmToken) => { + // Process your token as required + this.token = newFcmToken; + try { + // Save the User's token + if (this.centralServerProvider.isUserConnected()) { + await this.centralServerProvider.saveUserMobileToken({ + id: this.centralServerProvider.getUserInfo().id, + mobileToken: this.getToken(), + mobileOS: this.getOs() + }); + } + } catch (error) { + // tslint:disable-next-line: no-console + console.log('Error saving Mobile Token:', error); + } + }); + } + + public async stop() { + this.removeNotificationDisplayedListener(); + this.removeNotificationListener(); + this.removeNotificationOpenedListener(); + this.removeTokenRefreshListener(); + this.messageListener(); + } + + public getToken(): string { + return this.token; + } + + public getOs(): string { + return Platform.OS; + } + + public async checkOnHoldNotification() { + if (this.lastNotification) { + const notificationProcessed = await this.processOpenedNotification(this.lastNotification); + if (notificationProcessed) { + this.lastNotification = null; + } + } + } + + private async processOpenedNotification(notificationOpen: NotificationOpen): Promise { + // Get information about the notification that was opened + const notification: Notification = notificationOpen.notification; + // No: meaning the user got the notif and clicked on it, then navigate to the right screen + // User must be logged and Navigation available + if (!this.centralServerProvider.isUserConnectionValid() || !this.navigator) { + // Process it later + this.lastNotification = notificationOpen; + return false; + } + // Check Tenant + if (this.centralServerProvider.getUserInfo().tenantID !== notification.data.tenantID) { + Message.showError(I18n.t('general.wrongTenant')); + return false; + } + // Check + switch (notification.data.notificationType) { + // End of Transaction + case UserNotificationType.END_OF_SESSION: + // Navigate + this.navigator.dispatch( + NavigationActions.navigate({ + routeName: 'TransactionHistoryNavigator', + key: `${Utils.randomNumber()}`, + action: NavigationActions.navigate({ + routeName: 'TransactionDetailsTabs', + key: `${Utils.randomNumber()}`, + params: { + transactionID: parseInt(notification.data.transactionId, 10) + } + }), + }) + ); + break; + + // Session In Progress + case UserNotificationType.SESSION_STARTED: + case UserNotificationType.END_OF_CHARGE: + case UserNotificationType.OPTIMAL_CHARGE_REACHED: + // Navigate + this.navigator.dispatch( + NavigationActions.navigate({ + routeName: 'TransactionInProgressNavigator', + key: `${Utils.randomNumber()}`, + action: NavigationActions.navigate({ + routeName: 'ChargerConnectorDetailsTabs', + key: `${Utils.randomNumber()}`, + params: { + chargerID: notification.data.chargeBoxID, + connectorID: Utils.getConnectorIDFromConnectorLetter(notification.data.connectorId) + } + }), + }) + ); + break; + + case UserNotificationType.CHARGING_STATION_STATUS_ERROR: + case UserNotificationType.PREPARING_SESSION_NOT_STARTED: + // Navigate + this.navigator.dispatch( + NavigationActions.navigate({ + routeName: 'ChargersNavigator', + key: `${Utils.randomNumber()}`, + action: NavigationActions.navigate({ + routeName: 'ChargerConnectorDetailsTabs', + key: `${Utils.randomNumber()}`, + params: { + chargerID: notification.data.chargeBoxID, + connectorID: Utils.getConnectorIDFromConnectorLetter(notification.data.connectorId) + } + }), + }) + ); + break; + + // Charger just connected + case UserNotificationType.SESSION_NOT_STARTED_AFTER_AUTHORIZE: + case UserNotificationType.CHARGING_STATION_REGISTERED: + // Navigate + this.navigator.dispatch( + NavigationActions.navigate({ + routeName: 'ChargersNavigator', + key: `${Utils.randomNumber()}`, + action: NavigationActions.navigate({ + routeName: 'ChargerConnectorDetailsTabs', + key: `${Utils.randomNumber()}`, + params: { + chargerID: notification.data.chargeBoxID, + connectorID: 1 + } + }), + }) + ); + break; + + // Go to Charger list + case UserNotificationType.OFFLINE_CHARGING_STATION: + // Navigate + this.navigator.dispatch( + NavigationActions.navigate({ + routeName: 'Chargers', + key: `${Utils.randomNumber()}` + }) + ); + break; + + // No need to navigate + case UserNotificationType.UNKNOWN_USER_BADGED: + case UserNotificationType.OCPI_PATCH_STATUS_ERROR: + case UserNotificationType.SMTP_AUTH_ERROR: + case UserNotificationType.USER_ACCOUNT_STATUS_CHANGED: + case UserNotificationType.USER_ACCOUNT_INACTIVITY: + case UserNotificationType.BILLING_USER_SYNCHRONIZATION_FAILED: + break; + } + return true; + } +} diff --git a/src/provider/CentralServerProvider.tsx b/src/provider/CentralServerProvider.tsx new file mode 100644 index 000000000..335e7ebb9 --- /dev/null +++ b/src/provider/CentralServerProvider.tsx @@ -0,0 +1,735 @@ +import axios from 'axios'; +import jwtDecode from 'jwt-decode'; +import NotificationManager from 'notification/NotificationManager'; +import { NavigationParams, NavigationScreenProp, NavigationState } from 'react-navigation'; +import I18nManager from '../I18n/I18nManager'; +import MigrationManager from '../migration/MigrationManager'; +import { ActionResponse } from '../types/ActionResponse'; +import ChargingStation, { ChargingStationConfiguration } from '../types/ChargingStation'; +import { DataResult, TransactionDataResult } from '../types/DataResult'; +import Eula, { EulaAccepted } from '../types/Eula'; +import PagingParams from '../types/PagingParams'; +import Setting from '../types/Setting'; +import Site from '../types/Site'; +import SiteArea from '../types/SiteArea'; +import Tenant from '../types/Tenant'; +import Transaction from '../types/Transaction'; +import UserToken from '../types/UserToken'; +import Constants from '../utils/Constants'; +import SecuredStorage from '../utils/SecuredStorage'; +import Utils from '../utils/Utils'; +import SecurityProvider from './SecurityProvider'; + +export default class CentralServerProvider { + private debug: boolean = false; + private captchaBaseUrl: string = 'https://evse.cfapps.eu10.hana.ondemand.com'; + private centralRestServerServiceBaseURL: string = 'https://sap-ev-rest-server.cfapps.eu10.hana.ondemand.com'; + private centralRestServerServiceAuthURL: string = this.centralRestServerServiceBaseURL + '/client/auth'; + private centralRestServerServiceSecuredURL: string = this.centralRestServerServiceBaseURL + '/client/api'; + private captchaSiteKey: string = '6Lcmr6EUAAAAAIyn3LasUzk-0MpH2R1COXFYsxNw'; + + // Paste the token below + private token: string = null; + private decodedToken: UserToken = null; + private email: string = null; + private password: string = null; + private locale: string = null; + private tenantSubDomain: string = null; + private currency: string = null; + private siteImages: {id: string; image: string;}[] = []; + private autoLoginDisabled: boolean = false; + private notificationManager: NotificationManager; + + private securityProvider: SecurityProvider = null; + + constructor() { + if (__DEV__) { + // QA REST Server + // this.centralRestServerServiceBaseURL = 'https://sap-ev-rest-server-qa.cfapps.eu10.hana.ondemand.com'; + this.centralRestServerServiceAuthURL = this.centralRestServerServiceBaseURL + '/client/auth'; + this.centralRestServerServiceSecuredURL = this.centralRestServerServiceBaseURL + '/client/api'; + this.debug = true; + // Debug Axios + axios.interceptors.request.use(request => { + // tslint:disable-next-line: no-console + console.log(new Date().toISOString() + ' - Axios - Request:', request) + return request; + }); + axios.interceptors.response.use(response => { + // tslint:disable-next-line: no-console + console.log(new Date().toISOString() + ' - Axios - Response:', response) + return response; + }); + } + } + + public setNotificationManager(notificationManager: NotificationManager) { + this.notificationManager = notificationManager; + } + + public async initialize() { + // Get stored data + const credentials = await SecuredStorage.getUserCredentials(this.tenantSubDomain); + if (credentials) { + // Set + this.email = credentials.email; + this.password = credentials.password; + this.token = credentials.token; + this.tenantSubDomain = credentials.tenantSubDomain; + this.locale = credentials.locale; + this.currency = credentials.currency; + } else { + // Set + this.email = null; + this.password = null; + this.token = null; + this.tenantSubDomain = null; + this.locale = null; + this.currency = null; + } + // Check Token + if (this.token) { + // Try to decode the token + try { + // Decode the token + this.decodedToken = jwtDecode(this.token); + // Build Security Provider + this.securityProvider = new SecurityProvider(this.decodedToken); + } catch (error) {} + } + // Adjust the language according the last login info + I18nManager.switchLanguage(this.getUserLanguage(), this.currency); + } + + public getCaptchaBaseUrl(): string { + return this.captchaBaseUrl; + } + + public getCaptchaSiteKey(): string { + return this.captchaSiteKey; + } + + public getTenant(tenantSubDomain: string): Partial { + return this.getTenants().find((tenant: Partial) => tenant.subdomain === tenantSubDomain); + } + + // eslint-disable-next-line class-methods-use-this + public getTenants(): Partial[] { + if (__DEV__) { + return [ + { subdomain: 'testcharger', name: 'Test Chargers' }, + { subdomain: 'slf', name: 'SAP Labs France' }, + { subdomain: 'slfcah', name: 'SAP Labs France (Charge@Home)' }, + { subdomain: 'proviridis', name: 'Proviridis' }, + { subdomain: 'demo', name: 'SAP Labs Demo' }, + { subdomain: 'sapbelgium', name: 'SAP Belgium' }, + ]; + } + return [ + { subdomain: 'slf', name: 'SAP Labs France' }, + { subdomain: 'slfcah', name: 'SAP Labs France (Charge@Home)' }, + { subdomain: 'proviridis', name: 'Proviridis' }, + { subdomain: 'sapbelgium', name: 'SAP Belgium' }, + ]; + } + + public async triggerAutoLogin( + navigation: NavigationScreenProp, fctRefresh: any) { + this.debugMethod('triggerAutoLogin'); + try { + // Force log the user + await this.login(this.email, this.password, true, this.tenantSubDomain); + // Ok: Refresh + if (fctRefresh) { + fctRefresh(); + } + } catch (error) { + // Ko: Logoff + await this.logoff(); + // Go to login page + if (navigation) { + navigation.navigate('AuthNavigator'); + } + } + } + + public hasUserConnectionExpired(): boolean { + this.debugMethod('hasUserConnectionExpired'); + return this.isUserConnected() && !this.isUserConnectionValid(); + } + + public isUserConnected(): boolean { + this.debugMethod('isUserConnected'); + return !!this.token; + } + + public isUserConnectionValid(): boolean { + this.debugMethod('isUserConnectionValid'); + // Email and Password are mandatory + if (!this.email || !this.password || !this.tenantSubDomain) { + return false; + } + // Check Token + if (this.token) { + try { + // Try to decode the token + this.decodedToken = jwtDecode(this.token); + } catch (error) { + return false; + } + // Check if expired + if (this.decodedToken) { + if (this.decodedToken.exp < Date.now() / 1000) { + // Expired + return false; + } + return true; + } + } + return false; + } + + public async clearUserPassword() { + await SecuredStorage.clearUserPassword(this.tenantSubDomain); + this.password = null; + } + + public getUserEmail(): string { + return this.email; + } + + public getUserCurrency(): string { + return this.currency; + } + + public getUserLocale(): string { + if (this.locale) { + return this.locale; + } + return Utils.getDefaultLocale(); + } + + public getUserLanguage(): string { + if (this.locale) { + return Utils.getLanguageFromLocale(this.locale); + } + return Utils.getDefaultLanguage(); + } + + public getUserPassword(): string { + return this.password; + } + + public getUserTenant(): string { + return this.tenantSubDomain; + } + + public getUserToken(): string { + return this.token; + } + + public getUserInfo(): UserToken { + return this.decodedToken; + } + + public hasAutoLoginDisabled(): boolean { + return this.autoLoginDisabled; + } + + public setAutoLoginDisabled(autoLoginDisabled: boolean) { + this.autoLoginDisabled = autoLoginDisabled; + } + + public logoff() { + this.debugMethod('logoff'); + // Clear the token and tenant + SecuredStorage.clearUserToken(this.tenantSubDomain); + // Clear local data + this.token = null; + this.decodedToken = null; + } + + public async login(email: string, password: string, acceptEula: boolean, tenantSubDomain: string) { + this.debugMethod('login'); + // Call + const result = await axios.post( + `${this.centralRestServerServiceAuthURL}/Login`, + { + acceptEula, + email, + password, + tenant: tenantSubDomain, + }, + { + headers: this.buildHeaders(), + }, + ); + // Keep them + this.email = email; + this.password = password; + this.token = result.data.token; + this.decodedToken = jwtDecode(this.token); + this.locale = this.decodedToken.locale; + this.currency = this.decodedToken.currency; + this.tenantSubDomain = tenantSubDomain; + this.securityProvider = new SecurityProvider(this.decodedToken); + this.autoLoginDisabled = false; + // Save + await SecuredStorage.saveUserCredentials(tenantSubDomain, { + email, + password, + tenantSubDomain, + token: result.data.token, + locale: this.decodedToken.locale, + currency: this.decodedToken.currency + }); + // Adjust the language according the last login info + I18nManager.switchLanguage(this.getUserLanguage(), this.currency); + try { + // Save the User's token + await this.saveUserMobileToken({ + id: this.getUserInfo().id, + mobileToken: this.notificationManager.getToken(), + mobileOS: this.notificationManager.getOs() + }); + } catch (error) { + // tslint:disable-next-line: no-console + console.log('Error saving Mobile Token:', error); + } + // Check migration for logged user + const migrationManager = MigrationManager.getInstance(); + await migrationManager.migrate(); + // Check on hold notification + this.notificationManager.checkOnHoldNotification(); + } + + public async register(tenantSubDomain: string, name: string, firstName: string, email: string, + passwords: {password: string; repeatPassword: string; }, acceptEula: boolean, captcha: string) { + this.debugMethod('register'); + // Call + const result = await axios.post( + `${this.centralRestServerServiceAuthURL}/RegisterUser`, + { + acceptEula, + captcha, + email, + firstName, + name, + passwords, + tenant: tenantSubDomain, + }, + { + headers: this.buildHeaders(), + }, + ); + // Clear the token and tenant + SecuredStorage.clearUserToken(tenantSubDomain); + // Save + await SecuredStorage.saveUserCredentials(tenantSubDomain, { + email, + password: passwords.password, + tenantSubDomain, + }); + // Keep them + this.email = email; + this.password = passwords.password; + this.token = null; + this.decodedToken = null; + this.tenantSubDomain = tenantSubDomain; + return result.data; + } + + public async retrievePassword(tenantSubDomain: string, email: string, captcha: string) { + this.debugMethod('retrievePassword'); + const result = await axios.post( + `${this.centralRestServerServiceAuthURL}/Reset`, + { + tenant: tenantSubDomain, + captcha, + email, + }, + { + headers: this.buildHeaders(), + }, + ); + return result.data; + } + + public async resetPassword(tenantSubDomain: string, hash: string, passwords: {password: string; repeatPassword: string; }) { + this.debugMethod('resetPassword'); + const result = await axios.post( + `${this.centralRestServerServiceAuthURL}/Reset`, + { + tenant: tenantSubDomain, + hash, + passwords, + }, + { + headers: this.buildHeaders(), + }, + ); + return result.data; + } + + public async verifyEmail(tenantSubDomain: string, email: string, token: string): Promise { + this.debugMethod('verifyEmail'); + // Call + const result = await axios.get(`${this.centralRestServerServiceAuthURL}/VerifyEmail`, { + headers: this.buildHeaders(), + params:{ + Tenant: tenantSubDomain, + Email: email, + VerificationToken: token + }, + }); + return result.data; + } + + public async getChargers(params = {}, paging: PagingParams = Constants.DEFAULT_PAGING): Promise> { + this.debugMethod('getChargers'); + // Build Paging + this.buildPaging(paging, params); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/ChargingStations`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data; + } + + public async saveUserMobileToken(params: {id: string; mobileToken: string; mobileOS: string}): Promise { + this.debugMethod('saveUserMobileToken'); + // Call + const result = await axios.put(`${this.centralRestServerServiceSecuredURL}/UpdateUserMobileToken`, params, { + headers: this.buildSecuredHeaders(), + }); + return result.data; + } + + public async getCharger(params = {}): Promise { + this.debugMethod('getCharger'); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/ChargingStation`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data; + } + + public async getChargerConfiguration(id: string): Promise { + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/ChargingStationConfiguration?ChargeBoxID=${id}`, { + headers: this.buildSecuredHeaders() + }); + return result.data; + } + + public async getSettings(params: {} = {}): Promise> { + this.debugMethod('getCharger'); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/Settings`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data; + } + + public async getSites(params = {}, paging: PagingParams = Constants.DEFAULT_PAGING): Promise> { + this.debugMethod('getSites'); + // Build Paging + this.buildPaging(paging, params); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/Sites`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data; + } + + public async getSiteAreas(params = {}, paging: PagingParams = Constants.DEFAULT_PAGING): Promise> { + this.debugMethod('getSiteAreas'); + // Build Paging + this.buildPaging(paging, params); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/SiteAreas`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data; + } + + public async getEndUserLicenseAgreement(params: { Language: string; }): Promise { + this.debugMethod('getEndUserLicenseAgreement'); + // Call + const result = await axios.get(`${this.centralRestServerServiceAuthURL}/EndUserLicenseAgreement`, { + headers: this.buildHeaders(), + params + }); + return result.data; + } + + public async startTransaction(chargeBoxID: string, connectorId: number, tagID: string): Promise { + this.debugMethod('startTransaction'); + // Call + const result = await axios.post( + `${this.centralRestServerServiceSecuredURL}/ChargingStationRemoteStartTransaction`, + { + args: { + connectorId, + tagID, + }, + chargeBoxID, + }, + { + headers: this.buildSecuredHeaders(), + }, + ); + return result.data; + } + + public async stopTransaction(chargeBoxID: string, transactionId: number): Promise { + this.debugMethod('stopTransaction'); + // Call + const result = await axios.post( + `${this.centralRestServerServiceSecuredURL}/ChargingStationRemoteStopTransaction`, + { + args: { + transactionId, + }, + chargeBoxID, + }, + { + headers: this.buildSecuredHeaders(), + }, + ); + return result.data; + } + + public async reset(chargeBoxID: string, type: 'Soft'|'Hard'): Promise { + this.debugMethod('reset'); + // Call + const result = await axios.post( + `${this.centralRestServerServiceSecuredURL}/ChargingStationReset`, + { + args: { + type, + }, + chargeBoxID, + }, + { + headers: this.buildSecuredHeaders(), + }, + ); + return result.data; + } + + public async clearCache(chargeBoxID: string): Promise { + this.debugMethod('clearCache'); + // Call + const result = await axios.post( + `${this.centralRestServerServiceSecuredURL}/ChargingStationClearCache`, + { + args: {}, + chargeBoxID, + }, + { + headers: this.buildSecuredHeaders(), + }, + ); + return result.data; + } + + public async unlockConnector(chargeBoxID: string, connectorId: number): Promise { + this.debugMethod('clearCache'); + // Call + const result = await axios.post( + `${this.centralRestServerServiceSecuredURL}/ChargingStationUnlockConnector`, + { + args: { + connectorId + }, + chargeBoxID + }, + { + headers: this.buildSecuredHeaders(), + }, + ); + return result.data; + } + + public async getTransaction(params = {}): Promise { + this.debugMethod('getTransaction'); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/Transaction`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data; + } + + public async getLastTransaction(chargeBoxID: string, connectorId: number): Promise { + const params: { [param: string]: string } = {}; + params.ChargeBoxID = chargeBoxID; + params.ConnectorId = connectorId + ''; + params.Limit = '1'; + params.Skip = '0'; + params.SortFields = 'timestamp'; + params.SortDirs = '-1'; + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/ChargingStationTransactions`, { + headers: this.buildSecuredHeaders(), + params, + }); + if (result.data.count > 0) { + return result.data.result[0]; + } + return null; + } + + public async getTransactions(params = {}, paging: PagingParams = Constants.DEFAULT_PAGING): Promise { + this.debugMethod('getTransactions'); + // Build Paging + this.buildPaging(paging, params); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/TransactionsCompleted`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data; + } + + public async requestChargingStationOCPPConfiguration(id: string): Promise { + this.debugMethod('requestChargingStationOCPPConfiguration'); + // Call + const result = await axios.post(`${this.centralRestServerServiceSecuredURL}/ChargingStationRequestConfiguration`, + { + chargeBoxID: id, + forceUpdateOCPPParamsFromTemplate: false, + }, { + headers: this.buildSecuredHeaders(), + } + ); + return result.data; + } + + public async getTransactionsActive(params = {}, paging: PagingParams = Constants.DEFAULT_PAGING): Promise> { + this.debugMethod('getTransactionsActive'); + // Build Paging + this.buildPaging(paging, params); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/TransactionsActive`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data; + } + + public async getUserImage(params = {}): Promise { + this.debugMethod('getUserImage'); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/UserImage`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data.image; + } + + public async getSiteImage(id: string): Promise { + this.debugMethod('getSiteImage'); + // Check cache + let foundSiteImage = this.siteImages.find((siteImage) => siteImage.id === id); + if (!foundSiteImage) { + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/SiteImage`, { + headers: this.buildSecuredHeaders(), + params: { ID: id }, + }); + // Set + foundSiteImage = { + id, + image: result.data.image, + }; + // Add + this.siteImages.push(foundSiteImage); + } + return foundSiteImage.image; + } + + public async getTransactionWithConsumption(params = {}): Promise { + this.debugMethod('getChargingStationConsumption'); + // Call + const result = await axios.get(`${this.centralRestServerServiceSecuredURL}/ChargingStationConsumptionFromTransaction`, { + headers: this.buildSecuredHeaders(), + params, + }); + return result.data; + } + + public async checkEndUserLicenseAgreement(params: {email: string, tenantSubDomain: string;}): Promise { + this.debugMethod('checkEndUserLicenseAgreement'); + // Call + const result = await axios.get(`${this.centralRestServerServiceAuthURL}/CheckEndUserLicenseAgreement`, { + headers: this.buildHeaders(), + params: { + Email: params.email, + Tenant: params.tenantSubDomain + }, + }); + return result.data; + } + + public getSecurityProvider(): SecurityProvider { + return this.securityProvider; + } + + private buildPaging(paging: PagingParams, queryString: any) { + if (paging) { + // Limit + if (paging.limit) { + queryString.Limit = paging.limit; + } + // Skip + if (paging.skip) { + queryString.Skip = paging.skip; + } + // Record count + if (paging.onlyRecordCount) { + queryString.OnlyRecordCount = paging.onlyRecordCount; + } + } + } + + // // eslint-disable-next-line class-methods-use-this + // _buildOrdering(ordering, queryString) { + // if (ordering && ordering.length) { + // if (!queryString.SortFields) { + // queryString.SortFields = []; + // queryString.SortDirs = []; + // } + // ordering.forEach((order) => { + // queryString.SortFields.push(order.field); + // queryString.SortDirs.push(order.direction); + // }); + // } + // } + + private buildHeaders(): object { + return { + 'Content-Type': 'application/json', + }; + } + + private buildSecuredHeaders(): object { + return { + 'Authorization': 'Bearer ' + this.token, + 'Content-Type': 'application/json', + }; + } + + private debugMethod(methodName: string) { + if (this.debug) { + // tslint:disable-next-line: no-console + console.log(new Date().toISOString() + ' - ' + methodName); + } + } +} diff --git a/src/provider/ProviderFactory.tsx b/src/provider/ProviderFactory.tsx new file mode 100644 index 000000000..2b305e8f9 --- /dev/null +++ b/src/provider/ProviderFactory.tsx @@ -0,0 +1,36 @@ +import Utils from '../utils/Utils'; +import CentralServerProvider from './CentralServerProvider'; + +export default class ProviderFactory { + private static centralServerProvider: CentralServerProvider; + private static underInitialization: boolean; + + private constructor() { + ProviderFactory.underInitialization = false; + } + + private static async checkAndWaitForEndOfInit() { + // Wait + while (ProviderFactory.underInitialization) { + await Utils.sleep(500); + } + } + + public static async getProvider(): Promise { + // Check + await ProviderFactory.checkAndWaitForEndOfInit(); + // Init + if (!ProviderFactory.centralServerProvider) { + // Handling singleton + ProviderFactory.underInitialization = true; + // No: return the real provider + ProviderFactory.centralServerProvider = new CentralServerProvider(); + // Init + await ProviderFactory.centralServerProvider.initialize(); + // End + ProviderFactory.underInitialization = false; + } + return ProviderFactory.centralServerProvider; + } + +} diff --git a/src/provider/SecurityProvider.tsx b/src/provider/SecurityProvider.tsx new file mode 100644 index 000000000..cfaf46fca --- /dev/null +++ b/src/provider/SecurityProvider.tsx @@ -0,0 +1,114 @@ +import { Action, Entity, Role } from '../types/Authorization'; +import { ComponentType } from '../types/Setting'; +import SiteArea from '../types/SiteArea'; +import UserToken from '../types/UserToken'; + +export default class SecurityProvider { + private loggedUser: UserToken; + + constructor(loggedUser: UserToken) { + this.loggedUser = loggedUser; + } + + public isAdmin(): boolean { + return this.loggedUser.role === Role.ADMIN; + } + + public hasSiteAdmin(): boolean { + if (this.isAdmin()) { + return true; + } + return this.loggedUser.sitesAdmin && this.loggedUser.sitesAdmin.length > 0; + } + + public isSiteAdmin(siteID: string): boolean { + if (this.isAdmin()) { + return true; + } + if (this.canAccess(Entity.SITE, Action.UPDATE)) { + return this.loggedUser.sitesAdmin && this.loggedUser.sitesAdmin.includes(siteID); + } + return false; + } + + public isSiteUser(siteID: string) { + if (this.isAdmin()) { + return true; + } + if (this.canAccess(Entity.SITE, Action.READ)) { + return this.loggedUser.sites && this.loggedUser.sites.includes(siteID); + } + return false; + } + + public isBasic(): boolean { + return this.loggedUser.role === Role.BASIC; + } + + public isDemo(): boolean { + return this.loggedUser.role === Role.DEMO; + } + + public isComponentPricingActive(): boolean { + return this.isComponentActive(ComponentType.PRICING); + } + + public isComponentOrganizationActive(): boolean { + return this.isComponentActive(ComponentType.ORGANIZATION); + } + + public isComponentActive(componentName: string): boolean { + if (this.loggedUser && this.loggedUser.activeComponents) { + return this.loggedUser.activeComponents.includes(componentName); + } + return false; + } + + public canUpdateChargingStation(): boolean { + return this.canAccess(Entity.CHARGING_STATION, Action.UPDATE); + } + + public canStopTransaction(siteArea: SiteArea, badgeID: string): boolean { + if (this.canAccess(Entity.CHARGING_STATION, Action.REMOTE_STOP_TRANSACTION)) { + if (this.loggedUser.tagIDs.includes(badgeID)) { + return true; + } + if (this.isComponentActive(ComponentType.ORGANIZATION)) { + return siteArea && this.isSiteAdmin(siteArea.siteID); + } + return this.isAdmin(); + } + return false; + } + + public canStartTransaction(siteArea: SiteArea): boolean { + if (this.canAccess(Entity.CHARGING_STATION, Action.REMOTE_START_TRANSACTION)) { + if (this.isComponentActive(ComponentType.ORGANIZATION)) { + if (!siteArea) { + return false; + } + return !siteArea.accessControl || this.isSiteAdmin(siteArea.siteID) || + this.loggedUser.sites.includes(siteArea.siteID); + } + return true; + } + return false; + } + + public canReadTransaction(siteArea: SiteArea, badgeID: string): boolean { + if (this.canAccess(Entity.TRANSACTION, Action.READ)) { + if (this.loggedUser.tagIDs.includes(badgeID)) { + return true; + } + if (this.isComponentActive(ComponentType.ORGANIZATION) && siteArea) { + return this.isSiteAdmin(siteArea.siteID) || (this.isDemo() && this.isSiteUser(siteArea.siteID)); + } + return this.isAdmin() || this.isDemo(); + } + return false; + } + + public canAccess(resource: string, action: string): boolean { + return this.loggedUser && this.loggedUser.scopes && this.loggedUser.scopes.includes(`${resource}:${action}`); + } +} diff --git a/src/re-captcha/ReactNativeRecaptchaV3.tsx b/src/re-captcha/ReactNativeRecaptchaV3.tsx new file mode 100644 index 000000000..eb156320d --- /dev/null +++ b/src/re-captcha/ReactNativeRecaptchaV3.tsx @@ -0,0 +1,58 @@ +import React, { PureComponent } from 'react'; +import { WebView } from 'react-native-webview'; + +const recaptchaHtml = ` + + + + + + + + + + +`; + +interface Props { + url: string; + siteKey: string; + action: string; + onHandleToken?: (token: string) => void; +} + +class ReactNativeRecaptchaV3 extends PureComponent { + public static defaultProps = { + leftActionIconType: 'MaterialIcons', + rightActionIconType: 'MaterialIcons' + }; + + public render() { + const { onHandleToken, url, siteKey, action } = this.props; + const recaptchaHtmlWithKey = recaptchaHtml.replace(/SITEKEY/g, siteKey).replace(/ACTION/g, action); + return ( + onHandleToken(event.nativeEvent.data)} + /> + ); + } +} + +export default ReactNativeRecaptchaV3; diff --git a/src/screens/auth/AuthHeader.tsx b/src/screens/auth/AuthHeader.tsx new file mode 100644 index 000000000..b198058a0 --- /dev/null +++ b/src/screens/auth/AuthHeader.tsx @@ -0,0 +1,44 @@ +import I18n from 'i18n-js'; +import { Text, View } from 'native-base'; +import React from 'react'; +import { Image } from 'react-native'; +import DeviceInfo from 'react-native-device-info'; +import BaseProps from '../../types/BaseProps'; +import BaseScreen from '../base-screen/BaseScreen'; +import computeStyleSheet from './AuthStyles'; + +import logo from '../../../assets/logo-low.png'; + +export interface Props extends BaseProps { + tenantName?: string; +} + +interface State { +} + +export default class AuthHeader extends BaseScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public render() { + const style = computeStyleSheet(); + const { tenantName } = this.props; + return ( + + + e-Mobility + {/* {`${I18n.t("general.version")} ${DeviceInfo.getVersion()}`} (Beta) */} + {`${I18n.t('general.version')} ${DeviceInfo.getVersion()}`} + {tenantName} + + ); + } +} diff --git a/src/screens/auth/AuthStyles.tsx b/src/screens/auth/AuthStyles.tsx new file mode 100644 index 000000000..a5fb1b092 --- /dev/null +++ b/src/screens/auth/AuthStyles.tsx @@ -0,0 +1,180 @@ +import deepmerge from 'deepmerge'; +import { Platform } from 'react-native'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + noDisplay: { + flex: 1, + backgroundColor: commonColor.brandPrimaryDark + }, + spinner: { + flex: 1 + }, + container: { + flex: 1, + backgroundColor: commonColor.brandPrimaryDark + }, + keyboardContainer: { + flex: 1 + }, + scrollContainer: { + minHeight: '90%' + }, + formContainer: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }, + formHeader: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }, + form: { + flex: 1, + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'center' + }, + logo: { + resizeMode: 'contain', + marginTop: '10@s', + height: '100@s' + }, + appText: { + color: commonColor.inverseTextColor, + fontSize: '40@s', + fontWeight: 'bold', + paddingTop: '5@s' + }, + appVersionText: { + color: commonColor.inverseTextColor, + marginTop: '-5@s', + fontSize: '15@s' + }, + appTenantName: { + color: commonColor.inverseTextColor, + marginTop: '5@s', + marginBottom: '10@s', + fontSize: '15@s', + fontWeight: 'bold' + }, + button: { + width: '90%', + alignSelf: 'center', + height: '40@s', + marginBottom: '10@s', + backgroundColor: commonColor.buttonBg + }, + buttonText: { + width: '100%', + textAlign: 'center', + fontSize: '15@s', + color: commonColor.inverseTextColor + }, + inputGroup: { + height: '40@s', + borderRadius: '20@s', + flexDirection: 'row', + justifyContent: 'flex-start', + marginBottom: '10@s', + backgroundColor: commonColor.inputGroupBg, + borderWidth: '0@s', + borderColor: 'transparent' + }, + inputIcon: { + color: commonColor.inverseTextColor, + alignSelf: 'center', + textAlign: 'center', + width: '11%', + fontSize: Platform.OS === 'ios' ? '20@s' : '15@s' + }, + inputIconLock: { + fontSize: '20@s' + }, + inputField: { + width: '79%', + fontSize: '15@s', + color: commonColor.inverseTextColor + }, + formErrorText: { + fontSize: '12@s', + marginLeft: 30, + color: commonColor.brandDangerLight, + alignSelf: 'flex-start', + top: '-5@s' + }, + formErrorTextEula: { + alignSelf: 'center', + marginLeft: 0, + textDecorationLine: 'none' + }, + eulaContainer: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + borderBottomWidth: '0@s', + marginBottom: '20@s', + marginTop: '10@s' + }, + eulaCheckbox: { + marginRight: '15@s' + }, + eulaText: { + fontSize: '13@s', + color: commonColor.inverseTextColor + }, + eulaLink: { + fontSize: '13@s', + color: commonColor.inverseTextColor, + textDecorationLine: 'underline' + }, + linksButton: {}, + linksButtonLeft: { + alignSelf: 'flex-start', + marginLeft: '15@s' + }, + linksButtonRight: { + alignSelf: 'flex-end', + marginRight: '15@s' + }, + linksTextButton: { + fontSize: '12@s', + fontWeight: 'bold', + paddingBottom: '15@s', + color: commonColor.inverseTextColor + }, + linksTextButtonRight: { + textAlign: 'right' + }, + footer: { + elevation: 0, + borderColor: 'transparent', + backgroundColor: 'transparent' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = { + button: { + width: '65%' + }, + inputIcon: { + width: '7%' + }, + inputField: { + width: '58%' + } +}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/auth/eula/Eula.tsx b/src/screens/auth/eula/Eula.tsx new file mode 100644 index 000000000..d4f1cee23 --- /dev/null +++ b/src/screens/auth/eula/Eula.tsx @@ -0,0 +1,88 @@ +import I18n from 'i18n-js'; +import { Container, Spinner } from 'native-base'; +import React from 'react'; +import { ScrollView } from 'react-native'; +import HTMLView from 'react-native-htmlview'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import BaseProps from '../../../types/BaseProps'; +import Utils from '../../../utils/Utils'; +import BaseScreen from '../../base-screen/BaseScreen'; +import computeStyleSheet from './EulaStyles'; + +export interface Props extends BaseProps { +} + +interface State { + i18nLocale?: string; + loading?: boolean; + eulaTextHtml?: string; +} + +export default class Eula extends BaseScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + eulaTextHtml: '', + i18nLocale: I18n.currentLocale().substr(0, 2), + loading: true, + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + await super.componentDidMount(); + await this.loadEndUserLicenseAgreement(); + }; + + public loadEndUserLicenseAgreement = async () => { + const { i18nLocale } = this.state; + try { + const result: any = await this.centralServerProvider.getEndUserLicenseAgreement({ + Language: i18nLocale + }); + this.setState({ + loading: false, + eulaTextHtml: result.text + }); + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'general.eulaUnexpectedError', this.props.navigation); + } + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.navigate('Login'); + // Do not bubble up + return true; + }; + + public render() { + const style = computeStyleSheet(); + const { eulaTextHtml, loading } = this.state; + return ( + + this.props.navigation.navigate('Login')} + leftActionIcon={'navigate-before'} + /> + {loading ? ( + + ) : ( + + + + )} + + ); + } +} diff --git a/src/screens/auth/eula/EulaStyles.tsx b/src/screens/auth/eula/EulaStyles.tsx new file mode 100644 index 000000000..15714fe65 --- /dev/null +++ b/src/screens/auth/eula/EulaStyles.tsx @@ -0,0 +1,38 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + paddingLeft: 10, + paddingRight: 10, + paddingBottom: 10, + backgroundColor: 'white' + }, + spinner: { + flex: 2, + color: commonColor.textColor + } +}); + +const portraitStyles = {}; + +const landscapeStyles = { + button: { + width: '65%' + }, + inputIcon: { + width: '7%' + }, + inputField: { + width: '58%' + } +}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/auth/login/Login.tsx b/src/screens/auth/login/Login.tsx new file mode 100644 index 000000000..f9512b137 --- /dev/null +++ b/src/screens/auth/login/Login.tsx @@ -0,0 +1,383 @@ +import I18n from 'i18n-js'; +import { ActionSheet, Button, CheckBox, Footer, Form, Icon, Item, Left, Right, Spinner, Text, View } from 'native-base'; +import React from 'react'; +import { Alert, BackHandler, Keyboard, KeyboardAvoidingView, ScrollView, Text as TextRN, TextInput } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import commonColor from '../../../theme/variables/commonColor'; +import BaseProps from '../../../types/BaseProps'; +import Tenant from '../../../types/Tenant'; +import Constants from '../../../utils/Constants'; +import Message from '../../../utils/Message'; +import SecuredStorage from '../../../utils/SecuredStorage'; +import Utils from '../../../utils/Utils'; +import BaseScreen from '../../base-screen/BaseScreen'; +import AuthHeader from '../AuthHeader'; +import computeStyleSheet from '../AuthStyles'; + +export interface Props extends BaseProps { +} + +interface State { + eula?: boolean; + password?: string; + email?: string; + tenantSubDomain?: string; + tenantTitle?: string; + loading?: boolean; + initialLoading?: boolean; + errorEula?: object[]; + errorPassword?: object[]; + errorTenantSubDomain?: object[]; + errorEmail?: object[]; +} + +export default class Login extends BaseScreen { + public state: State; + public props: Props; + private tenants: Partial[]; + private passwordInput: TextInput; + private formValidationDef = { + tenantSubDomain: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryTenant') + } + }, + email: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryEmail') + }, + email: { + message: '^' + I18n.t('authentication.invalidEmail') + } + }, + password: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryPassword') + } + }, + eula: { + equality: { + attribute: 'ghost', + message: '^' + I18n.t('authentication.eulaNotAccepted'), + comparator(v1: boolean, v2: boolean) { + // True if EULA is checked + return v1; + } + } + } + }; + + constructor(props: Props) { + super(props); + this.state = { + eula: false, + password: null, + email: Utils.getParamFromNavigation(this.props.navigation, 'email', ''), + tenantSubDomain: Utils.getParamFromNavigation(this.props.navigation, 'tenantSubDomain', ''), + tenantTitle: I18n.t('authentication.tenant'), + loading: false, + initialLoading: true + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + await super.componentDidMount(); + // Get Tenants + this.tenants = this.centralServerProvider.getTenants(); + // Lock + // Orientation.lockToPortrait(); + // Load User data + if (!this.state.email || !this.state.tenantSubDomain) { + const tenantSubDomain = this.centralServerProvider.getUserTenant(); + const tenant = this.centralServerProvider.getTenant(tenantSubDomain); + const email = this.centralServerProvider.getUserEmail(); + const password = this.centralServerProvider.getUserPassword(); + // Set + this.setState({ + email, + password, + tenantSubDomain, + tenantTitle: tenant ? tenant.name : this.state.tenantTitle, + initialLoading: false + }); + // Check if user can be logged + if (Utils.canAutoLogin(this.centralServerProvider, this.props.navigation)) { + try { + // Check EULA + const result = await this.centralServerProvider.checkEndUserLicenseAgreement({email, tenantSubDomain}); + if (result.eulaAccepted) { + // Try to login + this.setState({eula: true}, () => this.login()); + } + } catch (error) { + // Do nothing: user must log on + } + } + } else { + // Set Tenant title + let tenantTitle = I18n.t('authentication.tenant'); + if (this.state.tenantSubDomain) { + tenantTitle = this.centralServerProvider.getTenant(this.state.tenantSubDomain).name; + } + // Set + this.setState({ + initialLoading: false, + tenantTitle + }); + } + } + + public login = async () => { + // Check field + const formIsValid = Utils.validateInput(this, this.formValidationDef); + // Ok? + if (formIsValid) { + // Login + const { password, email, eula, tenantSubDomain } = this.state; + try { + // Loading + this.setState({ loading: true } as State); + // Login + await this.centralServerProvider.login(email, password, eula, tenantSubDomain); + // Login Success + this.setState({ loading: false }); + // Navigate + this.navigateToSites(); + } catch (error) { + // Login failed + this.setState({ loading: false }); + // Check request? + if (error.request) { + // Show error + switch (error.request.status) { + // Unknown Email + case 500: + case 550: + Message.showError(I18n.t('authentication.wrongEmailOrPassword')); + break; + // Account is locked + case 570: + Message.showError(I18n.t('authentication.accountLocked')); + break; + // Account not Active + case 580: + Message.showError(I18n.t('authentication.accountNotActive')); + break; + // Account Pending + case 590: + Message.showError(I18n.t('authentication.accountPending')); + break; + // Eula no accepted + case 520: + Message.showError(I18n.t('authentication.eulaNotAccepted')); + break; + default: + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'authentication.loginUnexpectedError'); + } + } + } + } + }; + + public onBack = () => { + // Exit? + Alert.alert( + I18n.t('general.exitApp'), + I18n.t('general.exitAppConfirm'), + [{ text: I18n.t('general.no'), style: 'cancel' }, { text: I18n.t('general.yes'), onPress: () => BackHandler.exitApp() }], + { cancelable: false } + ); + // Do not bubble up + return true; + }; + + public navigateToSites() { + // Navigate to App + this.props.navigation.navigate('AppDrawerNavigator'); + } + + public setTenant = async (buttonIndex: number) => { + // Provided? + if (buttonIndex !== undefined) { + // Get stored data + const credentials = await SecuredStorage.getUserCredentials(this.tenants[buttonIndex].subdomain); + if (credentials) { + // Set Tenant + this.setState({ + email: credentials.email, + password: credentials.password, + tenantSubDomain: this.tenants[buttonIndex].subdomain, + tenantTitle: this.tenants[buttonIndex].name + }); + } else { + // Set Tenant + this.setState({ + tenantSubDomain: this.tenants[buttonIndex].subdomain, + tenantTitle: this.tenants[buttonIndex].name + }); + } + } + }; + + public newUser = () => { + const navigation = this.props.navigation; + // Tenant selected? + if (this.state.tenantSubDomain) { + navigation.navigate('SignUp', { + tenantSubDomain: this.state.tenantSubDomain, + email: this.state.email + }); + } else { + Message.showError(I18n.t('authentication.mustSelectTenant')); + } + }; + + public forgotPassword = () => { + const navigation = this.props.navigation; + // Tenant selected? + if (this.state.tenantSubDomain) { + navigation.navigate('RetrievePassword', { + tenantSubDomain: this.state.tenantSubDomain, + email: this.state.email + }); + } else { + // Error + Message.showError(I18n.t('authentication.mustSelectTenant')); + } + }; + + public render() { + const style = computeStyleSheet(); + const navigation = this.props.navigation; + const { eula, loading, initialLoading } = this.state; + // Render + return initialLoading ? ( + + ) : ( + + + + +
+ + {this.state.errorTenantSubDomain && + this.state.errorTenantSubDomain.map((errorMessage, index) => ( + + {errorMessage} + + ))} + + + this.passwordInput.focus()} + style={style.inputField} + autoCapitalize='none' + blurOnSubmit={false} + autoCorrect={false} + keyboardType={'email-address'} + secureTextEntry={false} + onChangeText={(text) => this.setState({ email: text })} + value={this.state.email} + /> + + {this.state.errorEmail && + this.state.errorEmail.map((errorMessage, index) => ( + + {errorMessage} + + ))} + + + (this.passwordInput = ref)} + onSubmitEditing={() => Keyboard.dismiss()} + placeholder={I18n.t('authentication.password')} + placeholderTextColor={commonColor.placeholderTextColor} + style={style.inputField} + autoCapitalize='none' + blurOnSubmit={false} + autoCorrect={false} + keyboardType={'default'} + secureTextEntry={true} + onChangeText={(text) => this.setState({ password: text })} + value={this.state.password} + /> + + {this.state.errorPassword && + this.state.errorPassword.map((errorMessage, index) => ( + + {errorMessage} + + ))} + + this.setState({ eula: !eula })} /> + + {I18n.t('authentication.acceptEula')} + navigation.navigate('Eula')} style={style.eulaLink}> + {I18n.t('authentication.eula')} + + + + {this.state.errorEula && + this.state.errorEula.map((errorMessage, index) => ( + + {errorMessage} + + ))} + {loading ? ( + + ) : ( + + )} + +
+
+
+ + + + + + +
+
+ ); + } +} diff --git a/src/screens/auth/reset-password/ResetPassword.tsx b/src/screens/auth/reset-password/ResetPassword.tsx new file mode 100644 index 000000000..1885fa3d0 --- /dev/null +++ b/src/screens/auth/reset-password/ResetPassword.tsx @@ -0,0 +1,229 @@ +import I18n from 'i18n-js'; +import { Button, Footer, Form, Icon, Item, Left, Spinner, Text } from 'native-base'; +import React from 'react'; +import { Keyboard, KeyboardAvoidingView, ScrollView, Text as TextRN, TextInput } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import { NavigationActions, StackActions } from 'react-navigation'; +import commonColor from '../../../theme/variables/commonColor'; +import BaseProps from '../../../types/BaseProps'; +import Constants from '../../../utils/Constants'; +import Message from '../../../utils/Message'; +import Utils from '../../../utils/Utils'; +import BaseScreen from '../../base-screen/BaseScreen'; +import AuthHeader from '../AuthHeader'; +import computeStyleSheet from '../AuthStyles'; + +export interface Props extends BaseProps { +} + +interface State { + tenantSubDomain?: string; + tenantName?: string; + hash?: string; + password?: string; + repeatPassword?: string; + errorPassword?: object[]; + errorRepeatPassword?: object[]; + loading?: boolean; +} + +export default class ResetPassword extends BaseScreen { + public state: State; + public props: Props; + private repeatPasswordInput: TextInput; + private formValidationDef = { + password: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryPassword') + }, + equality: { + attribute: 'ghost', + message: '^' + I18n.t('authentication.passwordRule'), + comparator(password: string, ghost: string) { + // True if EULA is checked + return /(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!#@:;,<>\/''\$%\^&\*\.\?\-_\+\=\(\)])(?=.{8,})/.test(password); + } + } + }, + repeatPassword: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryPassword') + }, + equality: { + attribute: 'password', + message: '^' + I18n.t('authentication.passwordNotMatch') + } + } + }; + + constructor(props: Props) { + super(props); + this.state = { + tenantSubDomain: Utils.getParamFromNavigation(this.props.navigation, 'tenantSubDomain', ''), + hash: Utils.getParamFromNavigation(this.props.navigation, 'hash', null), + tenantName: '', + password: '', + repeatPassword: '', + loading: false + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + // Call parent + await super.componentDidMount(); + // Init + const tenant = this.centralServerProvider.getTenant(this.state.tenantSubDomain); + this.setState({ + tenantName: tenant ? tenant.name : '' + }); + // Disable Auto Login + this.centralServerProvider.setAutoLoginDisabled(true); + } + + public recaptchaResponseToken = (captcha: string) => { + this.setState({ captcha }); + }; + + public resetPassword = async () => { + // Check field + const formIsValid = Utils.validateInput(this, this.formValidationDef); + if (formIsValid) { + const { tenantSubDomain, password, repeatPassword, hash } = this.state; + try { + // Loading + this.setState({ loading: true }); + // Register + await this.centralServerProvider.resetPassword(tenantSubDomain, hash, { password, repeatPassword }); + // Clear user's credentials + await this.centralServerProvider.clearUserPassword(); + // Reset + this.setState({ loading: false }); + // Show + Message.showSuccess(I18n.t('authentication.resetPasswordSuccess')); + // Navigate + this.props.navigation.dispatch( + StackActions.reset({ + index: 0, + actions: [ + NavigationActions.navigate({ + routeName: 'Login', + params: { + tenantSubDomain: this.state.tenantSubDomain + } + }) + ] + }) + ); + } catch (error) { + // Reset + this.setState({ loading: false }); + // Check request? + if (error.request) { + // Show error + switch (error.request.status) { + // Invalid Hash + case 550: + Message.showError(I18n.t('authentication.resetPasswordHashNotValid')); + break; + default: + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'authentication.resetPasswordUnexpectedError'); + } + } else { + Message.showError(I18n.t('authentication.resetPasswordUnexpectedError')); + } + } + } + }; + + public onBack = (): boolean => { + // Back mobile button: Force navigation + this.props.navigation.navigate('Login'); + // Do not bubble up + return true; + }; + + public render() { + const style = computeStyleSheet(); + const { tenantName, loading } = this.state; + return ( + + + + +
+ + + this.repeatPasswordInput.focus()} + returnKeyType={'next'} + placeholder={I18n.t('authentication.password')} + placeholderTextColor={commonColor.placeholderTextColor} + style={style.inputField} + autoCapitalize='none' + blurOnSubmit={false} + autoCorrect={false} + keyboardType={'default'} + onChangeText={(text) => this.setState({ password: text })} + secureTextEntry={true} + /> + + {this.state.errorPassword && + this.state.errorPassword.map((errorMessage, index) => ( + + {errorMessage} + + ))} + + + (this.repeatPasswordInput = ref)} + selectionColor={commonColor.inverseTextColor} + onSubmitEditing={() => Keyboard.dismiss()} + returnKeyType={'next'} + placeholder={I18n.t('authentication.repeatPassword')} + placeholderTextColor={commonColor.placeholderTextColor} + style={style.inputField} + autoCapitalize='none' + blurOnSubmit={false} + autoCorrect={false} + keyboardType={'default'} + onChangeText={(text) => this.setState({ repeatPassword: text })} + secureTextEntry={true} + /> + + {this.state.errorRepeatPassword && + this.state.errorRepeatPassword.map((errorMessage, index) => ( + + {errorMessage} + + ))} + {loading ? ( + + ) : ( + + )} + +
+
+
+ + + +
+
+ ); + } +} diff --git a/src/screens/auth/retrieve-password/RetrievePassword.tsx b/src/screens/auth/retrieve-password/RetrievePassword.tsx new file mode 100644 index 000000000..a78a435a8 --- /dev/null +++ b/src/screens/auth/retrieve-password/RetrievePassword.tsx @@ -0,0 +1,202 @@ +import I18n from 'i18n-js'; +import { Button, Footer, Form, Icon, Item, Left, Spinner, Text } from 'native-base'; +import React from 'react'; +import { KeyboardAvoidingView, ScrollView, Text as TextRN, TextInput } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import { NavigationActions, StackActions } from 'react-navigation'; +import ReactNativeRecaptchaV3 from '../../../re-captcha/ReactNativeRecaptchaV3'; +import commonColor from '../../../theme/variables/commonColor'; +import BaseProps from '../../../types/BaseProps'; +import Constants from '../../../utils/Constants'; +import Message from '../../../utils/Message'; +import Utils from '../../../utils/Utils'; +import BaseScreen from '../../base-screen/BaseScreen'; +import AuthHeader from '../AuthHeader'; +import computeStyleSheet from '../AuthStyles'; + +export interface Props extends BaseProps { +} + +interface State { + tenantSubDomain?: string; + tenantName?: string; + email?: string; + captchaSiteKey?: string; + captchaBaseUrl?: string; + captcha?: string; + loading?: boolean; + errorEmail?: object[]; +} + +export default class RetrievePassword extends BaseScreen { + public state: State; + public props: Props; + private formValidationDef = { + email: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryEmail') + }, + email: { + message: '^' + I18n.t('authentication.invalidEmail') + } + } + }; + + constructor(props: Props) { + super(props); + this.state = { + tenantSubDomain: Utils.getParamFromNavigation(this.props.navigation, 'tenantSubDomain', ''), + tenantName: '', + email: Utils.getParamFromNavigation(this.props.navigation, 'email', ''), + captchaSiteKey: null, + captchaBaseUrl: null, + captcha: null, + loading: false + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + // Call parent + await super.componentDidMount(); + // Init + const tenant = this.centralServerProvider.getTenant(this.state.tenantSubDomain); + this.setState({ + tenantName: tenant ? tenant.name : '', + captchaSiteKey: this.centralServerProvider.getCaptchaSiteKey(), + captchaBaseUrl: this.centralServerProvider.getCaptchaBaseUrl() + }); + // Disable Auto Login + this.centralServerProvider.setAutoLoginDisabled(true); + } + + public recaptchaResponseToken = (captcha: string) => { + this.setState({ captcha }); + }; + + public retrievePassword = async () => { + // Check field + const formIsValid = Utils.validateInput(this, this.formValidationDef); + if (formIsValid) { + const { tenantSubDomain, email, captcha } = this.state; + try { + this.setState({ loading: true }); + // Login + await this.centralServerProvider.retrievePassword(tenantSubDomain, email, captcha); + // Login Success + this.setState({ loading: false }); + // Show + Message.showSuccess(I18n.t('authentication.resetSuccess')); + // Navigate + this.props.navigation.dispatch( + StackActions.reset({ + index: 0, + actions: [ + NavigationActions.navigate({ + routeName: 'Login', + params: { + tenantSubDomain: this.state.tenantSubDomain, + email: this.state.email + } + }) + ] + }) + ); + } catch (error) { + // Login failed + this.setState({ loading: false }); + // Check request? + if (error.request) { + // Show error + switch (error.request.status) { + // Invalid Captcha + case 530: + Message.showError(I18n.t('authentication.invalidCaptcha')); + break; + // Unknown Email + case 550: + Message.showError(I18n.t('authentication.wrongEmail')); + break; + default: + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'authentication.resetPasswordUnexpectedError'); + } + } else { + Message.showError(I18n.t('authentication.resetPasswordUnexpectedError')); + } + } + } + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.navigate('Login'); + // Do not bubble up + return true; + }; + + public render() { + const style = computeStyleSheet(); + const { loading, captcha, tenantName, captchaSiteKey, captchaBaseUrl } = this.state; + return ( + + + + +
+ + + this.setState({ email: text })} + value={this.state.email} + /> + + {this.state.errorEmail && + this.state.errorEmail.map((errorMessage, index) => ( + + {errorMessage} + + ))} + {loading || !captcha ? ( + + ) : ( + + )} + +
+ {captchaSiteKey && captchaBaseUrl && ( + + )} +
+
+ + + +
+
+ ); + } +} diff --git a/src/screens/auth/sign-up/SignUp.tsx b/src/screens/auth/sign-up/SignUp.tsx new file mode 100644 index 000000000..88358fdee --- /dev/null +++ b/src/screens/auth/sign-up/SignUp.tsx @@ -0,0 +1,383 @@ +import I18n from 'i18n-js'; +import { Button, CheckBox, Footer, Form, Icon, Item, Left, Spinner, Text, View } from 'native-base'; +import React from 'react'; +import { Keyboard, KeyboardAvoidingView, ScrollView, Text as TextRN, TextInput } from 'react-native'; +import * as Animatable from 'react-native-animatable'; +import { NavigationActions, StackActions } from 'react-navigation'; +import ReactNativeRecaptchaV3 from '../../../re-captcha/ReactNativeRecaptchaV3'; +import commonColor from '../../../theme/variables/commonColor'; +import BaseProps from '../../../types/BaseProps'; +import Constants from '../../../utils/Constants'; +import Message from '../../../utils/Message'; +import Utils from '../../../utils/Utils'; +import BaseScreen from '../../base-screen/BaseScreen'; +import AuthHeader from '../AuthHeader'; +import computeStyleSheet from '../AuthStyles'; + +export interface Props extends BaseProps { +} + +interface State { + tenantSubDomain?: string; + tenantName?: string; + name?: string; + firstName?: string; + email?: string; + password?: string; + repeatPassword?: string; + eula?: boolean; + captchaSiteKey?: string; + captchaBaseUrl?: string; + captcha?: string; + loading?: boolean; + errorEula?: object[]; + errorPassword?: object[]; + errorTenant?: object[]; + errorEmail?: object[]; + errorName?: object[]; + errorFirstName?: object[]; + errorRepeatPassword?: object[]; +} + +export default class SignUp extends BaseScreen { + public state: State; + public props: Props; + private passwordInput: TextInput; + private firstNameInput: TextInput; + private emailInput: TextInput; + private repeatPasswordInput: TextInput; + private formValidationDef = { + name: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryName') + } + }, + firstName: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryFirstName') + } + }, + email: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryEmail') + }, + email: { + message: '^' + I18n.t('authentication.invalidEmail') + } + }, + password: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryPassword') + }, + equality: { + attribute: 'ghost', + message: '^' + I18n.t('authentication.passwordRule'), + comparator(password: string, ghost: string) { + // True if EULA is checked + return /(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!#@:;,<>\/''\$%\^&\*\.\?\-_\+\=\(\)])(?=.{8,})/.test(password); + } + } + }, + repeatPassword: { + presence: { + allowEmpty: false, + message: '^' + I18n.t('authentication.mandatoryPassword') + }, + equality: { + attribute: 'password', + message: '^' + I18n.t('authentication.passwordNotMatch') + } + }, + eula: { + equality: { + attribute: 'ghost', + message: I18n.t('authentication.eulaNotAccepted'), + comparator(eula: boolean, ghost: boolean) { + // True if EULA is checked + return eula; + } + } + } + }; + + constructor(props: Props) { + super(props); + this.state = { + tenantSubDomain: Utils.getParamFromNavigation(this.props.navigation, 'tenantSubDomain', ''), + tenantName: '', + name: '', + firstName: '', + email: Utils.getParamFromNavigation(this.props.navigation, 'email', ''), + password: '', + repeatPassword: '', + eula: false, + captchaSiteKey: null, + captchaBaseUrl: null, + captcha: null, + loading: false + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + // Call parent + await super.componentDidMount(); + // Init + const tenant = this.centralServerProvider.getTenant(this.state.tenantSubDomain); + this.setState({ + tenantName: tenant ? tenant.name : '', + captchaSiteKey: this.centralServerProvider.getCaptchaSiteKey(), + captchaBaseUrl: this.centralServerProvider.getCaptchaBaseUrl() + }); + // Disable Auto Login + this.centralServerProvider.setAutoLoginDisabled(true); + } + + public recaptchaResponseToken = (captcha: string) => { + this.setState({ captcha }); + }; + + public signUp = async () => { + // Check field + const formIsValid = Utils.validateInput(this, this.formValidationDef); + if (formIsValid) { + const { tenantSubDomain, name, firstName, email, password, repeatPassword, eula, captcha } = this.state; + try { + // Loading + this.setState({ loading: true }); + // Register + await this.centralServerProvider.register(tenantSubDomain, name, firstName, email, { password, repeatPassword }, eula, captcha); + // Reset + this.setState({ loading: false }); + // Show + Message.showSuccess(I18n.t('authentication.registerSuccess')); + // Navigate + this.props.navigation.dispatch( + StackActions.reset({ + index: 0, + actions: [ + NavigationActions.navigate({ + routeName: 'Login', + params: { + tenantSubDomain: this.state.tenantSubDomain, + email: this.state.email + } + }) + ] + }) + ); + } catch (error) { + // Reset + this.setState({ loading: false }); + // Check request? + if (error.request) { + // Show error + switch (error.request.status) { + // Email already exists + case 510: + Message.showError(I18n.t('authentication.emailAlreadyExists')); + break; + // Invalid Captcha + case 530: + Message.showError(I18n.t('authentication.invalidCaptcha')); + break; + default: + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'authentication.registerUnexpectedError'); + } + } else { + Message.showError(I18n.t('authentication.registerUnexpectedError')); + } + } + } + }; + + public onBack = (): boolean => { + // Back mobile button: Force navigation + this.props.navigation.navigate('Login'); + // Do not bubble up + return true; + }; + + public render() { + const style = computeStyleSheet(); + const navigation = this.props.navigation; + const { eula, loading, captcha, tenantName, captchaSiteKey, captchaBaseUrl } = this.state; + return ( + + + + +
+ + + this.firstNameInput.focus()} + selectionColor={commonColor.inverseTextColor} + returnKeyType={'next'} + placeholder={I18n.t('authentication.name')} + placeholderTextColor={commonColor.placeholderTextColor} + style={style.inputField} + autoCapitalize='characters' + blurOnSubmit={false} + autoCorrect={false} + onChangeText={(text) => this.setState({ name: text })} + secureTextEntry={false} + /> + + {this.state.errorName && + this.state.errorName.map((errorMessage, index) => ( + + {errorMessage} + + ))} + + + + (this.firstNameInput = ref)} + selectionColor={commonColor.inverseTextColor} + onSubmitEditing={() => this.emailInput.focus()} + returnKeyType={'next'} + placeholder={I18n.t('authentication.firstName')} + placeholderTextColor={commonColor.placeholderTextColor} + style={style.inputField} + autoCapitalize='words' + blurOnSubmit={false} + autoCorrect={false} + onChangeText={(text) => this.setState({ firstName: text })} + secureTextEntry={false} + /> + + {this.state.errorFirstName && + this.state.errorFirstName.map((errorMessage, index) => ( + + {errorMessage} + + ))} + + + + (this.emailInput = ref)} + selectionColor={commonColor.inverseTextColor} + onSubmitEditing={() => this.passwordInput.focus()} + returnKeyType={'next'} + placeholder={I18n.t('authentication.email')} + placeholderTextColor={commonColor.placeholderTextColor} + style={style.inputField} + autoCapitalize='none' + blurOnSubmit={false} + autoCorrect={false} + keyboardType={'email-address'} + onChangeText={(text) => this.setState({ email: text })} + secureTextEntry={false} + /> + + {this.state.errorEmail && + this.state.errorEmail.map((errorMessage, index) => ( + + {errorMessage} + + ))} + + + + (this.passwordInput = ref)} + selectionColor={commonColor.inverseTextColor} + onSubmitEditing={() => this.repeatPasswordInput.focus()} + returnKeyType={'next'} + placeholder={I18n.t('authentication.password')} + placeholderTextColor={commonColor.placeholderTextColor} + style={style.inputField} + autoCapitalize='none' + blurOnSubmit={false} + autoCorrect={false} + keyboardType={'default'} + onChangeText={(text) => this.setState({ password: text })} + secureTextEntry={true} + /> + + {this.state.errorPassword && + this.state.errorPassword.map((errorMessage, index) => ( + + {errorMessage} + + ))} + + + (this.repeatPasswordInput = ref)} + selectionColor={commonColor.inverseTextColor} + onSubmitEditing={() => Keyboard.dismiss()} + returnKeyType={'next'} + placeholder={I18n.t('authentication.repeatPassword')} + placeholderTextColor={commonColor.placeholderTextColor} + style={style.inputField} + autoCapitalize='none' + blurOnSubmit={false} + autoCorrect={false} + keyboardType={'default'} + onChangeText={(text) => this.setState({ repeatPassword: text })} + secureTextEntry={true} + /> + + {this.state.errorRepeatPassword && + this.state.errorRepeatPassword.map((errorMessage, index) => ( + + {errorMessage} + + ))} + + this.setState({ eula: !eula })} /> + + {I18n.t('authentication.acceptEula')} + navigation.navigate('Eula')} style={style.eulaLink}> + {I18n.t('authentication.eula')} + + + + {this.state.errorEula && + this.state.errorEula.map((errorMessage, index) => ( + + {errorMessage} + + ))} + {loading || (!captcha && this.state.eula) ? ( + + ) : ( + + )} + +
+ {this.state.eula && captchaSiteKey && captchaBaseUrl && ( + + )} +
+
+ + + +
+
+ ); + } +} diff --git a/src/screens/base-screen/BaseAutoRefreshScreen.tsx b/src/screens/base-screen/BaseAutoRefreshScreen.tsx new file mode 100644 index 000000000..1ea311c53 --- /dev/null +++ b/src/screens/base-screen/BaseAutoRefreshScreen.tsx @@ -0,0 +1,151 @@ +import moment from 'moment'; +import BaseProps from '../../types/BaseProps'; +import Constants from '../../utils/Constants'; +import BaseScreen from './BaseScreen'; + +export interface Props extends BaseProps { +} + +interface State { +} + +export default class BaseAutoRefreshScreen extends BaseScreen { + private timerRefresh: ReturnType; + private timerRefreshActive: boolean; + private refreshOngoing: boolean = false; + private refreshPeriodMillis: number; + private lastRefreshDate: Date; + + constructor(props: Props) { + super(props); + // Init + this.timerRefresh = null; + this.timerRefreshActive = true; + this.refreshPeriodMillis = Constants.AUTO_REFRESH_MEDIUM_PERIOD_MILLIS; + } + + public async componentDidMount() { + await super.componentDidMount(); + // Refresh + if (this.props.navigation.isFocused() && this.canRefresh()) { + // Refresh + await this.refresh(); + this.lastRefreshDate = new Date(); + } + // Start the timer + this.startRefreshTimer(); + } + + public async componentWillUnmount() { + await super.componentWillUnmount(); + // Clear the timer + this.clearRefreshTimer(); + } + + public async componentDidFocus() { + await super.componentDidFocus(); + // Refresh + if (this.isMounted() && this.props.navigation.isFocused() && this.canRefresh()) { + this.refresh(); + this.lastRefreshDate = new Date(); + } + // Start the timer + this.startRefreshTimer(); + } + + private canRefresh(): boolean { + if (!this.lastRefreshDate) { + return true; + } + return moment().diff(this.lastRefreshDate) > Constants.AUTO_REFRESH_DUPS_INTERVAL; + } + + public async componentDidBlur() { + await super.componentDidBlur(); + // Clear the timer + this.clearRefreshTimer(); + } + + public onBack = (): boolean => { + // Not Handled: has to be taken in the sub-classes + return false; + } + + public setActive(active: boolean) { + this.timerRefreshActive = active; + } + + public isActive(): boolean { + return this.timerRefreshActive; + } + + public setRefreshPeriodMillis(refreshPeriodMillis: number) { + // Set new interval + this.refreshPeriodMillis = refreshPeriodMillis; + // Restart the timer + this.restartTimer(); + } + + public getRefreshPeriodMillis(): number { + return this.refreshPeriodMillis; + } + + public async refresh() { + // tslint:disable-next-line: no-console + console.log('BaseAutoRefreshScreen: Refresh not implemented!!!'); + } + + private startRefreshTimer() { + // Start the timer + if (!this.timerRefresh) { + // Timer + this.timerRefresh = setTimeout(async () => { + // Refresh + if (this.timerRefreshActive && !this.refreshOngoing) { + // Start (necessary for the simulators) + this.refreshOngoing = true; + // Component Mounted? + if (this.mounted) { + try { + if (this.props.navigation.isFocused()) { + // Already refreshed? + if (this.canRefresh()) { + // No: Refresh + await this.refresh(); + this.lastRefreshDate = new Date(); + } + } else { + // Stop the timer + this.clearRefreshTimer(); + } + } catch (error) { + // Ignore + } + } + // Restart + this.restartTimer(); + // End + this.refreshOngoing = false; + } + }, this.refreshPeriodMillis); + } + } + + private restartTimer = () => { + // Already started + if (this.timerRefresh) { + // Clear the timer + this.clearRefreshTimer(); + // Start the timer + this.startRefreshTimer(); + } + } + + private clearRefreshTimer = () => { + // Stop the timer + if (this.timerRefresh) { + clearTimeout(this.timerRefresh); + this.timerRefresh = null; + } + } +} diff --git a/src/screens/base-screen/BaseScreen.tsx b/src/screens/base-screen/BaseScreen.tsx new file mode 100644 index 000000000..e23283dee --- /dev/null +++ b/src/screens/base-screen/BaseScreen.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import { BackHandler } from 'react-native'; +import { NavigationEventSubscription } from 'react-navigation'; +import HeaderComponent from '../../components/header/HeaderComponent'; +import ScreenFilters from '../../components/search/filter/screen/ScreenFilters'; +import CentralServerProvider from '../../provider/CentralServerProvider'; +import ProviderFactory from '../../provider/ProviderFactory'; +import BaseProps from '../../types/BaseProps'; + +export interface Props extends BaseProps { +} + +interface State { +} + +export default class BaseScreen extends React.Component { + protected mounted: boolean; + protected centralServerProvider: CentralServerProvider; + private didFocus: NavigationEventSubscription; + private didBlur: NavigationEventSubscription; + private headerComponent: HeaderComponent; + private screenFilters: ScreenFilters; + + constructor(props: Props) { + super(props); + this.mounted = false; + } + + public isMounted(): boolean { + return this.mounted; + } + + public async componentDidMount() { + // Add listeners + this.didFocus = this.props.navigation.addListener('didFocus', this.componentDidFocus.bind(this)); + this.didBlur = this.props.navigation.addListener('didBlur', this.componentDidBlur.bind(this)); + // Get provider + this.centralServerProvider = await ProviderFactory.getProvider(); + // Remove Backhandler for Android + BackHandler.removeEventListener('hardwareBackPress', this.onBack); + // Ok + this.mounted = true; + } + + public async componentWillUnmount() { + this.mounted = false; + // Remove listeners + if (this.didFocus) { + this.didFocus.remove(); + } + if (this.didBlur) { + this.didBlur.remove(); + } + } + + public setHeaderComponent(headerComponent: HeaderComponent) { + if (headerComponent) { + this.headerComponent = headerComponent; + // Set modal filter component + if (this.headerComponent && this.screenFilters && this.screenFilters.getFilterModalContainerComponent()) { + this.headerComponent.setFilterModalContainerComponent(this.screenFilters.getFilterModalContainerComponent()); + } + } + } + + public getHeaderComponent(): HeaderComponent { + return this.headerComponent; + } + + public setScreenFilters(screenFilters: ScreenFilters) { + if (screenFilters) { + this.screenFilters = screenFilters; + // Set modal filter component + if (this.headerComponent && this.screenFilters.getFilterModalContainerComponent()) { + this.headerComponent.setFilterModalContainerComponent(this.screenFilters.getFilterModalContainerComponent()); + } + } + } + + public getScreenFilters(): ScreenFilters { + return this.screenFilters; + } + + public onBack(): boolean { + // Not Handled: has to be taken in the sub-classes + return false; + } + + public async componentDidFocus() { + BackHandler.addEventListener('hardwareBackPress', this.onBack.bind(this)); + } + + // tslint:disable-next-line: no-empty + public async componentDidBlur() {} +} diff --git a/src/screens/chargers/actions/ChargerActions.tsx b/src/screens/chargers/actions/ChargerActions.tsx new file mode 100644 index 000000000..f12b8b0fb --- /dev/null +++ b/src/screens/chargers/actions/ChargerActions.tsx @@ -0,0 +1,219 @@ +import I18n from 'i18n-js'; +import { Button, Container, Icon, Spinner, Text, View } from 'native-base'; +import React from 'react'; +import { Alert, ScrollView } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import BaseProps from '../../../types/BaseProps'; +import ChargingStation from '../../../types/ChargingStation'; +import Message from '../../../utils/Message'; +import Utils from '../../../utils/Utils'; +import BaseScreen from '../../base-screen/BaseScreen'; +import computeStyleSheet from './ChargerActionsStyles'; + +export interface Props extends BaseProps { +} + +interface State { + loading?: boolean; + charger: ChargingStation; +} + +export default class ChargerActions extends BaseScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + loading: true, + charger: null, + } + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + // Call parent + await super.componentDidMount(); + const chargerID = Utils.getParamFromNavigation(this.props.navigation, 'chargerID', null); + // Get Charger + const charger = await this.getCharger(chargerID); + // Set + this.setState({ + loading: false, + charger, + }); + } + + public getCharger = async (chargerID: string): Promise => { + try { + // Get Charger + const charger = await this.centralServerProvider.getCharger({ ID: chargerID }); + return charger; + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerUnexpectedError', this.props.navigation); + } + return null; + }; + + public resetHardConfirm() { + const { charger } = this.state; + Alert.alert(I18n.t('chargers.resetHard'), I18n.t('chargers.resetHardMessage', { chargeBoxID: charger.id }), [ + { text: I18n.t('general.yes'), onPress: () => this.reset(charger.id, 'Hard') }, + { text: I18n.t('general.cancel') } + ]); + } + + public resetSoftConfirm() { + const { charger } = this.state; + Alert.alert(I18n.t('chargers.resetSoft'), I18n.t('chargers.resetSoftMessage', { chargeBoxID: charger.id }), [ + { text: I18n.t('general.yes'), onPress: () => this.reset(charger.id, 'Soft') }, + { text: I18n.t('general.cancel') } + ]); + } + + public async reset(chargeBoxID: string, type: 'Soft'|'Hard') { + try { + // Start the Transaction + const status = await this.centralServerProvider.reset(chargeBoxID, type); + // Check + if (status.status && status.status === 'Accepted') { + Message.showSuccess(I18n.t('details.accepted')); + } else { + Message.showError(I18n.t('details.denied')); + } + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + type === 'Hard' ? 'chargers.chargerRebootUnexpectedError' : 'chargers.chargerResetUnexpectedError', + this.props.navigation); + } + } + + public clearCacheConfirm() { + const { charger } = this.state; + Alert.alert(I18n.t('chargers.clearCache'), I18n.t('chargers.clearCacheMessage', { chargeBoxID: charger.id }), [ + { text: I18n.t('general.yes'), onPress: () => this.clearCache(charger.id) }, + { text: I18n.t('general.cancel') } + ]); + } + + public async clearCache(chargeBoxID: string) { + try { + // Clear Cache + const status = await this.centralServerProvider.clearCache(chargeBoxID); + // Check + if (status.status && status.status === 'Accepted') { + Message.showSuccess(I18n.t('details.accepted')); + } else { + Message.showError(I18n.t('details.denied')); + } + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerClearCacheUnexpectedError', this.props.navigation); + } + } + + public unlockConnectorConfirm(connectorId: number) { + const { charger } = this.state; + Alert.alert + (I18n.t('chargers.unlockConnector', { connectorId: Utils.getConnectorLetterFromConnectorID(connectorId) }), + I18n.t('chargers.unlockConnectorMessage', + { chargeBoxID: charger.id, connectorId: Utils.getConnectorLetterFromConnectorID(connectorId) }), [ + { text: I18n.t('general.yes'), onPress: () => this.unlockConnector(charger.id, connectorId) }, + { text: I18n.t('general.cancel') } + ]); + } + + public async unlockConnector(chargeBoxID: string, connectorID: number) { + try { + // Unlock Connector + const status = await this.centralServerProvider.unlockConnector(chargeBoxID, connectorID); + // Check + if (status.status && status.status === 'Accepted') { + Message.showSuccess(I18n.t('details.accepted')); + } else { + Message.showError(I18n.t('details.denied')); + } + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerUnlockUnexpectedError', this.props.navigation); + } + } + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.goBack(null); + // Do not bubble up + return true; + }; + + public render() { + const { navigation } = this.props; + const style = computeStyleSheet(); + const { loading, charger } = this.state; + return ( + loading ? ( + + ) : ( + + this.onBack()} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + /> + + + + + + { charger && charger.connectors.map((connector) => + + + + )} + + + + + + + + + + ) + ); + } +} diff --git a/src/screens/chargers/actions/ChargerActionsStyles.tsx b/src/screens/chargers/actions/ChargerActionsStyles.tsx new file mode 100644 index 000000000..7e8243cbd --- /dev/null +++ b/src/screens/chargers/actions/ChargerActionsStyles.tsx @@ -0,0 +1,53 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + backgroundColor: commonColor.containerBgColor + }, + scrollViewContainer: { + flex: 1, + flexDirection: 'column', + justifyContent: 'space-between' + }, + viewContainer: { + flex: 1, + marginTop: '5@s', + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'center' + }, + spinner: { + flex: 1, + color: commonColor.textColor + }, + actionContainer: { + width: '90%', + marginTop: '5@s', + justifyContent: 'center' + }, + actionButton: { + height: '40@s', + justifyContent: 'center' + }, + actionButtonIcon: { + fontSize: '20@s', + }, + actionButtonText: { + fontSize: '18@s' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/chargers/connector-details/ChargerConnectorDetails.tsx b/src/screens/chargers/connector-details/ChargerConnectorDetails.tsx new file mode 100644 index 000000000..320ec6808 --- /dev/null +++ b/src/screens/chargers/connector-details/ChargerConnectorDetails.tsx @@ -0,0 +1,682 @@ +import I18n from 'i18n-js'; +import { Container, Icon, Spinner, Text, Thumbnail, View } from 'native-base'; +import React from 'react'; +import { Alert, Image, RefreshControl, ScrollView, TouchableOpacity } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import noPhotoActive from '../../../../assets/no-photo-active.png'; +import noPhoto from '../../../../assets/no-photo.png'; +import noSite from '../../../../assets/no-site.png'; +import ConnectorStatusComponent from '../../../components/connector-status/ConnectorStatusComponent'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseProps from '../../../types/BaseProps'; +import ChargingStation, { ChargePointStatus, Connector } from '../../../types/ChargingStation'; +import Transaction from '../../../types/Transaction'; +import User from '../../../types/User'; +import Constants from '../../../utils/Constants'; +import Message from '../../../utils/Message'; +import Utils from '../../../utils/Utils'; +import BaseAutoRefreshScreen from '../../base-screen/BaseAutoRefreshScreen'; +import computeStyleSheet from './ChargerConnectorDetailsStyles'; + +const START_TRANSACTION_NB_TRIAL = 4; + +export interface Props extends BaseProps { +} + +interface State { + loading?: boolean; + charger?: ChargingStation; + connector?: Connector; + transaction?: Transaction; + isAdmin?: boolean; + isSiteAdmin?: boolean; + canStartTransaction?: boolean; + canStopTransaction?: boolean; + canDisplayTransaction?: boolean; + userImage?: string; + siteImage?: string; + elapsedTimeFormatted?: string; + totalInactivitySecs?: number; + inactivityFormatted?: string; + startTransactionNbTrial?: number; + isPricingActive?: boolean; + buttonDisabled?: boolean; + refreshing?: boolean; +} + +export default class ChargerConnectorDetails extends BaseAutoRefreshScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + loading: true, + charger: null, + connector: null, + transaction: null, + isAdmin: false, + isSiteAdmin: false, + canStartTransaction: false, + canStopTransaction: false, + canDisplayTransaction: false, + userImage: null, + siteImage: null, + elapsedTimeFormatted: '-', + totalInactivitySecs: 0, + inactivityFormatted: '-', + startTransactionNbTrial: 0, + isPricingActive: false, + buttonDisabled: true, + refreshing: false + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public getSiteImage = async (siteID: string): Promise => { + try { + // Get Site + const site = await this.centralServerProvider.getSiteImage(siteID); + return site; + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'sites.siteUnexpectedError', this.props.navigation, this.refresh); + } + return null; + }; + + public getCharger = async (chargerID: string): Promise => { + try { + // Get Charger + const charger = await this.centralServerProvider.getCharger({ ID: chargerID }); + return charger; + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerUnexpectedError', this.props.navigation, this.refresh); + } + return null; + }; + + public getTransaction = async (transactionID: number): Promise => { + try { + // Get Transaction + const transaction = await this.centralServerProvider.getTransaction({ ID: transactionID }); + return transaction; + } catch (error) { + // Check if HTTP? + if (!error.request || error.request.status !== 560) { + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionUnexpectedError', this.props.navigation, this.refresh); + } + } + return null; + }; + + public getLastTransaction = async (chargeBoxID: string, connectorId: number): Promise => { + try { + // Get Transaction + const transaction = await this.centralServerProvider.getLastTransaction(chargeBoxID, connectorId); + return transaction; + } catch (error) { + // Check if HTTP? + if (!error.request || error.request.status !== 560) { + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionUnexpectedError', this.props.navigation, this.refresh); + } + } + return null; + }; + + public getUserImage = async (user: User): Promise => { + try { + // User provided? + if (user) { + return await this.centralServerProvider.getUserImage({ ID: user.id }); + } + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'users.userUnexpectedError', this.props.navigation, this.refresh); + } + return null; + }; + + public showLastTransaction = async () => { + const { navigation } = this.props; + const chargerID = Utils.getParamFromNavigation(this.props.navigation, 'chargerID', null); + const connectorID: number = parseInt(Utils.getParamFromNavigation(this.props.navigation, 'connectorID', null), 10); + // Get the last session + const transaction = await this.getLastTransaction(chargerID, connectorID); + if (transaction) { + // Navigate + navigation.navigate({ + routeName: 'TransactionDetailsTabs', + params: { transactionID: transaction.id }, + key: `${Utils.randomNumber()}` + }); + } else { + Alert.alert(I18n.t('chargers.noSession'), I18n.t('chargers.noSessionMessage')); + } + } + + // tslint:disable-next-line: cyclomatic-complexity + public refresh = async () => { + let siteImage = null; + let userImage = null; + let transaction = null; + const chargerID = Utils.getParamFromNavigation(this.props.navigation, 'chargerID', null); + const connectorID: number = parseInt(Utils.getParamFromNavigation(this.props.navigation, 'connectorID', null), 10); + // Get Charger + const charger = await this.getCharger(chargerID); + const connector = charger ? charger.connectors[connectorID - 1] : null; + // Get the Site Image + if (charger && charger.siteArea && !this.state.siteImage) { + siteImage = await this.getSiteImage(charger.siteArea.siteID); + } + // Get Current Transaction + if (connector && connector.activeTransactionID) { + transaction = await this.getTransaction(connector.activeTransactionID); + if (transaction) { + // Get User Picture + if (!this.state.transaction || (transaction && transaction.id !== this.state.transaction.id)) { + userImage = await this.getUserImage(transaction.user); + } + } + } + // Check to enable the buttons after a certain period of time + const startStopTransactionButtonStatus = this.getStartStopTransactionButtonStatus(connector); + // Compute Duration + const durationInfos = this.getDurationInfos(transaction, connector); + // Get the provider + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Set + this.setState({ + charger, + connector: charger ? charger.connectors[connectorID - 1] : null, + transaction, + siteImage: siteImage ? siteImage : this.state.siteImage, + userImage: userImage ? userImage : transaction ? this.state.userImage : null, + isAdmin: securityProvider ? securityProvider.isAdmin() : false, + isSiteAdmin: securityProvider && charger && charger.siteArea ? securityProvider.isSiteAdmin(charger.siteArea.siteID) : false, + canDisplayTransaction: charger ? this.canDisplayTransaction(charger, connector) : false, + canStartTransaction: charger ? this.canStartTransaction(charger, connector) : false, + canStopTransaction: charger ? this.canStopTransaction(charger, connector) : false, + isPricingActive: securityProvider.isComponentPricingActive(), + ...startStopTransactionButtonStatus, + ...durationInfos, + loading: false + }); + }; + + public canStopTransaction = (charger: ChargingStation, connector: Connector): boolean => { + // Transaction? + if (connector && connector.activeTransactionID !== 0) { + // Get the Security Provider + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Check Auth + return securityProvider.canStopTransaction(charger.siteArea, connector.activeTagID); + } + return false; + }; + + public canStartTransaction = (charger: ChargingStation, connector: Connector): boolean => { + // Transaction? + if (connector && connector.activeTransactionID === 0) { + // Get the Security Provider + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Check Auth + return securityProvider.canStartTransaction(charger.siteArea); + } + return false; + }; + + public canDisplayTransaction = (charger: ChargingStation, connector: Connector): boolean => { + // Transaction? + if (connector && connector.activeTransactionID !== 0) { + // Get the Security Provider + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Check Auth + return securityProvider.canReadTransaction(charger.siteArea, connector.activeTagID); + } + return false; + }; + + public manualRefresh = async () => { + // Display spinner + this.setState({ refreshing: true }); + // Refresh + await this.refresh(); + // Hide spinner + this.setState({ refreshing: false }); + }; + + public startTransactionConfirm = () => { + const { charger } = this.state; + Alert.alert(I18n.t('details.startTransaction'), I18n.t('details.startTransactionMessage', { chargeBoxID: charger.id }), [ + { text: I18n.t('general.yes'), onPress: () => this.startTransaction() }, + { text: I18n.t('general.no') } + ]); + }; + + public startTransaction = async () => { + const { charger, connector } = this.state; + try { + // Check Tag ID + const userInfo = this.centralServerProvider.getUserInfo(); + if (!userInfo.tagIDs || userInfo.tagIDs.length === 0) { + Message.showError(I18n.t('details.noBadgeID')); + return; + } + // Disable the button + this.setState({ buttonDisabled: true }); + // Start the Transaction + const status = await this.centralServerProvider.startTransaction(charger.id, connector.connectorId, userInfo.tagIDs[0]); + // Check + if (status && status.status === 'Accepted') { + // Show message + Message.showSuccess(I18n.t('details.accepted')); + // Nb trials the button stays disabled + this.setState({ startTransactionNbTrial: START_TRANSACTION_NB_TRIAL }); + } else { + // Enable the button + this.setState({ buttonDisabled: false }); + // Show message + Message.showError(I18n.t('details.denied')); + } + } catch (error) { + // Enable the button + this.setState({ buttonDisabled: false }); + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionStartUnexpectedError', this.props.navigation, this.refresh); + } + }; + + public stopTransactionConfirm = async () => { + const { charger } = this.state; + // Confirm + Alert.alert(I18n.t('details.stopTransaction'), I18n.t('details.stopTransactionMessage', { chargeBoxID: charger.id }), [ + { text: I18n.t('general.yes'), onPress: () => this.stopTransaction() }, + { text: I18n.t('general.no') } + ]); + }; + + public stopTransaction = async () => { + const { charger, connector } = this.state; + try { + // Disable button + this.setState({ buttonDisabled: true }); + // Stop the Transaction + const status = await this.centralServerProvider.stopTransaction(charger.id, connector.activeTransactionID); + // Check + if (status && status.status === 'Accepted') { + Message.showSuccess(I18n.t('details.accepted')); + } else { + Message.showError(I18n.t('details.denied')); + } + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionStopUnexpectedError', this.props.navigation, this.refresh); + } + }; + + public getStartStopTransactionButtonStatus(connector: Connector): { buttonDisabled?: boolean; startTransactionNbTrial?: number; } { + const { startTransactionNbTrial } = this.state; + // Check if the Start/Stop Button should stay disabled + if (connector && + ((connector.status === ChargePointStatus.AVAILABLE && startTransactionNbTrial <= START_TRANSACTION_NB_TRIAL - 2) || + (connector.status === ChargePointStatus.PREPARING && startTransactionNbTrial === 0)) + ) { + // Button are set to available after the nbr of trials + return { + buttonDisabled: false + }; + // Still trials? (only for Start Transaction) + } else if (startTransactionNbTrial > 0) { + // Trial - 1 + return { + startTransactionNbTrial: startTransactionNbTrial > 0 ? startTransactionNbTrial - 1 : 0 + }; + // Transaction ongoing + } else if (connector && connector.activeTransactionID !== 0) { + // Transaction has started, enable the buttons again + return { + startTransactionNbTrial: 0, + buttonDisabled: false + }; + // Transaction is stopped (activeTransactionID == 0) + } else if (connector && connector.status === ChargePointStatus.FINISHING) { + // Disable the button until the user unplug the cable + return { + buttonDisabled: true + }; + } + return {}; + } + + public getDurationInfos = (transaction: Transaction, connector: Connector): + {totalInactivitySecs?: number; elapsedTimeFormatted?: string; inactivityFormatted?: string;} => { + // Transaction loaded? + if (transaction) { + let elapsedTimeFormatted = Constants.DEFAULT_DURATION; + let inactivityFormatted = Constants.DEFAULT_DURATION; + // Elapsed Time? + if (transaction.timestamp) { + // Format + const durationSecs = (Date.now() - new Date(transaction.timestamp).getTime()) / 1000; + elapsedTimeFormatted = Utils.formatDurationHHMMSS(durationSecs, false); + } + // Inactivity? + if (transaction.currentTotalInactivitySecs) { + // Format + inactivityFormatted = Utils.formatDurationHHMMSS(transaction.currentTotalInactivitySecs, false); + } + // Set + return { + totalInactivitySecs: transaction.currentTotalInactivitySecs, + elapsedTimeFormatted, + inactivityFormatted + }; + // Basic User: Use the connector data + } else if (connector && connector.activeTransactionID) { + let elapsedTimeFormatted = Constants.DEFAULT_DURATION; + let inactivityFormatted = Constants.DEFAULT_DURATION; + // Elapsed Time? + if (connector.activeTransactionDate) { + // Format + const durationSecs = (Date.now() - new Date(connector.activeTransactionDate).getTime()) / 1000; + elapsedTimeFormatted = Utils.formatDurationHHMMSS(durationSecs, false); + } + // Inactivity? + if (connector && connector.totalInactivitySecs) { + // Format + inactivityFormatted = Utils.formatDurationHHMMSS(connector.totalInactivitySecs, false); + } + // Set + return { + totalInactivitySecs: connector ? connector.totalInactivitySecs : 0, + elapsedTimeFormatted, + inactivityFormatted + }; + } + return { + elapsedTimeFormatted: Constants.DEFAULT_DURATION + } + }; + + public renderConnectorStatus = (style: any) => { + const { connector, isAdmin, isSiteAdmin } = this.state; + return ( + + + {(isAdmin || isSiteAdmin) && connector && connector.status === ChargePointStatus.FAULTED && ( + ({connector.errorCode}) + )} + + ); + }; + + public renderUserInfo = (style: any) => { + const { userImage, transaction, isAdmin, isSiteAdmin } = this.state; + return transaction ? ( + + + + {Utils.buildUserName(transaction.user)} + + {(isAdmin || isSiteAdmin) && ({transaction.tagID})} + + ) : ( + + + - + + ); + }; + + public renderPrice = (style: any) => { + const { transaction, connector } = this.state; + let price = 0; + if (transaction) { + price = Math.round(transaction.currentCumulatedPrice * 100) / 100; + } + return connector && connector.activeTransactionID && transaction && !isNaN(price) ? ( + + + {price} + ({transaction.priceUnit}) + + ) : ( + + + - + + ); + }; + + public renderInstantPower = (style: any) => { + const { connector } = this.state; + return connector && connector.activeTransactionID && !isNaN(connector.currentConsumption) ? ( + + + + {connector.currentConsumption / 1000 > 0 ? I18nManager.formatNumber(Math.round(connector.currentConsumption / 10) / 100) : 0} + + {I18n.t('details.instant')} (kW) + + ) : ( + + + - + + ); + }; + + public renderElapsedTime = (style: any) => { + const { elapsedTimeFormatted, connector } = this.state; + return connector && connector.activeTransactionID ? ( + + + {elapsedTimeFormatted} + {I18n.t('details.duration')} + + ) : ( + + + - + + ); + }; + + public renderInactivity = (style: any) => { + const { connector, inactivityFormatted } = this.state; + const inactivityStyle = connector ? Utils.computeInactivityStyle(connector.inactivityStatus) : ''; + return connector && connector.activeTransactionID ? ( + + + {inactivityFormatted} + {I18n.t('details.duration')} + + ) : ( + + + - + + ); + }; + + public renderTotalConsumption = (style: any) => { + const { connector } = this.state; + return connector && connector.activeTransactionID && !isNaN(connector.totalConsumption) ? ( + + + + {connector ? I18nManager.formatNumber(Math.round(connector.totalConsumption / 10) / 100) : ''} + + {I18n.t('details.total')} (kW.h) + + ) : ( + + + - + + ); + }; + + public renderBatteryLevel = (style: any) => { + const { transaction, connector } = this.state; + return connector && connector.currentStateOfCharge && !isNaN(connector.currentStateOfCharge) ? ( + + + + {transaction ? `${transaction.stateOfCharge} > ${transaction.currentStateOfCharge}` : connector.currentStateOfCharge} + + (%) + + ) : ( + + + - + + ); + }; + + public renderShowLastTransactionButton = (style: any) => { + const { isAdmin, isSiteAdmin, connector, canStartTransaction } = this.state; + if ((isAdmin || isSiteAdmin) && canStartTransaction && connector && connector.activeTransactionID === 0) { + return ( + this.showLastTransaction()}> + + + + + ); + } + return ( + + ); + }; + + public renderStartTransactionButton = (style: any) => { + const { buttonDisabled } = this.state; + return ( + this.startTransactionConfirm()}> + + + + + ); + }; + + public renderStopTransactionButton = (style: any) => { + const { buttonDisabled } = this.state; + return ( + this.stopTransactionConfirm()} disabled={buttonDisabled}> + + + + + ); + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.goBack(null); + // Do not bubble up + return true; + }; + + public render() { + const { navigation } = this.props; + const style = computeStyleSheet(); + const { connector, canStopTransaction, canStartTransaction, charger, loading, siteImage, isPricingActive } = this.state; + const connectorLetter = Utils.getConnectorLetterFromConnectorID(connector ? connector.connectorId : null); + return ( + loading ? ( + + ) : ( + + this.onBack()} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + /> + {/* Site Image */} + + {/* Show Last Transaction */} + {this.renderShowLastTransactionButton(style)} + {/* Start/Stop Transaction */} + {canStartTransaction && connector && connector.activeTransactionID === 0 ? ( + + {this.renderStartTransactionButton(style)} + + ) : canStopTransaction && connector && connector.activeTransactionID > 0 ? ( + + {this.renderStopTransactionButton(style)} + + ) : ( + + )} + {/* Details */} + }> + + {this.renderConnectorStatus(style)} + {this.renderUserInfo(style)} + + + {this.renderInstantPower(style)} + {this.renderTotalConsumption(style)} + + + {this.renderElapsedTime(style)} + {this.renderInactivity(style)} + + + {this.renderBatteryLevel(style)} + {isPricingActive ? this.renderPrice(style) : } + + + + ) + ); + } +} diff --git a/src/screens/chargers/connector-details/ChargerConnectorDetailsStyles.tsx b/src/screens/chargers/connector-details/ChargerConnectorDetailsStyles.tsx new file mode 100644 index 000000000..2eea3a320 --- /dev/null +++ b/src/screens/chargers/connector-details/ChargerConnectorDetailsStyles.tsx @@ -0,0 +1,179 @@ +import deepmerge from 'deepmerge'; +import { Platform } from 'react-native'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'center', + backgroundColor: commonColor.containerBgColor + }, + spinner: { + flex: 1, + color: commonColor.textColor + }, + backgroundImage: { + width: '100%', + height: '125@s', + }, + lastTransactionContainer: { + width: '50@s', + height: '50@s', + marginTop: '-90@s', + marginLeft: '-220@s', + marginBottom: '25@s', + backgroundColor: 'transparent', + }, + buttonLastTransaction: { + width: '50@s', + height: '50@s', + borderRadius: '25@s', + borderStyle: 'solid', + borderWidth: '4@s', + borderColor: commonColor.textColor, + backgroundColor: commonColor.containerBgColor, + justifyContent: 'center', + alignItems: 'center' + }, + transactionContainer: { + width: '100@s', + height: '100@s', + padding: 0, + paddingBottom: '25@s', + justifyContent: 'center', + alignItems: 'center', + marginTop: '-85@s', + backgroundColor: 'transparent', + // zIndex: 1, + }, + buttonTransaction: { + width: '100@s', + height: '100@s', + borderRadius: '50@s', + borderStyle: 'solid', + borderWidth: '4@s', + borderColor: commonColor.textColor, + backgroundColor: commonColor.containerBgColor, + justifyContent: 'center', + alignItems: 'center', + }, + noButtonStopTransaction: { + height: '15@s' + }, + startTransaction: { + borderColor: commonColor.brandSuccess + }, + stopTransaction: { + borderColor: commonColor.brandDanger + }, + transactionIcon: { + fontSize: '75@s' + }, + lastTransactionIcon: { + fontSize: '25@s' + }, + startTransactionIcon: { + color: commonColor.brandSuccess + }, + stopTransactionIcon: { + color: commonColor.brandDanger + }, + buttonTransactionDisabled: { + borderColor: commonColor.buttonDisabledBg + }, + transactionDisabledIcon: { + color: commonColor.buttonDisabledBg, + backgroundColor: 'transparent' + }, + scrollViewContainer: { + flex: 1, + flexDirection: 'column', + justifyContent: 'space-evenly', + alignItems: 'center' + }, + rowContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + height: '100@s' + }, + columnContainer: { + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '50%', + }, + connectorLetter: { + marginTop: '5@s', + marginBottom: '5@s' + }, + label: { + fontSize: '16@s', + color: commonColor.brandPrimaryDark, + alignSelf: 'center' + }, + labelValue: { + fontSize: '25@s', + fontWeight: 'bold' + }, + labelUser: { + fontSize: '10@s' + }, + subLabel: { + fontSize: '10@s', + marginTop: Platform.OS === 'ios' ? '0@s' : '-2@s', + color: commonColor.brandPrimaryDark, + alignSelf: 'center' + }, + subLabelStatusError: { + color: commonColor.brandDanger, + marginTop: '2@s' + }, + subLabelUser: { + fontSize: '8@s', + marginTop: '0@s' + }, + icon: { + fontSize: '25@s' + }, + userImage: { + height: '52@s', + width: '52@s', + alignSelf: 'center', + marginBottom: '5@s', + borderRadius: '26@s', + borderWidth: '3@s', + borderColor: commonColor.textColor + }, + info: { + color: commonColor.brandPrimaryDark, + borderColor: commonColor.brandPrimaryDark + }, + success: { + color: commonColor.brandSuccess + }, + warning: { + color: commonColor.brandWarning + }, + danger: { + color: commonColor.brandDanger + }, + disabled: { + color: commonColor.buttonDisabledBg, + borderColor: commonColor.buttonDisabledBg + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/chargers/list/Chargers.tsx b/src/screens/chargers/list/Chargers.tsx new file mode 100644 index 000000000..58be0948e --- /dev/null +++ b/src/screens/chargers/list/Chargers.tsx @@ -0,0 +1,239 @@ +import I18n from 'i18n-js'; +import { Container, Spinner, View } from 'native-base'; +import React from 'react'; +import { FlatList, Platform, RefreshControl } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import ChargerComponent from '../../../components/charger/ChargerComponent'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import ListEmptyTextComponent from '../../../components/list/empty-text/ListEmptyTextComponent'; +import ListFooterComponent from '../../../components/list/footer/ListFooterComponent'; +import SimpleSearchComponent from '../../../components/search/simple/SimpleSearchComponent'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseProps from '../../../types/BaseProps'; +import ChargingStation, { ChargePointStatus } from '../../../types/ChargingStation'; +import { DataResult } from '../../../types/DataResult'; +import { GlobalFilters } from '../../../types/Filter'; +import Constants from '../../../utils/Constants'; +import SecuredStorage from '../../../utils/SecuredStorage'; +import Utils from '../../../utils/Utils'; +import BaseAutoRefreshScreen from '../../base-screen/BaseAutoRefreshScreen'; +import ChargersFilters, { ChargersFiltersDef } from './ChargersFilters'; +import computeStyleSheet from './ChargersStyles'; + +export interface Props extends BaseProps { +} + +interface State { + chargers?: ChargingStation[]; + siteAreaID?: string; + loading?: boolean; + refreshing?: boolean; + isAdmin?: boolean; + skip?: number; + limit?: number; + count?: number; + initialFilters?: ChargersFiltersDef; + filters?: ChargersFiltersDef; +} + +export default class Chargers extends BaseAutoRefreshScreen { + public state: State; + public props: Props; + private searchText: string; + + constructor(props: Props) { + super(props); + // Init State + this.state = { + chargers: [], + siteAreaID: Utils.getParamFromNavigation(this.props.navigation, 'siteAreaID', null), + loading: true, + refreshing: false, + isAdmin: false, + initialFilters: {}, + filters: {}, + skip: 0, + limit: Constants.PAGING_SIZE, + count: 0 + }; + } + + public async componentDidMount() { + // Get initial filters + await this.loadInitialFilters(); + await super.componentDidMount(); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async loadInitialFilters() { + const connectorStatus = await SecuredStorage.loadFilterValue( + GlobalFilters.ONLY_AVAILABLE_CHARGERS) as ChargePointStatus; + const connectorType = await SecuredStorage.loadFilterValue( + GlobalFilters.CONNECTOR_TYPES) as string; + this.setState({ + initialFilters: { connectorStatus, connectorType }, + filters: { connectorStatus, connectorType} + }); + } + + public getChargers = async (searchText: string, skip: number, limit: number): Promise> => { + const { siteAreaID } = this.state; + let chargers: DataResult; + try { + // Get with the Site Area + chargers = await this.centralServerProvider.getChargers({ + Search: searchText, + SiteAreaID: siteAreaID, + Issuer: true, + ConnectorStatus: this.state.filters.connectorStatus, + ConnectorType: this.state.filters.connectorType + }, { skip, limit }); + // Check + if (chargers.count === -1) { + // Request nbr of records + const chargersNbrRecordsOnly = await this.centralServerProvider.getChargers({ + Search: searchText, + SiteAreaID: siteAreaID, + Issuer: true, + ConnectorStatus: this.state.filters.connectorStatus + }, Constants.ONLY_RECORD_COUNT_PAGING); + // Set + chargers.count = chargersNbrRecordsOnly.count; + } + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerUnexpectedError', this.props.navigation, this.refresh); + } + return chargers; + }; + + public onEndScroll = async () => { + const { count, skip, limit } = this.state; + // No reached the end? + if (skip + limit < count || count === -1) { + // No: get next sites + const chargers = await this.getChargers(this.searchText, skip + Constants.PAGING_SIZE, limit); + // Add sites + this.setState((prevState, props) => ({ + chargers: chargers ? [...prevState.chargers, ...chargers.result] : prevState.chargers, + skip: prevState.skip + Constants.PAGING_SIZE, + refreshing: false + })); + } + }; + + public onBack = (): boolean => { + const { siteAreaID } = this.state; + if (siteAreaID) { + // Go Back + this.props.navigation.goBack(); + } else { + // Go back to the top + this.props.navigation.goBack(null); + } + // Do not bubble up + return true; + }; + + public refresh = async () => { + // Component Mounted? + if (this.isMounted()) { + const { skip, limit } = this.state; + // Refresh All + const chargers = await this.getChargers(this.searchText, 0, skip + limit); + // Get the provider + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Add Chargers + this.setState(() => ({ + loading: false, + chargers: chargers ? chargers.result : [], + count: chargers ? chargers.count : 0, + isAdmin: securityProvider ? securityProvider.isAdmin() : false + })); + } + }; + + public manualRefresh = async () => { + // Display spinner + this.setState({ refreshing: true }); + // Refresh + await this.refresh(); + // Hide spinner + this.setState({ refreshing: false }); + }; + + public getSiteIDFromChargers(): string { + const { chargers } = this.state; + // Find the first available Site ID + if (chargers && chargers.length > 0) { + for (const charger of chargers) { + if (charger.siteArea) { + return charger.siteArea.siteID; + } + } + } + return null; + } + + public search = async (searchText: string) => { + this.searchText = searchText; + await this.refresh(); + } + + public render() { + const style = computeStyleSheet(); + const { navigation } = this.props; + const { loading, chargers, isAdmin, initialFilters, + skip, count, limit, filters } = this.state; + return ( + + + this.setHeaderComponent(headerComponent)} + navigation={navigation} + title={I18n.t('chargers.title')} + subTitle={count > 0 ? `${I18nManager.formatNumber(count)} ${I18n.t('chargers.chargers')}` : null} + leftAction={this.onBack} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + filters={filters} + /> + this.search(searchText)} + navigation={navigation} + /> + + {loading ? ( + + ) : ( + + this.setState({ filters: newFilters }, () => this.refresh())} + ref={(chargersFilters: ChargersFilters) => + this.setScreenFilters(chargersFilters)} + /> + + } + keyExtractor={(item) => item.id} + refreshControl={} + onEndReached={this.onEndScroll} + onEndReachedThreshold={Platform.OS === 'android' ? 1 : 0.1} + ListFooterComponent={() => } + ListEmptyComponent={() => } + /> + + )} + + + ); + } +} diff --git a/src/screens/chargers/list/ChargersFilters.tsx b/src/screens/chargers/list/ChargersFilters.tsx new file mode 100644 index 000000000..84908bec6 --- /dev/null +++ b/src/screens/chargers/list/ChargersFilters.tsx @@ -0,0 +1,90 @@ +import I18n from 'i18n-js'; +import { View } from 'native-base'; +import React from 'react'; +import * as Animatable from 'react-native-animatable'; +import FilterVisibleContainerComponent from '../../../components/search/filter/containers/FilterVisibleContainerComponent'; +import ConnectorTypeFilterControlComponent from '../../../components/search/filter/controls/connector-type/ConnectorTypeFilterControlComponent'; +import OnlyAvailableChargerSwitchFilterControlComponent from '../../../components/search/filter/controls/only-available-chargers/OnlyAvailableChargerSwitchFilterControlComponent'; +import ScreenFilters, { ScreenFiltersState } from '../../../components/search/filter/screen/ScreenFilters'; +import { ChargePointStatus } from '../../../types/ChargingStation'; +import { GlobalFilters } from '../../../types/Filter'; +import computeStyleSheet from './ChargersStyles'; +import computeControlStyleSheet from '../../../components/search/filter/controls/FilterControlComponentStyles'; + +export interface Props { + onFilterChanged?: (filters: ChargersFiltersDef) => void; + initialFilters?: ChargersFiltersDef; +} + +interface State extends ScreenFiltersState { + filters?: ChargersFiltersDef; +} + +export interface ChargersFiltersDef { + connectorStatus?: ChargePointStatus; + connectorType?: string; +} + +export default class ChargersFilters extends ScreenFilters { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + filters: {} + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public onFilterChanged = (newFilters: ChargersFiltersDef) => { + const { onFilterChanged } = this.props; + this.setState({ + filters: { ...this.state.filters, ...newFilters } + }, () => onFilterChanged(newFilters)); + } + + public render = () => { + const { initialFilters } = this.props; + const { filters } = this.state; + const style = computeStyleSheet(); + const controlStyle = computeControlStyleSheet(); + return ( + + this.setViewExpanded(expanded, style.filtersHidden, style.filtersExpanded)} + onFilterChanged={this.onFilterChanged} + ref={(filterVisibleContainerComponent: FilterVisibleContainerComponent) => + this.setFilterVisibleContainerComponent(filterVisibleContainerComponent)} + > + + this.getFilterVisibleContainerComponent().setFilter(id, value)} + ref={(onlyAvailableChargerSwitchFilterControlComponent: OnlyAvailableChargerSwitchFilterControlComponent) => + this.addVisibleFilter(onlyAvailableChargerSwitchFilterControlComponent)} + /> + + + this.getFilterVisibleContainerComponent().setFilter(id, value)} + ref={(connectorTypeFilterControlComponent: ConnectorTypeFilterControlComponent) => + this.addVisibleFilter(connectorTypeFilterControlComponent)} + /> + + + + ); + }; +} diff --git a/src/screens/chargers/list/ChargersStyles.tsx b/src/screens/chargers/list/ChargersStyles.tsx new file mode 100644 index 000000000..f2c4c58eb --- /dev/null +++ b/src/screens/chargers/list/ChargersStyles.tsx @@ -0,0 +1,36 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + backgroundColor: commonColor.containerBgColor + }, + content: { + flex: 1 + }, + spinner: { + flex: 1 + }, + filtersExpanded: { + opacity: 1, + height: '100@s', + }, + filtersHidden: { + opacity: 0, + height: 0 + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/chargers/ocpp/ChargerOcppParameters.tsx b/src/screens/chargers/ocpp/ChargerOcppParameters.tsx new file mode 100644 index 000000000..b5c3355ab --- /dev/null +++ b/src/screens/chargers/ocpp/ChargerOcppParameters.tsx @@ -0,0 +1,196 @@ +import I18n from 'i18n-js'; +import { Button, Container, Icon, Spinner, Text, View } from 'native-base'; +import React from 'react'; +import { Alert, FlatList, RefreshControl, ScrollView } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import ListEmptyTextComponent from '../../../components/list/empty-text/ListEmptyTextComponent'; +import BaseProps from '../../../types/BaseProps'; +import ChargingStation, { ChargingStationConfiguration } from '../../../types/ChargingStation'; +import Message from '../../../utils/Message'; +import Utils from '../../../utils/Utils'; +import BaseScreen from '../../base-screen/BaseScreen'; +import computeStyleSheet from './ChargerOcppParametersStyles'; + +export interface Props extends BaseProps { +} + +interface State { + loading?: boolean; + refreshing?: boolean; + charger: ChargingStation; + chargerConfiguration?: ChargingStationConfiguration; +} + +export default class ChargerOcppParameters extends BaseScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + charger: null, + loading: true, + refreshing: false, + chargerConfiguration: null + } + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + // Call parent + await super.componentDidMount(); + await this.refresh(); + } + + public refresh = async () => { + // Component Mounted? + if (this.isMounted()) { + // Get Charger + let charger = this.state.charger; + if (!charger) { + const chargerID = Utils.getParamFromNavigation(this.props.navigation, 'chargerID', null); + charger = await this.getCharger(chargerID); + } + // Get Charger Config + const chargerConfiguration = await this.getChargerConfiguration(charger.id); + // Sort + if (chargerConfiguration && chargerConfiguration.configuration) { + chargerConfiguration.configuration.sort((a, b) => { + // ignore upper and lowercase + const keyA = a.key.toUpperCase(); + const keyB = b.key.toUpperCase(); + if (keyA < keyB) { + return -1; + } + if (keyA > keyB) { + return 1; + } + return 0; + }); + } + // Set + this.setState({ + loading: false, + charger, + chargerConfiguration + }); + } + }; + + public getCharger = async (chargerID: string): Promise => { + try { + // Get Charger + const charger = await this.centralServerProvider.getCharger({ ID: chargerID }); + return charger; + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerUnexpectedError', this.props.navigation); + } + return null; + }; + + public getChargerConfiguration = async (chargerID: string): Promise => { + try { + // Get Charger + const chargerConfiguration = await this.centralServerProvider.getChargerConfiguration(chargerID); + return chargerConfiguration; + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerConfigurationUnexpectedError', this.props.navigation); + } + return null; + }; + + public manualRefresh = async () => { + // Display spinner + this.setState({ refreshing: true }); + // Refresh + await this.refresh(); + // Hide spinner + this.setState({ refreshing: false }); + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.goBack(null); + // Do not bubble up + return true; + }; + + public requestConfigurationConfirm() { + const { charger } = this.state; + Alert.alert + (I18n.t('chargers.requestConfiguration', { chargeBoxID: charger.id }), + I18n.t('chargers.requestConfigurationMessage', { chargeBoxID: charger.id }), [ + { text: I18n.t('general.yes'), onPress: () => this.requestConfiguration(charger.id) }, + { text: I18n.t('general.cancel') } + ]); + } + + public async requestConfiguration(chargeBoxID: string) { + try { + // Unlock Connector + const status = await this.centralServerProvider.requestChargingStationOCPPConfiguration(chargeBoxID); + // Check + if (status.status && status.status === 'Accepted') { + Message.showSuccess(I18n.t('details.accepted')); + await this.refresh(); + } else { + Message.showError(I18n.t('details.denied')); + } + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerConfigurationUnexpectedError', this.props.navigation); + } + } + + public render() { + const { navigation } = this.props; + const style = computeStyleSheet(); + const { loading, charger, chargerConfiguration } = this.state; + return ( + + this.onBack()} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + /> + + {loading ? ( + + ) : ( + ( + + {item.key} + + {item.value} + + + )} + keyExtractor={(item) => `${item.key}`} + refreshControl={} + ListEmptyComponent={() => } + /> + )} + + ); + } +} diff --git a/src/screens/chargers/ocpp/ChargerOcppParametersStyles.tsx b/src/screens/chargers/ocpp/ChargerOcppParametersStyles.tsx new file mode 100644 index 000000000..d143d0dcf --- /dev/null +++ b/src/screens/chargers/ocpp/ChargerOcppParametersStyles.tsx @@ -0,0 +1,80 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + backgroundColor: commonColor.containerBgColor + }, + scrollViewContainer: { + flexDirection: 'column' + }, + viewContainer: { + flex: 1, + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'center' + }, + spinner: { + flex: 1, + color: commonColor.textColor + }, + actionButton: { + }, + actionButtonIcon: { + fontSize: '20@s' + }, + actionButtonText: { + fontSize: '15@s' + }, + descriptionContainer: { + width: '100%', + flexDirection: 'row', + justifyContent: 'flex-start', + alignItems: 'center' + }, + label: { + width: '50%', + marginLeft: '10@s', + marginTop: '5@s', + marginBottom: '5@s', + fontSize: '12@s', + fontWeight: 'bold', + color: commonColor.textColor, + }, + scrollViewValue: { + marginTop: '5@s', + marginBottom: '5@s' + }, + value: { + fontSize: '12@s', + marginLeft: '15@s', + color: commonColor.textColor + }, + scrollViewValues: { + flexDirection: 'column', + marginTop: '5@s' + }, + values: { + fontSize: '15@s', + marginLeft: '15@s', + marginBottom: '5@s', + color: commonColor.textColor + }, + rowBackground: { + backgroundColor: commonColor.headerBgColor + }, +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/chargers/properties/ChargerProperties.tsx b/src/screens/chargers/properties/ChargerProperties.tsx new file mode 100644 index 000000000..dc511025a --- /dev/null +++ b/src/screens/chargers/properties/ChargerProperties.tsx @@ -0,0 +1,230 @@ +import I18n from 'i18n-js'; +import { Container, Spinner, Text, View } from 'native-base'; +import React from 'react'; +import { FlatList, RefreshControl, ScrollView } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import ListEmptyTextComponent from '../../../components/list/empty-text/ListEmptyTextComponent'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseProps from '../../../types/BaseProps'; +import ChargingStation, { ChargingStationCapabilities, OcppAdvancedCommands, OcppCommand } from '../../../types/ChargingStation'; +import { KeyValue, PropertyDisplay } from '../../../types/Global'; +import Utils from '../../../utils/Utils'; +import BaseScreen from '../../base-screen/BaseScreen'; +import computeStyleSheet from './ChargerPropertiesStyles'; + +export interface Props extends BaseProps { +} + +interface State { + loading?: boolean; + refreshing?: boolean; + charger: ChargingStation; +} + +export default class ChargerProperties extends BaseScreen { + public state: State; + public props: Props; + private displayedProperties: PropertyDisplay[] = [ + { key: 'chargePointVendor', title: 'details.vendor' }, + { key: 'chargePointModel', title: 'details.model' }, + { key: 'chargeBoxSerialNumber', title: 'details.serialNumber' }, + { key: 'firmwareVersion', title: 'details.firmwareVersion' }, + { key: 'endpoint', title: 'details.privateURL' }, + { key: 'chargingStationURL', title: 'details.publicURL' }, + { key: 'currentIPAddress', title: 'details.currentIP' }, + { key: 'ocppVersion', title: 'details.ocppVersion' }, + { + key: 'lastReboot', title: 'details.lastReboot', formatter: (lastReboot: Date): string => { + return I18nManager.formatDateTime(lastReboot); + }, + }, + { + key: 'createdOn', title: 'general.createdOn', formatter: (createdOn: Date): string => { + return I18nManager.formatDateTime(createdOn); + }, + }, + { + key: 'capabilities', title: 'details.capabilities', formatterWithComponents: true, + formatter: (capabilities: ChargingStationCapabilities): Element[] => { + const formatterValues: Element[] = []; + if (capabilities) { + const style = computeStyleSheet(); + for (const key in capabilities) { + if (capabilities.hasOwnProperty(key)) { + // @ts-ignore + formatterValues.push({`${key}: ${capabilities[key]}`}); + } + } + } + return formatterValues; + }, + }, + { + key: 'ocppStandardParameters', title: 'details.ocppStandardParams', formatterWithComponents: true, + formatter: (ocppStandardParameters: KeyValue[]): Element[] => { + const formatterValues: Element[] = []; + if (ocppStandardParameters) { + const style = computeStyleSheet(); + for (const ocppStandardParameter of ocppStandardParameters) { + formatterValues.push({`${ocppStandardParameter.key}: ${ocppStandardParameter.value}`}); + } + } + return formatterValues; + }, + }, + { + key: 'ocppVendorParameters', title: 'details.ocppVendorParams', formatterWithComponents: true, + formatter: (ocppVendorParameters: KeyValue[]): Element[] => { + const formatterValues: Element[] = []; + if (ocppVendorParameters) { + const style = computeStyleSheet(); + for (const ocppVendorParameter of ocppVendorParameters) { + formatterValues.push({`${ocppVendorParameter.key}: ${ocppVendorParameter.value}`}); + } + } + return formatterValues; + }, + }, + { + key: 'ocppAdvancedCommands', title: 'details.ocppAdvancedCommands', formatterWithComponents: true, + formatter: (ocppAdvancedCommands: OcppAdvancedCommands[]): Element[] => { + const formatterValues: Element[] = []; + if (ocppAdvancedCommands) { + const style = computeStyleSheet(); + for (const ocppAdvancedCommand of ocppAdvancedCommands) { + if (typeof ocppAdvancedCommand === 'object') { + const advancedCommand = ocppAdvancedCommand as OcppCommand; + formatterValues.push({`${advancedCommand.command} ${advancedCommand.parameters ? '(' + advancedCommand.parameters.join(', ') + ')' : ''}`}); + } else { + formatterValues.push({ocppAdvancedCommand}); + } + } + } + return formatterValues; + }, + }, + ]; + + constructor(props: Props) { + super(props); + this.state = { + loading: true, + refreshing: false, + charger: null, + } + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + // Call parent + await super.componentDidMount(); + await this.refresh(); + } + + public refresh = async () => { + // Component Mounted? + if (this.isMounted()) { + const chargerID = Utils.getParamFromNavigation(this.props.navigation, 'chargerID', null); + // Get Charger + const charger = await this.getCharger(chargerID); + // Build props + const chargerProperties = this.buildChargerProperties(charger); + // Set + this.setState({ + loading: false, + charger, + chargerProperties, + }); + } + }; + + public getCharger = async (chargerID: string): Promise => { + try { + // Get Charger + const charger = await this.centralServerProvider.getCharger({ ID: chargerID }); + return charger; + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerUnexpectedError', this.props.navigation); + } + return null; + }; + + public manualRefresh = async () => { + // Display spinner + this.setState({ refreshing: true }); + // Refresh + await this.refresh(); + // Hide spinner + this.setState({ refreshing: false }); + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.goBack(null); + // Do not bubble up + return true; + }; + + private buildChargerProperties(charger: ChargingStation) { + if (charger) { + for (const displayedProperty of this.displayedProperties) { + // @ts-ignore + displayedProperty.value = charger && charger[displayedProperty.key] ? charger[displayedProperty.key] : '-'; + } + } + } + + public render() { + const { navigation } = this.props; + const style = computeStyleSheet(); + const { loading, charger } = this.state; + return ( + + this.onBack()} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + /> + {loading ? ( + + ) : ( + ( + + {I18n.t(item.title)} + {item.formatter && item.value !== '-' ? + item.formatterWithComponents ? + + {item.formatter(item.value)} + + : + + {item.formatter(item.value)} + + : + + {item.value} + + } + + )} + keyExtractor={(item) => `${item.key}`} + refreshControl={} + ListEmptyComponent={() => } + /> + )} + + ); + } +} diff --git a/src/screens/chargers/properties/ChargerPropertiesStyles.tsx b/src/screens/chargers/properties/ChargerPropertiesStyles.tsx new file mode 100644 index 000000000..f6bdea517 --- /dev/null +++ b/src/screens/chargers/properties/ChargerPropertiesStyles.tsx @@ -0,0 +1,72 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + backgroundColor: commonColor.containerBgColor + }, + scrollViewContainer: { + flexDirection: 'column' + }, + viewContainer: { + flex: 1, + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'center' + }, + spinner: { + flex: 1, + color: commonColor.textColor + }, + descriptionContainer: { + width: '100%', + flexDirection: 'row', + justifyContent: 'flex-start', + alignItems: 'center' + }, + label: { + width: '150@s', + marginLeft: '10@s', + marginTop: '5@s', + marginBottom: '5@s', + fontSize: '12@s', + fontWeight: 'bold', + color: commonColor.textColor, + }, + scrollViewValue: { + marginTop: '5@s', + marginBottom: '5@s' + }, + value: { + fontSize: '12@s', + marginLeft: '15@s', + color: commonColor.textColor + }, + scrollViewValues: { + flexDirection: 'column', + marginTop: '5@s' + }, + values: { + fontSize: '12@s', + marginLeft: '15@s', + marginBottom: '5@s', + color: commonColor.textColor + }, + rowBackground: { + backgroundColor: commonColor.headerBgColor + }, +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/home/Home.tsx b/src/screens/home/Home.tsx new file mode 100644 index 000000000..fbd979314 --- /dev/null +++ b/src/screens/home/Home.tsx @@ -0,0 +1,168 @@ +import I18n from 'i18n-js'; +import { Body, Card, CardItem, Container, Content, Icon, Left, Text } from 'native-base'; +import React from 'react'; +import { Alert, BackHandler } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import Transaction from 'types/Transaction'; +import HeaderComponent from '../../components/header/HeaderComponent'; +import BaseProps from '../../types/BaseProps'; +import Constants from '../../utils/Constants'; +import Utils from '../../utils/Utils'; +import BaseScreen from '../base-screen/BaseScreen'; +import computeStyleSheet from './HomeStyles'; + +export interface Props extends BaseProps { +} + +interface State { + isAdmin?: boolean; + isComponentOrganizationActive?: boolean; + transactionsActive?: Transaction[]; +} + +export default class Home extends BaseScreen { + public state: State; + public props: Props; + private userID: string; + + constructor(props: Props) { + super(props); + // Init State + this.state = { + isComponentOrganizationActive: false, + isAdmin: false, + transactionsActive: null, + }; + } + + public async componentDidMount() { + await super.componentDidMount(); + // Get the security provider + const securityProvider = this.centralServerProvider.getSecurityProvider(); + this.userID = this.centralServerProvider.getUserInfo().id; + this.setState({ + loading: false, + isComponentOrganizationActive: securityProvider ? securityProvider.isComponentOrganizationActive() : false, + }); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public onBack = (): boolean => { + Alert.alert( + I18n.t('general.exitApp'), + I18n.t('general.exitAppConfirm'), + [{ text: I18n.t('general.no'), style: 'cancel' }, { text: I18n.t('general.yes'), onPress: () => BackHandler.exitApp() }], + { cancelable: false } + ); + return true; + } + + public navigateToTransactionInProgress = async () => { + const { navigation } = this.props; + try { + if (!this.state.isAdmin) { + // Get the Transactions + const transactions = await this.centralServerProvider.getTransactionsActive({ + UserID: this.userID, + }, Constants.ONLY_ONE_PAGING); + // User has only one transaction? + if (transactions.count === 1) { + navigation.navigate({ + routeName: 'ChargerConnectorDetailsTabs', + params: { + chargerID: transactions.result[0].chargeBoxID, + connectorID: transactions.result[0].connectorId + }, + key: `${Utils.randomNumber()}` + }); + } else { + navigation.navigate({ routeName: 'TransactionInProgressNavigator' }); + } + } else { + navigation.navigate({ routeName: 'TransactionInProgressNavigator' }); + } + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionUnexpectedError', this.props.navigation); + } + } + + public render = () => { + const style = computeStyleSheet(); + const { navigation } = this.props; + const { isComponentOrganizationActive } = this.state; + return ( + + navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + /> + + {isComponentOrganizationActive && ( + + navigation.navigate({ routeName: 'SitesNavigator' })}> + + + + {I18n.t('home.browseSites')} + {I18n.t('home.browseSitesNote')} + + + + + )} + + navigation.navigate({ routeName: 'ChargersNavigator' })}> + + + + {I18n.t('home.browseChargers')} + {I18n.t('home.browseChargersNote')} + + + + + + navigation.navigate({ routeName: 'TransactionHistoryNavigator' })}> + + + + {I18n.t('home.browseSessions')} + {I18n.t('home.browseSessionsNote')} + + + + + + + + + + {I18n.t('home.ongoingSessions')} + {I18n.t('home.ongoingSessionsNote')} + + + + + + navigation.navigate({ routeName: 'StatisticsNavigator' })}> + + + + {I18n.t('home.browseStatistics')} + {I18n.t('home.browseStatisticsNote')} + + + + + + + ); + }; +} diff --git a/src/screens/home/HomeStyles.tsx b/src/screens/home/HomeStyles.tsx new file mode 100644 index 000000000..22169cb3e --- /dev/null +++ b/src/screens/home/HomeStyles.tsx @@ -0,0 +1,44 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + height: '100%', + backgroundColor: commonColor.containerBgColor + }, + spinner: { + flex: 1, + color: commonColor.textColor + }, + content: { + padding: '5@s' + }, + tabHeader: {}, + cardIcon: { + textAlign: 'center', + fontSize: '50@s', + width: '55@s' + }, + cardText: { + fontSize: '20@s', + }, + cardNote: { + fontStyle: 'italic', + fontSize: '12@s' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/sidebar/SideBar.tsx b/src/screens/sidebar/SideBar.tsx new file mode 100644 index 000000000..aefbb9f38 --- /dev/null +++ b/src/screens/sidebar/SideBar.tsx @@ -0,0 +1,188 @@ +import I18n from 'i18n-js'; +import moment from 'moment'; +import { Container, Content, Header, Icon, ListItem, Text, Thumbnail, View } from 'native-base'; +import React from 'react'; +import { Image, TouchableOpacity } from 'react-native'; +import DeviceInfo from 'react-native-device-info'; +import { DrawerActions, NavigationActions } from 'react-navigation'; +import logo from '../../../assets/logo-low.png'; +import noPhoto from '../../../assets/no-photo-inverse.png'; +import BaseProps from '../../types/BaseProps'; +import Constants from '../../utils/Constants'; +import Utils from '../../utils/Utils'; +import BaseScreen from '../base-screen/BaseScreen'; +import computeStyleSheet from './SideBarStyles'; + +export interface Props extends BaseProps { +} + +interface State { + userName?: string; + userID?: string; + userImage?: string; + tenantName?: string; + isComponentOrganizationActive?: boolean; +} + +export default class SideBar extends BaseScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + userName: '', + userID: '', + userImage: '', + tenantName: '', + isComponentOrganizationActive: false + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + await super.componentDidMount(); + // Init User (delay it) + this.refresh(); + } + + public refresh = async () => { + await this.getUserInfo(); + }; + + public getUserInfo = async () => { + // Logoff + const userInfo = this.centralServerProvider.getUserInfo(); + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Add sites + this.setState( + { + userName: userInfo ? `${userInfo.name} ${userInfo.firstName}` : '', + userID: userInfo ? `${userInfo.id}` : '', + isComponentOrganizationActive: securityProvider ? securityProvider.isComponentOrganizationActive() : false, + tenantName: userInfo.tenantName + }, + async () => { + await this.getUserImage(); + } + ); + }; + + public async getUserImage() { + const { userID } = this.state; + try { + const image = await this.centralServerProvider.getUserImage({ ID: userID }); + if (image) { + this.setState({ userImage: image }); + } + } catch (error) { + // Other common Error + setTimeout(() => this.refresh(), Constants.AUTO_REFRESH_ON_ERROR_PERIOD_MILLIS); + } + } + + public async logoff() { + // Logoff + this.centralServerProvider.setAutoLoginDisabled(true); + this.centralServerProvider.logoff(); + // Back to login + this.props.navigation.navigate('AuthNavigator'); + } + + public navigateTo = (container: string, screen: string, params = {}) => { + // Navigate + this.props.navigation.dispatch( + NavigationActions.navigate({ + routeName: container, + key: `${Utils.randomNumber()}`, + action: NavigationActions.navigate({ + routeName: screen, + key: `${Utils.randomNumber()}` + }), + }) + ); + // Close + this.props.navigation.closeDrawer(); + }; + + public render() { + const style = computeStyleSheet(); + const { navigation } = this.props; + const { userName, userImage, tenantName, isComponentOrganizationActive } = this.state; + return ( + + +
+ + + {tenantName} + + {/* {`${I18n.t("general.version")} ${DeviceInfo.getVersion()}`} (Beta) */} + {`${I18n.t('general.version')} ${DeviceInfo.getVersion()}`} + {DeviceInfo.getLastUpdateTime() && ( + {moment(DeviceInfo.getLastUpdateTime()).format('LL')} + )} +
+ + this.navigateTo('HomeNavigator', 'Home')}> + + {I18n.t('sidebar.home')} + + {isComponentOrganizationActive && ( + this.navigateTo('SitesNavigator', 'Sites')}> + + {I18n.t('sidebar.sites')} + + )} + this.navigateTo('ChargersNavigator', 'Chargers')}> + + {I18n.t('sidebar.chargers')} + + this.navigateTo('TransactionHistoryNavigator', 'TransactionsHistory')}> + + {I18n.t('sidebar.transactionsHistory')} + + this.navigateTo('TransactionInProgressNavigator', 'TransactionsInProgress')}> + + {I18n.t('sidebar.transactionsInProgress')} + + this.navigateTo('StatisticsNavigator', 'Statistics')}> + + {I18n.t('sidebar.statistics')} + + {/* navigation.navigate("Settings")} iconLeft style={style.links}> + + SETTINGS + */} + {/* navigation.navigate("Feedback")} iconLeft style={style.links}> + + FEEDBACK + */} + +
+ + + + + this.logoff()}> + {I18n.t('authentication.logOut')} + + {userName} + + + + + navigation.navigate('Profile')}> + + + + + + +
+ ); + } +} diff --git a/src/screens/sidebar/SideBarStyles.tsx b/src/screens/sidebar/SideBarStyles.tsx new file mode 100644 index 000000000..b2cef2822 --- /dev/null +++ b/src/screens/sidebar/SideBarStyles.tsx @@ -0,0 +1,130 @@ +import deepmerge from 'deepmerge'; +import { Platform } from 'react-native'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + backgroundColor: commonColor.brandPrimaryDark + }, + background: { + flex: 1 + }, + drawerContent: { + paddingTop: '5@s', + flex: 1 + }, + header: { + flexDirection: 'column', + borderColor: commonColor.inverseTextColor, + borderBottomWidth: 1, + height: '120@s', + paddingBottom: '10@s', + marginTop: Platform.OS === 'ios' ? '-5@s' : '10@s' + }, + logo: { + resizeMode: 'contain', + width: '100@s', + height: '50@s', + alignSelf: 'center', + margin: '5@s' + }, + tenantName: { + color: commonColor.inverseTextColor, + fontSize: '14@s', + margin: '2@s', + alignSelf: 'center', + textAlign: 'center', + width: '90%' + }, + versionText: { + color: commonColor.inverseTextColor, + fontSize: '14@s', + margin: '2@s', + alignSelf: 'center' + }, + versionDate: { + color: commonColor.inverseTextColor, + fontSize: '14@s', + alignSelf: 'center', + marginBottom: '2@s' + }, + linkContainer: { + paddingTop: '10@s', + paddingLeft: '10@s' + }, + links: { + borderBottomWidth: '0@s', + borderBottomColor: 'transparent', + height: Platform.OS === 'ios' ? undefined : '35@s', + paddingTop: '10@s', + paddingBottom: '10@s' + }, + linkIcon: { + fontSize: '20@s', + color: commonColor.inverseTextColor + }, + linkText: { + color: commonColor.inverseTextColor, + fontSize: '16@s', + paddingLeft: '10@s' + }, + logoutContainer: { + padding: 30, + paddingTop: '0@s' + }, + logoutButton: { + paddingTop: '10@s', + flexDirection: 'row', + borderTopWidth: 1, + borderTopColor: commonColor.inverseTextColor + }, + gridLogoutContainer: { + flex: 1, + flexDirection: 'row' + }, + columnAccount: { + flexDirection: 'column', + flexGrow: 2, + flex: 1 + }, + buttonLogout: { + alignSelf: 'flex-start', + backgroundColor: 'transparent' + }, + logoutText: { + fontWeight: 'bold', + fontSize: '14@s', + color: commonColor.inverseTextColor + }, + userName: { + paddingTop: '5@s', + fontSize: '14@s', + color: commonColor.inverseTextColor + }, + columnThumbnail: { + flex: 1, + flexDirection: 'column' + }, + buttonThumbnail: { + alignSelf: 'flex-end' + }, + profilePic: { + width: '40@s', + height: '40@s', + borderRadius: '20@s' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/site-areas/SiteAreas.tsx b/src/screens/site-areas/SiteAreas.tsx new file mode 100644 index 000000000..0c85754d3 --- /dev/null +++ b/src/screens/site-areas/SiteAreas.tsx @@ -0,0 +1,162 @@ +import I18n from 'i18n-js'; +import { Container, Spinner, View } from 'native-base'; +import React from 'react'; +import { FlatList, Platform, RefreshControl } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import HeaderComponent from '../../components/header/HeaderComponent'; +import ListEmptyTextComponent from '../../components/list/empty-text/ListEmptyTextComponent'; +import ListFooterComponent from '../../components/list/footer/ListFooterComponent'; +import SimpleSearchComponent from '../../components/search/simple/SimpleSearchComponent'; +import SiteAreaComponent from '../../components/site-area/SiteAreaComponent'; +import BaseProps from '../../types/BaseProps'; +import { DataResult } from '../../types/DataResult'; +import SiteArea from '../../types/SiteArea'; +import Constants from '../../utils/Constants'; +import Utils from '../../utils/Utils'; +import BaseAutoRefreshScreen from '../base-screen/BaseAutoRefreshScreen'; +import computeStyleSheet from './SiteAreasStyles'; + +export interface Props extends BaseProps { +} + +interface State { + siteAreas?: SiteArea[]; + loading?: boolean; + refreshing?: boolean; + skip?: number; + limit?: number; + count?: number; +} + +export default class SiteAreas extends BaseAutoRefreshScreen { + public state: State; + public props: Props; + private searchText: string; + + constructor(props: Props) { + super(props); + this.state = { + siteAreas: [], + loading: true, + refreshing: false, + skip: 0, + limit: Constants.PAGING_SIZE, + count: 0 + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public getSiteAreas = async (searchText: string, skip: number, limit: number): Promise> => { + let siteAreas:DataResult; + const siteID = Utils.getParamFromNavigation(this.props.navigation, 'siteID', null); + try { + // Get the Site Areas + siteAreas = await this.centralServerProvider.getSiteAreas({ + Search: searchText, + SiteID: siteID, + Issuer: true, + WithAvailableChargers: true + }, + { skip, limit } + ); + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'siteAreas.siteAreaUnexpectedError', this.props.navigation, this.refresh); + } + // Return + return siteAreas; + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.goBack(); + // Do not bubble up + return true; + }; + + public refresh = async () => { + // Component Mounted? + if (this.isMounted()) { + const { skip, limit } = this.state; + // Refresh All + const siteAreas = await this.getSiteAreas(this.searchText, 0, skip + limit); + // Set Site Areas + this.setState({ + loading: false, + siteAreas: siteAreas ? siteAreas.result : [], + count: siteAreas ? siteAreas.count : 0 + }); + } + }; + + public manualRefresh = async () => { + // Display spinner + this.setState({ refreshing: true }); + // Refresh + await this.refresh(); + // Hide spinner + this.setState({ refreshing: false }); + }; + + public onEndScroll = async () => { + const { count, skip, limit } = this.state; + // No reached the end? + if (skip + limit < count || count === -1) { + // No: get next sites + const siteAreas = await this.getSiteAreas(this.searchText, skip + Constants.PAGING_SIZE, limit); + // Add sites + this.setState((prevState, props) => ({ + siteAreas: [...prevState.siteAreas, ...siteAreas.result], + skip: prevState.skip + Constants.PAGING_SIZE, + refreshing: false + })); + } + }; + + public search = async (searchText: string) => { + this.searchText = searchText; + await this.refresh(); + } + + public render() { + const style = computeStyleSheet(); + const { navigation } = this.props; + const { loading, skip, count, limit } = this.state; + return ( + + navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + /> + this.search(searchText)} + navigation={navigation} + /> + + {loading ? ( + + ) : ( + } + keyExtractor={(item) => item.id} + refreshControl={} + onEndReached={this.onEndScroll} + onEndReachedThreshold={Platform.OS === 'android' ? 1 : 0.1} + ListEmptyComponent={() => } + ListFooterComponent={() => } + /> + )} + + + ); + } +} diff --git a/src/screens/site-areas/SiteAreasStyles.tsx b/src/screens/site-areas/SiteAreasStyles.tsx new file mode 100644 index 000000000..b08f1f791 --- /dev/null +++ b/src/screens/site-areas/SiteAreasStyles.tsx @@ -0,0 +1,33 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + backgroundColor: commonColor.containerBgColor + }, + content: { + flex: 1 + }, + spinner: { + flex: 1 + }, + noRecordFound: { + flex: 1, + paddingTop: '10@s', + alignSelf: 'center' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/sites/Sites.tsx b/src/screens/sites/Sites.tsx new file mode 100644 index 000000000..e6ff2a951 --- /dev/null +++ b/src/screens/sites/Sites.tsx @@ -0,0 +1,168 @@ +import I18n from 'i18n-js'; +import { Container, Spinner, View } from 'native-base'; +import React from 'react'; +import { FlatList, Platform, RefreshControl } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import HeaderComponent from '../../components/header/HeaderComponent'; +import ListEmptyTextComponent from '../../components/list/empty-text/ListEmptyTextComponent'; +import ListFooterComponent from '../../components/list/footer/ListFooterComponent'; +import SimpleSearchComponent from '../../components/search/simple/SimpleSearchComponent'; +import SiteComponent from '../../components/site/SiteComponent'; +import BaseProps from '../../types/BaseProps'; +import { DataResult } from '../../types/DataResult'; +import Site from '../../types/Site'; +import Constants from '../../utils/Constants'; +import Utils from '../../utils/Utils'; +import BaseAutoRefreshScreen from '../base-screen/BaseAutoRefreshScreen'; +import computeStyleSheet from './SitesStyles'; + +export interface Props extends BaseProps { +} + +interface State { + sites?: Site[]; + loading?: boolean; + refreshing?: boolean; + skip?: number; + limit?: number; + count?: number; +} + +export default class Sites extends BaseAutoRefreshScreen { + public state: State; + public props: Props; + private searchText: string; + + constructor(props: Props) { + super(props); + this.state = { + sites: [], + loading: true, + refreshing: false, + skip: 0, + limit: Constants.PAGING_SIZE, + count: 0 + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + // Call parent + await super.componentDidMount(); + // No Site Management: Go to chargers + const securityProvider = this.centralServerProvider.getSecurityProvider(); + if (securityProvider && !securityProvider.isComponentOrganizationActive()) { + this.props.navigation.navigate('Chargers'); + } + } + + public getSites = async (searchText = '', skip: number, limit: number): Promise> => { + let sites: DataResult; + try { + // Get the Sites + sites = await this.centralServerProvider.getSites({ + Search: searchText, + Issuer: true, + WithAvailableChargers: true + }, { skip, limit }); + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'sites.siteUnexpectedError', this.props.navigation, this.refresh); + } + // Return + return sites; + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.navigate({ routeName: 'HomeNavigator' }); + // Do not bubble up + return true; + }; + + public refresh = async () => { + // Component Mounted? + if (this.isMounted()) { + const { skip, limit } = this.state; + // Refresh All + const sites = await this.getSites(this.searchText, 0, skip + limit); + // Add sites + this.setState({ + loading: false, + count: sites ? sites.count : 0, + sites: sites ? sites.result : [] + }); + } + }; + + public manualRefresh = async () => { + // Display spinner + this.setState({ refreshing: true }); + // Refresh + await this.refresh(); + // Hide spinner + this.setState({ refreshing: false }); + }; + + public onEndScroll = async () => { + const { count, skip, limit } = this.state; + // No reached the end? + if (skip + limit < count || count === -1) { + // No: get next sites + const sites = await this.getSites(this.searchText, skip + Constants.PAGING_SIZE, limit); + // Add sites + this.setState((prevState, props) => ({ + sites: sites ? [...prevState.sites, ...sites.result] : prevState.sites, + skip: prevState.skip + Constants.PAGING_SIZE, + refreshing: false + })); + } + }; + + public search = async (searchText: string) => { + this.searchText = searchText; + await this.refresh(); + } + + public render() { + const style = computeStyleSheet(); + const { navigation } = this.props; + const { loading, skip, count, limit } = this.state; + return ( + + navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + /> + this.search(searchText)} + navigation={navigation} + /> + + {loading ? ( + + ) : ( + } + keyExtractor={(item) => item.id} + refreshControl={} + onEndReached={this.onEndScroll} + onEndReachedThreshold={Platform.OS === 'android' ? 1 : 0.1} + ListEmptyComponent={() => } + ListFooterComponent={() => } + /> + )} + + + ); + } +} diff --git a/src/screens/sites/SitesStyles.tsx b/src/screens/sites/SitesStyles.tsx new file mode 100644 index 000000000..12e81e367 --- /dev/null +++ b/src/screens/sites/SitesStyles.tsx @@ -0,0 +1,28 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + backgroundColor: commonColor.containerBgColor + }, + content: { + flex: 1 + }, + spinner: { + flex: 1 + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/statistics/Statistics.tsx b/src/screens/statistics/Statistics.tsx new file mode 100644 index 000000000..c26d06238 --- /dev/null +++ b/src/screens/statistics/Statistics.tsx @@ -0,0 +1,225 @@ +import I18n from 'i18n-js'; +import { Body, Card, CardItem, Container, Content, Icon, Left, Spinner, Text } from 'native-base'; +import React from 'react'; +import { DrawerActions } from 'react-navigation-drawer'; +import HeaderComponent from '../../components/header/HeaderComponent'; +import I18nManager from '../../I18n/I18nManager'; +import ProviderFactory from '../../provider/ProviderFactory'; +import TransactionsHistoryFilters, { TransactionsHistoryFiltersDef } from '../../screens/transactions/list/TransactionsHistoryFilters'; +import BaseProps from '../../types/BaseProps'; +import { TransactionDataResult } from '../../types/DataResult'; +import { GlobalFilters } from '../../types/Filter'; +import Constants from '../../utils/Constants'; +import SecuredStorage from '../../utils/SecuredStorage'; +import Utils from '../../utils/Utils'; +import BaseAutoRefreshScreen from '../base-screen/BaseAutoRefreshScreen'; +import computeStyleSheet from './StatisticsStyles'; + +export interface Props extends BaseProps { +} + +interface State { + loading?: boolean; + totalNumberOfSession?: number; + totalConsumptionWattHours?: number; + totalDurationSecs?: number; + totalInactivitySecs?: number; + totalPrice?: number; + priceCurrency?: string; + isPricingActive?: boolean; + showFilter?: boolean; + initialFilters?: TransactionsHistoryFiltersDef; + filters?: TransactionsHistoryFiltersDef; +} + +export default class Statistics extends BaseAutoRefreshScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + // Init State + this.state = { + loading: true, + totalNumberOfSession: 0, + totalConsumptionWattHours: 0, + totalDurationSecs: 0, + totalInactivitySecs: 0, + totalPrice: 0, + isPricingActive: false, + showFilter: false, + initialFilters: {}, + filters: {} + }; + this.setRefreshPeriodMillis(Constants.AUTO_REFRESH_LONG_PERIOD_MILLIS); + } + + public async componentDidMount() { + // Get initial filters + await this.loadInitialFilters(); + await super.componentDidMount(); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async loadInitialFilters() { + const userID = await SecuredStorage.loadFilterValue(GlobalFilters.MY_USER_FILTER); + this.setState({ + initialFilters: { userID }, + filters: { userID } + }); + } + + public refresh = async () => { + const { filters } = this.state; + // Get the provider + const centralServerProvider = await ProviderFactory.getProvider(); + const securityProvider = centralServerProvider.getSecurityProvider(); + // Get the ongoing Transaction stats + const transactionStats = await this.getTransactionsStats(); + // Set + this.setState({ + initialFilters: { + ...this.state.initialFilters, + startDateTime: filters.startDateTime ? this.state.initialFilters.startDateTime : new Date(transactionStats.stats.firstTimestamp), + endDateTime: filters.endDateTime ? this.state.initialFilters.endDateTime : new Date(transactionStats.stats.lastTimestamp), + }, + totalNumberOfSession: transactionStats.stats.count, + totalConsumptionWattHours: transactionStats.stats.totalConsumptionWattHours, + totalDurationSecs: transactionStats.stats.totalDurationSecs, + totalInactivitySecs: transactionStats.stats.totalInactivitySecs, + totalPrice: transactionStats.stats.totalPrice, + isPricingActive: securityProvider.isComponentPricingActive(), + loading: false + }); + }; + + public getTransactionsStats = async (): Promise => { + try { + // Get active transaction + const transactions = await this.centralServerProvider.getTransactions( + { + Statistics: 'history', + UserID: this.state.filters.userID, + StartDateTime: this.state.filters.startDateTime ? this.state.filters.startDateTime.toISOString() : null, + EndDateTime: this.state.filters.endDateTime ? this.state.filters.endDateTime.toISOString() : null, + }, + Constants.ONLY_RECORD_COUNT_PAGING + ); + return transactions; + } catch (error) { + // Check if HTTP? + if (!error.request || error.request.status !== 560) { + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionStatsUnexpectedError', this.props.navigation, this.refresh); + } + } + return null; + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.navigate({ routeName: 'HomeNavigator' }); + // Do not bubble up + return true; + }; + + public render = () => { + const style = computeStyleSheet(); + const { navigation } = this.props; + const { loading, totalNumberOfSession, totalConsumptionWattHours, initialFilters, filters, + totalDurationSecs, totalInactivitySecs, totalPrice, isPricingActive } = this.state; + return ( + + + this.setHeaderComponent(headerComponent)} + navigation={navigation} + title={I18n.t('home.statistics')} + leftAction={() => this.onBack()} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + filters={filters} + /> + {loading ? ( + + ) : ( + + this.setState({ filters: newFilters }, () => this.refresh())} + ref={(transactionsHistoryFilters: TransactionsHistoryFilters) => + this.setScreenFilters(transactionsHistoryFilters)} + /> + + + + + + {I18n.t('home.numberOfSessions', + { nbrSessions: I18nManager.formatNumber(totalNumberOfSession)})} + {I18n.t('home.numberOfSessionsNote')} + + + + + + + + + + {I18n.t('home.totalConsumptiom', + { totalConsumptiom: I18nManager.formatNumber(Math.round(totalConsumptionWattHours / 1000))})} + {I18n.t('home.totalConsumptiomNote')} + + + + + + + + + + {I18n.t('home.totalDuration', + { totalDuration: Utils.formatDuration(totalDurationSecs) })} + {I18n.t('home.totalDurationNote')} + + + + + + + + + + {I18n.t('home.totalInactivity', + { totalInactivity: Utils.formatDuration(totalInactivitySecs), + totalInactivityPercent: I18nManager.formatPercentage((totalInactivitySecs / totalDurationSecs)) })} + {I18n.t('home.totalInactivityNote')} + + + + + { isPricingActive && + + + + + + {I18n.t('home.totalPrice', + { totalPrice: I18nManager.formatCurrency(totalPrice) }) } + {I18n.t('home.totalPriceNote')} + + + + + } + + )} + + ); + }; +} diff --git a/src/screens/statistics/StatisticsStyles.tsx b/src/screens/statistics/StatisticsStyles.tsx new file mode 100644 index 000000000..1591d386f --- /dev/null +++ b/src/screens/statistics/StatisticsStyles.tsx @@ -0,0 +1,44 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + height: '100%', + backgroundColor: commonColor.containerBgColor + }, + spinner: { + flex: 1, + color: commonColor.textColor + }, + content: { + padding: '5@s' + }, + tabHeader: {}, + cardIcon: { + textAlign: 'center', + fontSize: '35@s', + width: '40@s' + }, + cardText: { + fontSize: '20@s', + }, + cardNote: { + fontSize: '12@s', + fontStyle: 'italic' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/transactions/TransactionsStyles.tsx b/src/screens/transactions/TransactionsStyles.tsx new file mode 100644 index 000000000..12e81e367 --- /dev/null +++ b/src/screens/transactions/TransactionsStyles.tsx @@ -0,0 +1,28 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + backgroundColor: commonColor.containerBgColor + }, + content: { + flex: 1 + }, + spinner: { + flex: 1 + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/transactions/chart/TransactionChart.tsx b/src/screens/transactions/chart/TransactionChart.tsx new file mode 100644 index 000000000..f6fddd56d --- /dev/null +++ b/src/screens/transactions/chart/TransactionChart.tsx @@ -0,0 +1,384 @@ +import I18n from 'i18n-js'; +import { Spinner, Text } from 'native-base'; +import React from 'react'; +import { processColor, View } from 'react-native'; +import { LineChart } from 'react-native-charts-wrapper'; +import { scale } from 'react-native-size-matters'; +import { DrawerActions } from 'react-navigation-drawer'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import TransactionHeaderComponent from '../../../components/transaction/header/TransactionHeaderComponent'; +import commonColor from '../../../theme/variables/commonColor'; +import BaseProps from '../../../types/BaseProps'; +import ChargingStation, { Connector } from '../../../types/ChargingStation'; +import Consumption from '../../../types/Consumption'; +import Transaction from '../../../types/Transaction'; +import Constants from '../../../utils/Constants'; +import Utils from '../../../utils/Utils'; +import BaseAutoRefreshScreen from '../../base-screen/BaseAutoRefreshScreen'; +import computeStyleSheet from './TransactionChartStyles'; + +export interface Props extends BaseProps { +} + +interface State { + loading?: boolean; + charger?: ChargingStation; + connector?: Connector; + transaction?: Transaction; + values?: Consumption[]; + consumptionValues?: ChartPoint[]; + stateOfChargeValues?: ChartPoint[]; + showTransactionDetails?: boolean; + canDisplayTransaction?: boolean; + isAdmin: boolean; + isSiteAdmin?: boolean; +} + +interface ChartPoint { + x: number; + y: number; +} + +export default class TransactionChart extends BaseAutoRefreshScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + loading: true, + isAdmin: false, + isSiteAdmin: false, + transaction: null, + values: [], + canDisplayTransaction: false, + consumptionValues: null, + stateOfChargeValues: null, + showTransactionDetails: false + }; + // Set Refresh + this.setRefreshPeriodMillis(Constants.AUTO_REFRESH_LONG_PERIOD_MILLIS); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + // tslint:disable-next-line: cyclomatic-complexity + public refresh = async () => { + // Component Mounted? + if (this.isMounted()) { + const chargerID = Utils.getParamFromNavigation(this.props.navigation, 'chargerID', null); + const connectorID = Utils.getParamFromNavigation(this.props.navigation, 'connectorID', null); + const transactionID = Utils.getParamFromNavigation(this.props.navigation, 'transactionID', null); + let transactionWithConsumptions = null; + let charger = null; + let connector = null; + // Get Transaction and Charger + if (transactionID) { + transactionWithConsumptions = await this.getTransactionWithConsumptions(parseInt(transactionID, 10)); + if (transactionWithConsumptions && transactionWithConsumptions.transaction) { + charger = await this.getCharger(transactionWithConsumptions.transaction.chargeBoxID); + if (charger) { + connector = charger ? charger.connectors[transactionWithConsumptions.transaction.connectorId - 1] : null; + } + } + // Get Charger and Transaction + } else if (chargerID) { + // Get Charger + charger = await this.getCharger(chargerID); + if (charger) { + connector = charger ? charger.connectors[parseInt(connectorID, 10) - 1] : null; + // Refresh Consumption + if (connector.activeTransactionID && (!this.state.transaction || !this.state.transaction.stop)) { + transactionWithConsumptions = await this.getTransactionWithConsumptions(connector.activeTransactionID); + } + } + } + // Get the provider + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Set + this.setState({ + loading: false, + transaction: transactionWithConsumptions ? transactionWithConsumptions.transaction : this.state.transaction, + charger: !this.state.charger ? charger : this.state.charger, + connector, + isAdmin: securityProvider ? securityProvider.isAdmin() : false, + isSiteAdmin: securityProvider && charger && charger.siteArea ? securityProvider.isSiteAdmin(charger.siteArea.siteID) : false, + canDisplayTransaction: charger ? this.canDisplayTransaction( + transactionWithConsumptions ? transactionWithConsumptions.transaction : null, charger, connector) : false, + ...transactionWithConsumptions + }); + } + }; + + public getCharger = async (chargerID: string): Promise => { + try { + // Get Charger + const charger = await this.centralServerProvider.getCharger({ ID: chargerID }); + return charger; + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'chargers.chargerUnexpectedError', this.props.navigation, this.refresh); + } + return null; + }; + + public getTransactionWithConsumptions = async (transactionID: number): + Promise<{ transaction: Transaction; values: Consumption[], consumptionValues: ChartPoint[], stateOfChargeValues: ChartPoint[] }> => { + try { + // Active Transaction? + if (transactionID) { + // Get the consumption + const transaction = await this.centralServerProvider.getTransactionWithConsumption({ + TransactionId: transactionID + }); + // At least 2 values for the chart!!! + if (transaction.values && transaction.values.length > 1) { + // Convert + const consumptionValues: ChartPoint[] = []; + const stateOfChargeValues: ChartPoint[] = []; + for (const value of transaction.values) { + const date = new Date(value.date).getTime(); + // Add + consumptionValues.push({ + x: date, + y: value.instantPower ? value.instantPower / 1000 : 0 + }); + if (value.stateOfCharge > 0) { + stateOfChargeValues.push({ + x: date, + y: value.stateOfCharge ? value.stateOfCharge : 0 + }); + } + } + // Set + return { + transaction, + values: transaction.values, + consumptionValues, + stateOfChargeValues + }; + } + } + } catch (error) { + // Check if HTTP? + if (!error.request || error.request.status !== 560) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionUnexpectedError', this.props.navigation, this.refresh); + } + } + // Clear + return { + transaction: null, + values: null, + consumptionValues: null, + stateOfChargeValues: null + }; + }; + + public canDisplayTransaction = (transaction: Transaction, charger: ChargingStation, connector: Connector): boolean => { + // Transaction? + if (charger) { + // Get the Security Provider + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Check Auth + return securityProvider.canReadTransaction(charger.siteArea, transaction ? transaction.tagID : connector.activeTagID); + } + return false; + }; + + public createChart(consumptionValues: ChartPoint[], stateOfChargeValues: ChartPoint[]) { + const chartDefinition: any = {}; + // Add Data + chartDefinition.data = { dataSets: [] }; + // Check Consumptions + if (consumptionValues && consumptionValues.length > 1) { + chartDefinition.data.dataSets.push({ + values: consumptionValues, + label: I18n.t('details.instantPowerChartLabel'), + config: { + mode: 'LINEAR', + drawValues: false, + lineWidth: 2, + drawCircles: false, + circleColor: processColor(commonColor.brandInfo), + drawCircleHole: false, + circleRadius: 5, + highlightColor: processColor('white'), + color: processColor(commonColor.brandInfo), + drawFilled: true, + fillAlpha: 65, + fillColor: processColor(commonColor.brandInfo), + valueTextSize: scale(8) + } + }); + } + // Check SoC + if (stateOfChargeValues && stateOfChargeValues.length > 1) { + chartDefinition.data.dataSets.push({ + values: stateOfChargeValues, + label: I18n.t('details.batteryChartLabel'), + config: { + axisDependency: 'RIGHT', + mode: 'LINEAR', + drawValues: false, + lineWidth: 2, + drawCircles: false, + circleColor: processColor(commonColor.brandSuccess), + drawCircleHole: false, + circleRadius: 5, + highlightColor: processColor('white'), + color: processColor(commonColor.brandSuccess), + drawFilled: true, + fillAlpha: 65, + fillColor: processColor(commonColor.brandSuccess), + valueTextSize: scale(8) + } + }); + } + // X Axis + chartDefinition.xAxis = { + enabled: true, + labelRotationAngle: -45, + granularity: 1, + drawLabels: true, + position: 'BOTTOM', + drawAxisLine: true, + drawGridLines: false, + fontFamily: 'HelveticaNeue-Medium', + fontWeight: 'bold', + valueFormatter: 'date', + valueFormatterPattern: 'HH:mm', + textSize: scale(8), + textColor: processColor(commonColor.brandInfo) + }; + // Y Axis + chartDefinition.yAxis = {}; + // Check Consumptions + if (consumptionValues && consumptionValues.length > 1) { + chartDefinition.yAxis.left = { + enabled: true, + valueFormatter: '##0 kW', + axisMinimum: 0, + textColor: processColor(commonColor.brandInfo), + textSize: scale(8) + // limitLines: [{ + // limit: connector.power, + // label: I18n.t("details.connectorMax"), + // valueTextColor: processColor("white"), + // lineColor: processColor(commonColor.brandDanger), + // lineDashPhase: 2, + // lineWidth: 1, + // lineDashLengths: [10,10] + // }] + }; + } else { + chartDefinition.yAxis.left = { + enabled: false + }; + } + // Check SoC + if (stateOfChargeValues && stateOfChargeValues.length > 1) { + chartDefinition.yAxis.right = { + enabled: true, + valueFormatter: '##0', + axisMinimum: 0, + axisMaximum: 100, + textColor: processColor(commonColor.brandSuccess), + textSize: scale(8) + }; + } else { + chartDefinition.yAxis.right = { + enabled: false + }; + } + // Return + return chartDefinition; + } + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.goBack(null); + // Do not bubble up + return true; + }; + + public render() { + const { navigation } = this.props; + const style = computeStyleSheet(); + const { showTransactionDetails, isAdmin, isSiteAdmin, loading, transaction, charger, + connector, consumptionValues, stateOfChargeValues, canDisplayTransaction } = this.state; + const chartDefinition = this.createChart(consumptionValues, stateOfChargeValues); + const connectorLetter = Utils.getConnectorLetterFromConnectorID(connector ? connector.connectorId : null); + return ( + loading ? ( + + ) : ( + + this.onBack()} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + /> + {showTransactionDetails && transaction && ( + + )} + {transaction && consumptionValues && consumptionValues.length > 1 && canDisplayTransaction ? ( + + ) : ( + transaction || (connector && connector.activeTransactionID) ? + canDisplayTransaction ? + {I18n.t('details.noData')} + : + {I18n.t('details.notAuthorized')} + : + {I18n.t('details.noSessionInProgress')} + )} + + ) + ); + } +} diff --git a/src/screens/transactions/chart/TransactionChartStyles.tsx b/src/screens/transactions/chart/TransactionChartStyles.tsx new file mode 100644 index 000000000..b98a58c4f --- /dev/null +++ b/src/screens/transactions/chart/TransactionChartStyles.tsx @@ -0,0 +1,71 @@ +import deepmerge from 'deepmerge'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + backgroundColor: commonColor.containerBgColor, + paddingBottom: '5@s' + }, + spinner: { + flex: 1, + justifyContent: 'center', + color: commonColor.textColor + }, + chart: { + height: '87%' + }, + chartWithHeader: { + height: '78%' + }, + notAuthorizedContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center' + }, + header: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + padding: '8@s', + backgroundColor: commonColor.headerBgColorLight + }, + headerValue: { + fontSize: '18@s', + fontWeight: 'bold' + }, + subHeaderName: { + color: commonColor.headerTextColor, + fontSize: '15@s', + width: '49%' + }, + subHeaderNameLeft: {}, + subHeaderNameRight: { + textAlign: 'right' + }, + notData: { + marginTop: '20@s', + fontSize: '14@s', + textAlign: 'center' + } +}); + +const portraitStyles = {}; + +const landscapeStyles = { + chart: { + height: '82%' + }, + chartWithHeader: { + height: '73%' + }, +}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/transactions/details/TransactionDetails.tsx b/src/screens/transactions/details/TransactionDetails.tsx new file mode 100644 index 000000000..0a9e53f98 --- /dev/null +++ b/src/screens/transactions/details/TransactionDetails.tsx @@ -0,0 +1,300 @@ +import I18n from 'i18n-js'; +import moment from 'moment'; +import { Container, Icon, Spinner, Text, Thumbnail, View } from 'native-base'; +import React from 'react'; +import { Image, ScrollView } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import noPhotoActive from '../../../../assets/no-photo-active.png'; +import noPhoto from '../../../../assets/no-photo.png'; +import noSite from '../../../../assets/no-site.png'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseProps from '../../../types/BaseProps'; +import Transaction from '../../../types/Transaction'; +import User from '../../../types/User'; +import Constants from '../../../utils/Constants'; +import Message from '../../../utils/Message'; +import Utils from '../../../utils/Utils'; +import BaseScreen from '../../base-screen/BaseScreen'; +import computeStyleSheet from './TransactionDetailsStyles'; + +export interface Props extends BaseProps { +} + +interface State { + loading?: boolean; + transaction?: Transaction; + userImage?: string; + siteImage?: string; + elapsedTimeFormatted?: string; + totalInactivitySecs?: number; + inactivityFormatted?: string; + startTransactionNbTrial?: number; + isPricingActive?: boolean; + buttonDisabled?: boolean; + refreshing?: boolean; + isAdmin?: boolean; + isSiteAdmin?: boolean; +} + +export default class TransactionDetails extends BaseScreen { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + loading: true, + userImage: null, + siteImage: null, + isAdmin: false, + isSiteAdmin: false, + elapsedTimeFormatted: '-', + totalInactivitySecs: 0, + inactivityFormatted: '-', + startTransactionNbTrial: 0, + isPricingActive: false, + buttonDisabled: true, + refreshing: false + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async componentDidMount() { + await super.componentDidMount(); + let siteImage = null; + let userImage = null; + // Get IDs + const transactionID = Utils.getParamFromNavigation(this.props.navigation, 'transactionID', null); + // Get Transaction + const transaction = await this.getTransaction(transactionID); + // Get the Site Image + if (transaction && transaction.siteID && this.isMounted()) { + siteImage = await this.getSiteImage(transaction.siteID); + } + // Get the User Image + if (transaction && transaction.user && this.isMounted()) { + userImage = await this.getUserImage(transaction.user); + } + // Compute Duration + this.computeDurationInfos(transaction); + // Get the provider + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Set + this.setState({ + transaction, + loading: false, + siteImage, + userImage, + isAdmin: securityProvider ? securityProvider.isAdmin() : false, + isSiteAdmin: securityProvider && transaction && transaction.siteID ? securityProvider.isSiteAdmin(transaction.siteID) : false, + isPricingActive: securityProvider.isComponentPricingActive() + }); + } + + public getTransaction = async (transactionID: string): Promise => { + try { + // Get Transaction + const transaction = await this.centralServerProvider.getTransaction({ ID: transactionID }); + return transaction; + } catch (error) { + switch (error.request.status) { + case 550: + Message.showError(I18n.t('transactions.transactionDoesNotExist')); + break; + default: + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionUnexpectedError', this.props.navigation); + } + } + return null; + }; + + public getSiteImage = async (siteID: string): Promise => { + try { + const siteImage = await this.centralServerProvider.getSiteImage(siteID); + return siteImage; + } catch (error) { + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'sites.siteUnexpectedError', this.props.navigation); + } + return null; + }; + + public getUserImage = async (user: User): Promise => { + try { + const userImage = await this.centralServerProvider.getUserImage({ ID: user.id }); + return userImage; + } catch (error) { + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'users.userUnexpectedError', this.props.navigation); + } + return null; + }; + + public computeDurationInfos = (transaction: Transaction) => { + if (transaction) { + // Compute duration + const elapsedTimeFormatted = Utils.formatDurationHHMMSS( + ((new Date(transaction.stop.timestamp).getTime() - new Date(transaction.timestamp).getTime()) / 1000), false); + // Compute Inactivity + const totalInactivitySecs = transaction.stop.totalInactivitySecs + + (transaction.stop.extraInactivitySecs ? transaction.stop.extraInactivitySecs : 0); + const inactivityFormatted = Utils.formatDurationHHMMSS(totalInactivitySecs, false); + // Set + this.setState({ + totalInactivitySecs, + elapsedTimeFormatted, + inactivityFormatted + }); + } else { + // Set + this.setState({ + totalInactivitySecs: 0, + elapsedTimeFormatted: Constants.DEFAULT_DURATION, + inactivityFormatted: Constants.DEFAULT_DURATION + }); + } + }; + + public renderUserInfo = (style: any) => { + const { transaction, isAdmin, isSiteAdmin } = this.state; + const { userImage } = this.state; + return transaction ? ( + + + + {Utils.buildUserName(transaction.user)} + + {(isAdmin || isSiteAdmin) && ({transaction.tagID})} + + ) : ( + + + - + + ); + }; + + public renderPrice = (style: any) => { + const { transaction } = this.state; + return ( + + + {transaction ? I18nManager.formatCurrency(transaction.stop.price) : '-'} + ({transaction ? transaction.priceUnit : '-'}) + + ); + }; + + public renderElapsedTime = (style: any) => { + const { elapsedTimeFormatted } = this.state; + return ( + + + {elapsedTimeFormatted} + {I18n.t('details.duration')} + + ); + }; + + public renderInactivity = (style: any) => { + const { transaction } = this.state; + const { inactivityFormatted } = this.state; + const inactivityStyle = Utils.computeInactivityStyle(transaction ? transaction.stop.inactivityStatus : null); + return ( + + + {inactivityFormatted} + {I18n.t('details.duration')} + + ); + }; + + public renderTotalConsumption = (style: any) => { + const { transaction } = this.state; + return ( + + + {transaction ? I18nManager.formatNumber(Math.round(transaction.stop.totalConsumption / 10) / 100) : '-'} + {I18n.t('details.total')} (kW.h) + + ); + }; + + public renderBatteryLevel = (style: any) => { + const { transaction } = this.state; + return transaction && transaction.stateOfCharge ? ( + + + {transaction.stateOfCharge} > {transaction.stop.stateOfCharge} + (%) + + ) : ( + + + - + + ); + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.goBack(null); + // Do not bubble up + return true; + }; + + public render() { + const { navigation } = this.props; + const style = computeStyleSheet(); + const { transaction } = this.state; + const { loading, siteImage, isPricingActive } = this.state; + const connectorLetter = Utils.getConnectorLetterFromConnectorID(transaction ? transaction.connectorId : null); + return ( + loading ? ( + + ) : ( + + this.onBack()} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + /> + {/* Site Image */} + + + + {transaction ? moment(new Date(transaction.timestamp)).format('LLL') : ''} + ({transaction ? moment(new Date(transaction.stop.timestamp)).format('LLL') : ''}) + {(transaction.userID !== transaction.stop.userID) && + ({I18n.t('details.stoppedBy')} {Utils.buildUserName(transaction.stop.user)}) + } + + + + + {this.renderUserInfo(style)} + {this.renderTotalConsumption(style)} + + + {this.renderElapsedTime(style)} + {this.renderInactivity(style)} + + + {this.renderBatteryLevel(style)} + {isPricingActive ? this.renderPrice(style) : } + + + + ) + ); + } +} diff --git a/src/screens/transactions/details/TransactionDetailsStyles.tsx b/src/screens/transactions/details/TransactionDetailsStyles.tsx new file mode 100644 index 000000000..504542e36 --- /dev/null +++ b/src/screens/transactions/details/TransactionDetailsStyles.tsx @@ -0,0 +1,149 @@ +import deepmerge from 'deepmerge'; +import { Platform } from 'react-native'; +import ResponsiveStylesheet from 'react-native-responsive-stylesheet' +import { ScaledSheet } from 'react-native-size-matters'; +import commonColor from '../../../theme/variables/commonColor'; + +const commonStyles = ScaledSheet.create({ + container: { + flex: 1, + flexDirection: 'column', + justifyContent: 'flex-start', + alignItems: 'center', + backgroundColor: commonColor.containerBgColor + }, + spinner: { + flex: 1, + color: commonColor.textColor + }, + backgroundImage: { + width: '100%', + height: '125@s' + }, + transactionContainer: { + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'transparent' + }, + headerContent: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + padding: '5@s', + borderBottomWidth: 1, + borderBottomColor: commonColor.listBorderColor, + backgroundColor: commonColor.headerBgColor + }, + headerRowContainer: { + width: '100%', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center' + }, + headerName: { + color: commonColor.headerTextColor, + fontSize: '18@s', + marginLeft: '5@s', + marginRight: '5@s', + fontWeight: 'bold' + }, + subHeaderName: { + color: commonColor.headerTextColor, + fontSize: '14@s', + marginLeft: '5@s', + marginRight: '5@s', + }, + subSubHeaderName: { + color: commonColor.headerTextColor, + fontSize: '12@s', + marginLeft: '5@s', + marginRight: '5@s', + }, + scrollViewContainer: { + flex: 1, + flexDirection: 'column', + justifyContent: 'space-evenly', + alignItems: 'center' + }, + rowContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + height: '100@s' + }, + columnContainer: { + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '50%' + }, + connectorLetter: { + marginTop: '5@s', + marginBottom: '5@s' + }, + label: { + fontSize: '16@s', + color: commonColor.brandPrimaryDark, + alignSelf: 'center' + }, + labelValue: { + fontSize: '25@s', + fontWeight: 'bold' + }, + labelUser: { + fontSize: '10@s' + }, + subLabel: { + fontSize: '10@s', + marginTop: Platform.OS === 'ios' ? '0@s' : '-5@s', + color: commonColor.brandPrimaryDark, + alignSelf: 'center' + }, + subLabelStatusError: { + color: commonColor.brandDanger, + marginTop: '2@s' + }, + subLabelUser: { + fontSize: '8@s', + marginTop: '0@s' + }, + icon: { + fontSize: '25@s' + }, + userImage: { + height: '52@s', + width: '52@s', + alignSelf: 'center', + marginBottom: '5@s', + borderRadius: '26@s', + borderWidth: '3@s', + borderColor: commonColor.textColor + }, + info: { + color: commonColor.brandPrimaryDark, + borderColor: commonColor.brandPrimaryDark + }, + success: { + color: commonColor.brandSuccess + }, + warning: { + color: commonColor.brandWarning + }, + danger: { + color: commonColor.brandDanger + }, + disabled: { + color: commonColor.buttonDisabledBg, + borderColor: commonColor.buttonDisabledBg + } +}); + +const portraitStyles = {}; + +const landscapeStyles = {}; + +export default function computeStyleSheet(): any { + return ResponsiveStylesheet.createOriented({ + landscape: deepmerge(commonStyles, landscapeStyles), + portrait: deepmerge(commonStyles, portraitStyles) + }); +} diff --git a/src/screens/transactions/in-progress/TransactionsInProgress.tsx b/src/screens/transactions/in-progress/TransactionsInProgress.tsx new file mode 100644 index 000000000..98bb39966 --- /dev/null +++ b/src/screens/transactions/in-progress/TransactionsInProgress.tsx @@ -0,0 +1,216 @@ +import I18n from 'i18n-js'; +import { Container, Spinner, View } from 'native-base'; +import React from 'react'; +import { FlatList, Platform, RefreshControl } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import ListEmptyTextComponent from '../../../components/list/empty-text/ListEmptyTextComponent'; +import ListFooterComponent from '../../../components/list/footer/ListFooterComponent'; +import TransactionInProgressComponent from '../../../components/transaction/in-progress/TransactionInProgressComponent'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseProps from '../../../types/BaseProps'; +import { DataResult } from '../../../types/DataResult'; +import { GlobalFilters } from '../../../types/Filter'; +import Transaction from '../../../types/Transaction'; +import Constants from '../../../utils/Constants'; +import SecuredStorage from '../../../utils/SecuredStorage'; +import Utils from '../../../utils/Utils'; +import BaseAutoRefreshScreen from '../../base-screen/BaseAutoRefreshScreen'; +import computeStyleSheet from '../TransactionsStyles'; +import TransactionsInProgressFilters, { TransactionsInProgressFiltersDef } from './TransactionsInProgressFilters'; + +export interface Props extends BaseProps { +} + +interface State { + transactions?: Transaction[]; + loading?: boolean; + refreshing?: boolean; + skip?: number; + limit?: number; + count?: number; + isPricingActive: boolean; + isAdmin?: boolean; + hasSiteAdmin: boolean; + initialFilters?: TransactionsInProgressFiltersDef; + filters?: TransactionsInProgressFiltersDef; +} + +export default class TransactionsInProgress extends BaseAutoRefreshScreen { + public state: State; + public props: Props; + private searchText: string; + + constructor(props: Props) { + super(props); + // Init State + this.state = { + transactions: [], + loading: true, + refreshing: false, + skip: 0, + limit: Constants.PAGING_SIZE, + count: 0, + isPricingActive: false, + isAdmin: false, + hasSiteAdmin: false, + initialFilters: {}, + filters: {} + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async loadInitialFilters() { + const userID = await SecuredStorage.loadFilterValue(GlobalFilters.MY_USER_FILTER); + this.setState({ + initialFilters: { userID }, + filters: { userID } + }); + } + + public async componentDidMount() { + // Get initial filters + await this.loadInitialFilters(); + await super.componentDidMount(); + } + + public getTransactionsInProgress = async (searchText: string, skip: number, limit: number): Promise> => { + try { + // Get the Transactions + const transactions = await this.centralServerProvider.getTransactionsActive({ + UserID: this.state.filters.userID, + Search: searchText + }, { skip, limit }); + // Check + if (transactions.count === -1) { + // Request nbr of records + const transactionsNbrRecordsOnly = await this.centralServerProvider.getTransactionsActive({ + UserID: this.state.filters.userID, + Search: searchText + }, Constants.ONLY_RECORD_COUNT_PAGING); + // Set + transactions.count = transactionsNbrRecordsOnly.count; + } + return transactions; + } catch (error) { + // Other common Error + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionUnexpectedError', this.props.navigation, this.refresh); + } + return null; + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.navigate({ routeName: 'HomeNavigator' }); + // Do not bubble up + return true; + }; + + public manualRefresh = async () => { + // Display spinner + this.setState({ refreshing: true }); + // Refresh + await this.refresh(); + // Hide spinner + this.setState({ refreshing: false }); + }; + + public refresh = async () => { + // Component Mounted? + if (this.isMounted()) { + const { skip, limit } = this.state; + // Refresh All + const transactions = await this.getTransactionsInProgress(this.searchText, 0, skip + limit); + // Refresh Admin + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Set + this.setState({ + loading: false, + transactions: transactions ? transactions.result : [], + count: transactions ? transactions.count : 0, + isAdmin: securityProvider ? securityProvider.isAdmin() : false, + hasSiteAdmin: securityProvider ? securityProvider.hasSiteAdmin() : false, + isPricingActive: securityProvider.isComponentPricingActive() + }); + } + }; + + public onEndScroll = async () => { + const { count, skip, limit } = this.state; + // No reached the end? + if (skip + limit < count || count === -1) { + // No: get next sites + const transactions = await this.getTransactionsInProgress(this.searchText, skip + Constants.PAGING_SIZE, limit); + // Add sites + this.setState((prevState) => ({ + transactions: transactions ? [...prevState.transactions, ...transactions.result] : prevState.transactions, + skip: prevState.skip + Constants.PAGING_SIZE, + refreshing: false + })); + } + }; + + public search = async (searchText: string) => { + this.searchText = searchText; + await this.refresh(); + } + + public render = () => { + const style = computeStyleSheet(); + const { navigation } = this.props; + const { loading, isAdmin, hasSiteAdmin, transactions, isPricingActive, + skip, count, limit, initialFilters, filters } = this.state; + return ( + + + this.setHeaderComponent(headerComponent)} + navigation={navigation} + title={I18n.t('transactions.transactionsInProgress')} + subTitle={count > 0 ? `${I18nManager.formatNumber(count)} ${I18n.t('transactions.transactions')}` : null} + leftAction={this.onBack} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + filters={filters} + /> + {loading ? ( + + ) : ( + + {(isAdmin || hasSiteAdmin) && + this.setState({ filters: newFilters }, () => this.refresh())} + ref={(transactionsInProgressFilters: TransactionsInProgressFilters) => + this.setScreenFilters(transactionsInProgressFilters)} + /> + } + ( + + )} + keyExtractor={(item) => `${item.id}`} + refreshControl={} + onEndReached={this.onEndScroll} + onEndReachedThreshold={Platform.OS === 'android' ? 1 : 0.1} + ListFooterComponent={() => } + ListEmptyComponent={() => } + /> + + )} + + ); + }; +} diff --git a/src/screens/transactions/in-progress/TransactionsInProgressFilters.tsx b/src/screens/transactions/in-progress/TransactionsInProgressFilters.tsx new file mode 100644 index 000000000..209b409a7 --- /dev/null +++ b/src/screens/transactions/in-progress/TransactionsInProgressFilters.tsx @@ -0,0 +1,76 @@ +import I18n from 'i18n-js'; +import { View } from 'native-base'; +import React from 'react'; +import FilterVisibleContainerComponent from '../../../components/search/filter/containers/FilterVisibleContainerComponent'; +import MyUserSwitchFilterControlComponent from '../../../components/search/filter/controls/my-user-switch/MyUserSwitchFilterControlComponent'; +import ScreenFilters, { ScreenFiltersState } from '../../../components/search/filter/screen/ScreenFilters'; +import { GlobalFilters } from '../../../types/Filter'; + +export interface Props { + onFilterChanged?: (filters: TransactionsInProgressFiltersDef) => void; + initialFilters?: TransactionsInProgressFiltersDef; +} + +export interface TransactionsInProgressFiltersDef { + userID?: string; +} + +interface State extends ScreenFiltersState { + filters?: TransactionsInProgressFiltersDef; +} + +export default class TransactionsInProgressFilters extends ScreenFilters { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + filters: {} + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public onFilterChanged = (newFilters: TransactionsInProgressFiltersDef, applyFilters: boolean) => { + const { onFilterChanged } = this.props; + if (applyFilters) { + this.setState({ + filters: { ...this.state.filters, ...newFilters } + }, () => onFilterChanged(newFilters)); + } else { + this.setState({ + filters: { ...this.state.filters, ...newFilters } + }); + } + } + + public render = () => { + const { initialFilters } = this.props; + const { filters, isAdmin, hasSiteAdmin } = this.state; + return ( + + {(isAdmin || hasSiteAdmin) && + + this.setFilterVisibleContainerComponent(filterVisibleContainerComponent)} + > + + this.getFilterVisibleContainerComponent().setFilter(id, value)} + ref={(myUserSwitchFilterControlComponent: MyUserSwitchFilterControlComponent) => + this.addVisibleFilter(myUserSwitchFilterControlComponent)} + /> + + } + + ); + } +} diff --git a/src/screens/transactions/list/TransactionsHistory.tsx b/src/screens/transactions/list/TransactionsHistory.tsx new file mode 100644 index 000000000..a116796e9 --- /dev/null +++ b/src/screens/transactions/list/TransactionsHistory.tsx @@ -0,0 +1,234 @@ +import I18n from 'i18n-js'; +import { Container, Spinner, View } from 'native-base'; +import React from 'react'; +import { FlatList, Platform, RefreshControl } from 'react-native'; +import { DrawerActions } from 'react-navigation-drawer'; +import HeaderComponent from '../../../components/header/HeaderComponent'; +import ListEmptyTextComponent from '../../../components/list/empty-text/ListEmptyTextComponent'; +import ListFooterComponent from '../../../components/list/footer/ListFooterComponent'; +import SimpleSearchComponent from '../../../components/search/simple/SimpleSearchComponent'; +import TransactionHistoryComponent from '../../../components/transaction/history/TransactionHistoryComponent'; +import I18nManager from '../../../I18n/I18nManager'; +import BaseProps from '../../../types/BaseProps'; +import { TransactionDataResult } from '../../../types/DataResult'; +import { GlobalFilters } from '../../../types/Filter'; +import Transaction from '../../../types/Transaction'; +import Constants from '../../../utils/Constants'; +import SecuredStorage from '../../../utils/SecuredStorage'; +import Utils from '../../../utils/Utils'; +import BaseAutoRefreshScreen from '../../base-screen/BaseAutoRefreshScreen'; +import computeStyleSheet from '../TransactionsStyles'; +import TransactionsHistoryFilters, { TransactionsHistoryFiltersDef } from './TransactionsHistoryFilters'; + +export interface Props extends BaseProps { +} + +interface State { + transactions?: Transaction[]; + loading?: boolean, + refreshing?: boolean; + skip?: number; + limit?: number; + count?: number; + isPricingActive?: boolean; + isAdmin?: boolean; + initialFilters?: TransactionsHistoryFiltersDef; + filters?: TransactionsHistoryFiltersDef; +} + +export default class TransactionsHistory extends BaseAutoRefreshScreen { + public state: State; + public props: Props; + private searchText: string; + + constructor(props: Props) { + super(props); + // Init State + this.state = { + transactions: [], + loading: true, + refreshing: false, + skip: 0, + limit: Constants.PAGING_SIZE, + count: 0, + isPricingActive: false, + isAdmin: false, + initialFilters: {}, + filters: {} + }; + // Set refresh period + this.setRefreshPeriodMillis(Constants.AUTO_REFRESH_LONG_PERIOD_MILLIS); + } + + public async componentDidMount() { + // Get initial filters + await this.loadInitialFilters(); + await super.componentDidMount(); + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public async loadInitialFilters() { + const userID = await SecuredStorage.loadFilterValue(GlobalFilters.MY_USER_FILTER); + this.setState({ + initialFilters: { userID }, + filters: { userID } + }); + } + + public getTransactions = async (searchText: string, skip: number, limit: number): Promise => { + try { + // Get active transaction + const transactions = await this.centralServerProvider.getTransactions({ + Statistics: 'history', + UserID: this.state.filters.userID, + StartDateTime: this.state.filters.startDateTime ? this.state.filters.startDateTime.toISOString() : null, + EndDateTime: this.state.filters.endDateTime ? this.state.filters.endDateTime.toISOString() : null, + Search: searchText + }, { skip, limit }); + // Check + if (transactions.count === -1) { + // Request nbr of records + const transactionsNbrRecordsOnly = await this.centralServerProvider.getTransactions({ + Statistics: 'history', + UserID: this.state.filters.userID, + StartDateTime: this.state.filters.startDateTime ? this.state.filters.startDateTime.toISOString() : null, + EndDateTime: this.state.filters.endDateTime ? this.state.filters.endDateTime.toISOString() : null, + Search: searchText + }, Constants.ONLY_RECORD_COUNT_PAGING); + // Set + transactions.count = transactionsNbrRecordsOnly.count; + transactions.stats = transactionsNbrRecordsOnly.stats; + } + return transactions; + } catch (error) { + // Check if HTTP? + if (!error.request || error.request.status !== 560) { + Utils.handleHttpUnexpectedError(this.centralServerProvider, error, + 'transactions.transactionUnexpectedError', this.props.navigation, this.refresh); + } + } + return null; + }; + + public onBack = () => { + // Back mobile button: Force navigation + this.props.navigation.navigate({ routeName: 'HomeNavigator' }); + // Do not bubble up + return true; + }; + + public manualRefresh = async () => { + // Display spinner + this.setState({ refreshing: true }); + // Refresh + await this.refresh(); + // Hide spinner + this.setState({ refreshing: false }); + }; + + public refresh = async () => { + // Component Mounted? + if (this.isMounted()) { + const { skip, limit, filters } = this.state; + // Set + const securityProvider = this.centralServerProvider.getSecurityProvider(); + // Refresh All + const transactions = await this.getTransactions(this.searchText, 0, skip + limit); + // Set + this.setState({ + loading: false, + transactions: transactions ? transactions.result : [], + initialFilters: { + ...this.state.initialFilters, + startDateTime: filters.startDateTime ? this.state.initialFilters.startDateTime : new Date(transactions.stats.firstTimestamp), + endDateTime: filters.endDateTime ? this.state.initialFilters.endDateTime : new Date(transactions.stats.lastTimestamp), + }, + count: transactions ? transactions.count : 0, + isAdmin: securityProvider ? securityProvider.isAdmin() : false, + isPricingActive: securityProvider ? securityProvider.isComponentPricingActive() : false + }); + } + }; + + public onEndScroll = async () => { + const { count, skip, limit } = this.state; + // No reached the end? + if (skip + limit < count || count === -1) { + // No: get next sites + const transactions = await this.getTransactions(this.searchText, skip + Constants.PAGING_SIZE, limit); + // Add sites + this.setState((prevState) => ({ + transactions: transactions ? [...prevState.transactions, ...transactions.result] : prevState.transactions, + skip: prevState.skip + Constants.PAGING_SIZE, + refreshing: false + })); + } + }; + + public search = async (searchText: string) => { + this.searchText = searchText; + await this.refresh(); + } + + public render = () => { + const style = computeStyleSheet(); + const { navigation } = this.props; + const { loading, isAdmin, transactions, isPricingActive, + skip, count, limit, initialFilters, filters } = this.state; + return ( + + { + this.setHeaderComponent(headerComponent); + }} + navigation={navigation} + title={I18n.t('transactions.transactionsHistory')} + subTitle={count > 0 ? `${I18nManager.formatNumber(count)} ${I18n.t('transactions.transactions')}` : null} + leftAction={this.onBack} + leftActionIcon={'navigate-before'} + rightAction={() => navigation.dispatch(DrawerActions.openDrawer())} + rightActionIcon={'menu'} + filters={filters} + /> + this.search(searchText)} + navigation={navigation} + /> + {loading ? ( + + ) : ( + + + this.setState({ filters: newFilters }, () => this.refresh())} + ref={(transactionsHistoryFilters: TransactionsHistoryFilters) => + this.setScreenFilters(transactionsHistoryFilters)} + /> + ( + + )} + keyExtractor={(item) => `${item.id}`} + refreshControl={} + onEndReached={this.onEndScroll} + onEndReachedThreshold={Platform.OS === 'android' ? 1 : 0.1} + ListFooterComponent={() => } + ListEmptyComponent={() => } + /> + + )} + + ); + }; +} diff --git a/src/screens/transactions/list/TransactionsHistoryFilters.tsx b/src/screens/transactions/list/TransactionsHistoryFilters.tsx new file mode 100644 index 000000000..6f0237fc9 --- /dev/null +++ b/src/screens/transactions/list/TransactionsHistoryFilters.tsx @@ -0,0 +1,125 @@ +import I18n from 'i18n-js'; +import moment from 'moment'; +import { View } from 'native-base'; +import React from 'react'; +import FilterModalContainerComponent from '../../../components/search/filter/containers/FilterModalContainerComponent'; +import FilterVisibleContainerComponent from '../../../components/search/filter/containers/FilterVisibleContainerComponent'; +import DateFilterControlComponent from '../../../components/search/filter/controls/date/DateFilterControlComponent'; +import MyUserSwitchFilterControlComponent from '../../../components/search/filter/controls/my-user-switch/MyUserSwitchFilterControlComponent'; +import ScreenFilters, { ScreenFiltersState } from '../../../components/search/filter/screen/ScreenFilters'; +import { GlobalFilters } from '../../../types/Filter'; + +export interface Props { + onFilterChanged?: (filters: TransactionsHistoryFiltersDef) => void; + initialFilters?: TransactionsHistoryFiltersDef; +} + +export interface TransactionsHistoryFiltersDef { + startDateTime?: Date; + endDateTime?: Date; + userID?: string; +} + +interface State extends ScreenFiltersState { + filters?: TransactionsHistoryFiltersDef; +} + +export default class TransactionsHistoryFilters extends ScreenFilters { + public state: State; + public props: Props; + + constructor(props: Props) { + super(props); + this.state = { + filters: {} + }; + } + + public setState = (state: State | ((prevState: Readonly, props: Readonly) => State | Pick) | Pick, callback?: () => void) => { + super.setState(state, callback); + } + + public onFilterChanged = (newFilters: TransactionsHistoryFiltersDef, applyFilters: boolean) => { + const { onFilterChanged } = this.props; + // User ID has been changed: Clear Start/End Date + if (applyFilters && newFilters.hasOwnProperty('userID') && this.state.filters.userID !== newFilters.userID) { + this.getFilterModalContainerComponent().clearFilters(); + newFilters.startDateTime = null; + newFilters.endDateTime = null; + } + if (newFilters.startDateTime) { + newFilters.startDateTime = moment(newFilters.startDateTime).startOf('day').toDate(); + } + if (newFilters.endDateTime) { + newFilters.endDateTime = moment(newFilters.endDateTime).endOf('day').toDate(); + } + if (applyFilters) { + this.setState({ + filters: { ...this.state.filters, ...newFilters } + }, () => onFilterChanged(this.state.filters)); + } else { + this.setState({ + filters: { ...this.state.filters, ...newFilters } + }); + } + } + + public render = () => { + const { initialFilters } = this.props; + const { filters, isAdmin, hasSiteAdmin } = this.state; + return ( + + {(isAdmin || hasSiteAdmin) && + + this.setFilterVisibleContainerComponent(filterVisibleContainerComponent)} + > + + this.getFilterVisibleContainerComponent().setFilter(id, value)} + ref={(myUserSwitchFilterControlComponent: MyUserSwitchFilterControlComponent) => + this.addVisibleFilter(myUserSwitchFilterControlComponent)} + /> + + } + + this.setFilterModalContainerComponent(filterModalContainerComponent)} + > + + this.getFilterModalContainerComponent().setFilter(id, value)} + ref={(dateFilterControlComponent: DateFilterControlComponent) => + this.addModalFilter(dateFilterControlComponent)} + locale={this.state.locale} + minimumDate={initialFilters.startDateTime} + defaultDate={filters.startDateTime ? filters.startDateTime : initialFilters.startDateTime} + maximumDate={filters.endDateTime ? filters.endDateTime : initialFilters.endDateTime} + /> + + this.getFilterModalContainerComponent().setFilter(id, value)} + ref={(dateFilterControlComponent: DateFilterControlComponent) => + this.addModalFilter(dateFilterControlComponent)} + locale={this.state.locale} + minimumDate={filters.startDateTime ? filters.startDateTime : initialFilters.startDateTime} + defaultDate={filters.endDateTime ? filters.endDateTime : initialFilters.endDateTime} + maximumDate={initialFilters.endDateTime} + /> + + + ); + }; +} diff --git a/src/theme/components/Badge.tsx b/src/theme/components/Badge.tsx new file mode 100644 index 000000000..4ae41fbb1 --- /dev/null +++ b/src/theme/components/Badge.tsx @@ -0,0 +1,47 @@ +import { moderateScale, scale } from 'react-native-size-matters'; +import commonColor from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const badgeTheme: any = { + '.primary': { + backgroundColor: variables.buttonPrimaryBg + }, + '.warning': { + backgroundColor: variables.buttonWarningBg + }, + '.info': { + backgroundColor: variables.buttonInfoBg + }, + '.success': { + backgroundColor: variables.buttonSuccessBg + }, + '.danger': { + backgroundColor: variables.buttonDangerBg + }, + 'NativeBase.Text': { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + alignSelf: 'center', + color: variables.badgeColor, + fontSize: variables.fontSizeBase, + lineHeight: variables.lineHeight - 5, + textAlign: 'center', + paddingTop: moderateScale(11, 4), + paddingBottom: moderateScale(8), + paddingHorizontal: 3 + }, + backgroundColor: variables.badgeBg, + padding: variables.badgePadding, + paddingHorizontal: 6, + borderStyle: 'solid', + borderColor: commonColor.textColor, + borderWidth: scale(4), + justifyContent: 'center', + alignItems: 'center', + width: scale(44), + height: scale(44) + }; + return badgeTheme; +}; diff --git a/src/theme/components/Body.tsx b/src/theme/components/Body.tsx new file mode 100644 index 000000000..b75ebe372 --- /dev/null +++ b/src/theme/components/Body.tsx @@ -0,0 +1,9 @@ +export default () => { + const bodyTheme: any = { + flex: 1, + alignItems: 'center', + alignSelf: 'center' + }; + + return bodyTheme; +}; diff --git a/src/theme/components/Button.tsx b/src/theme/components/Button.tsx new file mode 100644 index 000000000..18a21b8da --- /dev/null +++ b/src/theme/components/Button.tsx @@ -0,0 +1,382 @@ +import { scale } from 'react-native-size-matters'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const platformStyle = variables.platformStyle; + const platform = variables.platform; + const darkCommon = { + 'NativeBase.Text': { + color: variables.brandDark + }, + 'NativeBase.Icon': { + color: variables.brandDark + }, + 'NativeBase.IconNB': { + color: variables.brandDark + } + }; + const lightCommon = { + 'NativeBase.Text': { + color: variables.brandLight + }, + 'NativeBase.Icon': { + color: variables.brandLight + }, + 'NativeBase.IconNB': { + color: variables.brandLight + } + }; + const primaryCommon = { + 'NativeBase.Text': { + color: variables.buttonPrimaryBg + }, + 'NativeBase.Icon': { + color: variables.buttonPrimaryBg + }, + 'NativeBase.IconNB': { + color: variables.buttonPrimaryBg + } + }; + const successCommon = { + 'NativeBase.Text': { + color: variables.buttonSuccessBg + }, + 'NativeBase.Icon': { + color: variables.buttonSuccessBg + }, + 'NativeBase.IconNB': { + color: variables.buttonSuccessBg + } + }; + const infoCommon = { + 'NativeBase.Text': { + color: variables.buttonInfoBg + }, + 'NativeBase.Icon': { + color: variables.buttonInfoBg + }, + 'NativeBase.IconNB': { + color: variables.buttonInfoBg + } + }; + const warningCommon = { + 'NativeBase.Text': { + color: variables.buttonWarningBg + }, + 'NativeBase.Icon': { + color: variables.buttonWarningBg + }, + 'NativeBase.IconNB': { + color: variables.buttonWarningBg + } + }; + const dangerCommon = { + 'NativeBase.Text': { + color: variables.buttonDangerBg + }, + 'NativeBase.Icon': { + color: variables.buttonDangerBg + }, + 'NativeBase.IconNB': { + color: variables.buttonDangerBg + } + }; + const buttonTheme: any = { + '.disabled': { + '.transparent': { + backgroundColor: 'transparent', + 'NativeBase.Text': { + color: variables.buttonDisabledBg + }, + 'NativeBase.Icon': { + color: variables.buttonDisabledBg + }, + 'NativeBase.IconNB': { + color: variables.buttonDisabledBg + } + }, + 'NativeBase.Icon': { + color: variables.brandLight + }, + 'NativeBase.IconNB': { + color: variables.brandLight + }, + backgroundColor: variables.buttonDisabledBg + }, + '.bordered': { + '.dark': { + ...darkCommon, + backgroundColor: 'transparent', + borderColor: variables.brandDark, + borderWidth: variables.borderWidth * 2 + }, + '.light': { + ...lightCommon, + backgroundColor: 'transparent', + borderColor: variables.brandLight, + borderWidth: variables.borderWidth * 2 + }, + '.primary': { + ...primaryCommon, + backgroundColor: 'transparent', + borderColor: variables.buttonPrimaryBg, + borderWidth: variables.borderWidth * 2 + }, + '.success': { + ...successCommon, + backgroundColor: 'transparent', + borderColor: variables.buttonSuccessBg, + borderWidth: variables.borderWidth * 2 + }, + '.info': { + ...infoCommon, + backgroundColor: 'transparent', + borderColor: variables.buttonInfoBg, + borderWidth: variables.borderWidth * 2 + }, + '.warning': { + ...warningCommon, + backgroundColor: 'transparent', + borderColor: variables.buttonWarningBg, + borderWidth: variables.borderWidth * 2 + }, + '.danger': { + ...dangerCommon, + backgroundColor: 'transparent', + borderColor: variables.buttonDangerBg, + borderWidth: variables.borderWidth * 2 + }, + '.disabled': { + backgroundColor: 'transparent', + borderColor: variables.buttonDisabledBg, + borderWidth: variables.borderWidth * 2, + 'NativeBase.Text': { + color: variables.buttonDisabledBg + } + }, + ...primaryCommon, + borderWidth: variables.borderWidth * 2, + elevation: null, + shadowColor: null, + shadowOffset: null, + shadowOpacity: null, + shadowRadius: null, + backgroundColor: 'transparent' + }, + + '.dark': { + '.bordered': { + ...darkCommon + }, + backgroundColor: variables.brandDark + }, + '.light': { + '.transparent': { + ...lightCommon, + backgroundColor: 'transparent' + }, + '.bordered': { + ...lightCommon + }, + ...darkCommon, + backgroundColor: variables.brandLight + }, + + '.primary': { + '.bordered': { + ...primaryCommon + }, + backgroundColor: variables.buttonPrimaryBg + }, + + '.success': { + '.bordered': { + ...successCommon + }, + backgroundColor: variables.buttonSuccessBg + }, + + '.info': { + '.bordered': { + ...infoCommon + }, + backgroundColor: variables.buttonInfoBg + }, + + '.warning': { + '.bordered': { + ...warningCommon + }, + backgroundColor: variables.buttonWarningBg + }, + + '.danger': { + '.bordered': { + ...dangerCommon + }, + backgroundColor: variables.buttonDangerBg + }, + + '.block': { + justifyContent: 'center', + alignSelf: 'stretch' + }, + + '.full': { + justifyContent: 'center', + alignSelf: 'stretch', + borderRadius: 0 + }, + + '.rounded': { + borderRadius: variables.borderRadiusLarge + }, + + '.transparent': { + backgroundColor: 'transparent', + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null, + ...primaryCommon, + '.dark': { + ...darkCommon + }, + '.danger': { + ...dangerCommon + }, + '.warning': { + ...warningCommon + }, + '.info': { + ...infoCommon + }, + '.primary': { + ...primaryCommon + }, + '.success': { + ...successCommon + }, + '.light': { + ...lightCommon + }, + '.disabled': { + backgroundColor: 'transparent', + borderColor: variables.buttonDisabledBg, + borderWidth: variables.borderWidth * 2, + 'NativeBase.Text': { + color: variables.buttonDisabledBg + }, + 'NativeBase.Icon': { + color: variables.buttonDisabledBg + }, + 'NativeBase.IconNB': { + color: variables.buttonDisabledBg + } + } + }, + + '.small': { + height: 30, + 'NativeBase.Text': { + fontSize: 14 + }, + 'NativeBase.Icon': { + fontSize: 20, + paddingTop: 0 + }, + 'NativeBase.IconNB': { + fontSize: 20, + paddingTop: 0 + } + }, + + '.large': { + height: 60, + 'NativeBase.Text': { + fontSize: 22 + } + }, + + '.capitalize': {}, + + '.vertical': { + flexDirection: 'column', + height: null + }, + + 'NativeBase.Text': { + fontFamily: variables.buttonFontFamily, + marginLeft: 0, + marginRight: 0, + color: variables.inverseTextColor, + fontSize: variables.buttonTextSize, + paddingHorizontal: 16, + backgroundColor: 'transparent' + }, + + 'NativeBase.Icon': { + color: variables.inverseTextColor, + fontSize: 24, + // marginHorizontal: 16, + paddingTop: platform === PLATFORM.IOS ? 2 : undefined + }, + 'NativeBase.IconNB': { + color: variables.inverseTextColor, + fontSize: 24, + // marginHorizontal: 16, + paddingTop: platform === PLATFORM.IOS ? 2 : undefined + }, + + '.iconLeft': { + 'NativeBase.Text': { + marginLeft: 0 + }, + 'NativeBase.IconNB': { + marginRight: 0, + marginLeft: 16 + }, + 'NativeBase.Icon': { + marginRight: 0, + marginLeft: 16 + } + }, + '.iconRight': { + 'NativeBase.Text': { + marginRight: 0 + }, + 'NativeBase.IconNB': { + marginLeft: 0, + marginRight: 16 + }, + 'NativeBase.Icon': { + marginLeft: 0, + marginRight: 16 + } + }, + '.picker': { + 'NativeBase.Text': { + '.note': { + fontSize: 16, + lineHeight: null + } + } + }, + paddingVertical: variables.buttonPadding, + backgroundColor: variables.buttonPrimaryBg, + borderColor: variables.buttonPrimaryBg, + borderWidth: null, + height: scale(35), + flexDirection: 'row', + elevation: 2, + shadowColor: platformStyle === PLATFORM.MATERIAL ? variables.brandDark : undefined, + shadowOffset: platformStyle === PLATFORM.MATERIAL ? { width: 0, height: 2 } : undefined, + shadowOpacity: platformStyle === PLATFORM.MATERIAL ? 0.2 : undefined, + shadowRadius: platformStyle === PLATFORM.MATERIAL ? 1.2 : undefined, + alignItems: 'center', + justifyContent: 'space-between' + }; + return buttonTheme; +}; diff --git a/src/theme/components/Card.tsx b/src/theme/components/Card.tsx new file mode 100644 index 000000000..c0754c0c9 --- /dev/null +++ b/src/theme/components/Card.tsx @@ -0,0 +1,35 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const cardTheme: any = { + '.transparent': { + shadowColor: null, + shadowOffset: null, + shadowOpacity: null, + shadowRadius: null, + elevation: null, + backgroundColor: 'transparent', + borderWidth: 0 + }, + '.noShadow': { + shadowColor: null, + shadowOffset: null, + shadowOpacity: null, + elevation: null + }, + marginVertical: 5, + marginHorizontal: 2, + borderWidth: variables.borderWidth, + borderRadius: variables.cardBorderRadius, + borderColor: variables.cardBorderColor, + flexWrap: 'nowrap', + backgroundColor: variables.cardDefaultBg, + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.1, + shadowRadius: 1.5, + elevation: 3 + }; + + return cardTheme; +}; diff --git a/src/theme/components/CardItem.tsx b/src/theme/components/CardItem.tsx new file mode 100644 index 000000000..c84a5fa25 --- /dev/null +++ b/src/theme/components/CardItem.tsx @@ -0,0 +1,195 @@ +import { StyleSheet } from 'react-native'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const platform = variables.platform; + const transparentBtnCommon: any = { + 'NativeBase.Text': { + fontSize: variables.DefaultFontSize - 3, + color: variables.sTabBarActiveTextColor + }, + 'NativeBase.Icon': { + fontSize: variables.iconFontSize - 10, + color: variables.sTabBarActiveTextColor, + marginHorizontal: null + }, + 'NativeBase.IconNB': { + fontSize: variables.iconFontSize - 10, + color: variables.sTabBarActiveTextColor + }, + paddingVertical: null, + paddingHorizontal: null + }; + + const cardItemTheme: any = { + 'NativeBase.Left': { + 'NativeBase.Body': { + 'NativeBase.Text': { + '.note': { + color: variables.listNoteColor, + fontWeight: '400', + marginRight: 20 + } + }, + flex: 1, + marginLeft: 10, + alignItems: null + }, + 'NativeBase.Icon': { + fontSize: variables.iconFontSize + }, + 'NativeBase.IconNB': { + fontSize: variables.iconFontSize + }, + 'NativeBase.Text': { + marginLeft: 10, + alignSelf: 'center' + }, + 'NativeBase.Button': { + '.transparent': { + ...transparentBtnCommon, + paddingRight: variables.cardItemPadding + 5 + } + }, + flex: 1, + flexDirection: 'row', + alignItems: 'center' + }, + '.content': { + 'NativeBase.Text': { + color: platform === PLATFORM.IOS ? '#555' : '#222', + fontSize: variables.DefaultFontSize - 2 + } + }, + '.cardBody': { + padding: -5, + 'NativeBase.Text': { + marginTop: 5 + } + }, + 'NativeBase.Body': { + 'NativeBase.Text': { + '.note': { + color: variables.listNoteColor, + fontWeight: '200', + marginRight: 20 + } + }, + 'NativeBase.Button': { + '.transparent': { + ...transparentBtnCommon, + paddingRight: variables.cardItemPadding + 5, + alignSelf: 'stretch' + } + }, + flex: 1, + alignSelf: 'stretch', + alignItems: 'flex-start' + }, + 'NativeBase.Right': { + 'NativeBase.Badge': { + alignSelf: null + }, + 'NativeBase.Button': { + '.transparent': { + ...transparentBtnCommon + }, + alignSelf: null + }, + 'NativeBase.Icon': { + alignSelf: null, + fontSize: variables.iconFontSize - 8, + color: variables.cardBorderColor + }, + 'NativeBase.IconNB': { + alignSelf: null, + fontSize: variables.iconFontSize - 8, + color: variables.cardBorderColor + }, + 'NativeBase.Text': { + fontSize: variables.DefaultFontSize - 1, + alignSelf: null + }, + 'NativeBase.Thumbnail': { + alignSelf: null + }, + 'NativeBase.Image': { + alignSelf: null + }, + 'NativeBase.Radio': { + alignSelf: null + }, + 'NativeBase.Checkbox': { + alignSelf: null + }, + 'NativeBase.Switch': { + alignSelf: null + }, + flex: 0.8 + }, + '.header': { + 'NativeBase.Text': { + fontSize: 16, + fontWeight: platform === PLATFORM.IOS ? '600' : '500' + }, + '.bordered': { + 'NativeBase.Text': { + color: variables.brandPrimary, + fontWeight: platform === PLATFORM.IOS ? '600' : '500' + }, + borderBottomWidth: variables.borderWidth + }, + borderBottomWidth: null, + paddingVertical: variables.cardItemPadding + 5 + }, + '.footer': { + 'NativeBase.Text': { + fontSize: 16, + fontWeight: platform === PLATFORM.IOS ? '600' : '500' + }, + '.bordered': { + 'NativeBase.Text': { + color: variables.brandPrimary, + fontWeight: platform === PLATFORM.IOS ? '600' : '500' + }, + borderTopWidth: variables.borderWidth + }, + borderBottomWidth: null + }, + 'NativeBase.Text': { + '.note': { + color: variables.listNoteColor, + fontWeight: '200' + } + }, + 'NativeBase.Icon': { + width: variables.iconFontSize + 5, + fontSize: variables.iconFontSize - 2 + }, + 'NativeBase.IconNB': { + width: variables.iconFontSize + 5, + fontSize: variables.iconFontSize - 2 + }, + '.bordered': { + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: variables.cardBorderColor + }, + '.first': { + borderTopLeftRadius: variables.cardBorderRadius, + borderTopRightRadius: variables.cardBorderRadius + }, + '.last': { + borderBottomLeftRadius: variables.cardBorderRadius, + borderBottomRightRadius: variables.cardBorderRadius + }, + flexDirection: 'row', + alignItems: 'center', + borderRadius: variables.cardBorderRadius, + padding: variables.cardItemPadding + 5, + paddingVertical: variables.cardItemPadding, + backgroundColor: variables.cardDefaultBg + }; + + return cardItemTheme; +}; diff --git a/src/theme/components/CheckBox.tsx b/src/theme/components/CheckBox.tsx new file mode 100644 index 000000000..fd9e2d4f7 --- /dev/null +++ b/src/theme/components/CheckBox.tsx @@ -0,0 +1,36 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const checkBoxTheme: any = { + '.checked': { + 'NativeBase.Icon': { + color: variables.checkboxTickColor + }, + 'NativeBase.IconNB': { + color: variables.checkboxTickColor + } + }, + 'NativeBase.Icon': { + color: 'transparent', + lineHeight: variables.CheckboxIconSize, + marginTop: variables.CheckboxIconMarginTop, + fontSize: variables.CheckboxFontSize + }, + 'NativeBase.IconNB': { + color: 'transparent', + lineHeight: variables.CheckboxIconSize, + marginTop: variables.CheckboxIconMarginTop, + fontSize: variables.CheckboxFontSize + }, + borderRadius: variables.CheckboxRadius, + overflow: 'hidden', + width: variables.checkboxSize, + height: variables.checkboxSize, + borderWidth: variables.CheckboxBorderWidth, + paddingLeft: variables.CheckboxPaddingLeft - 1, + paddingBottom: variables.CheckboxPaddingBottom, + left: 10 + }; + + return checkBoxTheme; +}; diff --git a/src/theme/components/Container.tsx b/src/theme/components/Container.tsx new file mode 100644 index 000000000..a1afb7d38 --- /dev/null +++ b/src/theme/components/Container.tsx @@ -0,0 +1,14 @@ +import { Dimensions, Platform } from 'react-native'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +const deviceHeight = Dimensions.get('window').height; +export default (variables /* : * */ = variable) => { + const theme: any = { + flex: 1, + height: Platform.OS === PLATFORM.IOS ? deviceHeight : deviceHeight - 20, + backgroundColor: variables.containerBgColor + }; + + return theme; +}; diff --git a/src/theme/components/Content.tsx b/src/theme/components/Content.tsx new file mode 100644 index 000000000..72f4778b6 --- /dev/null +++ b/src/theme/components/Content.tsx @@ -0,0 +1,13 @@ + +export default () => { + const contentTheme: any = { + flex: 1, + backgroundColor: 'transparent', + 'NativeBase.Segment': { + borderWidth: 0, + backgroundColor: 'transparent' + } + }; + + return contentTheme; +}; diff --git a/src/theme/components/Fab.tsx b/src/theme/components/Fab.tsx new file mode 100644 index 000000000..93a5cb4bb --- /dev/null +++ b/src/theme/components/Fab.tsx @@ -0,0 +1,23 @@ +export default () => { + const fabTheme: any = { + 'NativeBase.Button': { + alignItems: 'center', + padding: null, + justifyContent: 'center', + 'NativeBase.Icon': { + alignSelf: 'center', + fontSize: 20, + marginLeft: 0, + marginRight: 0 + }, + 'NativeBase.IconNB': { + alignSelf: 'center', + fontSize: 20, + marginLeft: 0, + marginRight: 0 + } + } + }; + + return fabTheme; +}; diff --git a/src/theme/components/Footer.tsx b/src/theme/components/Footer.tsx new file mode 100644 index 000000000..a1c6c427e --- /dev/null +++ b/src/theme/components/Footer.tsx @@ -0,0 +1,111 @@ +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const platformStyle = variables.platformStyle; + const platform = variables.platform; + + const iconCommon = { + 'NativeBase.Icon': { + color: variables.tabBarActiveTextColor + } + }; + const iconNBCommon = { + 'NativeBase.IconNB': { + color: variables.tabBarActiveTextColor + } + }; + const textCommon = { + 'NativeBase.Text': { + color: variables.tabBarActiveTextColor + } + }; + const footerTheme: any = { + 'NativeBase.Left': { + 'NativeBase.Button': { + '.transparent': { + backgroundColor: 'transparent', + borderColor: null, + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null, + ...iconCommon, + ...iconNBCommon, + ...textCommon + }, + alignSelf: null, + ...iconCommon, + ...iconNBCommon + // ...textCommon + }, + flex: 1, + alignSelf: 'center', + alignItems: 'flex-start' + }, + 'NativeBase.Body': { + flex: 1, + alignItems: 'center', + alignSelf: 'center', + flexDirection: 'row', + 'NativeBase.Button': { + alignSelf: 'center', + '.transparent': { + backgroundColor: 'transparent', + borderColor: null, + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null, + ...iconCommon, + ...iconNBCommon, + ...textCommon + }, + '.full': { + height: variables.footerHeight, + paddingBottom: variables.footerPaddingBottom, + flex: 1 + }, + ...iconCommon, + ...iconNBCommon + // ...textCommon + } + }, + 'NativeBase.Right': { + 'NativeBase.Button': { + '.transparent': { + backgroundColor: 'transparent', + borderColor: null, + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null, + ...iconCommon, + ...iconNBCommon, + ...textCommon + }, + alignSelf: null, + ...iconCommon, + ...iconNBCommon + // ...textCommon + }, + flex: 1, + alignSelf: 'center', + alignItems: 'flex-end' + }, + backgroundColor: variables.footerDefaultBg, + flexDirection: 'row', + justifyContent: 'center', + borderTopWidth: platform === PLATFORM.IOS && platformStyle !== PLATFORM.MATERIAL ? variables.borderWidth : undefined, + borderColor: platform === PLATFORM.IOS && platformStyle !== PLATFORM.MATERIAL ? '#cbcbcb' : undefined, + height: variables.footerHeight, + paddingBottom: variables.footerPaddingBottom, + elevation: 3, + left: 0, + right: 0 + }; + return footerTheme; +}; diff --git a/src/theme/components/FooterTab.tsx b/src/theme/components/FooterTab.tsx new file mode 100644 index 000000000..64a9101b3 --- /dev/null +++ b/src/theme/components/FooterTab.tsx @@ -0,0 +1,75 @@ +import { Platform } from 'react-native'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const platform = variables.platform; + + const footerTabTheme: any = { + 'NativeBase.Button': { + '.active': { + 'NativeBase.Text': { + color: variables.tabBarActiveTextColor, + fontSize: variables.tabBarTextSize, + lineHeight: 16 + }, + 'NativeBase.Icon': { + color: variables.tabBarActiveTextColor + }, + 'NativeBase.IconNB': { + color: variables.tabBarActiveTextColor + }, + backgroundColor: variables.tabActiveBgColor + }, + flexDirection: null, + backgroundColor: 'transparent', + borderColor: null, + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null, + alignSelf: 'center', + flex: 1, + height: variables.footerHeight, + justifyContent: 'center', + '.badge': { + 'NativeBase.Badge': { + 'NativeBase.Text': { + fontSize: 11, + fontWeight: platform === PLATFORM.IOS ? '600' : undefined, + lineHeight: 14 + }, + top: -3, + alignSelf: 'center', + left: 10, + zIndex: 99, + height: 18, + padding: 1.7, + paddingHorizontal: 3 + }, + 'NativeBase.Icon': { + marginTop: -18 + } + }, + 'NativeBase.Icon': { + color: variables.tabBarTextColor + }, + 'NativeBase.IconNB': { + color: variables.tabBarTextColor + }, + 'NativeBase.Text': { + color: variables.tabBarTextColor, + fontSize: variables.tabBarTextSize, + lineHeight: 16 + } + }, + backgroundColor: Platform.OS === PLATFORM.ANDROID ? variables.footerDefaultBg : undefined, + flexDirection: 'row', + justifyContent: 'space-between', + flex: 1, + alignSelf: 'stretch' + }; + + return footerTabTheme; +}; diff --git a/src/theme/components/Form.tsx b/src/theme/components/Form.tsx new file mode 100644 index 000000000..b1ef617a2 --- /dev/null +++ b/src/theme/components/Form.tsx @@ -0,0 +1,84 @@ +export default () => { + const theme: any = { + 'NativeBase.Item': { + '.fixedLabel': { + 'NativeBase.Label': { + paddingLeft: null + }, + marginLeft: 15 + }, + '.inlineLabel': { + 'NativeBase.Label': { + paddingLeft: null + }, + marginLeft: 15 + }, + '.placeholderLabel': { + 'NativeBase.Input': {} + }, + '.stackedLabel': { + 'NativeBase.Label': { + top: 5, + paddingLeft: null + }, + 'NativeBase.Input': { + paddingLeft: null, + marginLeft: null + }, + 'NativeBase.Icon': { + marginTop: 36 + }, + marginLeft: 15 + }, + '.floatingLabel': { + 'NativeBase.Input': { + paddingLeft: null, + top: 10, + marginLeft: null + }, + 'NativeBase.Label': { + left: 0, + top: 6 + }, + 'NativeBase.Icon': { + top: 6 + }, + marginTop: 15, + marginLeft: 15 + }, + '.regular': { + 'NativeBase.Label': { + left: 0 + }, + marginLeft: 0 + }, + '.rounded': { + 'NativeBase.Label': { + left: 0 + }, + marginLeft: 0 + }, + '.underline': { + 'NativeBase.Label': { + left: 0, + top: 0, + position: 'relative' + }, + 'NativeBase.Input': { + left: -15 + }, + marginLeft: 15 + }, + '.last': { + marginLeft: 0, + paddingLeft: 15 + }, + 'NativeBase.Label': { + paddingRight: 5 + }, + marginLeft: 15 + } + }; + + return theme; +}; diff --git a/src/theme/components/H1.tsx b/src/theme/components/H1.tsx new file mode 100644 index 000000000..c06ff9af2 --- /dev/null +++ b/src/theme/components/H1.tsx @@ -0,0 +1,11 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const h1Theme: any = { + color: variables.textColor, + fontSize: variables.fontSizeH1, + lineHeight: variables.lineHeightH1 + }; + + return h1Theme; +}; diff --git a/src/theme/components/H2.tsx b/src/theme/components/H2.tsx new file mode 100644 index 000000000..bff4db2d4 --- /dev/null +++ b/src/theme/components/H2.tsx @@ -0,0 +1,11 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const h2Theme: any = { + color: variables.textColor, + fontSize: variables.fontSizeH2, + lineHeight: variables.lineHeightH2 + }; + + return h2Theme; +}; diff --git a/src/theme/components/H3.tsx b/src/theme/components/H3.tsx new file mode 100644 index 000000000..055fec988 --- /dev/null +++ b/src/theme/components/H3.tsx @@ -0,0 +1,11 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const h3Theme: any = { + color: variables.textColor, + fontSize: variables.fontSizeH3, + lineHeight: variables.lineHeightH3 + }; + + return h3Theme; +}; diff --git a/src/theme/components/Header.tsx b/src/theme/components/Header.tsx new file mode 100644 index 000000000..a4c258445 --- /dev/null +++ b/src/theme/components/Header.tsx @@ -0,0 +1,386 @@ +import { PixelRatio, StatusBar } from 'react-native'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +const buildTheme = (variables: any) => { + // Forced to break up the theme to avoid typescript infinite run! + const platformStyle = variables.platformStyle; + const platform = variables.platform; + + const headerTheme: any = { + backgroundColor: 'transparent', + flexDirection: 'row', + paddingLeft: platform === PLATFORM.IOS ? 5 : 0, + paddingRight: platform === PLATFORM.IOS ? 5 : 0, + justifyContent: 'center', + // paddingTop: platform === PLATFORM.IOS ? 18 : 0, + borderBottomWidth: platform === PLATFORM.IOS ? 1 / PixelRatio.getPixelSizeForLayoutSize(1) : 0, + borderBottomColor: variables.toolbarDefaultBorder, + height: + variables.platform === PLATFORM.IOS && variables.platformStyle === PLATFORM.MATERIAL + ? variables.toolbarHeight + 10 + : variables.toolbarHeight, + top: 0, + left: 0, + right: 0 + }; + + headerTheme['.span'] = { + height: 128, + 'NativeBase.Left': { + alignSelf: 'flex-start' + }, + 'NativeBase.Body': { + alignSelf: 'flex-end', + alignItems: 'flex-start', + justifyContent: 'center', + paddingBottom: 26 + }, + 'NativeBase.Right': { + alignSelf: 'flex-start' + } + }; + + headerTheme['.hasSubtitle'] = { + 'NativeBase.Body': { + 'NativeBase.Title': { + fontSize: variables.titleFontSize - 2, + fontFamily: variables.titleFontfamily, + textAlign: 'center', + fontWeight: '500', + paddingBottom: 3 + }, + 'NativeBase.Subtitle': { + fontSize: variables.subTitleFontSize, + fontFamily: variables.titleFontfamily, + color: variables.subtitleColor, + textAlign: 'center' + } + } + }; + + headerTheme['.transparent'] = { + backgroundColor: 'transparent', + borderBottomColor: 'transparent', + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null, + paddingTop: platform === PLATFORM.ANDROID ? StatusBar.currentHeight : undefined, + height: platform === PLATFORM.ANDROID ? variables.toolbarHeight + StatusBar.currentHeight : variables.toolbarHeight + }; + + headerTheme['.noShadow'] = { + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null + }; + + headerTheme['.hasTabs'] = { + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null, + borderBottomWidth: null + }; + + headerTheme['.hasSegment'] = { + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null, + borderBottomWidth: null, + 'NativeBase.Left': { + flex: 0.3 + }, + 'NativeBase.Right': { + flex: 0.3 + }, + 'NativeBase.Body': { + flex: 1, + 'NativeBase.Segment': { + marginRight: 0, + alignSelf: 'center', + 'NativeBase.Button': { + paddingLeft: 0, + paddingRight: 0 + } + } + } + }; + + headerTheme['.noLeft'] = { + 'NativeBase.Left': { + width: platform === PLATFORM.IOS ? undefined : 0, + flex: platform === PLATFORM.IOS ? 1 : 0 + }, + 'NativeBase.Body': { + 'NativeBase.Title': { + paddingLeft: platform === PLATFORM.IOS ? undefined : 10 + }, + 'NativeBase.Subtitle': { + paddingLeft: platform === PLATFORM.IOS ? undefined : 10 + } + } + }; + + headerTheme['NativeBase.Button'] = { + justifyContent: 'center', + alignSelf: 'center', + alignItems: 'center', + '.transparent': { + 'NativeBase.Text': { + color: variables.toolbarBtnTextColor, + fontWeight: '600' + }, + 'NativeBase.Icon': { + color: variables.toolbarBtnColor + }, + 'NativeBase.IconNB': { + color: variables.toolbarBtnColor + }, + paddingHorizontal: variables.buttonPadding + }, + paddingHorizontal: 15 + }; + + headerTheme['.searchBar'] = { + 'NativeBase.Item': { + 'NativeBase.Icon': { + backgroundColor: 'transparent', + color: variables.dropdownLinkColor, + fontSize: variables.toolbarSearchIconSize, + alignItems: 'center', + marginTop: 2, + paddingRight: 10, + paddingLeft: 10 + }, + 'NativeBase.IconNB': { + backgroundColor: 'transparent', + color: null, + alignSelf: 'center' + }, + 'NativeBase.Input': { + alignSelf: 'center', + lineHeight: null, + height: variables.searchBarInputHeight + }, + alignSelf: 'center', + alignItems: 'center', + justifyContent: 'flex-start', + flex: 1, + height: variables.searchBarHeight, + borderColor: 'transparent', + backgroundColor: variables.toolbarInputColor + }, + 'NativeBase.Button': { + '.transparent': { + 'NativeBase.Text': { + fontWeight: '500' + }, + paddingHorizontal: null, + paddingLeft: platform === PLATFORM.IOS ? 10 : null + }, + paddingHorizontal: platform === PLATFORM.IOS ? undefined : null, + width: platform === PLATFORM.IOS ? undefined : 0, + height: platform === PLATFORM.IOS ? undefined : 0 + } + }; + + headerTheme['.rounded'] = { + 'NativeBase.Item': { + borderRadius: platform === PLATFORM.IOS && platformStyle !== PLATFORM.MATERIAL ? 25 : 3 + } + }; + + headerTheme['NativeBase.Left'] = { + 'NativeBase.Button': { + '.hasText': { + marginLeft: -10, + height: 30, + 'NativeBase.Icon': { + color: variables.toolbarBtnColor, + fontSize: variables.iconHeaderSize, + marginTop: 2, + marginRight: 5, + marginLeft: 2 + }, + 'NativeBase.Text': { + color: variables.toolbarBtnTextColor, + fontSize: platform === PLATFORM.IOS ? 17 : 0, + marginLeft: 7, + lineHeight: 19.5 + }, + 'NativeBase.IconNB': { + color: variables.toolbarBtnColor, + fontSize: variables.iconHeaderSize, + marginTop: 2, + marginRight: 5, + marginLeft: 2 + } + }, + '.transparent': { + 'NativeBase.Icon': { + color: variables.toolbarBtnColor, + fontSize: + platform === PLATFORM.IOS && variables.platformStyle !== PLATFORM.MATERIAL + ? variables.iconHeaderSize + 1 + : variables.iconHeaderSize, + marginTop: 0, + marginRight: 2, + marginLeft: 1, + paddingTop: 1 + }, + 'NativeBase.IconNB': { + color: variables.toolbarBtnColor, + fontSize: + platform === PLATFORM.IOS && variables.platformStyle !== PLATFORM.MATERIAL + ? variables.iconHeaderSize + 1 + : variables.iconHeaderSize - 2, + marginTop: 0, + marginRight: 2, + marginLeft: 1, + paddingTop: 1 + }, + 'NativeBase.Text': { + color: variables.toolbarBtnTextColor, + fontSize: platform === PLATFORM.IOS ? 17 : 0, + top: platform === PLATFORM.IOS ? 1 : -1.5, + paddingLeft: platform === PLATFORM.IOS && platformStyle !== PLATFORM.MATERIAL ? 2 : 5, + paddingRight: platform === PLATFORM.IOS && platformStyle !== PLATFORM.MATERIAL ? undefined : 10 + }, + padding: 0, + marginLeft: platform === PLATFORM.IOS && platformStyle !== PLATFORM.MATERIAL ? -3 : 0, + backgroundColor: 'transparent', + borderColor: null, + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null + }, + 'NativeBase.Icon': { + color: variables.toolbarBtnColor + }, + 'NativeBase.IconNB': { + color: variables.toolbarBtnColor + }, + alignSelf: null, + paddingRight: variables.buttonPadding, + paddingLeft: platform === PLATFORM.IOS && platformStyle !== PLATFORM.MATERIAL ? 4 : 8 + }, + flex: platform === PLATFORM.IOS && platformStyle !== PLATFORM.MATERIAL ? 1 : 0.4, + alignSelf: 'center', + alignItems: 'flex-start' + }; + + headerTheme['NativeBase.Body'] = { + flex: 1, + alignItems: platform === PLATFORM.IOS && platformStyle !== PLATFORM.MATERIAL ? 'center' : 'center', + alignSelf: 'center', + 'NativeBase.Segment': { + borderWidth: 0, + alignSelf: 'flex-end', + marginRight: platform === PLATFORM.IOS ? -40 : -55 + }, + 'NativeBase.Button': { + alignSelf: 'center', + '.transparent': { + backgroundColor: 'transparent' + }, + 'NativeBase.Icon': { + color: variables.toolbarBtnColor + }, + 'NativeBase.IconNB': { + color: variables.toolbarBtnColor + }, + 'NativeBase.Text': { + color: variables.inverseTextColor, + backgroundColor: 'transparent' + } + } + }; + + headerTheme['NativeBase.Right'] = { + 'NativeBase.Button': { + '.hasText': { + height: 30, + 'NativeBase.Icon': { + color: variables.toolbarBtnColor, + fontSize: variables.iconHeaderSize - 2, + marginTop: 2, + marginRight: 2, + marginLeft: 5 + }, + 'NativeBase.Text': { + color: variables.toolbarBtnTextColor, + fontSize: platform === PLATFORM.IOS ? 17 : 14, + lineHeight: 19.5 + }, + 'NativeBase.IconNB': { + color: variables.toolbarBtnColor, + fontSize: variables.iconHeaderSize - 2, + marginTop: 2, + marginRight: 2, + marginLeft: 5 + } + }, + '.transparent': { + 'NativeBase.Icon': { + color: variables.toolbarBtnColor, + fontSize: variables.iconHeaderSize - 2, + marginTop: 0, + marginLeft: 2, + marginRight: 0 + // paddingTop: 0 + }, + 'NativeBase.IconNB': { + color: variables.toolbarBtnColor, + fontSize: variables.iconHeaderSize - 2, + marginTop: 0, + marginLeft: 2, + marginRight: 0 + // paddingTop: 0 + }, + 'NativeBase.Text': { + color: variables.toolbarBtnTextColor, + fontSize: platform === PLATFORM.IOS ? 17 : 14, + top: platform === PLATFORM.IOS ? 1 : -1.5, + paddingRight: platform === PLATFORM.IOS && variables.platformStyle !== PLATFORM.MATERIAL ? 0 : undefined + }, + padding: 0, + marginLeft: platform === PLATFORM.IOS ? -9 : -5, + backgroundColor: 'transparent', + borderColor: null, + elevation: 0, + shadowColor: null, + shadowOffset: null, + shadowRadius: null, + shadowOpacity: null + }, + 'NativeBase.Icon': { + color: variables.toolbarBtnColor + }, + 'NativeBase.IconNB': { + color: variables.toolbarBtnColor + }, + alignSelf: null, + paddingHorizontal: variables.buttonPadding + }, + flex: 1, + alignSelf: 'center', + alignItems: 'flex-end', + flexDirection: 'row', + justifyContent: 'flex-end' + }; + return headerTheme; +}; + +export default (variables /* : * */ = variable) => { + return buildTheme(variables); +}; diff --git a/src/theme/components/Icon.tsx b/src/theme/components/Icon.tsx new file mode 100644 index 000000000..3f0a9220a --- /dev/null +++ b/src/theme/components/Icon.tsx @@ -0,0 +1,10 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const iconTheme: any = { + fontSize: variables.iconFontSize, + color: variable.textColor + }; + + return iconTheme; +}; diff --git a/src/theme/components/Input.tsx b/src/theme/components/Input.tsx new file mode 100644 index 000000000..dc8bd2742 --- /dev/null +++ b/src/theme/components/Input.tsx @@ -0,0 +1,17 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const inputTheme: any = { + '.multiline': { + height: null + }, + height: variables.inputHeightBase, + color: variables.inputColor, + paddingLeft: 5, + paddingRight: 5, + flex: 1, + fontSize: variables.inputFontSize + }; + + return inputTheme; +}; diff --git a/src/theme/components/InputGroup.tsx b/src/theme/components/InputGroup.tsx new file mode 100644 index 000000000..28a3dee05 --- /dev/null +++ b/src/theme/components/InputGroup.tsx @@ -0,0 +1,130 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const inputGroupTheme: any = { + 'NativeBase.Icon': { + fontSize: 24, + color: variables.sTabBarActiveTextColor, + paddingHorizontal: 5 + }, + 'NativeBase.IconNB': { + fontSize: 24, + color: variables.sTabBarActiveTextColor, + paddingHorizontal: 5 + }, + 'NativeBase.Input': { + height: variables.inputHeightBase, + color: variables.inputColor, + paddingLeft: 5, + paddingRight: 5, + flex: 1, + fontSize: variables.inputFontSize, + lineHeight: variables.inputLineHeight + }, + '.underline': { + '.success': { + borderColor: variables.inputSuccessBorderColor + }, + '.error': { + borderColor: variables.inputErrorBorderColor + }, + paddingLeft: 5, + borderWidth: variables.borderWidth, + borderTopWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderColor: variables.inputBorderColor + }, + '.regular': { + '.success': { + borderColor: variables.inputSuccessBorderColor + }, + '.error': { + borderColor: variables.inputErrorBorderColor + }, + paddingLeft: 5, + borderWidth: variables.borderWidth, + borderColor: variables.inputBorderColor + }, + '.rounded': { + '.success': { + borderColor: variables.inputSuccessBorderColor + }, + '.error': { + borderColor: variables.inputErrorBorderColor + }, + paddingLeft: 5, + borderWidth: variables.borderWidth, + borderRadius: variables.inputGroupRoundedBorderRadius, + borderColor: variables.inputBorderColor + }, + + '.success': { + 'NativeBase.Icon': { + color: variables.inputSuccessBorderColor + }, + 'NativeBase.IconNB': { + color: variables.inputSuccessBorderColor + }, + '.rounded': { + borderRadius: 30, + borderColor: variables.inputSuccessBorderColor + }, + '.regular': { + borderColor: variables.inputSuccessBorderColor + }, + '.underline': { + borderWidth: variables.borderWidth, + borderTopWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderColor: variables.inputSuccessBorderColor + }, + borderColor: variables.inputSuccessBorderColor + }, + + '.error': { + 'NativeBase.Icon': { + color: variables.inputErrorBorderColor + }, + 'NativeBase.IconNB': { + color: variables.inputErrorBorderColor + }, + '.rounded': { + borderRadius: 30, + borderColor: variables.inputErrorBorderColor + }, + '.regular': { + borderColor: variables.inputErrorBorderColor + }, + '.underline': { + borderWidth: variables.borderWidth, + borderTopWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderColor: variables.inputErrorBorderColor + }, + borderColor: variables.inputErrorBorderColor + }, + '.disabled': { + 'NativeBase.Icon': { + color: '#384850' + }, + 'NativeBase.IconNB': { + color: '#384850' + } + }, + + paddingLeft: 5, + borderWidth: variables.borderWidth, + borderTopWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderColor: variables.inputBorderColor, + backgroundColor: 'transparent', + flexDirection: 'row', + alignItems: 'center' + }; + + return inputGroupTheme; +}; diff --git a/src/theme/components/Item.tsx b/src/theme/components/Item.tsx new file mode 100644 index 000000000..32c4a58a2 --- /dev/null +++ b/src/theme/components/Item.tsx @@ -0,0 +1,238 @@ +import { Platform } from 'react-native'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const itemTheme: any = { + '.floatingLabel': { + 'NativeBase.Input': { + height: 50, + top: 8, + paddingTop: 3, + paddingBottom: 7, + '.multiline': { + minHeight: variables.inputHeightBase, + paddingTop: Platform.OS === PLATFORM.IOS ? 10 : 3, + paddingBottom: Platform.OS === PLATFORM.IOS ? 14 : 10 + } + }, + 'NativeBase.Label': { + paddingTop: 5 + }, + 'NativeBase.Icon': { + top: 6, + paddingTop: 8 + }, + 'NativeBase.IconNB': { + top: 6, + paddingTop: 8 + } + }, + '.fixedLabel': { + 'NativeBase.Label': { + position: null, + top: null, + left: null, + right: null, + flex: 1, + height: null, + width: null, + fontSize: variables.inputFontSize + }, + 'NativeBase.Input': { + flex: 2, + fontSize: variables.inputFontSize + } + }, + '.stackedLabel': { + 'NativeBase.Label': { + position: null, + top: null, + left: null, + right: null, + paddingTop: 5, + alignSelf: 'flex-start', + fontSize: variables.inputFontSize - 2 + }, + 'NativeBase.Icon': { + marginTop: 36 + }, + 'NativeBase.Input': { + alignSelf: Platform.OS === PLATFORM.IOS ? 'stretch' : 'flex-start', + flex: 1, + width: Platform.OS === PLATFORM.IOS ? null : variables.deviceWidth - 25, + fontSize: variables.inputFontSize, + lineHeight: variables.inputLineHeight - 6, + '.secureTextEntry': { + fontSize: variables.inputFontSize - 4 + }, + '.multiline': { + paddingTop: Platform.OS === PLATFORM.IOS ? 9 : undefined, + paddingBottom: Platform.OS === PLATFORM.IOS ? 9 : undefined + } + }, + flexDirection: null, + minHeight: variables.inputHeightBase + 15 + }, + '.inlineLabel': { + 'NativeBase.Label': { + position: null, + top: null, + left: null, + right: null, + paddingRight: 20, + height: null, + width: null, + fontSize: variables.inputFontSize + }, + 'NativeBase.Input': { + paddingLeft: 5, + fontSize: variables.inputFontSize + }, + flexDirection: 'row' + }, + 'NativeBase.Label': { + fontSize: variables.inputFontSize, + color: variables.inputColorPlaceholder, + paddingRight: 5 + }, + 'NativeBase.Icon': { + fontSize: 24, + paddingRight: 8 + }, + 'NativeBase.IconNB': { + fontSize: 24, + paddingRight: 8 + }, + 'NativeBase.Input': { + '.multiline': { + height: null + }, + height: variables.inputHeightBase, + color: variables.inputColor, + flex: 1, + top: Platform.OS === PLATFORM.IOS ? 1.5 : undefined, + fontSize: variables.inputFontSize + }, + '.underline': { + 'NativeBase.Input': { + paddingLeft: 15 + }, + '.success': { + borderColor: variables.inputSuccessBorderColor + }, + '.error': { + borderColor: variables.inputErrorBorderColor + }, + borderWidth: variables.borderWidth * 2, + borderTopWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderColor: variables.inputBorderColor + }, + '.regular': { + 'NativeBase.Input': { + paddingLeft: 8 + }, + 'NativeBase.Icon': { + paddingLeft: 10 + }, + '.success': { + borderColor: variables.inputSuccessBorderColor + }, + '.error': { + borderColor: variables.inputErrorBorderColor + }, + borderWidth: variables.borderWidth * 2, + borderColor: variables.inputBorderColor + }, + '.rounded': { + 'NativeBase.Input': { + paddingLeft: 8 + }, + 'NativeBase.Icon': { + paddingLeft: 10 + }, + '.success': { + borderColor: variables.inputSuccessBorderColor + }, + '.error': { + borderColor: variables.inputErrorBorderColor + }, + borderWidth: variables.borderWidth * 2, + borderRadius: 30, + borderColor: variables.inputBorderColor + }, + + '.success': { + 'NativeBase.Icon': { + color: variables.inputSuccessBorderColor + }, + 'NativeBase.IconNB': { + color: variables.inputSuccessBorderColor + }, + '.rounded': { + borderRadius: 30, + borderColor: variables.inputSuccessBorderColor + }, + '.regular': { + borderColor: variables.inputSuccessBorderColor + }, + '.underline': { + borderWidth: variables.borderWidth * 2, + borderTopWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderColor: variables.inputSuccessBorderColor + }, + borderColor: variables.inputSuccessBorderColor + }, + + '.error': { + 'NativeBase.Icon': { + color: variables.inputErrorBorderColor + }, + 'NativeBase.IconNB': { + color: variables.inputErrorBorderColor + }, + '.rounded': { + borderRadius: 30, + borderColor: variables.inputErrorBorderColor + }, + '.regular': { + borderColor: variables.inputErrorBorderColor + }, + '.underline': { + borderWidth: variables.borderWidth * 2, + borderTopWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderColor: variables.inputErrorBorderColor + }, + borderColor: variables.inputErrorBorderColor + }, + '.disabled': { + 'NativeBase.Icon': { + color: '#384850' + }, + 'NativeBase.IconNB': { + color: '#384850' + } + }, + '.picker': { + marginLeft: 0 + }, + + borderWidth: variables.borderWidth * 2, + borderTopWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderColor: variables.inputBorderColor, + backgroundColor: 'transparent', + flexDirection: 'row', + alignItems: 'center', + marginLeft: 2 + }; + + return itemTheme; +}; diff --git a/src/theme/components/Label.tsx b/src/theme/components/Label.tsx new file mode 100644 index 000000000..33fa597fe --- /dev/null +++ b/src/theme/components/Label.tsx @@ -0,0 +1,10 @@ +export default () => { + const labelTheme: any = { + '.focused': { + width: 0 + }, + fontSize: 17 + }; + + return labelTheme; +}; diff --git a/src/theme/components/Left.tsx b/src/theme/components/Left.tsx new file mode 100644 index 000000000..53938d940 --- /dev/null +++ b/src/theme/components/Left.tsx @@ -0,0 +1,9 @@ +export default () => { + const leftTheme: any = { + flex: 1, + alignSelf: 'center', + alignItems: 'flex-start' + }; + + return leftTheme; +}; diff --git a/src/theme/components/ListItem.tsx b/src/theme/components/ListItem.tsx new file mode 100644 index 000000000..c54ac024d --- /dev/null +++ b/src/theme/components/ListItem.tsx @@ -0,0 +1,437 @@ +import { PixelRatio, Platform } from 'react-native'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; +import pickerTheme from './Picker'; + +export default (variables /* : * */ = variable) => { + const platform = variables.platform; + const selectedStyle = { + 'NativeBase.Text': { + color: variables.listItemSelected + }, + 'NativeBase.Icon': { + color: variables.listItemSelected + } + }; + + const listItemTheme: any = { + 'NativeBase.InputGroup': { + 'NativeBase.Icon': { + paddingRight: 5 + }, + 'NativeBase.IconNB': { + paddingRight: 5 + }, + 'NativeBase.Input': { + paddingHorizontal: 5 + }, + flex: 1, + borderWidth: null, + margin: -10, + borderBottomColor: 'transparent' + }, + '.searchBar': { + 'NativeBase.Item': { + 'NativeBase.Icon': { + backgroundColor: 'transparent', + color: variables.dropdownLinkColor, + fontSize: platform === PLATFORM.IOS ? variables.iconFontSize - 10 : variables.iconFontSize - 5, + alignItems: 'center', + marginTop: 2, + paddingRight: 8 + }, + 'NativeBase.IconNB': { + backgroundColor: 'transparent', + color: null, + alignSelf: 'center' + }, + 'NativeBase.Input': { + alignSelf: 'center' + }, + alignSelf: 'center', + alignItems: 'center', + justifyContent: 'flex-start', + flex: 1, + height: platform === PLATFORM.IOS ? 30 : 40, + borderColor: 'transparent', + backgroundColor: '#fff', + borderRadius: 5 + }, + 'NativeBase.Button': { + '.transparent': { + 'NativeBase.Text': { + fontWeight: '500' + }, + paddingHorizontal: null, + paddingLeft: platform === PLATFORM.IOS ? 10 : null + }, + paddingHorizontal: platform === PLATFORM.IOS ? undefined : null, + width: platform === PLATFORM.IOS ? undefined : 0, + height: platform === PLATFORM.IOS ? undefined : 0 + }, + backgroundColor: variables.toolbarInputColor, + padding: 10, + marginLeft: null + }, + 'NativeBase.CheckBox': { + marginLeft: -10, + marginRight: 10 + }, + '.first': { + '.itemHeader': { + paddingTop: variables.listItemPadding + 3 + } + }, + '.itemHeader': { + '.first': { + paddingTop: variables.listItemPadding + 3 + }, + borderBottomWidth: platform === PLATFORM.IOS ? variables.borderWidth : null, + marginLeft: null, + padding: variables.listItemPadding, + paddingLeft: variables.listItemPadding + 5, + paddingTop: platform === PLATFORM.IOS ? variables.listItemPadding + 25 : undefined, + paddingBottom: platform === PLATFORM.ANDROID ? variables.listItemPadding + 20 : undefined, + flexDirection: 'row', + borderColor: variables.listBorderColor, + 'NativeBase.Text': { + fontSize: 14, + color: platform === PLATFORM.IOS ? undefined : variables.listNoteColor + } + }, + '.itemDivider': { + borderBottomWidth: null, + marginLeft: null, + padding: variables.listItemPadding, + paddingLeft: variables.listItemPadding + 5, + backgroundColor: variables.listDividerBg, + flexDirection: 'row', + borderColor: variables.listBorderColor + }, + '.selected': { + 'NativeBase.Left': { + ...selectedStyle + }, + 'NativeBase.Body': { + ...selectedStyle + }, + 'NativeBase.Right': { + ...selectedStyle + }, + ...selectedStyle + }, + 'NativeBase.Left': { + 'NativeBase.Body': { + 'NativeBase.Text': { + '.note': { + color: variables.listNoteColor, + fontWeight: '200' + }, + fontWeight: '600' + }, + marginLeft: 10, + alignItems: null, + alignSelf: null + }, + 'NativeBase.Icon': { + width: variables.iconFontSize - 10, + fontSize: variables.iconFontSize - 10 + }, + 'NativeBase.IconNB': { + width: variables.iconFontSize - 10, + fontSize: variables.iconFontSize - 10 + }, + 'NativeBase.Text': { + alignSelf: 'center' + }, + flexDirection: 'row' + }, + 'NativeBase.Body': { + 'NativeBase.Text': { + marginHorizontal: variables.listItemPadding, + '.note': { + color: variables.listNoteColor, + fontWeight: '200' + } + }, + alignSelf: null, + alignItems: null + }, + 'NativeBase.Right': { + 'NativeBase.Badge': { + alignSelf: null + }, + 'NativeBase.PickerNB': { + 'NativeBase.Button': { + marginRight: -15, + 'NativeBase.Text': { + color: variables.topTabBarActiveTextColor + } + } + }, + 'NativeBase.Button': { + alignSelf: null, + '.transparent': { + 'NativeBase.Text': { + color: variables.topTabBarActiveTextColor + } + } + }, + 'NativeBase.Icon': { + alignSelf: null, + fontSize: variables.iconFontSize - 8, + color: '#c9c8cd' + }, + 'NativeBase.IconNB': { + alignSelf: null, + fontSize: variables.iconFontSize - 8, + color: '#c9c8cd' + }, + 'NativeBase.Text': { + '.note': { + color: variables.listNoteColor, + fontWeight: '200' + }, + alignSelf: null + }, + 'NativeBase.Thumbnail': { + alignSelf: null + }, + 'NativeBase.Image': { + alignSelf: null + }, + 'NativeBase.Radio': { + alignSelf: null + }, + 'NativeBase.Checkbox': { + alignSelf: null + }, + 'NativeBase.Switch': { + alignSelf: null + }, + padding: null, + flex: 0.28 + }, + 'NativeBase.Text': { + '.note': { + color: variables.listNoteColor, + fontWeight: '200' + }, + alignSelf: 'center' + }, + '.last': { + marginLeft: -(variables.listItemPadding + 5), + paddingLeft: (variables.listItemPadding + 5) * 2, + top: 1 + }, + '.avatar': { + 'NativeBase.Left': { + flex: 0, + alignSelf: 'flex-start', + paddingTop: 14 + }, + 'NativeBase.Body': { + 'NativeBase.Text': { + marginLeft: null + }, + flex: 1, + paddingVertical: variables.listItemPadding, + borderBottomWidth: variables.borderWidth, + borderColor: variables.listBorderColor, + marginLeft: variables.listItemPadding + 5 + }, + 'NativeBase.Right': { + 'NativeBase.Text': { + '.note': { + fontSize: variables.noteFontSize - 2 + } + }, + flex: 0, + paddingRight: variables.listItemPadding + 5, + alignSelf: 'stretch', + paddingVertical: variables.listItemPadding, + borderBottomWidth: variables.borderWidth, + borderColor: variables.listBorderColor + }, + '.noBorder': { + 'NativeBase.Body': { + borderBottomWidth: null + }, + 'NativeBase.Right': { + borderBottomWidth: null + } + }, + borderBottomWidth: null, + paddingVertical: null, + paddingRight: null + }, + '.thumbnail': { + 'NativeBase.Left': { + flex: 0 + }, + 'NativeBase.Body': { + 'NativeBase.Text': { + marginLeft: null + }, + flex: 1, + paddingVertical: variables.listItemPadding + 8, + borderBottomWidth: variables.borderWidth, + borderColor: variables.listBorderColor, + marginLeft: variables.listItemPadding + 5 + }, + 'NativeBase.Right': { + 'NativeBase.Button': { + '.transparent': { + 'NativeBase.Text': { + fontSize: variables.listNoteSize, + color: variables.sTabBarActiveTextColor + } + }, + height: null + }, + flex: 0, + justifyContent: 'center', + alignSelf: 'stretch', + paddingRight: variables.listItemPadding + 5, + paddingVertical: variables.listItemPadding + 5, + borderBottomWidth: variables.borderWidth, + borderColor: variables.listBorderColor + }, + '.noBorder': { + 'NativeBase.Body': { + borderBottomWidth: null + }, + 'NativeBase.Right': { + borderBottomWidth: null + } + }, + borderBottomWidth: null, + paddingVertical: null, + paddingRight: null + }, + '.icon': { + '.last': { + 'NativeBase.Body': { + borderBottomWidth: null + }, + 'NativeBase.Right': { + borderBottomWidth: null + }, + borderBottomWidth: variables.borderWidth, + borderColor: variables.listBorderColor + }, + 'NativeBase.Left': { + 'NativeBase.Button': { + 'NativeBase.IconNB': { + marginHorizontal: null, + fontSize: variables.iconFontSize - 5 + }, + 'NativeBase.Icon': { + marginHorizontal: null, + fontSize: variables.iconFontSize - 8 + }, + alignSelf: 'center', + height: 29, + width: 29, + borderRadius: 6, + paddingVertical: null, + paddingHorizontal: null, + alignItems: 'center', + justifyContent: 'center' + }, + 'NativeBase.Icon': { + width: variables.iconFontSize - 5, + fontSize: variables.iconFontSize - 2 + }, + 'NativeBase.IconNB': { + width: variables.iconFontSize - 5, + fontSize: variables.iconFontSize - 2 + }, + paddingRight: variables.listItemPadding + 5, + flex: 0, + height: 44, + justifyContent: 'center', + alignItems: 'center' + }, + 'NativeBase.Body': { + 'NativeBase.Text': { + marginLeft: null, + fontSize: 17 + }, + flex: 1, + height: 44, + justifyContent: 'center', + borderBottomWidth: 1 / PixelRatio.getPixelSizeForLayoutSize(1), + borderColor: variables.listBorderColor + }, + 'NativeBase.Right': { + 'NativeBase.Text': { + textAlign: 'center', + color: '#8F8E95', + fontSize: 17 + }, + 'NativeBase.IconNB': { + color: '#C8C7CC', + fontSize: variables.iconFontSize - 10, + alignSelf: 'center', + paddingLeft: 10, + paddingTop: 3 + }, + 'NativeBase.Icon': { + color: '#C8C7CC', + fontSize: variables.iconFontSize - 10, + alignSelf: 'center', + paddingLeft: 10, + paddingTop: 3 + }, + 'NativeBase.Switch': { + marginRight: Platform.OS === PLATFORM.IOS ? undefined : -5, + alignSelf: null + }, + 'NativeBase.PickerNB': { + ...pickerTheme() + }, + flexDirection: 'row', + alignItems: 'center', + flex: 0, + alignSelf: 'stretch', + height: 44, + justifyContent: 'flex-end', + borderBottomWidth: 1 / PixelRatio.getPixelSizeForLayoutSize(1), + borderColor: variables.listBorderColor, + paddingRight: variables.listItemPadding + 5 + }, + '.noBorder': { + 'NativeBase.Body': { + borderBottomWidth: null + }, + 'NativeBase.Right': { + borderBottomWidth: null + } + }, + borderBottomWidth: null, + paddingVertical: null, + paddingRight: null, + height: 44, + justifyContent: 'center' + }, + '.noBorder': { + borderBottomWidth: null + }, + '.noIndent': { + marginLeft: null, + padding: variables.listItemPadding, + paddingLeft: variables.listItemPadding + 6 + }, + alignItems: 'center', + flexDirection: 'row', + paddingRight: variables.listItemPadding + 6, + paddingVertical: variables.listItemPadding + 3, + marginLeft: variables.listItemPadding + 6, + borderBottomWidth: 1 / PixelRatio.getPixelSizeForLayoutSize(1), + backgroundColor: variables.listBg, + borderColor: variables.listBorderColor + }; + + return listItemTheme; +}; diff --git a/src/theme/components/Picker.android.tsx b/src/theme/components/Picker.android.tsx new file mode 100644 index 000000000..2c441cd9b --- /dev/null +++ b/src/theme/components/Picker.android.tsx @@ -0,0 +1,12 @@ +export default () => { + const pickerTheme: any = { + '.note': { + color: '#8F8E95' + }, + // width: 90, + marginRight: -4, + flexGrow: 1 + }; + + return pickerTheme; +}; diff --git a/src/theme/components/Picker.ios.tsx b/src/theme/components/Picker.ios.tsx new file mode 100644 index 000000000..13d853f6a --- /dev/null +++ b/src/theme/components/Picker.ios.tsx @@ -0,0 +1,5 @@ +export default () => { + const pickerTheme: any = {}; + + return pickerTheme; +}; diff --git a/src/theme/components/Picker.tsx b/src/theme/components/Picker.tsx new file mode 100644 index 000000000..2c441cd9b --- /dev/null +++ b/src/theme/components/Picker.tsx @@ -0,0 +1,12 @@ +export default () => { + const pickerTheme: any = { + '.note': { + color: '#8F8E95' + }, + // width: 90, + marginRight: -4, + flexGrow: 1 + }; + + return pickerTheme; +}; diff --git a/src/theme/components/Radio.tsx b/src/theme/components/Radio.tsx new file mode 100644 index 000000000..ce6ebd068 --- /dev/null +++ b/src/theme/components/Radio.tsx @@ -0,0 +1,22 @@ +import { Platform } from 'react-native'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const radioTheme: any = { + '.selected': { + 'NativeBase.IconNB': { + color: Platform.OS === PLATFORM.IOS ? variables.radioColor : variables.radioSelectedColorAndroid, + lineHeight: Platform.OS === PLATFORM.IOS ? 25 : variables.radioBtnLineHeight, + height: Platform.OS === PLATFORM.IOS ? 20 : undefined + } + }, + 'NativeBase.IconNB': { + color: Platform.OS === PLATFORM.IOS ? 'transparent' : undefined, + lineHeight: Platform.OS === PLATFORM.IOS ? undefined : variables.radioBtnLineHeight, + fontSize: Platform.OS === PLATFORM.IOS ? undefined : variables.radioBtnSize + } + }; + + return radioTheme; +}; diff --git a/src/theme/components/Right.tsx b/src/theme/components/Right.tsx new file mode 100644 index 000000000..05e32b260 --- /dev/null +++ b/src/theme/components/Right.tsx @@ -0,0 +1,12 @@ +export default () => { + const rightTheme: any = { + 'NativeBase.Button': { + alignSelf: null + }, + flex: 1, + alignSelf: 'center', + alignItems: 'flex-end' + }; + + return rightTheme; +}; diff --git a/src/theme/components/Segment.tsx b/src/theme/components/Segment.tsx new file mode 100644 index 000000000..24a337b0b --- /dev/null +++ b/src/theme/components/Segment.tsx @@ -0,0 +1,55 @@ +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const platform = variables.platform; + + const segmentTheme: any = { + height: 45, + borderColor: variables.segmentBorderColorMain, + flexDirection: 'row', + justifyContent: 'center', + backgroundColor: variables.segmentBackgroundColor, + 'NativeBase.Button': { + alignSelf: 'center', + borderRadius: 0, + paddingTop: 3, + paddingBottom: 3, + height: 30, + backgroundColor: 'transparent', + borderWidth: 1, + borderLeftWidth: 0, + borderColor: variables.segmentBorderColor, + elevation: 0, + '.active': { + backgroundColor: variables.segmentActiveBackgroundColor, + 'NativeBase.Text': { + color: variables.segmentActiveTextColor + }, + 'NativeBase.Icon': { + color: variables.segmentActiveTextColor + } + }, + '.first': { + borderTopLeftRadius: platform === PLATFORM.IOS ? 5 : undefined, + borderBottomLeftRadius: platform === PLATFORM.IOS ? 5 : undefined, + borderLeftWidth: 1 + }, + '.last': { + borderTopRightRadius: platform === PLATFORM.IOS ? 5 : undefined, + borderBottomRightRadius: platform === PLATFORM.IOS ? 5 : undefined + }, + 'NativeBase.Text': { + color: variables.segmentTextColor, + fontSize: 14 + }, + 'NativeBase.Icon': { + fontSize: 22, + paddingTop: 0, + color: variables.segmentTextColor + } + } + }; + + return segmentTheme; +}; diff --git a/src/theme/components/Separator.tsx b/src/theme/components/Separator.tsx new file mode 100644 index 000000000..e82ec4ff6 --- /dev/null +++ b/src/theme/components/Separator.tsx @@ -0,0 +1,47 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const theme: any = { + '.group': { + height: 50, + paddingVertical: variables.listItemPadding - 8, + paddingTop: variables.listItemPadding + 12, + '.bordered': { + height: 50, + paddingVertical: variables.listItemPadding - 8, + paddingTop: variables.listItemPadding + 12 + } + }, + '.bordered': { + '.noTopBorder': { + borderTopWidth: 0 + }, + '.noBottomBorder': { + borderBottomWidth: 0 + }, + height: 35, + paddingTop: variables.listItemPadding + 2, + paddingBottom: variables.listItemPadding, + borderBottomWidth: variables.borderWidth, + borderTopWidth: variables.borderWidth, + borderColor: variables.listBorderColor + }, + 'NativeBase.Text': { + fontSize: variables.tabBarTextSize - 2, + color: '#777' + }, + '.noTopBorder': { + borderTopWidth: 0 + }, + '.noBottomBorder': { + borderBottomWidth: 0 + }, + height: 38, + backgroundColor: '#F0EFF5', + flex: 1, + justifyContent: 'center', + paddingLeft: variables.listItemPadding + 5 + }; + + return theme; +}; diff --git a/src/theme/components/Spinner.tsx b/src/theme/components/Spinner.tsx new file mode 100644 index 000000000..8ff5d102d --- /dev/null +++ b/src/theme/components/Spinner.tsx @@ -0,0 +1,5 @@ +export default () => { + const spinnerTheme = {}; + + return spinnerTheme; +}; diff --git a/src/theme/components/Subtitle.tsx b/src/theme/components/Subtitle.tsx new file mode 100644 index 000000000..e39f697fa --- /dev/null +++ b/src/theme/components/Subtitle.tsx @@ -0,0 +1,16 @@ +import { Platform } from 'react-native'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const subtitleTheme: any = { + fontSize: variables.subTitleFontSize, + fontFamily: variables.titleFontfamily, + color: variables.subtitleColor, + textAlign: 'center', + paddingLeft: Platform.OS === PLATFORM.IOS ? 4 : 0, + marginLeft: Platform.OS === PLATFORM.IOS ? undefined : -3 + }; + + return subtitleTheme; +}; diff --git a/src/theme/components/SwipeRow.tsx b/src/theme/components/SwipeRow.tsx new file mode 100644 index 000000000..b51947850 --- /dev/null +++ b/src/theme/components/SwipeRow.tsx @@ -0,0 +1,44 @@ +export default () => { + const swipeRowTheme: any = { + 'NativeBase.ListItem': { + '.list': { + backgroundColor: '#FFF' + }, + marginLeft: 0 + }, + 'NativeBase.Left': { + flex: 0, + alignSelf: null, + alignItems: null, + 'NativeBase.Button': { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + alignSelf: 'stretch', + borderRadius: 0 + } + }, + 'NativeBase.Right': { + flex: 0, + alignSelf: null, + alignItems: null, + 'NativeBase.Button': { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + alignSelf: 'stretch', + borderRadius: 0 + } + }, + 'NativeBase.Button': { + flex: 1, + height: null, + alignItems: 'center', + justifyContent: 'center', + alignSelf: 'stretch', + borderRadius: 0 + } + }; + + return swipeRowTheme; +}; diff --git a/src/theme/components/Switch.tsx b/src/theme/components/Switch.tsx new file mode 100644 index 000000000..3f4417e4c --- /dev/null +++ b/src/theme/components/Switch.tsx @@ -0,0 +1,7 @@ +export default () => { + const switchTheme = { + marginVertical: -5 + }; + + return switchTheme; +}; diff --git a/src/theme/components/Tab.tsx b/src/theme/components/Tab.tsx new file mode 100644 index 000000000..9c07ea9a6 --- /dev/null +++ b/src/theme/components/Tab.tsx @@ -0,0 +1,8 @@ +export default () => { + const tabTheme = { + flex: 1, + backgroundColor: '#FFF' + }; + + return tabTheme; +}; diff --git a/src/theme/components/TabBar.tsx b/src/theme/components/TabBar.tsx new file mode 100644 index 000000000..3630d364c --- /dev/null +++ b/src/theme/components/TabBar.tsx @@ -0,0 +1,56 @@ +import { scale } from 'react-native-size-matters'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const tabBarTheme: any = { + '.tabIcon': { + height: undefined + }, + '.vertical': { + height: 60 + }, + 'NativeBase.Button': { + '.transparent': { + 'NativeBase.Text': { + fontSize: variables.tabFontSize, + color: variables.sTabBarActiveTextColor, + fontWeight: '400' + }, + 'NativeBase.IconNB': { + color: variables.sTabBarActiveTextColor + } + }, + 'NativeBase.IconNB': { + color: variables.sTabBarActiveTextColor + }, + 'NativeBase.Text': { + fontSize: variables.tabFontSize, + color: variables.sTabBarActiveTextColor, + fontWeight: '400' + }, + '.isTabActive': { + 'NativeBase.Text': { + fontWeight: '900' + } + }, + flex: 1, + alignSelf: 'stretch', + alignItems: 'center', + justifyContent: 'center', + borderRadius: null, + borderBottomColor: 'transparent', + backgroundColor: variables.tabBgColor + }, + height: scale(50), + flexDirection: 'row', + justifyContent: 'space-around', + borderWidth: 1, + borderTopWidth: 0, + borderLeftWidth: 0, + borderRightWidth: 0, + borderBottomColor: '#ccc', + backgroundColor: variables.tabBgColor + }; + + return tabBarTheme; +}; diff --git a/src/theme/components/TabContainer.tsx b/src/theme/components/TabContainer.tsx new file mode 100644 index 000000000..b2ee5b918 --- /dev/null +++ b/src/theme/components/TabContainer.tsx @@ -0,0 +1,16 @@ +import { Platform } from 'react-native'; +import { scale } from 'react-native-size-matters'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const tabContainerTheme: any = { + height: scale(50), + flexDirection: 'row', + justifyContent: 'space-around', + borderBottomWidth: Platform.OS === PLATFORM.IOS ? variables.borderWidth : 0, + borderColor: variables.topTabBarBorderColor + }; + + return tabContainerTheme; +}; diff --git a/src/theme/components/TabHeading.tsx b/src/theme/components/TabHeading.tsx new file mode 100644 index 000000000..5f9281ddb --- /dev/null +++ b/src/theme/components/TabHeading.tsx @@ -0,0 +1,41 @@ +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const platform = variables.platform; + + const tabHeadingTheme = { + flexDirection: 'row', + backgroundColor: variables.tabDefaultBg, + flex: 1, + alignItems: 'center', + justifyContent: 'center', + paddingTop: platform === PLATFORM.ANDROID ? 5 : 0, + '.scrollable': { + paddingHorizontal: 20, + flex: platform === PLATFORM.ANDROID ? 0 : 1, + minWidth: platform === PLATFORM.ANDROID ? undefined : 60 + }, + 'NativeBase.Text': { + color: variables.topTabBarTextColor, + marginHorizontal: 7, + marginTop: -5 + }, + 'NativeBase.Icon': { + color: variables.topTabBarTextColor, + fontSize: platform === PLATFORM.IOS ? 26 : undefined + }, + '.active': { + 'NativeBase.Text': { + color: variables.topTabBarActiveTextColor, + fontWeight: '600', + marginTop: -5 + }, + 'NativeBase.Icon': { + color: variables.topTabBarActiveTextColor + } + } + }; + + return tabHeadingTheme; +}; diff --git a/src/theme/components/Text.tsx b/src/theme/components/Text.tsx new file mode 100644 index 000000000..7c180871b --- /dev/null +++ b/src/theme/components/Text.tsx @@ -0,0 +1,15 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const textTheme: any = { + fontSize: variables.DefaultFontSize, + fontFamily: variables.fontFamily, + color: variables.textColor, + '.note': { + color: '#a7a7a7', + fontSize: variables.noteFontSize + } + }; + + return textTheme; +}; diff --git a/src/theme/components/Textarea.tsx b/src/theme/components/Textarea.tsx new file mode 100644 index 000000000..1ce89e72d --- /dev/null +++ b/src/theme/components/Textarea.tsx @@ -0,0 +1,23 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const textAreaTheme: any = { + '.underline': { + borderBottomWidth: variables.borderWidth, + marginTop: 5, + borderColor: variables.inputBorderColor + }, + '.bordered': { + borderWidth: 1, + marginTop: 5, + borderColor: variables.inputBorderColor + }, + color: variables.textColor, + paddingLeft: 10, + paddingRight: 5, + fontSize: 15, + textAlignVertical: 'top' + }; + + return textAreaTheme; +}; diff --git a/src/theme/components/Thumbnail.tsx b/src/theme/components/Thumbnail.tsx new file mode 100644 index 000000000..a6f94234a --- /dev/null +++ b/src/theme/components/Thumbnail.tsx @@ -0,0 +1,38 @@ +export default () => { + const thumbnailTheme: any = { + '.square': { + borderRadius: 0, + '.small': { + width: 36, + height: 36, + borderRadius: 0 + }, + '.large': { + width: 80, + height: 80, + borderRadius: 0 + } + }, + '.small': { + width: 36, + height: 36, + borderRadius: 18, + '.square': { + borderRadius: 0 + } + }, + '.large': { + width: 80, + height: 80, + borderRadius: 40, + '.square': { + borderRadius: 0 + } + }, + width: 56, + height: 56, + borderRadius: 28 + }; + + return thumbnailTheme; +}; diff --git a/src/theme/components/Title.tsx b/src/theme/components/Title.tsx new file mode 100644 index 000000000..0010c32ab --- /dev/null +++ b/src/theme/components/Title.tsx @@ -0,0 +1,18 @@ +import { Platform } from 'react-native'; +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const titleTheme: any = { + fontSize: variables.titleFontSize, + fontFamily: variables.titleFontfamily, + color: variables.titleFontColor, + fontWeight: Platform.OS === PLATFORM.IOS ? '700' : undefined, + textAlign: 'center', + paddingLeft: Platform.OS === PLATFORM.IOS ? 4 : 0, + marginLeft: Platform.OS === PLATFORM.IOS ? undefined : -3, + paddingTop: 1 + }; + + return titleTheme; +}; diff --git a/src/theme/components/Toast.tsx b/src/theme/components/Toast.tsx new file mode 100644 index 000000000..245084b63 --- /dev/null +++ b/src/theme/components/Toast.tsx @@ -0,0 +1,39 @@ +import { PLATFORM } from './../variables/commonColor'; +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const platform = variables.platform; + + const toastTheme: any = { + '.danger': { + backgroundColor: variables.brandDanger + }, + '.warning': { + backgroundColor: variables.brandWarning + }, + '.success': { + backgroundColor: variables.brandSuccess + }, + backgroundColor: 'rgba(0,0,0,0.8)', + borderRadius: platform === PLATFORM.IOS ? 5 : 0, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + padding: 10, + minHeight: 50, + 'NativeBase.Text': { + color: '#fff', + flex: 1 + }, + 'NativeBase.Button': { + backgroundColor: 'transparent', + height: 30, + elevation: 0, + 'NativeBase.Text': { + fontSize: 14 + } + } + }; + + return toastTheme; +}; diff --git a/src/theme/components/View.tsx b/src/theme/components/View.tsx new file mode 100644 index 000000000..f44ce4c57 --- /dev/null +++ b/src/theme/components/View.tsx @@ -0,0 +1,11 @@ +import variable from './../variables/platform'; + +export default (variables /* : * */ = variable) => { + const viewTheme: any = { + '.padder': { + padding: variables.contentPadding + } + }; + + return viewTheme; +}; diff --git a/src/theme/components/index.tsx b/src/theme/components/index.tsx new file mode 100644 index 000000000..23060e284 --- /dev/null +++ b/src/theme/components/index.tsx @@ -0,0 +1,238 @@ +import _ from 'lodash'; +import variable from './../variables/platform'; +import badgeTheme from './Badge'; +import bodyTheme from './Body'; +import buttonTheme from './Button'; +import cardTheme from './Card'; +import cardItemTheme from './CardItem'; +import checkBoxTheme from './CheckBox'; +import containerTheme from './Container'; +import contentTheme from './Content'; +import fabTheme from './Fab'; +import footerTheme from './Footer'; +import footerTabTheme from './FooterTab'; +import formTheme from './Form'; +import h1Theme from './H1'; +import h2Theme from './H2'; +import h3Theme from './H3'; +import headerTheme from './Header'; +import iconTheme from './Icon'; +import inputTheme from './Input'; +import inputGroupTheme from './InputGroup'; +import itemTheme from './Item'; +import labelTheme from './Label'; +import leftTheme from './Left'; +import listItemTheme from './ListItem'; +import pickerTheme from './Picker'; +import radioTheme from './Radio'; +import rightTheme from './Right'; +import segmentTheme from './Segment'; +import separatorTheme from './Separator'; +import spinnerTheme from './Spinner'; +import subtitleTheme from './Subtitle'; +import swipeRowTheme from './SwipeRow'; +import switchTheme from './Switch'; +import tabTheme from './Tab'; +import tabBarTheme from './TabBar'; +import tabContainerTheme from './TabContainer'; +import tabHeadingTheme from './TabHeading'; +import textTheme from './Text'; +import textAreaTheme from './Textarea'; +import thumbnailTheme from './Thumbnail'; +import titleTheme from './Title'; +import toastTheme from './Toast'; +import viewTheme from './View'; + +export default class Theme { + public static getTheme(variables = variable) { + const theme = { + variables, + 'NativeBase.Left': { + ...leftTheme() + }, + 'NativeBase.Right': { + ...rightTheme() + }, + 'NativeBase.Body': { + ...bodyTheme() + }, + + 'NativeBase.Header': { + ...headerTheme(variables) + }, + + 'NativeBase.Button': { + ...buttonTheme(variables) + }, + + 'NativeBase.Title': { + ...titleTheme(variables) + }, + 'NativeBase.Subtitle': { + ...subtitleTheme(variables) + }, + + 'NativeBase.InputGroup': { + ...inputGroupTheme(variables) + }, + + 'NativeBase.Input': { + ...inputTheme(variables) + }, + + 'NativeBase.Badge': { + ...badgeTheme(variables) + }, + + 'NativeBase.CheckBox': { + ...checkBoxTheme(variables) + }, + + 'NativeBase.Radio': { + ...radioTheme(variables) + }, + + 'NativeBase.Card': { + ...cardTheme(variables) + }, + + 'NativeBase.CardItem': { + ...cardItemTheme(variables) + }, + + 'NativeBase.Toast': { + ...toastTheme(variables) + }, + + 'NativeBase.H1': { + ...h1Theme(variables) + }, + 'NativeBase.H2': { + ...h2Theme(variables) + }, + 'NativeBase.H3': { + ...h3Theme(variables) + }, + 'NativeBase.Form': { + ...formTheme() + }, + + 'NativeBase.Container': { + ...containerTheme(variables) + }, + 'NativeBase.Content': { + ...contentTheme() + }, + + 'NativeBase.Footer': { + ...footerTheme(variables) + }, + + 'NativeBase.Tabs': { + flex: 1 + }, + + 'NativeBase.FooterTab': { + ...footerTabTheme(variables) + }, + + 'NativeBase.ListItem': { + ...listItemTheme(variables) + }, + + 'NativeBase.ListItem1': { + ...listItemTheme(variables) + }, + + 'NativeBase.Icon': { + ...iconTheme(variables) + }, + 'NativeBase.IconNB': { + ...iconTheme(variables) + }, + 'NativeBase.Text': { + ...textTheme(variables) + }, + 'NativeBase.Spinner': { + ...spinnerTheme() + }, + + 'NativeBase.Fab': { + ...fabTheme() + }, + + 'NativeBase.Item': { + ...itemTheme(variables) + }, + + 'NativeBase.Label': { + ...labelTheme() + }, + + 'NativeBase.Textarea': { + ...textAreaTheme(variables) + }, + + 'NativeBase.PickerNB': { + ...pickerTheme(), + 'NativeBase.Button': { + 'NativeBase.Text': {} + } + }, + + 'NativeBase.Tab': { + ...tabTheme() + }, + + 'NativeBase.Segment': { + ...segmentTheme(variables) + }, + + 'NativeBase.TabBar': { + ...tabBarTheme(variables) + }, + 'NativeBase.ViewNB': { + ...viewTheme(variables) + }, + 'NativeBase.TabHeading': { + ...tabHeadingTheme(variables) + }, + 'NativeBase.TabContainer': { + ...tabContainerTheme(variables) + }, + 'NativeBase.Switch': { + ...switchTheme() + }, + 'NativeBase.Separator': { + ...separatorTheme(variables) + }, + 'NativeBase.SwipeRow': { + ...swipeRowTheme() + }, + 'NativeBase.Thumbnail': { + ...thumbnailTheme() + } + }; + + const cssifyTheme = (grandparent: any, parent: any, parentKey: any) => { + _.forEach(parent, (style: any, styleName: any) => { + if (styleName.indexOf('.') === 0 && parentKey && parentKey.indexOf('.') === 0) { + if (grandparent) { + if (!grandparent[styleName]) { + grandparent[styleName] = {}; + } else { + grandparent[styleName][parentKey] = style; + } + } + } + if (style && typeof style === 'object' && styleName !== 'fontVariant' && styleName !== 'transform') { + cssifyTheme(parent, style, styleName); + } + }); + }; + + cssifyTheme(null, theme, null); + + return theme; + } +}; diff --git a/src/theme/variables/commonColor.tsx b/src/theme/variables/commonColor.tsx new file mode 100644 index 000000000..8bd8561e5 --- /dev/null +++ b/src/theme/variables/commonColor.tsx @@ -0,0 +1,313 @@ +import color from 'color'; +import { Dimensions, PixelRatio, Platform } from 'react-native'; +import { scale } from 'react-native-size-matters'; + +export const PLATFORM = { + ANDROID: 'android', + IOS: 'ios', + MATERIAL: 'material', + WEB: 'web' +}; + +const deviceHeight = Dimensions.get('window').height; +const deviceWidth = Dimensions.get('window').width; +const platform = Platform.OS; +const platformStyle: any = undefined; +const isIphoneX = platform === PLATFORM.IOS && (deviceHeight === 812 || deviceWidth === 812 || deviceHeight === 896 || deviceWidth === 896); + +const fiori3Brand = '#0a6ed1'; +const fiori3Success = '#16ab54'; +const fiori3Error = '#ee0000'; +const fiori3Bg = '#f7f7f7'; +const fiori3Primary2 = '#0a6ed1'; + +const darkLightRatio = 0.5; + +const primary = fiori3Brand; +const primaryLight = color(primary).lighten(darkLightRatio).hex(); +const primaryDark = color(primary).darken(darkLightRatio).hex(); +const info = fiori3Primary2; +const infoLight = color(info).lighten(darkLightRatio).hex(); +const infoDark = color(info).darken(darkLightRatio).hex(); +const success = fiori3Success; +const successLight = color(success).lighten(darkLightRatio).hex(); +const successDark = color(success).darken(darkLightRatio).hex(); +const danger = fiori3Error; +const dangerLight = color(danger).lighten(darkLightRatio).hex(); +const dangerDark = color(danger).darken(darkLightRatio).hex(); +const warning = '#FB8C00'; +const warningLight = color(warning).lighten(darkLightRatio).hex(); +const warningDark = color(warning).darken(darkLightRatio).hex(); +const disabled = '#757575'; +const disabledLight = color(disabled).lighten(darkLightRatio).hex(); +const disabledDark = color(disabled).darken(darkLightRatio).hex(); +const background = fiori3Bg; +const backgroundHeader = '#E7E7E7'; +const borderColor = '#ccc'; +const transparentBg = 'rgba(256,256,256,0.3)'; +const dark = '#000'; +const light = '#f4f4f4'; +const fontSize = scale(22); +const fontSizeIconBase = platform === PLATFORM.IOS ? 30 : 28; + +export class CommonColor { + public platformStyle = platformStyle; + public platform = platform; + + // Color + public brandPrimary = primary; + public brandPrimaryLight = primaryLight; + public brandPrimaryDark = primaryDark; + public brandInfo = info; + public brandInfoLight = infoLight; + public brandInfoDark = infoDark; + public brandSuccess = success; + public brandSuccessLight = successLight; + public brandSuccessDark = successDark; + public brandDanger = danger; + public brandDangerLight = dangerLight; + public brandDangerDark = dangerDark; + public brandWarning = warning; + public brandWarningLight = warningLight; + public brandWarningDark = warningDark; + public brandDisabled = disabled; + public brandDisabledLight = disabledLight; + public brandDisabledDark = disabledDark; + public brandBackground = background; + + public brandDark = dark; + public brandLight = light; + + // Accordion + public headerStyle = light; + public iconStyle = dark; + public contentStyle = light; + public expandedIconStyle = dark; + public accordionBorderColor = disabledLight; + + // ActionSheet + public elevation = 4; + public containerTouchableBackgroundColor = 'rgba(0,0,0,0.4)'; + public innerTouchableBackgroundColor = light; + public listItemHeight = 50; + public listItemBorderColor = 'transparent'; + public marginHorizontal = -15; + public marginLeft = 14; + public marginTop = 15; + public minHeight = 56; + public padding = 15; + public touchableTextColor = disabled; + + // Android + public androidRipple = true; + public androidRippleColor = transparentBg; + public androidRippleColorDark = 'rgba(0,0,0,0.15)'; + public buttonUppercaseAndroidText = true; + + // Badge + public badgeBg = light; + public badgeColor = primaryDark; + public badgePadding = platform === PLATFORM.IOS ? 3 : 0; + + // Button + public buttonFontFamily = platform === PLATFORM.IOS ? 'System' : 'Roboto_medium'; + public buttonDisabledBg = disabled; + public buttonBg = transparentBg; + public buttonPadding = 6; + public buttonPrimaryBg = primaryDark; + public buttonPrimaryColor = light; + public buttonInfoBg = info; + public buttonInfoColor = light; + public buttonSuccessBg = success; + public buttonSuccessColor = light; + public buttonDangerBg = danger; + public buttonDangerColor = light; + public buttonWarningBg = warning; + public buttonWarningColor = light; + public buttonTextSize = platform === PLATFORM.IOS ? fontSize * 1.1 : fontSize - 1; + public buttonTextSizeLarge = fontSize * 1.5; + public buttonTextSizeSmall = fontSize * 0.8; + public borderRadiusLarge = fontSize * 3.8; + public iconSizeLarge = fontSizeIconBase * 1.5; + public iconSizeSmall = fontSizeIconBase * 0.6; + + // Card + public cardDefaultBg = background; + public cardBorderColor = borderColor; + public cardBorderRadius = 2; + public cardItemPadding = platform === PLATFORM.IOS ? 10 : 12; + + // CheckBox + public CheckboxRadius = platform === PLATFORM.IOS ? scale(13) : 0; + public CheckboxBorderWidth = platform === PLATFORM.IOS ? scale(1) : scale(2); + public CheckboxPaddingLeft = platform === PLATFORM.IOS ? scale(4) : scale(2); + public CheckboxPaddingBottom = platform === PLATFORM.IOS ? 0 : scale(5); + public CheckboxIconSize = platform === PLATFORM.IOS ? scale(21) : scale(16); + public CheckboxIconMarginTop = platform === PLATFORM.IOS ? undefined : scale(0); + public CheckboxFontSize = platform === PLATFORM.IOS ? scale(23 / 0.9) : scale(17); + public checkboxBgColor = light; + public checkboxSize = scale(18); + public checkboxTickColor = primaryDark; + public checkboxDefaultColor = 'transparent'; + + // Container + public containerBgColor = background; + + // Date Picker + public datePickerTextColor = dark; + public datePickerBg = 'transparent'; + + // FAB + public fabWidth = 56; + + // Font + public DefaultFontSize = 16; + public fontFamily = platform === PLATFORM.IOS ? 'System' : 'Roboto'; + public fontSizeBase = fontSize; + public fontSizeH1 = fontSize * 1.8; + public fontSizeH2 = fontSize * 1.6; + public fontSizeH3 = fontSize * 1.4; + + // Footer + public footerHeight = scale(40); + public footerDefaultBg = primaryDark; + public footerPaddingBottom = 0; + + // FooterTab + public tabBarTextColor = primaryDark; + public tabBarTextSize = platform === PLATFORM.IOS ? 14 : 11; + public activeTab = platform === PLATFORM.IOS ? primary : light; + public sTabBarActiveTextColor = primaryLight; + public tabBarActiveTextColor = platform === PLATFORM.IOS ? primaryLight : light; + public tabActiveBgColor = platform === PLATFORM.IOS ? primaryLight : primary; + + // Header + public toolbarBtnColor = primaryDark; + public toolbarDefaultBg = primary; + public toolbarHeight = platform === PLATFORM.IOS ? 64 : 56; + public toolbarSearchIconSize = platform === PLATFORM.IOS ? 20 : 23; + public toolbarInputColor = platform === PLATFORM.IOS ? disabledLight : light; + public searchBarHeight = platform === PLATFORM.IOS ? 30 : 40; + public searchBarInputHeight = platform === PLATFORM.IOS ? 30 : 50; + public toolbarBtnTextColor = primaryDark; + public iosStatusbar = 'dark-content'; + public toolbarDefaultBorder = light; + public statusBarColor = color(primary).darken(0.2).hex(); + public darkenHeader = color(light).darken(0.03).hex(); + + // Icon + public iconFamily = 'Ionicons'; + public iconFontSize = fontSizeIconBase; + public iconHeaderSize = platform === PLATFORM.IOS ? 33 : 24; + + // InputGroup + public inputFontSize = 17; + public inputBorderColor = borderColor; + public inputSuccessBorderColor = success; + public inputErrorBorderColor = danger; + public inputHeightBase = 50; + public inputGroupBg = transparentBg; + public placeholderTextColor = borderColor; + public inputColor = primaryDark; + public inputColorPlaceholder = disabledDark; + + // Line Height + public buttonLineHeight = 19; + public lineHeightH1 = 32; + public lineHeightH2 = 27; + public lineHeightH3 = 22; + public lineHeight = platform === PLATFORM.IOS ? 20 : 24; + + // List + public listBg = 'transparent'; + public listBorderColor = borderColor; + public listDividerBg = light; + public listBtnUnderlayColor = disabledLight; + public listItemPadding = platform === PLATFORM.IOS ? 10 : 12; + public listNoteColor = disabledDark; + public listNoteSize = 13; + public listItemSelected = platform === PLATFORM.IOS ? info : primary; + + // Progress Bar + public defaultProgressColor = danger; + public inverseProgressColor = dark; + + // Radio Button + public radioBtnSize = platform === PLATFORM.IOS ? 25 : 23; + public radioSelectedColorAndroid = primary; + public radioBtnLineHeight = platform === PLATFORM.IOS ? 29 : 24; + public radioColor = primary; + + // Segment + public segmentBackgroundColor = platform === PLATFORM.IOS ? light : primary; + public segmentActiveBackgroundColor = platform === PLATFORM.IOS ? info : light; + public segmentTextColor = platform === PLATFORM.IOS ? info : light; + public segmentActiveTextColor = platform === PLATFORM.IOS ? light : primary; + public segmentBorderColor = platform === PLATFORM.IOS ? info : light; + public segmentBorderColorMain = platform === PLATFORM.IOS ? borderColor : primary; + + // Spinner + public defaultSpinnerColor = primaryDark; + public inverseSpinnerColor = primaryLight; + + // Tab + public tabDefaultBg = primaryDark; + public topTabBarTextColor = disabledLight; + public topTabBarActiveTextColor = light; + public topTabBarBorderColor = platform === PLATFORM.IOS ? borderColor : borderColor; + public topTabBarActiveBorderColor = borderColor; + + // Tabs + public tabBgColor = light; + public tabFontSize = 15; + + // Text + public textColor = primaryDark; + public headerTextColor = primaryDark; + public headerBgColor = backgroundHeader; + public headerBgColorLight = color(backgroundHeader).lighten(0.025).hex(); + public headerBgColorDark = color(backgroundHeader).darken(0.025).hex(); + public inverseTextColor = light; + public noteFontSize = 14; + public defaultTextColor = primaryDark; + + // Title + public titleFontfamily = platform === PLATFORM.IOS ? 'System' : 'Roboto_medium'; + public titleFontSize = platform === PLATFORM.IOS ? 17 : 19; + public subTitleFontSize = platform === PLATFORM.IOS ? 11 : 14; + public subtitleColor = primaryDark; + public titleFontColor = primaryDark; + + // Other + public borderRadiusBase = platform === PLATFORM.IOS ? 5 : 2; + public borderWidth = 1 / PixelRatio.getPixelSizeForLayoutSize(1); + public contentPadding = 10; + public dropdownLinkColor = disabledDark; + public inputLineHeight = 24; + public deviceWidth = deviceWidth; + public deviceHeight = deviceHeight; + public isIphoneX = isIphoneX; + + public inputGroupRoundedBorderRadius = 30; + + // iPhoneX SafeArea + public Inset = { + portrait: { + topInset: 24, + leftInset: 0, + rightInset: 0, + bottomInset: 34 + }, + landscape: { + topInset: 0, + leftInset: 44, + rightInset: 44, + bottomInset: 21 + } + } + + constructor() {} +}; + +export default new CommonColor(); + diff --git a/src/theme/variables/material.tsx b/src/theme/variables/material.tsx new file mode 100644 index 000000000..2e2f47a7a --- /dev/null +++ b/src/theme/variables/material.tsx @@ -0,0 +1,3 @@ +import { CommonColor } from './commonColor'; + +export default new CommonColor(); diff --git a/src/theme/variables/platform.tsx b/src/theme/variables/platform.tsx new file mode 100644 index 000000000..2e2f47a7a --- /dev/null +++ b/src/theme/variables/platform.tsx @@ -0,0 +1,3 @@ +import { CommonColor } from './commonColor'; + +export default new CommonColor(); diff --git a/src/types/ActionResponse.tsx b/src/types/ActionResponse.tsx new file mode 100644 index 000000000..7d8a1d0a4 --- /dev/null +++ b/src/types/ActionResponse.tsx @@ -0,0 +1,4 @@ +export interface ActionResponse { + status: string; + error: string; +} diff --git a/src/types/Address.tsx b/src/types/Address.tsx new file mode 100644 index 000000000..3e5471521 --- /dev/null +++ b/src/types/Address.tsx @@ -0,0 +1,11 @@ +export default interface Address { + address1: string; + address2?: string; + postalCode: string; + city: string; + department?: string; + region?: string; + country: string; + latitude: number; + longitude: number; +} diff --git a/src/types/Authorization.tsx b/src/types/Authorization.tsx new file mode 100644 index 000000000..caecda5dd --- /dev/null +++ b/src/types/Authorization.tsx @@ -0,0 +1,74 @@ +export enum Entity { + SITE = 'Site', + SITES = 'Sites', + SITE_AREA = 'SiteArea', + SITE_AREAS = 'SiteAreas', + COMPANY = 'Company', + COMPANIES = 'Companies', + CHARGING_STATION = 'ChargingStation', + CHARGING_STATIONS = 'ChargingStations', + TENANT = 'Tenant', + TENANTS = 'Tenants', + TRANSACTION = 'Transaction', + TRANSACTIONS = 'Transactions', + TRANSACTION_METER_VALUES = 'MeterValues', + TRANSACTION_STOP = 'Stop', + REPORT = 'Report', + USER = 'User', + USERS = 'Users', + VEHICLE_MANUFACTURER = 'VehicleManufacturer', + VEHICLE_MANUFACTURERS = 'VehicleManufacturers', + VEHICLES = 'Vehicles', + VEHICLE = 'Vehicle', + LOGGINGS = 'Loggings', + LOGGING = 'Logging', + PRICING = 'Pricing', + BILLING = 'Billing', + SETTING = 'Setting', + SETTINGS = 'Settings', + TOKENS = 'Tokens', + TOKEN = 'Token', + OCPI_ENDPOINT = 'OcpiEndpoint', + OCPI_ENDPOINTS = 'OcpiEndpoints', + CONNECTION = 'Connection', + CONNECTIONS = 'Connections', +} + +export enum Role { + SUPER_ADMIN = 'S', + ADMIN = 'A', + BASIC = 'B', + DEMO = 'D', +} + +export enum Action { + READ = 'Read', + CREATE = 'Create', + UPDATE = 'Update', + DELETE = 'Delete', + LOGOUT = 'Logout', + LIST = 'List', + RESET = 'Reset', + AUTHORIZE = 'Authorize', + CLEAR_CACHE = 'ClearCache', + DATA_TRANSFER = 'DataTransfer', + STOP_TRANSACTION = 'StopTransaction', + REMOTE_STOP_TRANSACTION = 'RemoteStopTransaction', + START_TRANSACTION = 'StartTransaction', + REMOTE_START_TRANSACTION = 'RemoteStartTransaction', + REFUND_TRANSACTION = 'RefundTransaction', + UNLOCK_CONNECTOR = 'UnlockConnector', + GET_CONFIGURATION = 'GetConfiguration', + PING = 'Ping', + TRIGGER_JOB = 'TriggerJob', + REGISTER = 'Register', + GENERATE_LOCAL_TOKEN = 'GenerateLocalToken', + CHECK_CONNECTION_BILLING = 'CheckBillingConnection', + SYNCHRONIZE_BILLING = 'SynchronizeUsersBilling', + BILLING_TRANSACTION = 'BillingTransaction', + READ_BILLING_TAXES = 'ReadBillingTaxes', + POWER_LIMITATION = 'PowerLimitation', + SET_CHARGING_PROFILE = 'SetChargingProfile', + EXPORT_PARAMS = 'ExportParams', +} + diff --git a/src/types/BaseProps.tsx b/src/types/BaseProps.tsx new file mode 100644 index 000000000..1ab9742f4 --- /dev/null +++ b/src/types/BaseProps.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +export default interface BaseProps { + navigation: any; + children?: React.ReactNode; + key?: string; +} diff --git a/src/types/ChargingStation.tsx b/src/types/ChargingStation.tsx new file mode 100644 index 000000000..e151a0843 --- /dev/null +++ b/src/types/ChargingStation.tsx @@ -0,0 +1,114 @@ +import CreatedUpdatedProps from './CreatedUpdatedProps'; +import { KeyValue } from './Global'; +import SiteArea from './SiteArea'; +import { InactivityStatus } from './Transaction'; + +export default interface ChargingStation extends CreatedUpdatedProps { + id?: string; + siteAreaID: string; + chargePointSerialNumber: string; + chargePointModel: string; + chargeBoxSerialNumber: string; + chargePointVendor: string; + iccid: string; + imsi: string; + meterType: string; + firmwareVersion: string; + meterSerialNumber: string; + endpoint: string; + ocppVersion: string; + ocppProtocol: string; + cfApplicationIDAndInstanceIndex: string; + lastHeartBeat: Date; + deleted: boolean; + inactive: boolean; + lastReboot: Date; + chargingStationURL: string; + numberOfConnectedPhase: number; + maximumPower: number; + cannotChargeInParallel: boolean; + powerLimitUnit: string; + latitude: number; + longitude: number; + connectors: Connector[]; + errorCode?: string; + currentIPAddress?: string; + siteArea?: SiteArea; + capabilities?: ChargingStationCapabilities; + ocppAdvancedCommands?: OcppAdvancedCommands[]; + ocppStandardParameters?: KeyValue[]; + ocppVendorParameters?: KeyValue[]; + currentType: ChargingStationCurrentType; +} + +export interface Connector { + connectorId: number; + currentConsumption: number; + currentStateOfCharge?: number; + totalInactivitySecs?: number; + totalConsumption?: number; + status: ChargePointStatus; + errorCode?: string; + info?: string; + vendorErrorCode?: string; + power: number; + type: ConnectorType; + voltage?: number; + amperage?: number; + activeTransactionID: number; + activeTransactionDate: Date; + activeTagID: string; + statusLastChangedOn?: Date; + inactivityStatus: InactivityStatus; +} + +export enum ChargePointStatus { + AVAILABLE = 'Available', + PREPARING = 'Preparing', + CHARGING = 'Charging', + OCCUPIED = 'Occupied', + SUSPENDED_EVSE = 'SuspendedEVSE', + SUSPENDED_EV = 'SuspendedEV', + FINISHING = 'Finishing', + RESERVED = 'Reserved', + UNAVAILABLE = 'Unavailable', + FAULTED = 'Faulted', +} + +export enum ConnectorType { + TYPE_2 = 'T2', + COMBO_CCS = 'CCS', + CHADEMO = 'C', + TYPE_1 = 'T1', + TYPE_1_CCS = 'T1CCS', + DOMESTIC = 'D', + UNKNOWN = 'U', +} + +export enum ChargingStationCurrentType { + AC = 'AC', + DC = 'DC', + AC_DC = 'AC/DC', +} + +export interface ChargingStationConfiguration { + id: string; + timestamp: Date; + configuration: KeyValue[]; +} + +export interface ChargingStationCapabilities { + supportStaticLimitationForChargingStation?: boolean; + supportStaticLimitationPerConnector?: boolean; + supportChargingProfiles?: boolean; + supportTxDefaultProfile?: boolean; +} + +export interface OcppCommand { + command: string; + parameters: string[]; +} + +export interface OcppAdvancedCommands { + command: string | OcppCommand; +} diff --git a/src/types/Company.tsx b/src/types/Company.tsx new file mode 100644 index 000000000..dac421af6 --- /dev/null +++ b/src/types/Company.tsx @@ -0,0 +1,9 @@ +import Address from './Address'; +import CreatedUpdatedProps from './CreatedUpdatedProps'; + +export default interface Company extends CreatedUpdatedProps { + id: string; + name: string; + address: Address; + logo?: string; +} diff --git a/src/types/Component.tsx b/src/types/Component.tsx new file mode 100644 index 000000000..c46345322 --- /dev/null +++ b/src/types/Component.tsx @@ -0,0 +1,9 @@ +export enum ComponentEnum { + OCPI = 'ocpi', + ORGANIZATION = 'organization', + PRICING = 'pricing', + BILLING = 'billing', + REFUND = 'refund', + STATISTICS = 'statistics', + ANALYTICS = 'analytics', +} diff --git a/src/types/ConnectorStats.tsx b/src/types/ConnectorStats.tsx new file mode 100644 index 000000000..c03faed25 --- /dev/null +++ b/src/types/ConnectorStats.tsx @@ -0,0 +1,12 @@ +export default interface ConnectorStats { + totalChargers?: number; + availableChargers?: number; + totalConnectors?: number; + unavailableConnectors?: number; + chargingConnectors?: number; + suspendedConnectors?: number; + availableConnectors?: number; + faultedConnectors?: number; + preparingConnectors?: number; + finishingConnectors?: number; +} diff --git a/src/types/Consumption.tsx b/src/types/Consumption.tsx new file mode 100644 index 000000000..94019a71a --- /dev/null +++ b/src/types/Consumption.tsx @@ -0,0 +1,9 @@ + +export default interface Consumption { + date: Date; + instantPower: number; + cumulatedConsumption: number; + stateOfCharge: number; + cumulatedAmount: number; + limitWatts: number; +} diff --git a/src/types/CreatedUpdatedProps.tsx b/src/types/CreatedUpdatedProps.tsx new file mode 100644 index 000000000..2b1a844bb --- /dev/null +++ b/src/types/CreatedUpdatedProps.tsx @@ -0,0 +1,8 @@ +import UserMin from '../types/User'; + +export default interface CreatedUpdatedProps { + createdBy: UserMin; + createdOn: Date; + lastChangedBy?: UserMin; + lastChangedOn?: Date; +} diff --git a/src/types/DataResult.tsx b/src/types/DataResult.tsx new file mode 100644 index 000000000..ac6ed036d --- /dev/null +++ b/src/types/DataResult.tsx @@ -0,0 +1,47 @@ +import Transaction from './Transaction'; + +export interface DataResult { + count: number; + result: T[]; +} + +export interface TransactionDataResult { + count: number; + result: Transaction[]; + stats: { + count: number; + firstTimestamp?: Date; + lastTimestamp?: Date; + totalConsumptionWattHours: number; + totalDurationSecs: number; + totalInactivitySecs: number; + totalPrice: number; + currency: string; + }; +} + +export interface TransactionRefundDataResult { + count: number; + result: Transaction[]; + stats: { + count: number; + totalConsumptionWattHours: number; + countRefundTransactions: number; + countPendingTransactions: number; + countRefundedReports: number; + totalPriceRefund: number; + totalPricePending: number; + currency: string; + }; +} + +export interface ImageResult { + id: string; + image: string; +} + +export interface LogoResult { + id: string; + logo: string; +} + diff --git a/src/types/Eula.tsx b/src/types/Eula.tsx new file mode 100644 index 000000000..325878183 --- /dev/null +++ b/src/types/Eula.tsx @@ -0,0 +1,11 @@ +export default interface Eula { + timestamp: Date; + language: string; + version: number; + text: string; + hash: string; +} + +export interface EulaAccepted { + eulaAccepted: boolean; +} diff --git a/src/types/Filter.tsx b/src/types/Filter.tsx new file mode 100644 index 000000000..57c37d82c --- /dev/null +++ b/src/types/Filter.tsx @@ -0,0 +1,8 @@ + +export enum GlobalFilters { + STATISTICS_START_DATE_FILTER = 'StatisticsStartDateFilter', + STATISTICS_END_DATE_FILTER = 'StatisticsStartEndFilter', + MY_USER_FILTER = 'MyUserFilter', + ONLY_AVAILABLE_CHARGERS = 'OnlyAvailableChargersFilter', + CONNECTOR_TYPES = 'ConnectorTypesFilter' +} diff --git a/src/types/Global.tsx b/src/types/Global.tsx new file mode 100644 index 000000000..00c2ea338 --- /dev/null +++ b/src/types/Global.tsx @@ -0,0 +1,12 @@ +export interface KeyValue { + key: string; + value: string; +} + +export interface PropertyDisplay { + key: string; + title: string; + value?: string|Element|Element[]|null; + formatter?: (value: any) => string|Element|Element[]|null; + formatterWithComponents?: boolean; +} diff --git a/src/types/Icon.tsx b/src/types/Icon.tsx new file mode 100644 index 000000000..2dd80e1d8 --- /dev/null +++ b/src/types/Icon.tsx @@ -0,0 +1,2 @@ + +export type IconType = 'AntDesign' | 'Entypo' | 'EvilIcons' | 'Feather' | 'FontAwesome' | 'FontAwesome5' | 'Foundation' | 'Ionicons' | 'MaterialCommunityIcons' | 'MaterialIcons' | 'Octicons' | 'SimpleLineIcons' | 'Zocial'; diff --git a/src/types/PagingParams.tsx b/src/types/PagingParams.tsx new file mode 100644 index 000000000..7e7dfdc75 --- /dev/null +++ b/src/types/PagingParams.tsx @@ -0,0 +1,6 @@ +export default interface PagingParams { + limit: number; + skip: number; + onlyRecordCount?: boolean; + sort?: any; +} diff --git a/src/types/Pricing.tsx b/src/types/Pricing.tsx new file mode 100644 index 000000000..4dc498e67 --- /dev/null +++ b/src/types/Pricing.tsx @@ -0,0 +1,9 @@ + +export class PricedConsumption { + constructor( + readonly amount: number, + readonly cumulatedAmount: number, + readonly roundedAmount: number, + readonly currencyCode: string, + readonly pricingSource: string) {} +} diff --git a/src/types/RegistrationToken.tsx b/src/types/RegistrationToken.tsx new file mode 100644 index 000000000..f413b96e5 --- /dev/null +++ b/src/types/RegistrationToken.tsx @@ -0,0 +1,13 @@ +import CreatedUpdatedProps from './CreatedUpdatedProps'; +import SiteArea from './SiteArea'; + +export default interface RegistrationToken extends CreatedUpdatedProps { + id?: string; + description: string; + expirationDate: Date; + revocationDate?: Date; + siteAreaID?: string; + siteArea?: SiteArea; + ocpp15Url?: string; + ocpp16Url?: string; +} diff --git a/src/types/RequestError.tsx b/src/types/RequestError.tsx new file mode 100644 index 000000000..b6bb12792 --- /dev/null +++ b/src/types/RequestError.tsx @@ -0,0 +1,5 @@ +export interface RequestError extends Error { + request?: { + status: number; + }; +} diff --git a/src/types/Setting.tsx b/src/types/Setting.tsx new file mode 100644 index 000000000..216ff3915 --- /dev/null +++ b/src/types/Setting.tsx @@ -0,0 +1,101 @@ +import CreatedUpdatedProps from './CreatedUpdatedProps'; + +export enum ComponentType { + OCPI = 'ocpi', + ORGANIZATION = 'organization', + PRICING = 'pricing', + BILLING = 'billing', + REFUND = 'refund', + STATISTICS = 'statistics', + ANALYTICS = 'analytics', + SMART_CHARGING = 'smartCharging', + BUILDING = 'building' +} + +export enum IdentifierType { + PRICING = 'pricing', + ANALYTICS = 'analytics', + REFUND = 'refund', + OCPI = 'ocpi' +} + +export default interface Setting extends CreatedUpdatedProps { + id?: string; + identifier: IdentifierType; + sensitiveData: string[]; + content: SettingContent; +} + +export enum SettingContentType { + GIREVE = 'gireve', + SAC = 'sac', + CONCUR = 'concur', + SIMPLE = 'simple', + CONVERGENT_CHARGING = 'convergentCharging', +} + +export interface SettingContent { + type: SettingContentType; + ocpi?: OcpiSettings; + simple?: SimplePricingSettings; + convergentCharging?: ConvergentChargingPricingSettings; + sac?: AnalyticsSettings; + links?: AnalyticsLink[]; + concur?: ConcurRefundSettings; +} + +export interface PricingSetting { +} + +export interface SimplePricingSettings extends PricingSetting { + price: number; + currency: string; +} + +export interface ConvergentChargingPricingSettings extends PricingSetting { + url: string; + chargeableItemName: string; + user: string; + password: string; +} + +export interface OcpiSettings { + countryCode: string; + partyID: string; + businessDetails: { + name: string; + website: string; + logo: { + url: string; + thumbnail: string; + category: string; + type: string; + width: string; + height: string; + }; + }; +} + +export interface AnalyticsSettings { + mainUrl: string; + timezone: string; +} + +export interface AnalyticsLink { + id: string; + name: string; + description: string; + role: string; + url: string; +} + +export interface ConcurRefundSettings { + authenticationUrl: string; + apiUrl: string; + clientId: string; + clientSecret: string; + paymentTypeId: string; + expenseTypeCode: string; + policyId: string; + reportName: string; +} diff --git a/src/types/Site.tsx b/src/types/Site.tsx new file mode 100644 index 000000000..6760fc813 --- /dev/null +++ b/src/types/Site.tsx @@ -0,0 +1,22 @@ +import Address from './Address'; +import Company from './Company'; +import ConnectorStats from './ConnectorStats'; +import CreatedUpdatedProps from './CreatedUpdatedProps'; + +export default interface Site extends CreatedUpdatedProps { + id: string; + name: string; + address: Address; + companyID: string; + autoUserSiteAssignment: boolean; + image?: string; + connectorStats: ConnectorStats; + company?: Company; +} + +export interface SiteUser { + site: Site; + userID: string; + siteAdmin: boolean; +} + diff --git a/src/types/SiteArea.tsx b/src/types/SiteArea.tsx new file mode 100644 index 000000000..8da76718e --- /dev/null +++ b/src/types/SiteArea.tsx @@ -0,0 +1,16 @@ +import Site from '../types/Site'; +import Address from './Address'; +import ConnectorStats from './ConnectorStats'; +import CreatedUpdatedProps from './CreatedUpdatedProps'; + +export default interface SiteArea extends CreatedUpdatedProps { + id: string; + name: string; + maximumPower: number; + address: Address; + image: string; + siteID: string; + site: Site; + accessControl: boolean; + connectorStats: ConnectorStats; +} diff --git a/src/types/Tag.tsx b/src/types/Tag.tsx new file mode 100644 index 000000000..c700ec8ec --- /dev/null +++ b/src/types/Tag.tsx @@ -0,0 +1,4 @@ +export default interface Tag { + id: string; + userID: string; +} diff --git a/src/types/Tenant.tsx b/src/types/Tenant.tsx new file mode 100644 index 000000000..bd7b9f4ae --- /dev/null +++ b/src/types/Tenant.tsx @@ -0,0 +1,33 @@ +import CreatedUpdatedProps from './CreatedUpdatedProps'; + +export default interface Tenant extends CreatedUpdatedProps { + id: string; + name: string; + email: string; + subdomain: string; + components: { + ocpi?: { + active: boolean; + type: string; + }; + organization?: { + active: boolean; + }; + pricing?: { + active: boolean; + type: string; + }; + refund?: { + active: boolean; + type: string; + }; + statistics?: { + active: boolean; + type: string; + }; + analytics?: { + active: boolean; + type: string; + }; + }; +} diff --git a/src/types/TenantComponents.tsx b/src/types/TenantComponents.tsx new file mode 100644 index 000000000..b0ee22ba1 --- /dev/null +++ b/src/types/TenantComponents.tsx @@ -0,0 +1,9 @@ +enum TenantComponents { + OCPI = 'ocpi', + REFUND = 'refund', + PRICING = 'pricing', + ORGANIZATION = 'organization', + STATISTICS = 'statistics', + ANALYTICS = 'analytics' +} +export default TenantComponents; diff --git a/src/types/Transaction.tsx b/src/types/Transaction.tsx new file mode 100644 index 000000000..fc4a14330 --- /dev/null +++ b/src/types/Transaction.tsx @@ -0,0 +1,79 @@ +import ChargingStation from '../types/ChargingStation'; +import Consumption from './Consumption'; +import User from './User'; + +export enum InactivityStatus { + INFO = 'I', + WARNING = 'W', + ERROR = 'E' +} + +export default interface Transaction { + id: number; + siteID: string; + siteAreaID: string; + connectorId: number; + tagID: string; + userID: string; + chargeBoxID: string; + signedData?: any; + user?: User; + stop?: { + tagID: string; + userID: string; + user?: User; + meterStop: number; + price: number; + roundedPrice: number; + priceUnit: string; + pricingSource: string; + stateOfCharge: number; + totalInactivitySecs: number; + extraInactivitySecs: number; + inactivityStatus?: InactivityStatus; + totalConsumption: number; + totalDurationSecs: number; + timestamp: Date; + transactionData?: any; + signedData?: any; + }; + remotestop?: { + timestamp: Date; + tagID: string; + userID: string; + }; + refundData?: { + refundId: string; + refundedAt: Date; + type: any; + reportId?: string; + status?: any; + }; + lastMeterValue?: { + value: number; + timestamp: Date; + }; + chargeBox?: ChargingStation; + meterStart: number; + timestamp: Date; + price: number; + roundedPrice: number; + priceUnit: string; + pricingSource: string; + stateOfCharge: number; + timezone: string; + lastUpdate?: Date; + currentTotalInactivitySecs: number; + currentInactivityStatus?: InactivityStatus; + currentStateOfCharge: number; + numberOfMeterValues: number; + currentConsumption: number; + currentConsumptionWh?: number; + currentCumulatedPrice: number; + currentTotalConsumption: number; + currentTotalDurationSecs: number; + currentSignedData?: number; + uniqueId?: string; + errorCode?: number; + values?: Consumption[] +} diff --git a/src/types/User.tsx b/src/types/User.tsx new file mode 100644 index 000000000..80c661cda --- /dev/null +++ b/src/types/User.tsx @@ -0,0 +1,53 @@ +import Address from './Address'; +import CreatedUpdatedProps from './CreatedUpdatedProps'; + +export default interface User extends CreatedUpdatedProps { + id: string; + email: string; + phone?: string; + mobile: string; + role: string; + status: string; + locale: string; + plateID?: string; + address?: Address; + image?: string; + notificationsActive?: boolean; + iNumber?: string; + costCenter?: string; + deleted: boolean; + eulaAcceptedHash: string; + eulaAcceptedVersion: number; + eulaAcceptedOn: Date; + name: string; + firstName: string; + password: string; + passwordResetHash: string; + passwordWrongNbrTrials: number; + passwordBlockedUntil: Date; + verificationToken?: string; + verifiedAt?: Date; + errorCode?: string; + tagIDs?: string[]; +} + +export interface UserCredentials { + email: string; + password: string; + tenantSubDomain: string; + token?: string; + locale?: string; + currency?: string; +} + +export interface UserMin { + id: string; + name: string; + firstName: string; +} + +export interface UserSite { + user: User; + siteID: string; + siteAdmin: boolean; +} diff --git a/src/types/UserNotifications.tsx b/src/types/UserNotifications.tsx new file mode 100644 index 000000000..86eb91839 --- /dev/null +++ b/src/types/UserNotifications.tsx @@ -0,0 +1,18 @@ +export enum UserNotificationType { + SESSION_STARTED = 'SessionStarted', + OPTIMAL_CHARGE_REACHED = 'OptimalChargeReached', + END_OF_CHARGE = 'EndOfCharge', + END_OF_SESSION = 'EndOfSession', + USER_ACCOUNT_STATUS_CHANGED = 'UserAccountStatusChanged', + UNKNOWN_USER_BADGED = 'UnknownUserBadged', + CHARGING_STATION_STATUS_ERROR = 'ChargingStationStatusError', + CHARGING_STATION_REGISTERED = 'ChargingStationRegistered', + OCPI_PATCH_STATUS_ERROR = 'OcpiPatchStatusError', + SMTP_AUTH_ERROR = 'SmtpAuthError', + PREPARING_SESSION_NOT_STARTED = 'PreparingSessionNotStarted', + USER_ACCOUNT_INACTIVITY = 'UserAccountInactivity', + OFFLINE_CHARGING_STATION = 'OfflineChargingStation', + BILLING_USER_SYNCHRONIZATION_FAILED = 'BillingUserSynchronizationFailed', + SESSION_NOT_STARTED_AFTER_AUTHORIZE = 'SessionNotStartedAfterAuthorize' +}; + diff --git a/src/types/UserToken.tsx b/src/types/UserToken.tsx new file mode 100644 index 000000000..835db8244 --- /dev/null +++ b/src/types/UserToken.tsx @@ -0,0 +1,20 @@ +export default interface UserToken { + id?: string; + role?: string; + name?: string; + firstName?: string; + locale?: string; + currency?: string; + language?: string; + tagIDs?: string[]; + tenantID: string; + tenantName?: string; + userHashID?: string; + tenantHashID?: string; + scopes?: string[]; + companies?: string[]; + sites?: string[]; + sitesAdmin?: string[]; + activeComponents?: string[]; + exp: number; +} diff --git a/src/types/Vehicle.tsx b/src/types/Vehicle.tsx new file mode 100644 index 000000000..de86eb24d --- /dev/null +++ b/src/types/Vehicle.tsx @@ -0,0 +1,22 @@ +import CreatedUpdatedProps from './CreatedUpdatedProps'; + +export default interface Vehicle extends CreatedUpdatedProps { + id: string; + images?: string[]; + numberOfImages: number; + vehicleManufacturerID: string; + type: string; + model: string; + batteryKW: number; + autonomyKmWLTP: number; + autonomyKmReal: number; + horsePower: number; + torqueNm: number; + performance0To100kmh: number; + weightKg: number; + lengthMeter: number; + widthMeter: number; + heightMeter: number; + releasedOn: Date; + logo?: string; +} diff --git a/src/types/VehicleManufacturer.tsx b/src/types/VehicleManufacturer.tsx new file mode 100644 index 000000000..20b1a28a7 --- /dev/null +++ b/src/types/VehicleManufacturer.tsx @@ -0,0 +1,9 @@ +import CreatedUpdatedProps from './CreatedUpdatedProps'; +import Vehicle from './Vehicle'; + +export default interface VehicleManufacturer extends CreatedUpdatedProps { + id: string; + name: string; + logo?: string; + vehicles?: Vehicle[]; +} diff --git a/src/utils/Constants.tsx b/src/utils/Constants.tsx new file mode 100644 index 000000000..732eea9ba --- /dev/null +++ b/src/utils/Constants.tsx @@ -0,0 +1,49 @@ +import PagingParams from '../types/PagingParams'; + +export default class Constants { + public static readonly REST_RESPONSE_SUCCESS = 'Success'; + + public static readonly SUPPORTED_LOCALES = ['en_US', 'fr_FR']; + public static readonly SUPPORTED_LANGUAGES = ['en', 'fr', 'de']; + public static readonly DEFAULT_LOCALE = 'en_US'; + public static readonly DEFAULT_LANGUAGE = 'en'; + + public static readonly DEFAULT_DURATION = '00:00'; + public static readonly DEFAULT_DURATION_WITH_SECS = '00:00:00'; + + // Auto Refresh + public static readonly AUTO_REFRESH_DUPS_INTERVAL = 2 * 1000; + public static readonly AUTO_REFRESH_ON_ERROR_PERIOD_MILLIS = 2 * 1000; + public static readonly AUTO_REFRESH_SHORT_PERIOD_MILLIS = 3 * 1000; + public static readonly AUTO_REFRESH_MEDIUM_PERIOD_MILLIS = 10 * 1000; + public static readonly AUTO_REFRESH_LONG_PERIOD_MILLIS = 30 * 1000; + + public static readonly SEARCH_CHECK_PERIOD_MILLIS = 50; + public static readonly ANIMATION_PERIOD_MILLIS = 5 * 1000; + public static readonly ANIMATION_SHOW_HIDE_MILLIS = 500; + public static readonly ANIMATION_ROTATION_MILLIS = 500; + + // Keystore + public static readonly SHARED_PREFERENCES_NAME = 'eMobilityPreferences'; + public static readonly KEYCHAIN_SERVICE = 'eMobilityKeyChain'; + + public static readonly KEY_CURRENT_TENANT_SUB_DOMAIN = 'currentTenantSubDomain'; + public static readonly KEY_CREDENTIALS = 'credentials'; + public static readonly KEY_NAVIGATION_STATE = 'navigation-state'; + + // Paging + public static readonly DEFAULT_PAGING: PagingParams = { + limit: 10, + skip: 0, + }; + public static readonly ONLY_ONE_PAGING: PagingParams = { + limit: 1, + skip: 0, + }; + public static readonly ONLY_RECORD_COUNT_PAGING: PagingParams = { + limit: 10, + skip: 0, + onlyRecordCount: true + }; + public static readonly PAGING_SIZE = 10; +} diff --git a/src/utils/Message.tsx b/src/utils/Message.tsx new file mode 100644 index 000000000..32b40aa8d --- /dev/null +++ b/src/utils/Message.tsx @@ -0,0 +1,34 @@ +import { Toast } from 'native-base'; +import { scale } from 'react-native-size-matters'; + +export default class Message { + public static showError(message: string) { + Message._show(message, 'danger'); + } + + public static showWarning(message: string) { + Message._show(message, 'warning'); + } + + public static showInfo(message: string) { + Message._show(message, 'success'); + } + + public static showSuccess(message: string) { + Message._show(message, 'success'); + } + + private static _show(message: string, type: 'danger' | 'success' | 'warning') { + Toast.show({ + text: message, + textStyle: { + fontSize: scale(15), + color: 'white', + textAlign: 'center' + }, + duration: 3000, + type, + position: 'top' + }); + } +} diff --git a/src/utils/SecuredStorage.tsx b/src/utils/SecuredStorage.tsx new file mode 100644 index 000000000..322c7a379 --- /dev/null +++ b/src/utils/SecuredStorage.tsx @@ -0,0 +1,148 @@ +import { NavigationState } from 'react-navigation'; +import RNSecureStorage, { ACCESSIBLE } from 'rn-secure-storage'; +import ProviderFactory from '../provider/ProviderFactory'; +import { UserCredentials } from '../types/User'; +import Constants from './Constants'; + +// Generate a new Id for persisting the navigation each time the app is launched first time +let navigationID: string = '' + new Date().getTime(); +if (__DEV__) { + // Keep the same key for dev + navigationID = '1234567'; +} + +export default class SecuredStorage { + public static async getNavigationState(): Promise { + const navigationState = await SecuredStorage._getJson(Constants.KEY_NAVIGATION_STATE); + // Check the key + if (navigationState) { + if (navigationState.key === navigationID) { + return navigationState.navigationState; + } + } + return null; + } + + public static async saveNavigationState(navigationState: NavigationState) { + // Add a key + await RNSecureStorage.set( + Constants.KEY_NAVIGATION_STATE, + JSON.stringify({ key: navigationID, navigationState }), + { accessible: ACCESSIBLE.WHEN_UNLOCKED} + ); + } + + public static async getUserCredentials(tenantSubDomain: string): Promise { + // Get current domain + if (!tenantSubDomain) { + tenantSubDomain = await SecuredStorage.getCurrentTenantSubDomain(); + } + // Get User Credentials + return SecuredStorage._getJson(`${tenantSubDomain}~${Constants.KEY_CREDENTIALS}`); + } + + public static async clearUserToken(tenantSubDomain: string) { + const credentials = await SecuredStorage._getJson(`${tenantSubDomain}~${Constants.KEY_CREDENTIALS}`); + if (credentials) { + Reflect.deleteProperty(credentials, 'token'); + await SecuredStorage.saveUserCredentials(tenantSubDomain, credentials); + } + } + + public static async clearUserPassword(tenantSubDomain: string) { + const credentials: UserCredentials = await SecuredStorage._getJson(`${tenantSubDomain}~${Constants.KEY_CREDENTIALS}`); + if (credentials) { + Reflect.deleteProperty(credentials, 'password'); + await SecuredStorage.saveUserCredentials(tenantSubDomain, credentials); + } + } + + public static async deleteUserCredentials(tenantSubDomain: string) { + await RNSecureStorage.remove(`${tenantSubDomain}~${Constants.KEY_CREDENTIALS}`); + } + + public static async saveUserCredentials(tenantSubDomain: string, credentials: UserCredentials) { + // Save last used domain + await SecuredStorage.saveCurrentTenantSubDomain(tenantSubDomain); + // Save Credentials + await RNSecureStorage.set(`${tenantSubDomain}~${Constants.KEY_CREDENTIALS}`, JSON.stringify(credentials), { + accessible: ACCESSIBLE.WHEN_UNLOCKED + }); + } + + public static async saveFilterValue(filterInternalID: string, filterValue: string) { + // Get Provider + const centralServerProvider = await ProviderFactory.getProvider(); + // Get Token + const user = await centralServerProvider.getUserInfo(); + // null value not allowed + if (!filterValue) { + filterValue = 'null'; + } + // Save + await RNSecureStorage.set(`${user.tenantID}~${user.id}~filter~${filterInternalID}`, filterValue, { + accessible: ACCESSIBLE.WHEN_UNLOCKED + }); + } + + public static async filterExists(filterInternalID: string): Promise { + try { + // Get Provider + const centralServerProvider = await ProviderFactory.getProvider(); + // Get Token + const user = await centralServerProvider.getUserInfo(); + // Check + const result = await RNSecureStorage.exists(`${user.tenantID}~${user.id}~filter~${filterInternalID}`); + // Returned result is a number, not a boolean! 0 = not found and 1 = found! + return result; + } catch (err) { + // Key does not exist: do nothing + } + return false; + } + + public static async loadFilterValue(filterInternalID: string): Promise { + // Get Provider + const centralServerProvider = await ProviderFactory.getProvider(); + // Get Token + const user = await centralServerProvider.getUserInfo(); + // Get + const value = await SecuredStorage._getString(`${user.tenantID}~${user.id}~filter~${filterInternalID}`); + if (value === 'null') { + return null; + } + return value; + } + + private static getCurrentTenantSubDomain(): Promise { + return SecuredStorage._getString(Constants.KEY_CURRENT_TENANT_SUB_DOMAIN); + } + + private static async saveCurrentTenantSubDomain(tenantSubDomain: string) { + await RNSecureStorage.set(Constants.KEY_CURRENT_TENANT_SUB_DOMAIN, tenantSubDomain, { + accessible: ACCESSIBLE.WHEN_UNLOCKED + }); + } + + private static async _getJson(key: string): Promise { + try { + const data = await RNSecureStorage.get(key); + if (data) { + return JSON.parse(data); + } + } catch (err) { + // Key does not exist: do nothing + } + return null; + } + + private static async _getString(key: string): Promise { + try { + const data = await RNSecureStorage.get(key); + return data; + } catch (err) { + // Key does not exist: do nothing + } + return null; + } +} diff --git a/src/utils/Utils.tsx b/src/utils/Utils.tsx new file mode 100644 index 000000000..a92e070bf --- /dev/null +++ b/src/utils/Utils.tsx @@ -0,0 +1,336 @@ +import I18n from 'i18n-js'; +import CentralServerProvider from 'provider/CentralServerProvider'; +import { ImageSourcePropType, NativeModules, Platform } from 'react-native'; +import { NavigationParams, NavigationScreenProp, NavigationState } from 'react-navigation'; +import validate from 'validate.js'; +import chademo from '../../assets/connectorType/chademo.gif'; +import combo from '../../assets/connectorType/combo_ccs.gif'; +import domestic from '../../assets/connectorType/domestic-ue.gif'; +import noConnector from '../../assets/connectorType/no-connector.gif'; +import type2 from '../../assets/connectorType/type2.gif'; +import commonColor from '../theme/variables/commonColor'; +import { ChargePointStatus, ConnectorType } from '../types/ChargingStation'; +import { RequestError } from '../types/RequestError'; +import { InactivityStatus } from '../types/Transaction'; +import User from '../types/User'; +import Constants from './Constants'; +import Message from './Message'; + +export default class Utils { + public static canAutoLogin(centralServerProvider: CentralServerProvider, navigation: NavigationScreenProp): boolean { + const tenantSubDomain = centralServerProvider.getUserTenant(); + const email = centralServerProvider.getUserEmail(); + const password = centralServerProvider.getUserPassword(); + return !centralServerProvider.hasAutoLoginDisabled() && + !Utils.isNullOrEmptyString(tenantSubDomain) && + !Utils.isNullOrEmptyString(email) && + !Utils.isNullOrEmptyString(password); + } + + public static countJsonProps(jsonDoc: object): number { + let count = 0; + if (!jsonDoc) { + return count; + } + for (const property in jsonDoc) { + if (jsonDoc.hasOwnProperty(property)) { + count++; + } + } + return count; + } + + public static cloneJSonDocument(jsonDocument: object): object { + return JSON.parse(JSON.stringify(jsonDocument)); + } + + public static isNullOrEmptyString(value: string) { + if (!value) { + return true; + } + if (value.length === 0) { + return true; + } + return false; + } + + public static async sleep(millis: number): Promise { + return new Promise((resolve) => setTimeout(resolve, millis)); + } + + public static getParamFromNavigation(navigation: NavigationScreenProp, + name: string, defaultValue: string): string { + // Has param object? + if (!navigation.state.params) { + return defaultValue; + } + // Has param + if (!navigation.state.params[name]) { + return defaultValue; + } + // Ok, return the value + return navigation.state.params[name]; + } + + public static getDefaultLocale(): string { + let deviceLanguage = Platform.OS === 'ios' ? + NativeModules.SettingsManager.settings.AppleLocale : + NativeModules.I18nManager.localeIdentifier; + // Filter only on supported languages + const shortDeviceLanguage = deviceLanguage ? deviceLanguage.substring(0, 2) : null; + // Default + if (!shortDeviceLanguage || (shortDeviceLanguage !== 'en' && shortDeviceLanguage !== 'de' && shortDeviceLanguage !== 'fr')) { + deviceLanguage = 'en-gb'; + } + return deviceLanguage; + } + + public static getDefaultLanguage(): string { + return Utils.getDefaultLocale().substring(0, 2); + } + + public static getLanguageFromLocale(locale: string) { + let language = null; + // Set the User's locale + if (locale && locale.length > 2) { + language = locale.substring(0, 2); + } + return language; + } + + public static formatDuration(durationSecs: number): string { + let result = ''; + if (durationSecs === 0) { + return `0 ${I18n.t('general.second')}`; + } + const days = Math.floor(durationSecs / (3600 * 24)); + durationSecs -= days * 3600 * 24; + const hours = Math.floor(durationSecs / 3600); + durationSecs -= hours * 3600; + const minutes = Math.floor(durationSecs / 60); + const seconds = Math.floor(durationSecs - (minutes * 60)); + if (days !== 0) { + result += `${days}${I18n.t('general.day')} `; + } + if (((hours !== 0) || (days !== 0)) && (hours !== 0 || (minutes !== 0 && days === 0))) { + result += `${hours}${I18n.t('general.hour')} `; + } + if (days === 0) { + if ((minutes !== 0) || (hours !== 0) && (minutes !== 0 || (seconds !== 0 && hours === 0))) { + result += `${minutes}${I18n.t('general.minute')} `; + } + if ((hours === 0) && (seconds !== 0)) { + result += `${seconds}${I18n.t('general.second')}`; + } + } + return result; + } + + public static computeInactivityStyle(inactivityStatus: InactivityStatus): object { + switch (inactivityStatus) { + case InactivityStatus.INFO: + return { color: commonColor.brandSuccess }; + case InactivityStatus.WARNING: + return { color: commonColor.brandWarning }; + case InactivityStatus.ERROR: + return { color: commonColor.brandDanger }; + default: + return { color: commonColor.brandInfo }; + } + } + + public static async handleHttpUnexpectedError(centralServerProvider: CentralServerProvider, + error: RequestError, defaultErrorMessage: string, navigation?: NavigationScreenProp, fctRefresh?: () => void) { + // Override + fctRefresh = () => { + setTimeout(() => fctRefresh, 2000); + }; + // tslint:disable-next-line: no-console + console.log(`HTTP request error`, error); + // Check if HTTP? + if (error.request) { + // Status? + switch (error.request.status) { + // Backend not available + case 0: + Message.showError(I18n.t('general.cannotConnectBackend')); + break; + // Not logged in? + case 401: + case 403: + // Force auto login + await centralServerProvider.triggerAutoLogin(navigation, fctRefresh); + break; + // Other errors + default: + Message.showError(I18n.t(defaultErrorMessage ? defaultErrorMessage : 'general.unexpectedErrorBackend')); + break; + } + } else if (error.name === 'InvalidTokenError') { + // Force auto login + await centralServerProvider.triggerAutoLogin(navigation, fctRefresh); + } else { + // Error in code + Message.showError(I18n.t('general.unexpectedErrorBackend')); + } + } + + public static buildUserName(user: User): string { + const userName = '-'; + // User? + if (user) { + // Firstname provided? + if (user.name && user.firstName) { + return `${user.name} ${user.firstName}`; + } else { + return `${user.name}`; + } + } + return userName; + } + + public static capitalizeFirstLetter(word: string): string { + return word.charAt(0).toUpperCase() + word.slice(1); + } + + public static validateInput(screen: React.Component, constraints: object): boolean { + let formValid = true; + const errorState: any = {}; + // Reset all errors + for (const key in screen.state) { + if (screen.state.hasOwnProperty(key)) { + // Error? + if (key.startsWith('error')) { + // Clear + const clearError: any = {}; + clearError[key] = null; + screen.setState(clearError); + } + } + } + // Check for errors + const error = validate(screen.state, constraints); + // Check for Errors + if (error) { + // Set in state the errors + for (const key in error) { + if (error.hasOwnProperty(key)) { + errorState['error' + Utils.capitalizeFirstLetter(key)] = error[key]; + } + } + formValid = false; + } + // Set + screen.setState(errorState); + // Return + return formValid; + } + + public static getConnectorLetterFromConnectorID(connectorID: number): string { + if (!connectorID) { + return '-'; + } + return String.fromCharCode(65 + connectorID - 1); + } + + public static getConnectorIDFromConnectorLetter(connectorLetter: string): number { + if (!connectorLetter) { + return 0; + } + return connectorLetter.charCodeAt(0) - 64; + } + + public static randomNumber(): number { + return Math.random() * 10000000; + } + + public static translateConnectorStatus = (status: string): string => { + switch (status) { + case ChargePointStatus.AVAILABLE: + return I18n.t('connector.available'); + case ChargePointStatus.CHARGING: + return I18n.t('connector.charging'); + case ChargePointStatus.OCCUPIED: + return I18n.t('connector.occupied'); + case ChargePointStatus.FAULTED: + return I18n.t('connector.faulted'); + case ChargePointStatus.RESERVED: + return I18n.t('connector.reserved'); + case ChargePointStatus.FINISHING: + return I18n.t('connector.finishing'); + case ChargePointStatus.PREPARING: + return I18n.t('connector.preparing'); + case ChargePointStatus.SUSPENDED_EVSE: + return I18n.t('connector.suspendedEVSE'); + case ChargePointStatus.SUSPENDED_EV: + return I18n.t('connector.suspendedEV'); + case ChargePointStatus.UNAVAILABLE: + return I18n.t('connector.unavailable'); + default: + return I18n.t('connector.unknown'); + } + }; + + public static translateConnectorType = (type: string): string => { + switch (type) { + case ConnectorType.TYPE_2: + return I18n.t('connector.type2'); + case ConnectorType.COMBO_CCS: + return I18n.t('connector.comboCCS'); + case ConnectorType.CHADEMO: + return I18n.t('connector.chademo'); + case ConnectorType.DOMESTIC: + return I18n.t('connector.domestic'); + default: + return I18n.t('connector.unknown'); + } + }; + + public static getConnectorTypeImage = (type: ConnectorType): ImageSourcePropType => { + switch (type) { + case ConnectorType.TYPE_2: + return type2; + case ConnectorType.COMBO_CCS: + return combo; + case ConnectorType.CHADEMO: + return chademo; + case ConnectorType.DOMESTIC: + return domestic; + default: + return noConnector; + } + }; + + public static formatDurationHHMMSS = (durationSecs: number, withSecs: boolean = true): string => { + if (durationSecs <= 0) { + return withSecs ? Constants.DEFAULT_DURATION_WITH_SECS : Constants.DEFAULT_DURATION; + } + // Set Hours + const hours = Math.trunc(durationSecs / 3600); + durationSecs -= hours * 3600; + // Set Mins + let minutes = 0; + if (durationSecs > 0) { + minutes = Math.trunc(durationSecs / 60); + durationSecs -= minutes * 60; + } + // Set Secs + if (withSecs) { + const seconds = Math.trunc(durationSecs); + // Format + return `${Utils.formatTimer(hours)}:${Utils.formatTimer(minutes)}:${Utils.formatTimer(seconds)}`; + } + // Format + return `${Utils.formatTimer(hours)}:${Utils.formatTimer(minutes)}`; + }; + + private static formatTimer = (val: number): string => { + // Put 0 next to the digit if lower than 10 + const valString = val + ''; + if (valString.length < 2) { + return '0' + valString; + } + // Return new digit + return valString; + }; +} diff --git a/store-images/android/android-e-mobility-1024x1024.png b/store-images/android/android-e-mobility-1024x1024.png new file mode 100644 index 000000000..756464faf Binary files /dev/null and b/store-images/android/android-e-mobility-1024x1024.png differ diff --git a/store-images/android/android-e-mobility-512x512.png b/store-images/android/android-e-mobility-512x512.png new file mode 100644 index 000000000..0b987ccde Binary files /dev/null and b/store-images/android/android-e-mobility-512x512.png differ diff --git a/store-images/android/generate-android-splashscreen.webloc b/store-images/android/generate-android-splashscreen.webloc new file mode 100644 index 000000000..51e93ebd7 --- /dev/null +++ b/store-images/android/generate-android-splashscreen.webloc @@ -0,0 +1,8 @@ + + + + + URL + https://apetools.webprofusion.com/#/tools/imagegorilla + + diff --git a/store-images/android/screenshots/mobile/en/Screenshot_1584814027.png b/store-images/android/screenshots/mobile/en/Screenshot_1584814027.png new file mode 100644 index 000000000..a9d32ca90 Binary files /dev/null and b/store-images/android/screenshots/mobile/en/Screenshot_1584814027.png differ diff --git a/store-images/android/screenshots/mobile/en/Screenshot_1584814031.png b/store-images/android/screenshots/mobile/en/Screenshot_1584814031.png new file mode 100644 index 000000000..b54717d47 Binary files /dev/null and b/store-images/android/screenshots/mobile/en/Screenshot_1584814031.png differ diff --git a/store-images/android/screenshots/mobile/en/Screenshot_1584814042.png b/store-images/android/screenshots/mobile/en/Screenshot_1584814042.png new file mode 100644 index 000000000..d97f5fe35 Binary files /dev/null and b/store-images/android/screenshots/mobile/en/Screenshot_1584814042.png differ diff --git a/store-images/android/screenshots/mobile/en/Screenshot_1584814063.png b/store-images/android/screenshots/mobile/en/Screenshot_1584814063.png new file mode 100644 index 000000000..6d413d8b4 Binary files /dev/null and b/store-images/android/screenshots/mobile/en/Screenshot_1584814063.png differ diff --git a/store-images/android/screenshots/mobile/en/Screenshot_1584814126.png b/store-images/android/screenshots/mobile/en/Screenshot_1584814126.png new file mode 100644 index 000000000..208e0558d Binary files /dev/null and b/store-images/android/screenshots/mobile/en/Screenshot_1584814126.png differ diff --git a/store-images/android/screenshots/mobile/en/Screenshot_1584814127.png b/store-images/android/screenshots/mobile/en/Screenshot_1584814127.png new file mode 100644 index 000000000..e7e602c48 Binary files /dev/null and b/store-images/android/screenshots/mobile/en/Screenshot_1584814127.png differ diff --git a/store-images/android/screenshots/mobile/en/Screenshot_1584814128.png b/store-images/android/screenshots/mobile/en/Screenshot_1584814128.png new file mode 100644 index 000000000..971a0ffd0 Binary files /dev/null and b/store-images/android/screenshots/mobile/en/Screenshot_1584814128.png differ diff --git a/store-images/android/screenshots/mobile/en/Screenshot_1584814191.png b/store-images/android/screenshots/mobile/en/Screenshot_1584814191.png new file mode 100644 index 000000000..983c61dd8 Binary files /dev/null and b/store-images/android/screenshots/mobile/en/Screenshot_1584814191.png differ diff --git a/store-images/android/screenshots/mobile/fr/Screenshot_1584813571.png b/store-images/android/screenshots/mobile/fr/Screenshot_1584813571.png new file mode 100644 index 000000000..462441024 Binary files /dev/null and b/store-images/android/screenshots/mobile/fr/Screenshot_1584813571.png differ diff --git a/store-images/android/screenshots/mobile/fr/Screenshot_1584813585.png b/store-images/android/screenshots/mobile/fr/Screenshot_1584813585.png new file mode 100644 index 000000000..d1fb0b7cc Binary files /dev/null and b/store-images/android/screenshots/mobile/fr/Screenshot_1584813585.png differ diff --git a/store-images/android/screenshots/mobile/fr/Screenshot_1584813591.png b/store-images/android/screenshots/mobile/fr/Screenshot_1584813591.png new file mode 100644 index 000000000..08eae7b88 Binary files /dev/null and b/store-images/android/screenshots/mobile/fr/Screenshot_1584813591.png differ diff --git a/store-images/android/screenshots/mobile/fr/Screenshot_1584813603.png b/store-images/android/screenshots/mobile/fr/Screenshot_1584813603.png new file mode 100644 index 000000000..7cd38c522 Binary files /dev/null and b/store-images/android/screenshots/mobile/fr/Screenshot_1584813603.png differ diff --git a/store-images/android/screenshots/mobile/fr/Screenshot_1584813604.png b/store-images/android/screenshots/mobile/fr/Screenshot_1584813604.png new file mode 100644 index 000000000..7353f1138 Binary files /dev/null and b/store-images/android/screenshots/mobile/fr/Screenshot_1584813604.png differ diff --git a/store-images/android/screenshots/mobile/fr/Screenshot_1584813654.png b/store-images/android/screenshots/mobile/fr/Screenshot_1584813654.png new file mode 100644 index 000000000..7e88913a8 Binary files /dev/null and b/store-images/android/screenshots/mobile/fr/Screenshot_1584813654.png differ diff --git a/store-images/android/screenshots/mobile/fr/Screenshot_1584813655.png b/store-images/android/screenshots/mobile/fr/Screenshot_1584813655.png new file mode 100644 index 000000000..a602d5ce4 Binary files /dev/null and b/store-images/android/screenshots/mobile/fr/Screenshot_1584813655.png differ diff --git a/store-images/android/screenshots/mobile/fr/Screenshot_1584813737.png b/store-images/android/screenshots/mobile/fr/Screenshot_1584813737.png new file mode 100644 index 000000000..4361603fa Binary files /dev/null and b/store-images/android/screenshots/mobile/fr/Screenshot_1584813737.png differ diff --git a/store-images/ios/icons/ios-e-mobility-20.png b/store-images/ios/icons/ios-e-mobility-20.png new file mode 100644 index 000000000..35edf3598 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-20.png differ diff --git a/store-images/ios/icons/ios-e-mobility-20@2x.png b/store-images/ios/icons/ios-e-mobility-20@2x.png new file mode 100644 index 000000000..2734840e8 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-20@2x.png differ diff --git a/store-images/ios/icons/ios-e-mobility-20@3x.png b/store-images/ios/icons/ios-e-mobility-20@3x.png new file mode 100644 index 000000000..d02f310f9 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-20@3x.png differ diff --git a/store-images/ios/icons/ios-e-mobility-29.png b/store-images/ios/icons/ios-e-mobility-29.png new file mode 100644 index 000000000..552c0b39d Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-29.png differ diff --git a/store-images/ios/icons/ios-e-mobility-29@2x.png b/store-images/ios/icons/ios-e-mobility-29@2x.png new file mode 100644 index 000000000..437feb36e Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-29@2x.png differ diff --git a/store-images/ios/icons/ios-e-mobility-29@3x.png b/store-images/ios/icons/ios-e-mobility-29@3x.png new file mode 100644 index 000000000..37500e0d8 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-29@3x.png differ diff --git a/store-images/ios/icons/ios-e-mobility-40.png b/store-images/ios/icons/ios-e-mobility-40.png new file mode 100644 index 000000000..2734840e8 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-40.png differ diff --git a/store-images/ios/icons/ios-e-mobility-40@2x.png b/store-images/ios/icons/ios-e-mobility-40@2x.png new file mode 100644 index 000000000..2bba80e15 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-40@2x.png differ diff --git a/store-images/ios/icons/ios-e-mobility-40@3x.png b/store-images/ios/icons/ios-e-mobility-40@3x.png new file mode 100644 index 000000000..1a96df800 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-40@3x.png differ diff --git a/store-images/ios/icons/ios-e-mobility-60@2x.png b/store-images/ios/icons/ios-e-mobility-60@2x.png new file mode 100644 index 000000000..1a96df800 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-60@2x.png differ diff --git a/store-images/ios/icons/ios-e-mobility-60@3x.png b/store-images/ios/icons/ios-e-mobility-60@3x.png new file mode 100644 index 000000000..3f8a39832 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-60@3x.png differ diff --git a/store-images/ios/icons/ios-e-mobility-76.png b/store-images/ios/icons/ios-e-mobility-76.png new file mode 100644 index 000000000..9d3291176 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-76.png differ diff --git a/store-images/ios/icons/ios-e-mobility-76@2x.png b/store-images/ios/icons/ios-e-mobility-76@2x.png new file mode 100644 index 000000000..10faecda6 Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-76@2x.png differ diff --git a/store-images/ios/icons/ios-e-mobility-83.5@2x.png b/store-images/ios/icons/ios-e-mobility-83.5@2x.png new file mode 100644 index 000000000..d26ee3b2c Binary files /dev/null and b/store-images/ios/icons/ios-e-mobility-83.5@2x.png differ diff --git a/store-images/ios/ios-e-mobility-1024x1024.png b/store-images/ios/ios-e-mobility-1024x1024.png new file mode 100644 index 000000000..4df955a06 Binary files /dev/null and b/store-images/ios/ios-e-mobility-1024x1024.png differ diff --git a/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.14.png b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.14.png new file mode 100644 index 000000000..a5a8ba86a Binary files /dev/null and b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.14.png differ diff --git a/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.17.png b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.17.png new file mode 100644 index 000000000..2b5d92048 Binary files /dev/null and b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.17.png differ diff --git a/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.21.png b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.21.png new file mode 100644 index 000000000..24e06d972 Binary files /dev/null and b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.21.png differ diff --git a/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.26.png b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.26.png new file mode 100644 index 000000000..3a80ea269 Binary files /dev/null and b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.26.png differ diff --git a/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.37.png b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.37.png new file mode 100644 index 000000000..542cbe03d Binary files /dev/null and b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.37.png differ diff --git a/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.50.png b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.50.png new file mode 100644 index 000000000..65ead11ea Binary files /dev/null and b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.11.50.png differ diff --git a/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.12.13.png b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.12.13.png new file mode 100644 index 000000000..9b48cab1e Binary files /dev/null and b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.12.13.png differ diff --git a/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.12.26.png b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.12.26.png new file mode 100644 index 000000000..cf1672e41 Binary files /dev/null and b/store-images/ios/screenshots/ipad/en/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.12.26.png differ diff --git a/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.41.11.png b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.41.11.png new file mode 100644 index 000000000..d90392581 Binary files /dev/null and b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.41.11.png differ diff --git a/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.42.11.png b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.42.11.png new file mode 100644 index 000000000..afac21fe0 Binary files /dev/null and b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.42.11.png differ diff --git a/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.42.15.png b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.42.15.png new file mode 100644 index 000000000..1b39585fc Binary files /dev/null and b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.42.15.png differ diff --git a/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.42.26.png b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.42.26.png new file mode 100644 index 000000000..fc9935264 Binary files /dev/null and b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 21.42.26.png differ diff --git a/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.08.02.png b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.08.02.png new file mode 100644 index 000000000..15c65a6a0 Binary files /dev/null and b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.08.02.png differ diff --git a/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.08.28.png b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.08.28.png new file mode 100644 index 000000000..2fcb41ee8 Binary files /dev/null and b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.08.28.png differ diff --git a/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.08.29.png b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.08.29.png new file mode 100644 index 000000000..00368cc85 Binary files /dev/null and b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.08.29.png differ diff --git a/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.16.34.png b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.16.34.png new file mode 100644 index 000000000..ec5650a32 Binary files /dev/null and b/store-images/ios/screenshots/ipad/fr/Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2020-03-21 at 22.16.34.png differ diff --git a/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.20.53.png b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.20.53.png new file mode 100644 index 000000000..7790ce07e Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.20.53.png differ diff --git a/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.20.57.png b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.20.57.png new file mode 100644 index 000000000..38da82b05 Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.20.57.png differ diff --git a/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.01.png b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.01.png new file mode 100644 index 000000000..6c1f0728c Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.01.png differ diff --git a/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.07.png b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.07.png new file mode 100644 index 000000000..7eed57b76 Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.07.png differ diff --git a/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.18.png b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.18.png new file mode 100644 index 000000000..d93896b58 Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.18.png differ diff --git a/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.31.png b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.31.png new file mode 100644 index 000000000..6ed4a085a Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.31.png differ diff --git a/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.49.png b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.49.png new file mode 100644 index 000000000..7954885ce Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.49.png differ diff --git a/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.58.png b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.58.png new file mode 100644 index 000000000..764e0ac01 Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/en/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.21.58.png differ diff --git a/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.28.png b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.28.png new file mode 100644 index 000000000..4982b132f Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.28.png differ diff --git a/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.29.png b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.29.png new file mode 100644 index 000000000..eb6714224 Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.29.png differ diff --git a/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.34.png b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.34.png new file mode 100644 index 000000000..36f6b8740 Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.34.png differ diff --git a/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.38.png b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.38.png new file mode 100644 index 000000000..4c646e444 Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.38.png differ diff --git a/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.51.png b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.51.png new file mode 100644 index 000000000..7cef89557 Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.12.51.png differ diff --git a/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.13.36.png b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.13.36.png new file mode 100644 index 000000000..71db4f45c Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.13.36.png differ diff --git a/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.14.19.png b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.14.19.png new file mode 100644 index 000000000..d3d395479 Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.14.19.png differ diff --git a/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.34.26.png b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.34.26.png new file mode 100644 index 000000000..8e20ac43a Binary files /dev/null and b/store-images/ios/screenshots/mobile-55/fr/Simulator Screen Shot - iPhone 6s Plus - 2020-03-21 at 21.34.26.png differ diff --git a/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.01.png b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.01.png new file mode 100644 index 000000000..600020462 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.01.png differ diff --git a/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.03.png b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.03.png new file mode 100644 index 000000000..24c4dc5c1 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.03.png differ diff --git a/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.07.png b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.07.png new file mode 100644 index 000000000..fde402c59 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.07.png differ diff --git a/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.11.png b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.11.png new file mode 100644 index 000000000..5a4c248a4 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.11.png differ diff --git a/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.19.png b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.19.png new file mode 100644 index 000000000..04869dddb Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.19.png differ diff --git a/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.28.png b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.28.png new file mode 100644 index 000000000..4f9d2e60e Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.28.png differ diff --git a/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.40.png b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.40.png new file mode 100644 index 000000000..ec52612b8 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.40.png differ diff --git a/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.49.png b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.49.png new file mode 100644 index 000000000..9d523fd39 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/en/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.30.49.png differ diff --git a/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.26.39.png b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.26.39.png new file mode 100644 index 000000000..1b959ba78 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.26.39.png differ diff --git a/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.21.png b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.21.png new file mode 100644 index 000000000..f99e48564 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.21.png differ diff --git a/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.25.png b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.25.png new file mode 100644 index 000000000..ff39134fe Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.25.png differ diff --git a/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.30.png b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.30.png new file mode 100644 index 000000000..37c8fe01b Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.30.png differ diff --git a/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.44.png b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.44.png new file mode 100644 index 000000000..b39b9aefd Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.44.png differ diff --git a/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.58.png b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.58.png new file mode 100644 index 000000000..e3fd4a618 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.27.58.png differ diff --git a/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.28.10.png b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.28.10.png new file mode 100644 index 000000000..57dba9805 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.28.10.png differ diff --git a/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.28.27.png b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.28.27.png new file mode 100644 index 000000000..2a1757560 Binary files /dev/null and b/store-images/ios/screenshots/mobile-65/fr/Simulator Screen Shot - iPhone Xs Max - 2020-03-21 at 22.28.27.png differ diff --git a/store-images/splash-screen-2048x2048.png b/store-images/splash-screen-2048x2048.png new file mode 100644 index 000000000..e9e89ee4d Binary files /dev/null and b/store-images/splash-screen-2048x2048.png differ diff --git a/store-images/splash-screen.png b/store-images/splash-screen.png new file mode 100644 index 000000000..6904c4cee Binary files /dev/null and b/store-images/splash-screen.png differ diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..e5f8a4ea2 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,76 @@ +{ + "compilerOptions": { + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es2016", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ + // "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": ["es7"], /* Specify library files to be included in the compilation. */ + "allowJs": false, /* Allow javascript files to be compiled. */ + "checkJs": false, /* Report errors in .js files. */ + "jsx": "react-native", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + // "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + "strictNullChecks": false, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + "baseUrl": "./src", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + "typeRoots": [ + "./node_modules/@types", + "./types/" + ], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + }, + // "include": [ + // "types/**/*.ts", + // "src/**/*.tsx" + // ], + "exclude": [ + "node_modules", + "babel.config.js", + "metro.config.js", + "jest.config.js" + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 000000000..fcf70b6e9 --- /dev/null +++ b/tslint.json @@ -0,0 +1,36 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended", + "tslint-react", + "tslint-config-prettier" + ], + "jsRules": {}, + "rules": { + "interface-name": [ + true, + "never-prefix" + ], + "cyclomatic-complexity": true, + "no-empty-interface": false, + "object-literal-sort-keys": false, + "jsx-no-lambda": false, + "member-ordering": false, + "quotemark": [ + true, + "single" + ], + "no-trailing-whitespace": true, + "indent": [ + true, + "spaces", + 2 + ], + "eofline": true, + "linebreak-style": [ + true, + "LF" + ] + }, + "rulesDirectory": [] +} diff --git a/types/gif.d.ts b/types/gif.d.ts new file mode 100644 index 000000000..54e9d3305 --- /dev/null +++ b/types/gif.d.ts @@ -0,0 +1,4 @@ +declare module "*.gif" { + const value: any; + export default value; +} \ No newline at end of file diff --git a/types/json.d.ts b/types/json.d.ts new file mode 100644 index 000000000..0c5b74038 --- /dev/null +++ b/types/json.d.ts @@ -0,0 +1,4 @@ +declare module "*.json" { + const value: any; + export default value; +} \ No newline at end of file diff --git a/types/png.d.ts b/types/png.d.ts new file mode 100644 index 000000000..1bbe6525d --- /dev/null +++ b/types/png.d.ts @@ -0,0 +1,4 @@ +declare module "*.png" { + const value: any; + export default value; +} \ No newline at end of file diff --git a/types/react-native-charts-wrapper.d.ts b/types/react-native-charts-wrapper.d.ts new file mode 100644 index 000000000..806b15b65 --- /dev/null +++ b/types/react-native-charts-wrapper.d.ts @@ -0,0 +1,26 @@ +declare module "react-native-charts-wrapper" { + interface Props { + style: any; + data: any; + chartDescription: any; + legend: any; + marker: any; + xAxis: any; + yAxis: any; + autoScaleMinMaxEnabled: boolean; + animation: any; + drawGridBackground: boolean; + drawBorders: boolean; + touchEnabled: boolean; + dragEnabled: boolean; + scaleEnabled: boolean; + scaleXEnabled: boolean; + scaleYEnabled: boolean; + doubleTapToZoomEnabled: boolean; + dragDecelerationEnabled: boolean; + dragDecelerationFrictionCoef: number; + keepPositionOnRotation: boolean; + pinchZoom: boolean; + } + export class LineChart extends React.Component { } +} diff --git a/types/react-native-deep-linking.d.ts b/types/react-native-deep-linking.d.ts new file mode 100644 index 000000000..61e62fac9 --- /dev/null +++ b/types/react-native-deep-linking.d.ts @@ -0,0 +1,7 @@ +declare module 'react-native-deep-linking' { + export default class DeepLinking { + static addScheme(scheme: string): void; + static evaluateUrl(url: string): void; + static addRoute(expression: string, callback: (response: any) => void): void; + } +} diff --git a/types/react-native-open-maps.d.ts b/types/react-native-open-maps.d.ts new file mode 100644 index 000000000..22838dab0 --- /dev/null +++ b/types/react-native-open-maps.d.ts @@ -0,0 +1,12 @@ +declare module 'react-native-open-maps' { + export default function openMap(params: { + latitude: number; + longitude: number; + zoom: number; + provider?: "google"|"apple"; + query?: string; + travelType?: "drive"|"walk"|"public_transport", + start?: string; + end?: string; + }): void; +} diff --git a/types/react-native-responsive-stylesheet.d.ts b/types/react-native-responsive-stylesheet.d.ts new file mode 100644 index 000000000..1ed54c54e --- /dev/null +++ b/types/react-native-responsive-stylesheet.d.ts @@ -0,0 +1,9 @@ +declare module 'react-native-responsive-stylesheet' { + export default class ResponsiveStyleSheet { + static create(styles: object): void; + static createSized(direction: "min-width"|"max-width"|"min-height"|"max-height"|"min-direction"|"max-direction", map: object): void; + static createOriented(map: object): void; + static validSizes(direction: "min-width"|"max-width"|"min-height"|"max-height"|"min-direction"|"max-direction", sizes: string[]): void; + static getOrientation(): "landscape"|"portrait"; + } +} diff --git a/types/react-native-svg-transformer.ts b/types/react-native-svg-transformer.ts new file mode 100644 index 000000000..d2fd2d5b2 --- /dev/null +++ b/types/react-native-svg-transformer.ts @@ -0,0 +1,5 @@ +declare module '*.svg' { + import { SvgProps } from 'react-native-svg'; + const content: React.FC; + export default content; +} \ No newline at end of file