diff --git a/.eslintrc b/.eslintrc index de00e71bc8..ace6e1e55b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -23,13 +23,15 @@ "ErrorUtils": true }, "rules": { - "prettier/prettier": "error", "strict": 0, "no-console": 2, "no-case-declarations": 0, - "import/order": [2, { - "newlines-between": "always" - }], + "import/order": [ + 2, + { + "newlines-between": "always" + } + ], "react/jsx-no-undef": 2, "react/jsx-uses-vars": 2, "react/jsx-uses-react": 2, @@ -47,18 +49,10 @@ "settings": { "import/resolver": { "node": { - "extensions": [ - ".js", - ".ios.js", - ".android.js" - ] + "extensions": [".js", ".ios.js", ".android.js"] } } }, - "extends": "plugin:prettier/recommended", - "plugins": [ - "react", - "import", - "prettier" - ] + "extends": "prettier", + "plugins": ["react", "import"] } diff --git a/.travis.yml b/.travis.yml index f2dd0a7985..3ab7a56199 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,21 @@ matrix: include: - - language: node_js node_js: - - '9' + - '9' script: - - yarn run test:coverage --maxWorkers=4 - - yarn run lint + - yarn run test:coverage --maxWorkers=4 + - yarn run lint + - yarn run prettier:check notifications: email: false after_success: - - bash <(curl -s https://codecov.io/bash) - - if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then + - bash <(curl -s https://codecov.io/bash) + - if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then yarn run onesky:upload; yarn run codepush-ios-staging --token "$APPCENTER_TOKEN" --description "#$TRAVIS_BUILD_NUMBER $TRAVIS_COMMIT_RANGE | $TRAVIS_COMMIT_MESSAGE"; yarn run codepush-android-staging --token "$APPCENTER_TOKEN" --description "#$TRAVIS_BUILD_NUMBER $TRAVIS_COMMIT_RANGE | $TRAVIS_COMMIT_MESSAGE"; - fi + fi cache: yarn: true @@ -25,52 +25,52 @@ matrix: os: osx osx_image: xcode9.2 env: - - ENVFILE=.env.production + - ENVFILE=.env.production install: - - brew install yarn - - yarn install - - yarn run onesky:download - - echo -e "machine github.com\n login $CI_USER_TOKEN" >> ~/.netrc - - cd ios - - unzip fastlane/lib/FacebookSDKs-iOS-4.31.1.zip -d ~/Documents/FacebookSDK - - bundler install + - brew install yarn + - yarn install + - yarn run onesky:download + - echo -e "machine github.com\n login $CI_USER_TOKEN" >> ~/.netrc + - cd ios + - unzip fastlane/lib/FacebookSDKs-iOS-4.31.1.zip -d ~/Documents/FacebookSDK + - bundler install script: - - fastlane ios beta + - fastlane ios beta - language: android android: components: - - tools - - build-tools-26.0.1 - - platform-tools - - tools + - tools + - build-tools-26.0.1 + - platform-tools + - tools - - android-26 + - android-26 - - extra-google-google_play_services + - extra-google-google_play_services licenses: - - android-sdk-license-.+ + - android-sdk-license-.+ if: branch = master and type = push env: - - ENVFILE=.env.production + - ENVFILE=.env.production before_install: - - git fetch --unshallow - - openssl aes-256-cbc -pass "pass:$GOOGLE_PLAY_API_FILE_PASSWORD" -in ./android/fastlane/GooglePlayAPI.enc -out ./android/fastlane/GooglePlayAPI.json -d -a - - wget -qO- https://deb.nodesource.com/setup_8.x | sudo bash - - - sudo apt-get install nodejs - - echo yes | sdkmanager "build-tools;26.0.1" # Android platform required by app - - echo yes | sdkmanager "build-tools;25.0.3" # Android platform required by some dependency - - echo yes | sdkmanager "build-tools;23.0.1" # Android platform required by some dependency + - git fetch --unshallow + - openssl aes-256-cbc -pass "pass:$GOOGLE_PLAY_API_FILE_PASSWORD" -in ./android/fastlane/GooglePlayAPI.enc -out ./android/fastlane/GooglePlayAPI.json -d -a + - wget -qO- https://deb.nodesource.com/setup_8.x | sudo bash - + - sudo apt-get install nodejs + - echo yes | sdkmanager "build-tools;26.0.1" # Android platform required by app + - echo yes | sdkmanager "build-tools;25.0.3" # Android platform required by some dependency + - echo yes | sdkmanager "build-tools;23.0.1" # Android platform required by some dependency install: - - yarn install - - yarn run onesky:download - - cd android - - bundler install + - yarn install + - yarn run onesky:download + - cd android + - bundler install script: - - fastlane android beta + - fastlane android beta - language: objective-c xcode_project: godtools.xcworkspace @@ -78,22 +78,22 @@ matrix: osx_image: xcode9.2 if: tag =~ ^v(\d+\.){1,}\d+ before_install: - - openssl aes-256-cbc -pass "pass:$GOOGLE_PLAY_API_FILE_PASSWORD" -in ./android/fastlane/GooglePlayAPI.enc -out ./android/fastlane/GooglePlayAPI.json -d -a + - openssl aes-256-cbc -pass "pass:$GOOGLE_PLAY_API_FILE_PASSWORD" -in ./android/fastlane/GooglePlayAPI.enc -out ./android/fastlane/GooglePlayAPI.json -d -a install: - - cd ios - - bundler install - - fastlane ios release submit:true auto_release:false - - cd ../android - - bundler install - - fastlane android release + - cd ios + - bundler install + - fastlane ios release submit:true auto_release:false + - cd ../android + - bundler install + - fastlane android release env: global: - - secure: Qo7WDyR6KtZnpk5ikAHSah/SdQGIP0lHU/IaCMe5XsIqHZnxPvKNy8cyUguxDqGkwPOyOqE8ZovNDQ7ZCdu0rEug9uMX/EZxoNc2Lfcps/VrUp84Hh0lYAUD1lfpn0Oz4XwVG/5yVjgtRGFdo8FNN+hf1DnbpuijhQ5g5bYYmjYy7Qbj+dxUo4FoiYxKxCunQUessvq1JWU2TfLkS1S2Rp+a/UjxyAoTuGuXisMI2fgESaYiC0Yh1L/7fRh4owR95lwQa7ox94Nloo4VPYxOvgZMoU1YV9e8FXgZ/IacKoqV0OKRxKx81T8/TSdLVQ7Z/+S6ejradLCzEEOvEPg4HPPdGzB9Mk+dkvqqhD/NzgDXOjFOU4dsb/I6+lydYVFQ2Mfgw4bfPcs34hGsdrnO1nwIyDrJXxbKeCE62WXUQhR8SM2o+MJJ5B9hdyFevwoaV2/MKrqq9GsEGVsMMMXK3cY2AyLEfu3DufEfEHmYD1+4TBpeqrqLog1lRITdzEAJGptnTXz/weyFKnBvmAzYgVMo8YAgYd2ZrvugeobA3WdkaqkiL6yqdH/PRjp+yk8uS3zdovdyLm2ZDcKjrvY8WKKglGKjEXbjjeNMLIJwgXtdiqb7396FpB7YKttB3Iw2Us9IbH2Y60A0kEGEvWE/DaIs6gY5ZQc0EsqqDo2Rrmw= - - secure: KOzE8ukv1toXhoEuTZ6LmREb3olfEqPbd3T8GUc0pHPVi2a2hEvvG5sVDC+JnVNeykSdbpQz5gnnzbXcC+7vUrSSN7jIfOsNbiQtLKk4MGKT0bh0jci0cTHfu2gWmYGxT2xS/Vy1lDOFyOJKU1mT9G/tbuXurc1tkm5X7gI93VZJgZy8KFtKi8654Fe1KEwdeSiKittPNUlJQFqnVmihumfx093YefgoKkwP3tr7e37ooU1k0JjxiE0WYXgz2iJ0bX2rmNBBVXTFxNzJbLZaN7smSCFhmb8e7VSObT6RnI52r7hcPQ+qQAQxvKg26qvDPnLUAOqoR4AoamxO52vINZl+UyQmk4RmcL9X1fLtBz2D+rBEmbh+6MNfrwkbal/ZiB6xULNINiQJDdCcOsn8X6ra8f75x/31ohQMMztlbDUmtbNzw1KI9vKvwY6C5zQcKG2L0PI6OE7V2fKjI8K2XxglZo8px46hbxDUH4Pv9TlwbFPl6W1X6GWuLTgk7VT1Uc/UevmlRxzz412E5Yi7rAju58z6WvBUESrZH4Dikmj+wwP6bSE0/c/m+lFmfZQiVcATU6Ky9v9rMg3u4Helsnz0ikFLGxX40RitEoFAJPJfZOyezpOcJiXpUtqLPcg7FY0qbujwp15At+pFAJ8syhwjIvPXJ+uQVMXZtuGNHb4= - - secure: LLr2Aq5SYO11S5DzXz/vXdrTKwO8vVT3EfWy8FlNM4FKAvP3J7PhtHBsHEOa68OUOw2njzeWPCkPLMKj733sRswxM+KvvEqYCX/rwNoNVDqBr5SJl6HfIGjeYI9jiKsx3Q1ga/+hbcl8DwL7dS+2FXQPYPCklCwirJ/vNHgVkDkg5WZjveaEuAtot5+BJhzU9XG1B87QfnsD3Or2Q6nmEk5DytYMp+vkSu4pr7izA3O+91M9GT+mdXbgf7VgZQvHoN90KVyan0j7mVEP4ruodLUa8NhPvu1dyu0sJWD0XXdG1Nmnd67Pw14jMeyLTczQakJQiG4YbGA6cu6rB3LYKUGScnBA5ugW8qguITCkvAKhMieENIzD3Ki7L4OqrR/20rDCvJE/DUao8r+a6/yoR1QbZc5y6wZRppG0IT0yX8fbCZ1DAilAo7I9IdLgDY9UW+NEd3zpoSkAyZETy+N2gRmASxpfuVt3AnF6zE4uATNl96KVT7cRFct8mSwpoKAdEfxTYKRHWzQMPW38X3thU7oWrgbVPDVSJoNibvS9sgvrrCIdyOZ38KnE5FTajKPq1qu0Aj5sH2m5YPqqFZQIdYcNtdL757LSrL1vfTFstjx9i+6+Xaa/R7Z3uq+kkf6Kzm+MQkiNg7yBOiNtGm8DtCDA3RzmqEprjhzwff2EUbU= - - secure: 5oEN3FvkMgKKmvIvxBFUPF3p+VPvHDMs1dVdrwUsURWFeK7qKSYVDVQ5+LGI6Ptm+X2906a/7TMfpMY/Gv8yxJQdbhwc2zZdrCnZrj34BUTdzAvuUbPQDRHCTbJnr6Rs+h7vI4/jLr1Wg/tle/a4GKXOKwEwJy3argDehU5wvGgTPtp1/Nb461h+Fpb8hqk4ET1PB/OnoXND9aTPlyFpWJC30j90ypWaqEVfG1OL3QjOcII1/TWB8+RK2C0vGEn6l7BWJahNFwg/aiMwCyDU1gENQNZ6aPb21rSyjM/G+rmt53xbLhJS50jjQYSynj1J890OT4U4/rOpIhkjXwIHdpyI5iSNP/thWD6oipSYsnlV7ET1O4wRukIwHt6by4xkD8TQySrs/fheuZSyQMNrveXQJcOwCSDWp4Q1p3vCwBv9BYrfu0nlsT8kCfjxbcXmuWn0kOQUl8o5+2EbCsCC3QmtX8wXWr0YIsWOVXIll5MA13MFXQax0ok6/0R7Wm/P7KYZMZkNytb1q3Q/dH+kxCQxS+c7PPbCmHKCKedI3NcjdKdTA12NO5j7wr5c2ohy1H00y6l+yh7+G5vZl2YpRNiRSwDeskLnfgtnjeeg/EX9vjCkYa9XJXZ972RHE94CfWCtv2dSVA1OBkDZlr9TDiWUg2FpKHVpltPmqQu1jFw= - - secure: xVF5oHvidtK/7p7Cz3O5MET6Ty6fYYVye4hTdeo+3BOUwR3mA0RkroGq+CAPhVQzTuGPblaO3ZiB0h2IZh2YrI6BF9z3yIVigAeWjW7tPdbul1Wi5mQpN3LixP2MtyrgG1UWo5Tvdd7jH3dt4zq3emyXIYM1jPUwmA3fsG5Ui6c9iUNwhzVSDWR9Jc0ZwlKNBzQtGZsfRV+hM7qtUVKdFCjhawfuK2tejt99jQ2qdxNgfgtBgoAIaKwPp597jWnUSrZc6NS3hGhPhO41CE36057w84zYEU/I4Nfd3liviPPgzLDBXTzlYTRKDoRvOt3Bf/0INkvb52wJcdREWF7Egecye86kfzxlnfgitxIKB0DY4wFMin3lU1PWBJAQgwyvS7aAtLOhH6siuZGKswKNx3k6MzzkMn6MIsaIe8gpqSWvaSo8WfbJ6ADV0jilEQu36dCEtpyEKyOd9+H6pM46SlPA75YjSamWd5WftWbceIKktdZVeMg2N9V84nkdF8aw3OgenBgm0kW87cTY7J8+IbO/3ZE8MWTEM+dXPZRYY5Cm9asBc2EcnIXtBOgCSPsbjSpd8PrsS6Q/tOWHRIb5seGMFOM1IM9SISyMGcZANejlHxKnngHr2SxzI8Wg3R5Fr4hlBOSLim+wEIwHNfiH7hHlg7GbjAiyj7ow6B0rhjE= - - secure: azo+/fy172hiup0s3jV3y7EXztDQWuk5QpHpIAFG4cWAeRjcAw5MUQB+yL1Qts9FPQrge7JPTGBdk1bCQW6VNEZcAbHgt17+jU40BV+zZ41t513PQU0GSRLsn2y9OSzS6O8SkWWA+SFR84MvGUIUXREKC4JV8dvdtQxNZOazoYcVFAGy5Uv1/9hn1ZuVBxSUMwl+DQuYboEoCXg0La5H2ZaBT3M1J7z0GktYPImOsM8a5Bk09jnEDRvWEIbUEf8r6dcEkDuR+RpxiAyFP4fzs7UPIBqkfEAXuY7xpi4x6h3UjhWG2uHk+idCfqw1AaztIUXONSTTaP1lJwLJwkycSpcMq/KuD6TWk2+NTETLFaaPIMlR37dMW0vzWhKisO6B9akahZ+axEw4Z0bW+u2y6//T3iXZJbpCb3XXXsT0exgaAfhIhYZmpQ/w61MtWyXXlmU7TrrSpT/Z46GyICX52CDT+v6zE5iSfl874yY73OVHrhTHnCi5/Gs7xfGCSVimxJLdbbiSDA/Km/u9zF9bNzQnzTYV/UMeCKLkepb74QujwaLKLUCZi/PypL69GZAUwGsaxsXXhAMkvlJl5Kq9Xsr1jXYHZpjdwjcbVL2mNUmncIl9IoQwiHGkUtewY31DLiu1k1BOGeQBCGwKAB+C4fqqkdljMEJuG94LrcILAho= - - secure: x+/ErK+mpslyOoJFQ9g5nAbriM6IbOoC2cJMat5oipsL1GYfSlf2Q/XopHEjJKm0hFenatXyhwq8qwVd2Qb+IWStWWJQ2ZKzgMJvQe8mmzMtK0fHRvr3TADMxiCn7BuBZpe7ag7r27vr0YJj1kOK0aiAiLMlGTnqMHai2B/fh34KWtWvk5Xm9wo/AE9zjOqi1pimRF3O8jfbFVxBb11RS5g3RsHRrKHtmUENdxM452fyeVlTbOjKmvFgss1E9926YYg77VJoeg1Dy8dcPKmsprn4Qcv+7BJOWJ7dLtnqHuZOnn9IrG1A8Bt8I8t/65J53MVe//40oTzuPsAJtMaRlw1k7EgDsuevQ4biMkLBuBJ7Moj8plZGwKCplyxgtvmxd7eJ1ndZlNIS5UDswqmUt66U4typH9E2wmcd56zQ8I/OcIQM24FURiCoeX2H4GTUv42KT40Tn4xOT8opVcPqNF5qYPxM8oaISBdPhR9IZyYaxecJ8rB4hbHezaW3TsXYNXihz/sIcNhAYMRc1BnbOj7hXXMgH4uFLayaq97LcqwIW/IH12p8fFlYjYJOMn3styGCgdsraTMCAfc1dC1u5EGrfEnQhc0EUlsv86P2KVm0wxuPUC8tEXq8QxYlWPhjh7cPN+M5yq6znJt61bMVR4Y/rtOt2jtAghybL7VG0SQ= - - secure: xU/4DwAKaz7i5bYMataoQRURNHxA6h+XSdAmgk5BL7G9cHms6Y55wx+I5hnwlY7xvxulIdUzewXaycBGDwKMxmfp9QkmFJp1IHl5etGHqBNc/GAAxh9mvPE+uBOMXMLqqKsxIuJVXNLVQKygFIZeOjUMuN3T2nBrGeVm1h9k1XQvhjaPTHasVbiEVrOCz1yEqr9e/sUZ8YYvUQwP1abrKj4UKBgekIFtxvpOyyE0VXOTLzjDRnlN52C2rFscNLAyrUGU32EL9NA/BFkDz7iv0ax01tUsZA9Ju3czcn0kvkLCjpibMqOll7UETg9vjWdyu2yp5ObEgG9zbOPijxMgBXDxuLh8DsTRjbxbn+sE1TV4Z8t+LMInQbCKkvNqiEEnJ1+O0gsZKsQbpH0x9aHgFTAcupyXgjZPCK6/lQ8U4Pe3Rtre+4fc7sdfN7qCfC0iwZKmkOCBmiF6aNxTCaMohdDuhG3dn/q4LQeDnttGBHM9Qa/2ofnh5GzrTZ/+rnVhWetsR5RicId1MfFXVqQXL37kJ+HdW4MRaY3jnaAzbx48ONUItj4l70gyT8tC/9Vj0i6JPQ4jlv0g2UcgUig2z4fzzScUvj+6PBcSyWLKOzdPaU+8zd1dyDfsMTdg0dEjsIIZs0bbnysPUuIaY2h6NebZ+3PaTX4D2xGQutTvdCY= + - secure: Qo7WDyR6KtZnpk5ikAHSah/SdQGIP0lHU/IaCMe5XsIqHZnxPvKNy8cyUguxDqGkwPOyOqE8ZovNDQ7ZCdu0rEug9uMX/EZxoNc2Lfcps/VrUp84Hh0lYAUD1lfpn0Oz4XwVG/5yVjgtRGFdo8FNN+hf1DnbpuijhQ5g5bYYmjYy7Qbj+dxUo4FoiYxKxCunQUessvq1JWU2TfLkS1S2Rp+a/UjxyAoTuGuXisMI2fgESaYiC0Yh1L/7fRh4owR95lwQa7ox94Nloo4VPYxOvgZMoU1YV9e8FXgZ/IacKoqV0OKRxKx81T8/TSdLVQ7Z/+S6ejradLCzEEOvEPg4HPPdGzB9Mk+dkvqqhD/NzgDXOjFOU4dsb/I6+lydYVFQ2Mfgw4bfPcs34hGsdrnO1nwIyDrJXxbKeCE62WXUQhR8SM2o+MJJ5B9hdyFevwoaV2/MKrqq9GsEGVsMMMXK3cY2AyLEfu3DufEfEHmYD1+4TBpeqrqLog1lRITdzEAJGptnTXz/weyFKnBvmAzYgVMo8YAgYd2ZrvugeobA3WdkaqkiL6yqdH/PRjp+yk8uS3zdovdyLm2ZDcKjrvY8WKKglGKjEXbjjeNMLIJwgXtdiqb7396FpB7YKttB3Iw2Us9IbH2Y60A0kEGEvWE/DaIs6gY5ZQc0EsqqDo2Rrmw= + - secure: KOzE8ukv1toXhoEuTZ6LmREb3olfEqPbd3T8GUc0pHPVi2a2hEvvG5sVDC+JnVNeykSdbpQz5gnnzbXcC+7vUrSSN7jIfOsNbiQtLKk4MGKT0bh0jci0cTHfu2gWmYGxT2xS/Vy1lDOFyOJKU1mT9G/tbuXurc1tkm5X7gI93VZJgZy8KFtKi8654Fe1KEwdeSiKittPNUlJQFqnVmihumfx093YefgoKkwP3tr7e37ooU1k0JjxiE0WYXgz2iJ0bX2rmNBBVXTFxNzJbLZaN7smSCFhmb8e7VSObT6RnI52r7hcPQ+qQAQxvKg26qvDPnLUAOqoR4AoamxO52vINZl+UyQmk4RmcL9X1fLtBz2D+rBEmbh+6MNfrwkbal/ZiB6xULNINiQJDdCcOsn8X6ra8f75x/31ohQMMztlbDUmtbNzw1KI9vKvwY6C5zQcKG2L0PI6OE7V2fKjI8K2XxglZo8px46hbxDUH4Pv9TlwbFPl6W1X6GWuLTgk7VT1Uc/UevmlRxzz412E5Yi7rAju58z6WvBUESrZH4Dikmj+wwP6bSE0/c/m+lFmfZQiVcATU6Ky9v9rMg3u4Helsnz0ikFLGxX40RitEoFAJPJfZOyezpOcJiXpUtqLPcg7FY0qbujwp15At+pFAJ8syhwjIvPXJ+uQVMXZtuGNHb4= + - secure: LLr2Aq5SYO11S5DzXz/vXdrTKwO8vVT3EfWy8FlNM4FKAvP3J7PhtHBsHEOa68OUOw2njzeWPCkPLMKj733sRswxM+KvvEqYCX/rwNoNVDqBr5SJl6HfIGjeYI9jiKsx3Q1ga/+hbcl8DwL7dS+2FXQPYPCklCwirJ/vNHgVkDkg5WZjveaEuAtot5+BJhzU9XG1B87QfnsD3Or2Q6nmEk5DytYMp+vkSu4pr7izA3O+91M9GT+mdXbgf7VgZQvHoN90KVyan0j7mVEP4ruodLUa8NhPvu1dyu0sJWD0XXdG1Nmnd67Pw14jMeyLTczQakJQiG4YbGA6cu6rB3LYKUGScnBA5ugW8qguITCkvAKhMieENIzD3Ki7L4OqrR/20rDCvJE/DUao8r+a6/yoR1QbZc5y6wZRppG0IT0yX8fbCZ1DAilAo7I9IdLgDY9UW+NEd3zpoSkAyZETy+N2gRmASxpfuVt3AnF6zE4uATNl96KVT7cRFct8mSwpoKAdEfxTYKRHWzQMPW38X3thU7oWrgbVPDVSJoNibvS9sgvrrCIdyOZ38KnE5FTajKPq1qu0Aj5sH2m5YPqqFZQIdYcNtdL757LSrL1vfTFstjx9i+6+Xaa/R7Z3uq+kkf6Kzm+MQkiNg7yBOiNtGm8DtCDA3RzmqEprjhzwff2EUbU= + - secure: 5oEN3FvkMgKKmvIvxBFUPF3p+VPvHDMs1dVdrwUsURWFeK7qKSYVDVQ5+LGI6Ptm+X2906a/7TMfpMY/Gv8yxJQdbhwc2zZdrCnZrj34BUTdzAvuUbPQDRHCTbJnr6Rs+h7vI4/jLr1Wg/tle/a4GKXOKwEwJy3argDehU5wvGgTPtp1/Nb461h+Fpb8hqk4ET1PB/OnoXND9aTPlyFpWJC30j90ypWaqEVfG1OL3QjOcII1/TWB8+RK2C0vGEn6l7BWJahNFwg/aiMwCyDU1gENQNZ6aPb21rSyjM/G+rmt53xbLhJS50jjQYSynj1J890OT4U4/rOpIhkjXwIHdpyI5iSNP/thWD6oipSYsnlV7ET1O4wRukIwHt6by4xkD8TQySrs/fheuZSyQMNrveXQJcOwCSDWp4Q1p3vCwBv9BYrfu0nlsT8kCfjxbcXmuWn0kOQUl8o5+2EbCsCC3QmtX8wXWr0YIsWOVXIll5MA13MFXQax0ok6/0R7Wm/P7KYZMZkNytb1q3Q/dH+kxCQxS+c7PPbCmHKCKedI3NcjdKdTA12NO5j7wr5c2ohy1H00y6l+yh7+G5vZl2YpRNiRSwDeskLnfgtnjeeg/EX9vjCkYa9XJXZ972RHE94CfWCtv2dSVA1OBkDZlr9TDiWUg2FpKHVpltPmqQu1jFw= + - secure: xVF5oHvidtK/7p7Cz3O5MET6Ty6fYYVye4hTdeo+3BOUwR3mA0RkroGq+CAPhVQzTuGPblaO3ZiB0h2IZh2YrI6BF9z3yIVigAeWjW7tPdbul1Wi5mQpN3LixP2MtyrgG1UWo5Tvdd7jH3dt4zq3emyXIYM1jPUwmA3fsG5Ui6c9iUNwhzVSDWR9Jc0ZwlKNBzQtGZsfRV+hM7qtUVKdFCjhawfuK2tejt99jQ2qdxNgfgtBgoAIaKwPp597jWnUSrZc6NS3hGhPhO41CE36057w84zYEU/I4Nfd3liviPPgzLDBXTzlYTRKDoRvOt3Bf/0INkvb52wJcdREWF7Egecye86kfzxlnfgitxIKB0DY4wFMin3lU1PWBJAQgwyvS7aAtLOhH6siuZGKswKNx3k6MzzkMn6MIsaIe8gpqSWvaSo8WfbJ6ADV0jilEQu36dCEtpyEKyOd9+H6pM46SlPA75YjSamWd5WftWbceIKktdZVeMg2N9V84nkdF8aw3OgenBgm0kW87cTY7J8+IbO/3ZE8MWTEM+dXPZRYY5Cm9asBc2EcnIXtBOgCSPsbjSpd8PrsS6Q/tOWHRIb5seGMFOM1IM9SISyMGcZANejlHxKnngHr2SxzI8Wg3R5Fr4hlBOSLim+wEIwHNfiH7hHlg7GbjAiyj7ow6B0rhjE= + - secure: azo+/fy172hiup0s3jV3y7EXztDQWuk5QpHpIAFG4cWAeRjcAw5MUQB+yL1Qts9FPQrge7JPTGBdk1bCQW6VNEZcAbHgt17+jU40BV+zZ41t513PQU0GSRLsn2y9OSzS6O8SkWWA+SFR84MvGUIUXREKC4JV8dvdtQxNZOazoYcVFAGy5Uv1/9hn1ZuVBxSUMwl+DQuYboEoCXg0La5H2ZaBT3M1J7z0GktYPImOsM8a5Bk09jnEDRvWEIbUEf8r6dcEkDuR+RpxiAyFP4fzs7UPIBqkfEAXuY7xpi4x6h3UjhWG2uHk+idCfqw1AaztIUXONSTTaP1lJwLJwkycSpcMq/KuD6TWk2+NTETLFaaPIMlR37dMW0vzWhKisO6B9akahZ+axEw4Z0bW+u2y6//T3iXZJbpCb3XXXsT0exgaAfhIhYZmpQ/w61MtWyXXlmU7TrrSpT/Z46GyICX52CDT+v6zE5iSfl874yY73OVHrhTHnCi5/Gs7xfGCSVimxJLdbbiSDA/Km/u9zF9bNzQnzTYV/UMeCKLkepb74QujwaLKLUCZi/PypL69GZAUwGsaxsXXhAMkvlJl5Kq9Xsr1jXYHZpjdwjcbVL2mNUmncIl9IoQwiHGkUtewY31DLiu1k1BOGeQBCGwKAB+C4fqqkdljMEJuG94LrcILAho= + - secure: x+/ErK+mpslyOoJFQ9g5nAbriM6IbOoC2cJMat5oipsL1GYfSlf2Q/XopHEjJKm0hFenatXyhwq8qwVd2Qb+IWStWWJQ2ZKzgMJvQe8mmzMtK0fHRvr3TADMxiCn7BuBZpe7ag7r27vr0YJj1kOK0aiAiLMlGTnqMHai2B/fh34KWtWvk5Xm9wo/AE9zjOqi1pimRF3O8jfbFVxBb11RS5g3RsHRrKHtmUENdxM452fyeVlTbOjKmvFgss1E9926YYg77VJoeg1Dy8dcPKmsprn4Qcv+7BJOWJ7dLtnqHuZOnn9IrG1A8Bt8I8t/65J53MVe//40oTzuPsAJtMaRlw1k7EgDsuevQ4biMkLBuBJ7Moj8plZGwKCplyxgtvmxd7eJ1ndZlNIS5UDswqmUt66U4typH9E2wmcd56zQ8I/OcIQM24FURiCoeX2H4GTUv42KT40Tn4xOT8opVcPqNF5qYPxM8oaISBdPhR9IZyYaxecJ8rB4hbHezaW3TsXYNXihz/sIcNhAYMRc1BnbOj7hXXMgH4uFLayaq97LcqwIW/IH12p8fFlYjYJOMn3styGCgdsraTMCAfc1dC1u5EGrfEnQhc0EUlsv86P2KVm0wxuPUC8tEXq8QxYlWPhjh7cPN+M5yq6znJt61bMVR4Y/rtOt2jtAghybL7VG0SQ= + - secure: xU/4DwAKaz7i5bYMataoQRURNHxA6h+XSdAmgk5BL7G9cHms6Y55wx+I5hnwlY7xvxulIdUzewXaycBGDwKMxmfp9QkmFJp1IHl5etGHqBNc/GAAxh9mvPE+uBOMXMLqqKsxIuJVXNLVQKygFIZeOjUMuN3T2nBrGeVm1h9k1XQvhjaPTHasVbiEVrOCz1yEqr9e/sUZ8YYvUQwP1abrKj4UKBgekIFtxvpOyyE0VXOTLzjDRnlN52C2rFscNLAyrUGU32EL9NA/BFkDz7iv0ax01tUsZA9Ju3czcn0kvkLCjpibMqOll7UETg9vjWdyu2yp5ObEgG9zbOPijxMgBXDxuLh8DsTRjbxbn+sE1TV4Z8t+LMInQbCKkvNqiEEnJ1+O0gsZKsQbpH0x9aHgFTAcupyXgjZPCK6/lQ8U4Pe3Rtre+4fc7sdfN7qCfC0iwZKmkOCBmiF6aNxTCaMohdDuhG3dn/q4LQeDnttGBHM9Qa/2ofnh5GzrTZ/+rnVhWetsR5RicId1MfFXVqQXL37kJ+HdW4MRaY3jnaAzbx48ONUItj4l70gyT8tC/9Vj0i6JPQ4jlv0g2UcgUig2z4fzzScUvj+6PBcSyWLKOzdPaU+8zd1dyDfsMTdg0dEjsIIZs0bbnysPUuIaY2h6NebZ+3PaTX4D2xGQutTvdCY= diff --git a/__tests__/actions/notifications.js b/__tests__/actions/notifications.js index 5aa0668e71..4911de6545 100644 --- a/__tests__/actions/notifications.js +++ b/__tests__/actions/notifications.js @@ -19,6 +19,7 @@ import { DISABLE_WELCOME_NOTIFICATION, NAVIGATE_FORWARD, LOAD_HOME_NOTIFICATION_REMINDER, + REQUEST_NOTIFICATIONS, } from '../../src/constants'; import * as common from '../../src/utils/common'; import callApi, { REQUESTS } from '../../src/actions/api'; @@ -50,7 +51,7 @@ beforeEach(() => { describe('showReminderScreen', () => { const descriptionText = 'test description'; - it('should do nothing for Android', () => { + it('should request permissions from device for Android', () => { const store = mockStore({ notifications: { pushDevice: {}, @@ -59,6 +60,7 @@ describe('showReminderScreen', () => { common.isAndroid = true; store.dispatch(showReminderScreen()); expect(PushNotification.checkPermissions).not.toHaveBeenCalled(); + expect(store.getActions()).toEqual([{ type: REQUEST_NOTIFICATIONS }]); }); it('should do nothing if we already have a token', () => { const store = mockStore({ @@ -80,7 +82,7 @@ describe('showReminderScreen', () => { store.dispatch(showReminderScreen(descriptionText)); expect(store.getActions()).toEqual([]); }); - it('should do nothing if permissions are already granted', () => { + it('should request permissions from device permissions are already granted by user', () => { const store = mockStore({ notifications: { pushDevice: {}, @@ -91,7 +93,7 @@ describe('showReminderScreen', () => { ); store.dispatch(showReminderScreen(descriptionText)); - expect(store.getActions()).toEqual([]); + expect(store.getActions()).toEqual([{ type: REQUEST_NOTIFICATIONS }]); }); it('should show Notification Primer screen', () => { const store = mockStore({ diff --git a/__tests__/components/GroupCardItem.js b/__tests__/components/GroupCardItem.js index 5857578f9f..60a7a85a60 100644 --- a/__tests__/components/GroupCardItem.js +++ b/__tests__/components/GroupCardItem.js @@ -10,6 +10,7 @@ const uncontactedCount = 56; let group = { name: 'Group Name', contactReport: {}, + user_created: false, }; const test = () => { @@ -21,6 +22,20 @@ describe('GroupCardItem', () => { test(); }); + it('renders with no report counts for user created org', () => { + group = { + ...group, + contactReport: { + contactsCount, + unassignedCount, + uncontactedCount, + }, + user_created: true, + }; + + test(); + }); + it('renders with all report counts', () => { group = { ...group, @@ -29,6 +44,7 @@ describe('GroupCardItem', () => { unassignedCount, uncontactedCount, }, + user_created: false, }; test(); @@ -41,6 +57,7 @@ describe('GroupCardItem', () => { contactsCount, unassignedCount, }, + user_created: false, }; test(); @@ -53,6 +70,7 @@ describe('GroupCardItem', () => { contactsCount, uncontactedCount, }, + user_created: false, }; test(); @@ -64,6 +82,7 @@ describe('GroupCardItem', () => { contactReport: { contactsCount, }, + user_created: false, }; test(); diff --git a/__tests__/components/GroupsPersonHeader.js b/__tests__/components/GroupsPersonHeader.js index 125a5dfc02..a6bc43a7a5 100644 --- a/__tests__/components/GroupsPersonHeader.js +++ b/__tests__/components/GroupsPersonHeader.js @@ -37,6 +37,7 @@ const contactAssignment = { organization: { id: '231413' }, }; const myStageId = 4; +const isCruOrg = true; const props = { person, @@ -44,6 +45,7 @@ const props = { dispatch, myId, stages, + isCruOrg, }; const phoneNumber = { number: '1800Roge' }; @@ -117,6 +119,12 @@ describe('isMember', () => { ); }); + it('renders no contact buttons for User-Created Org', () => { + testSnapshotShallow( + , + ); + }); + describe('has contact info and contact assignment', () => { beforeEach(() => { getPersonEmailAddress.mockReturnValue(emailAddress); @@ -238,6 +246,12 @@ describe('isContact', () => { ); }); + it('renders no contact buttons for User-Created Org', () => { + testSnapshotShallow( + , + ); + }); + it('should navigate to person stage screen', () => { const screen = renderShallow( { navigation={createMockNavState({ person, organization, + isCruOrg: true, })} />, store, diff --git a/__tests__/components/__snapshots__/GroupCardItem.js.snap b/__tests__/components/__snapshots__/GroupCardItem.js.snap index 1a4543a6fe..2e66325db5 100644 --- a/__tests__/components/__snapshots__/GroupCardItem.js.snap +++ b/__tests__/components/__snapshots__/GroupCardItem.js.snap @@ -352,3 +352,48 @@ exports[`GroupCardItem renders with no report counts 1`] = ` `; + +exports[`GroupCardItem renders with no report counts for user created org 1`] = ` + + + + GROUP NAME + + + + +`; diff --git a/__tests__/components/__snapshots__/GroupsPersonHeader.js.snap b/__tests__/components/__snapshots__/GroupsPersonHeader.js.snap index 87b8e6f739..3535590708 100644 --- a/__tests__/components/__snapshots__/GroupsPersonHeader.js.snap +++ b/__tests__/components/__snapshots__/GroupsPersonHeader.js.snap @@ -64,6 +64,29 @@ exports[`isContact with contact assignment does not render status button if cont `; +exports[`isContact with contact assignment renders no contact buttons for User-Created Org 1`] = ` + + + + +`; + exports[`isContact with contact assignment renders status button if contact is part of org 1`] = ` `; +exports[`isMember renders no contact buttons for User-Created Org 1`] = ` + + + + +`; + exports[`isMember renders null because its not supposed to be visible 1`] = `""`; exports[`isMember renders with no contact assignment and no contact info 1`] = ` diff --git a/__tests__/containers/Groups/PersonScreen/AssignedPersonScreen.js b/__tests__/containers/Groups/PersonScreen/AssignedPersonScreen.js index 784d40bcf2..b2f9ce6a36 100644 --- a/__tests__/containers/Groups/PersonScreen/AssignedPersonScreen.js +++ b/__tests__/containers/Groups/PersonScreen/AssignedPersonScreen.js @@ -20,6 +20,7 @@ jest.mock('../../../../src/selectors/organizations'); jest.mock('../../../../src/actions/navigation', () => ({ navigateBack: jest.fn(() => ({ type: 'test' })), })); +jest.mock('../../../../src/utils/common'); const organization = { id: '1', name: 'Test Org' }; const person = { id: '1', first_name: 'Test Person' }; @@ -73,6 +74,7 @@ const props = { myId: myId, stages: stages, isMember: true, + isCruOrg: true, }; beforeEach(() => { @@ -82,6 +84,7 @@ beforeEach(() => { describe('Contact', () => { it('should provide necessary props', () => { organizationSelector.mockReturnValue(undefined); + common.communityIsCru.mockReturnValue(true); expect(mapStateToProps(store, nav)).toEqual({ organization, @@ -90,7 +93,9 @@ describe('Contact', () => { myId, stages, myStageId: pathwayStage.id, + isCruOrg: true, }); + expect(common.communityIsCru).toHaveBeenCalledWith(organization); }); it('should render AssignedPersonScreen correctly without stage', () => { diff --git a/__tests__/containers/Groups/PersonScreen/__snapshots__/AssignedPersonScreen.js.snap b/__tests__/containers/Groups/PersonScreen/__snapshots__/AssignedPersonScreen.js.snap index a62be5c49b..c5ed21ed78 100644 --- a/__tests__/containers/Groups/PersonScreen/__snapshots__/AssignedPersonScreen.js.snap +++ b/__tests__/containers/Groups/PersonScreen/__snapshots__/AssignedPersonScreen.js.snap @@ -70,6 +70,7 @@ exports[`Contact hides the header when the keyboard is shown 1`] = ` ], } } + isCruOrg={true} isMember={true} isVisible={false} myId="1000" @@ -161,6 +162,7 @@ exports[`Contact should render AssignedPersonScreen correctly with stage 1`] = ` ], } } + isCruOrg={true} isMember={true} isVisible={true} myId="1000" @@ -249,6 +251,7 @@ exports[`Contact should render AssignedPersonScreen correctly without stage 1`] ], } } + isCruOrg={true} isMember={true} isVisible={true} myId="1000" diff --git a/__tests__/containers/PeopleItem.js b/__tests__/containers/PeopleItem.js index 2b2d2d62ae..98aaaa4d84 100644 --- a/__tests__/containers/PeopleItem.js +++ b/__tests__/containers/PeopleItem.js @@ -6,16 +6,27 @@ import { createMockStore, renderShallow, testSnapshot } from '../../testUtils'; import PeopleItem from '../../src/containers/PeopleItem'; import { navigatePush } from '../../src/actions/navigation'; import { PERSON_STAGE_SCREEN } from '../../src/containers/PersonStageScreen'; +import { communityIsCru, isMissionhubUser } from '../../src/utils/common'; + +const myId = '1'; +const stageId = '1'; + +const mockStages = { + [stageId]: { + id: stageId, + name: 'Stage 1', + }, +}; const mockState = { auth: { person: { - id: '1', - stage: { id: '1', name: 'Stage 1' }, + id: myId, + stage: mockStages[stageId], }, }, stages: { - stagesObj: {}, + stagesObj: mockStages, }, }; @@ -23,33 +34,32 @@ const store = createMockStore(mockState); const onSelect = jest.fn(); -const mockOrganization = { id: '1' }; +const mockPersonalMinistry = { id: 'personal' }; +const mockOrganization = { id: '1', user_created: false }; + +const mockOrgPermission = { + organization_id: mockOrganization.id, + followup_status: 'contacted', +}; +const mockOrgPermissionUncontacted = { + organization_id: mockOrganization.id, + followup_status: 'uncontacted', +}; const mockContactAssignment = { id: '90', - assigned_to: { id: '1' }, + assigned_to: { id: myId }, pathway_stage_id: '1', }; +const mockContactAssignmentNoStage = { + id: '90', + assigned_to: { id: myId }, +}; const mockPerson = { id: '123', first_name: 'John', last_name: 'Doe', full_name: 'John Doe', - gender: 'Female', - student_status: null, - campus: null, - year_in_school: null, - major: null, - minor: null, - birth_date: null, - date_became_christian: null, - graduation_date: null, - picture: 'https://graph.facebook.com/v2.5/0/picture', - fb_uid: 0, - created_at: '2017-12-05T15:13:10Z', - updated_at: '2017-12-05T15:13:10Z', - organizational_permissions: [ - { organization_id: mockOrganization.id, followup_status: 'uncontacted' }, - ], + organizational_permissions: [mockOrgPermission], reverse_contact_assignments: [mockContactAssignment], }; @@ -68,38 +78,52 @@ jest.mock('../../src/actions/navigation', () => ({ return mockNavigatePushResult; }), })); +jest.mock('../../src/utils/common'); + +beforeEach(() => { + jest.clearAllMocks(); +}); + +it('renders me correctly', () => { + const mePerson = { ...mockPerson, id: myId }; + + communityIsCru.mockReturnValue(false); + isMissionhubUser.mockReturnValue(false); -beforeEach(() => - (shallowScreen = renderShallow( - , - store, - ))); - -it('renders correctly', () => { testSnapshot( - + , ); + expect(communityIsCru).toHaveBeenCalledWith(mockPersonalMinistry); + expect(isMissionhubUser).not.toHaveBeenCalled(); }); -it('renders personal user correctly', () => { +it('renders personal ministry contact correctly', () => { + communityIsCru.mockReturnValue(false); + isMissionhubUser.mockReturnValue(false); + testSnapshot( , ); + expect(communityIsCru).toHaveBeenCalledWith(mockPersonalMinistry); + expect(isMissionhubUser).not.toHaveBeenCalled(); }); -it('renders org user correctly', () => { +it('renders cru org contact correctly', () => { + communityIsCru.mockReturnValue(true); + isMissionhubUser.mockReturnValue(false); + testSnapshot( { /> , ); + expect(communityIsCru).toHaveBeenCalledWith(mockOrganization); + expect(isMissionhubUser).toHaveBeenCalledWith(mockOrgPermission); }); -it('renders permission user correctly', () => { +it('renders cru org contact without stage correctly', () => { + communityIsCru.mockReturnValue(true); + isMissionhubUser.mockReturnValue(false); + testSnapshot( , ); + expect(communityIsCru).toHaveBeenCalledWith(mockOrganization); + expect(isMissionhubUser).toHaveBeenCalledWith(mockOrgPermission); +}); + +it('renders uncontacted cru org contact correctly', () => { + communityIsCru.mockReturnValue(true); + isMissionhubUser.mockReturnValue(false); + + testSnapshot( + + + , + ); + expect(communityIsCru).toHaveBeenCalledWith(mockOrganization); + expect(isMissionhubUser).toHaveBeenCalledWith(mockOrgPermissionUncontacted); +}); + +it('renders cru org member correctly', () => { + communityIsCru.mockReturnValue(true); + isMissionhubUser.mockReturnValue(true); + + testSnapshot( + + + , + ); + expect(communityIsCru).toHaveBeenCalledWith(mockOrganization); + expect(isMissionhubUser).toHaveBeenCalledWith(mockOrgPermission); }); describe('handleChangeStage', () => { it('navigates to person stage screen', () => { + shallowScreen = renderShallow( + , + store, + ); + shallowScreen .childAt(0) .childAt(1) @@ -157,6 +231,15 @@ describe('handleChangeStage', () => { describe('item selected', () => { it('calls onSelect', () => { + shallowScreen = renderShallow( + , + store, + ); + shallowScreen.props().onPress(); expect(onSelect).toHaveBeenCalledWith(mockPerson, mockOrganization); diff --git a/__tests__/containers/__snapshots__/PeopleItem.js.snap b/__tests__/containers/__snapshots__/PeopleItem.js.snap index 15fc2f3923..e60f8d6e64 100644 --- a/__tests__/containers/__snapshots__/PeopleItem.js.snap +++ b/__tests__/containers/__snapshots__/PeopleItem.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`renders correctly 1`] = ` +exports[`renders cru org contact correctly 1`] = ` - + Stage 1 + > + > + - + Contacted - - -  - - `; -exports[`renders org user correctly 1`] = ` +exports[`renders cru org contact without stage correctly 1`] = ` - + Contacted @@ -422,7 +366,7 @@ exports[`renders org user correctly 1`] = ` `; -exports[`renders permission user correctly 1`] = ` +exports[`renders cru org member correctly 1`] = ` - + Stage 1 + + +`; + +exports[`renders me correctly 1`] = ` + + + ME + + + + Stage 1 + + + + + + + + + +`; + +exports[`renders personal ministry contact correctly 1`] = ` + + + + -  + JOHN DOE + + + Stage 1 + + + + + + `; -exports[`renders personal user correctly 1`] = ` +exports[`renders uncontacted cru org contact correctly 1`] = ` - + Stage 1 + > + > + - + Uncontacted diff --git a/__tests__/reducers/auth.js b/__tests__/reducers/auth.js index 87091417a1..9f728deb7f 100644 --- a/__tests__/reducers/auth.js +++ b/__tests__/reducers/auth.js @@ -1,6 +1,9 @@ import auth from '../../src/reducers/auth'; import { REQUESTS } from '../../src/actions/api'; import { UPDATE_STAGES, UPDATE_TOKEN } from '../../src/constants'; +import { userIsJean } from '../../src/utils/common'; + +jest.mock('../../src/utils/common'); const token = 'asdfasndfiosdc'; const personId = '123456'; @@ -68,9 +71,15 @@ it('sets new token after refreshing anonymous login', () => { }); it('sets isJean after loading me', () => { + const isJeanResponse = 'isJean'; + userIsJean.mockReturnValue(isJeanResponse); + + const organizational_permissions = [ + { id: 1, type: 'organizational_permission' }, + ]; const response = { type: 'person', - organizational_permissions: [{ id: 1, type: 'organizational_permission' }], + organizational_permissions, user: { groups_feature: true, }, @@ -78,7 +87,8 @@ it('sets isJean after loading me', () => { const state = callAuth(REQUESTS.GET_ME.SUCCESS, { response }); - expect(state.isJean).toBe(true); + expect(state.isJean).toBe(isJeanResponse); + expect(userIsJean).toHaveBeenCalledWith(organizational_permissions); }); it('sets user time zone', () => { diff --git a/__tests__/utils/common.js b/__tests__/utils/common.js index 6925ed0ac5..c3ae7647e4 100644 --- a/__tests__/utils/common.js +++ b/__tests__/utils/common.js @@ -1,12 +1,17 @@ import { DrawerActions } from 'react-navigation'; import { + userIsJean, + communityIsCru, isMissionhubUser, isAdminForOrg, openMainMenu, getIconName, shuffleArray, getPagination, + showAssignButton, + showUnassignButton, + showDeleteButton, getAssignedByName, getAssignedToName, getPersonPhoneNumber, @@ -24,6 +29,34 @@ jest.mock('react-navigation', () => ({ const id = '123'; const first_name = 'Roger'; +describe('userIsJean', () => { + const caseyPermissions = [ + { id: '1', organization: { id: '1', user_created: true } }, + ]; + const jeanPermissions = [ + ...caseyPermissions, + { id: '2', organization: { id: '2', user_created: false } }, + ]; + it('should return false for Casey', () => { + expect(userIsJean(caseyPermissions)).toEqual(false); + }); + it('should return true for Jean', () => { + expect(userIsJean(jeanPermissions)).toEqual(true); + }); +}); + +describe('communityIsCru', () => { + it('returns false for personal ministry', () => { + expect(communityIsCru({ id: 'personal' })).toEqual(false); + }); + it('returns false for user-created community', () => { + expect(communityIsCru({ id: '1', user_created: true })).toEqual(false); + }); + it('returns true for cru community', () => { + expect(communityIsCru({ id: '1', user_created: false })).toEqual(true); + }); +}); + describe('isMissionhubUser', () => { it('should return true for admins', () => { expect(isMissionhubUser({ permission_id: 1 })).toEqual(true); @@ -150,6 +183,105 @@ describe('getPagination', () => { }); }); +describe('showAssignButton', () => { + let isCruOrg; + let personIsCurrentUser; + let contactAssignment; + + const test = () => { + return showAssignButton(isCruOrg, personIsCurrentUser, contactAssignment); + }; + + it('should return false if not cru org', () => { + isCruOrg = false; + personIsCurrentUser = false; + contactAssignment = false; + expect(test()).toEqual(false); + }); + it('should return false if is current user', () => { + isCruOrg = true; + personIsCurrentUser = true; + contactAssignment = false; + expect(test()).toEqual(false); + }); + it('should return false if assigned to you', () => { + isCruOrg = true; + personIsCurrentUser = false; + contactAssignment = true; + expect(test()).toEqual(false); + }); + it('should return true if cru org, not current user, and not assigned to you', () => { + isCruOrg = true; + personIsCurrentUser = false; + contactAssignment = false; + expect(test()).toEqual(true); + }); +}); + +describe('showUnassignButton', () => { + let isCruOrg; + let contactAssignment; + + const test = () => { + return showUnassignButton(isCruOrg, contactAssignment); + }; + + it('should return false if not cru org', () => { + isCruOrg = false; + contactAssignment = true; + expect(test()).toEqual(false); + }); + it('should return false if not assigned to you', () => { + isCruOrg = true; + contactAssignment = false; + expect(test()).toEqual(false); + }); + it('should return true if cru org and assigned to you', () => { + isCruOrg = true; + contactAssignment = true; + expect(test()).toEqual(true); + }); +}); + +describe('showDeleteButton', () => { + let personIsCurrentUser; + let contactAssignment; + let orgPermission; + + const test = () => { + return showDeleteButton( + personIsCurrentUser, + contactAssignment, + orgPermission, + ); + }; + + it('should return false if is current user', () => { + personIsCurrentUser = true; + contactAssignment = true; + orgPermission = false; + expect(test()).toEqual(false); + }); + it('should return false if not assigned to you', () => { + personIsCurrentUser = false; + contactAssignment = false; + orgPermission = false; + expect(test()).toEqual(false); + }); + it('should return false if not personal ministry', () => { + personIsCurrentUser = false; + contactAssignment = true; + orgPermission = true; + expect(test()).toEqual(false); + }); + it('should return true if not current user, assigned to you, and is personal ministry', () => { + personIsCurrentUser = false; + contactAssignment = true; + orgPermission = false; + expect(test()).toEqual(true); + }); +}); + describe('getAssignedToName', () => { it('should return You if the user is the assigned_to', () => { expect(getAssignedToName(id, { assigned_to: { id } })).toEqual('You'); diff --git a/android/app/build.gradle b/android/app/build.gradle index ee959411c5..2048b63ec2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -118,7 +118,7 @@ android { applicationId "com.missionhub" minSdkVersion 16 targetSdkVersion 26 - versionName "4.2.5" + versionName "4.2.6" versionCode grgit.log(includes:['HEAD']).size() + 363 ndk { abiFilters "armeabi-v7a", "x86" diff --git a/app.json b/app.json index 3bdda41b42..e8925e2a90 100644 --- a/app.json +++ b/app.json @@ -1,4 +1,4 @@ { "name": "MissionHub", "displayName": "Mission Hub" -} \ No newline at end of file +} diff --git a/bin/oneskyDownload.js b/bin/oneskyDownload.js index 85c8e84c18..a63855dd3c 100644 --- a/bin/oneskyDownload.js +++ b/bin/oneskyDownload.js @@ -21,10 +21,12 @@ async function downloadTranslations() { console.log('Successfully Downloaded.'); console.log('Writing translations.json...'); - fs.writeFileSync(path.resolve(__dirname, '../src/i18n/locales/translations.json'), content); + fs.writeFileSync( + path.resolve(__dirname, '../src/i18n/locales/translations.json'), + content, + ); console.log('Done.'); - } - catch (error) { + } catch (error) { console.log('Error downloading from OneSky:'); console.log(error); process.exit(1); diff --git a/bin/oneskyUpload.js b/bin/oneskyUpload.js index 3fa089c2b2..0f0c50e64a 100644 --- a/bin/oneskyUpload.js +++ b/bin/oneskyUpload.js @@ -21,8 +21,7 @@ async function uploadTranslations() { try { await oneSky.postFile(options); console.log('Successfully Uploaded.'); - } - catch (error) { + } catch (error) { console.log('Error uploading to OneSky:'); console.log(error); process.exit(1); diff --git a/ios/MissionHub/Info.plist b/ios/MissionHub/Info.plist index 7043d0f3a8..c0435ed0ef 100644 --- a/ios/MissionHub/Info.plist +++ b/ios/MissionHub/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 4.2.5 + 4.2.6 CFBundleSignature ???? CFBundleURLTypes diff --git a/jsconfig.json b/jsconfig.json index 5a6b24af72..6e91bfe207 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,10 +1,8 @@ { - "compilerOptions": { - "experimentalDecorators": true, - "allowJs": true, - "allowSyntheticDefaultImports": true - }, - "exclude": [ - "node_modules" - ] -} \ No newline at end of file + "compilerOptions": { + "experimentalDecorators": true, + "allowJs": true, + "allowSyntheticDefaultImports": true + }, + "exclude": ["node_modules"] +} diff --git a/package.json b/package.json index 663c1c9c5b..9299466541 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,8 @@ "ios": "react-native run-ios", "lint": "eslint ./*.js ./src ./__tests__", "lint:fix": "eslint ./*.js ./src ./__tests__ --fix", + "prettier:check": "prettier '{{src,bin,testUtils,__{tests,mocks}__}/**/*.{js,json},./*.{js,json,yml}}' --list-different", + "prettier:write": "prettier '{{src,bin,testUtils,__{tests,mocks}__}/**/*.{js,json},./*.{js,json,yml}}' --write", "android": "react-native run-android", "android:install:dev": "adb install android/app/build/outputs/apk/app-debug.apk", "android:install:release": "adb install android/app/build/outputs/apk/app-release.apk", @@ -81,16 +83,15 @@ "enzyme-adapter-react-16": "^1.1.1", "enzyme-to-json": "^3.3.4", "eslint": "^4.19.1", - "eslint-config-prettier": "^2.9.0", + "eslint-config-prettier": "^3.1.0", "eslint-plugin-import": "^2.12.0", - "eslint-plugin-prettier": "^2.6.0", "eslint-plugin-react": "^7.7.0", - "husky": "^0.14.3", + "husky": "^1.1.2", "jest": "^22.4.4", "jest-cli": "^22.4.4", "mockdate": "^2.0.2", - "prettier": "^1.12.1", - "pretty-quick": "^1.5.0", + "prettier": "^1.14.3", + "pretty-quick": "^1.8.0", "react-dom": "^16.3.2", "react-test-renderer": "^16.3.2", "redux-mock-store": "^1.5.1" diff --git a/src/actions/auth.js b/src/actions/auth.js index 1a4f7796dd..b804ac0d8b 100644 --- a/src/actions/auth.js +++ b/src/actions/auth.js @@ -164,7 +164,7 @@ export function firstTime() { } export function getTimezoneString() { - return `${new Date().getTimezoneOffset() / 60 * -1}`; + return `${(new Date().getTimezoneOffset() / 60) * -1}`; } export function updateLocaleAndTimezone() { diff --git a/src/actions/notifications.js b/src/actions/notifications.js index 12ded87442..d15e805e9f 100644 --- a/src/actions/notifications.js +++ b/src/actions/notifications.js @@ -25,8 +25,9 @@ export function showReminderScreen(descriptionText) { return (dispatch, getState) => { const { pushDevice, requestedNativePermissions } = getState().notifications; - // Android does not need to ask for notification permissions + // Android does not need to ask user for notification permissions if (isAndroid) { + dispatch(requestNativePermissions()); return; } @@ -37,10 +38,8 @@ export function showReminderScreen(descriptionText) { PushNotification.checkPermissions(permission => { const permissionsEnabled = permission && permission.alert; if (permissionsEnabled) { - return; - } - - if (requestedNativePermissions) { + dispatch(requestNativePermissions()); + } else if (requestedNativePermissions) { dispatch(navigatePush(NOTIFICATION_OFF_SCREEN)); } else { // If none of the other cases hit, show allow/not allow page diff --git a/src/components/GroupCardItem/index.js b/src/components/GroupCardItem/index.js index 564afa09ba..1a9f6d30d8 100644 --- a/src/components/GroupCardItem/index.js +++ b/src/components/GroupCardItem/index.js @@ -17,38 +17,41 @@ export default class GroupCardItem extends Component { const { t, group } = this.props; const { contactsCount, unassignedCount, uncontactedCount } = group.contactReport || {}; + const { user_created } = group; return ( {group.name.toUpperCase()} - {contactsCount ? ( - - - {t('numContacts', { number: contactsCount })} - - {unassignedCount ? ( - - - - {t('numUnassigned', { - number: unassignedCount, - })} - - - ) : null} - {uncontactedCount ? ( - - - - {t('numUncontacted', { - number: uncontactedCount, - })} - - - ) : null} - + {!user_created ? ( + contactsCount ? ( + + + {t('numContacts', { number: contactsCount })} + + {unassignedCount ? ( + + + + {t('numUnassigned', { + number: unassignedCount, + })} + + + ) : null} + {uncontactedCount ? ( + + + + {t('numUncontacted', { + number: uncontactedCount, + })} + + + ) : null} + + ) : null ) : null} @@ -61,5 +64,6 @@ GroupCardItem.propTypes = { group: PropTypes.shape({ name: PropTypes.string.isRequired, contactReport: PropTypes.object.isRequired, + user_created: PropTypes.bool, }).isRequired, }; diff --git a/src/components/GroupsPersonHeader/index.js b/src/components/GroupsPersonHeader/index.js index a228552804..88904dd570 100644 --- a/src/components/GroupsPersonHeader/index.js +++ b/src/components/GroupsPersonHeader/index.js @@ -25,12 +25,22 @@ import styles from './styles'; @translate() export default class GroupsPersonHeader extends Component { computeButtons() { - const { props } = this; - return props.person.id === props.myId + const { person, myId, isMember, contactAssignment, isCruOrg } = this.props; + const personStageButton = contactAssignment + ? [this.getPersonStageButton()] + : []; + const statusButton = + !isMember && contactAssignment && contactAssignment.organization + ? [this.getStatusButton()] + : []; + const contactButtons = + isCruOrg && (contactAssignment || isMember) + ? this.getContactOptionButtons() + : []; + + return person.id === myId ? this.getMeButton() - : props.isMember - ? this.getMemberButtons() - : this.getContactButtons(); + : [...personStageButton, ...statusButton, ...contactButtons]; } getSelfStageButton() { @@ -190,43 +200,18 @@ export default class GroupsPersonHeader extends Component { ); } - getMemberButtons() { - const { contactAssignment } = this.props; - const buttons = [ + getContactOptionButtons() { + return [ this.getMessageButton(), this.getCallButton(), this.getEmailButton(), ]; - return contactAssignment - ? [this.getPersonStageButton(), ...buttons] - : buttons; } getMeButton() { return this.getSelfStageButton(); } - getContactButtons() { - const { contactAssignment } = this.props; - - return contactAssignment - ? contactAssignment.organization - ? [ - this.getPersonStageButton(), - this.getStatusButton(), - this.getMessageButton(), - this.getCallButton(), - this.getEmailButton(), - ] - : [ - this.getPersonStageButton(), - this.getMessageButton(), - this.getCallButton(), - this.getEmailButton(), - ] - : null; - } - button(icon, text, onClick, buttonStyle, flexStyle) { return ( { const navParams = navigation.state.params; const orgId = navParams.organization && navParams.organization.id; @@ -147,7 +155,6 @@ const mapStateToProps = ({ auth, people }, { navigation }) => { return { ...(navigation.state.params || {}), person, - isJean: auth.isJean, personIsCurrentUser: navigation.state.params.person.id === auth.person.id, myId: auth.person.id, contactAssignment: contactAssignmentSelector({ auth }, { person, orgId }), diff --git a/src/containers/Groups/AssignedPersonScreen/index.js b/src/containers/Groups/AssignedPersonScreen/index.js index f4e0f8f11b..2b80f6088a 100644 --- a/src/containers/Groups/AssignedPersonScreen/index.js +++ b/src/containers/Groups/AssignedPersonScreen/index.js @@ -28,6 +28,7 @@ import { keyboardShow, keyboardHide, buildTrackingObj, + communityIsCru, } from '../../../utils/common'; import styles from './styles'; @@ -204,6 +205,7 @@ export class AssignedPersonScreen extends Component { myId, myStageId, stages, + isCruOrg, } = this.props; const name = (person.first_name || '').toUpperCase(); @@ -248,6 +250,7 @@ export class AssignedPersonScreen extends Component { myId={myId} myStageId={myStageId} stages={stages} + isCruOrg={isCruOrg} /> @@ -294,6 +297,7 @@ export const mapStateToProps = ( stages: stages.stages, myId: authPerson.id, myStageId: authPerson.user.pathway_stage_id, + isCruOrg: communityIsCru(navParams.organization), }; }; diff --git a/src/containers/ImpactView/index.js b/src/containers/ImpactView/index.js index 8254bb8575..d0f28325b8 100644 --- a/src/containers/ImpactView/index.js +++ b/src/containers/ImpactView/index.js @@ -60,6 +60,7 @@ export class ImpactView extends Component { person = {}, organization = {}, isPersonalMinistryMe, + isUserCreatedOrg, } = this.props; // We don't scope summary sentence by org unless we are only scoping by org (person is not specified) @@ -67,7 +68,7 @@ export class ImpactView extends Component { dispatch( getImpactSummary(person.id, person.id ? undefined : organization.id), ); - if (isPersonalMinistryMe) { + if (isPersonalMinistryMe || isUserCreatedOrg) { dispatch(getImpactSummary()); // Get global impact by calling without person or org } else { this.getInteractionReport(); diff --git a/src/containers/ImpactView/styles.js b/src/containers/ImpactView/styles.js index 9b578925d5..bf3b4745a2 100644 --- a/src/containers/ImpactView/styles.js +++ b/src/containers/ImpactView/styles.js @@ -12,7 +12,7 @@ export default StyleSheet.create({ width: theme.fullWidth, // Android was cutting off the top part of the clouds in the image. // Take the image scale and multiple it by the width to get the height - height: 205 / 375 * theme.fullWidth, + height: (205 / 375) * theme.fullWidth, }, text: { fontSize: 28, diff --git a/src/containers/PeopleItem/index.js b/src/containers/PeopleItem/index.js index 912b85f903..7d826008ec 100644 --- a/src/containers/PeopleItem/index.js +++ b/src/containers/PeopleItem/index.js @@ -7,7 +7,7 @@ import { Flex, Text, Touchable, Icon } from '../../components/common'; import { navigatePush } from '../../actions/navigation'; import { getMyPeople } from '../../actions/people'; import { PERSON_STAGE_SCREEN } from '../PersonStageScreen'; -import { isMissionhubUser } from '../../utils/common'; +import { isMissionhubUser, communityIsCru } from '../../utils/common'; import styles from './styles'; @@ -48,7 +48,7 @@ export class PeopleItem extends Component { }; render() { - const { person, me, t, stagesObj, organization, isJean } = this.props; + const { person, me, t, stagesObj, organization } = this.props; const { isPersonal, isMe } = this.state; const newPerson = isMe ? me : person; let personName = isMe ? t('me') : newPerson.full_name || ''; @@ -72,12 +72,14 @@ export class PeopleItem extends Component { } } + const isCruOrg = communityIsCru(organization); + let status = 'uncontacted'; const orgPermissions = person.organizational_permissions || []; - if (isMe || !isJean || isPersonal) { + if (isMe || !isCruOrg) { status = ''; - } else if (organization && organization.id) { + } else if (isCruOrg) { const personOrgPermissions = orgPermissions.find( o => o.organization_id === organization.id, ); @@ -151,7 +153,6 @@ PeopleItem.propTypes = { }; const mapStateToProps = ({ auth, stages }) => ({ - isJean: auth.isJean, me: auth.person, stagesObj: stages.stagesObj, }); diff --git a/src/i18n/locales/translations.json b/src/i18n/locales/translations.json index abbf01dcbf..777bc0a87c 100644 --- a/src/i18n/locales/translations.json +++ b/src/i18n/locales/translations.json @@ -1,33 +1,33 @@ { - "en-US": { - "translation": { - "common": { - "profileLabels": { - "firstName": "First Name", - "firstNameRequired": "$t(profileLabels.firstName) (Required)", - "lastName": "Last Name", - "email": "Email", - "phone": "Phone" - }, - "profileLabelFirstName": "First Name (Required)", - "profileLabelLastName": "Last Name", - "profileLabelEmail": "Email", - "profileLabelPhone": "Phone" - }, - "welcome": { - "welcome": "welcome!", - "welcomeDescription": "Growing closer to God involves helping others experience Him. MissionHub joins you in that journey by suggesting steps of faith to take with others." - }, - "interactions": { - "title": "Hi!" - }, - "login": { - "tagline1": "Grow closer to God.", - "tagline2": "Help others experience Him.", - "facebookSignup": "Sign up with Facebook", - "tryNow": "Try it now", - "signIn": "Sign In" - } - } + "en-US": { + "translation": { + "common": { + "profileLabels": { + "firstName": "First Name", + "firstNameRequired": "$t(profileLabels.firstName) (Required)", + "lastName": "Last Name", + "email": "Email", + "phone": "Phone" + }, + "profileLabelFirstName": "First Name (Required)", + "profileLabelLastName": "Last Name", + "profileLabelEmail": "Email", + "profileLabelPhone": "Phone" + }, + "welcome": { + "welcome": "welcome!", + "welcomeDescription": "Growing closer to God involves helping others experience Him. MissionHub joins you in that journey by suggesting steps of faith to take with others." + }, + "interactions": { + "title": "Hi!" + }, + "login": { + "tagline1": "Grow closer to God.", + "tagline2": "Help others experience Him.", + "facebookSignup": "Sign up with Facebook", + "tryNow": "Try it now", + "signIn": "Sign In" + } } -} \ No newline at end of file + } +} diff --git a/src/reducers/auth.js b/src/reducers/auth.js index b00bcae1dc..45252df0f8 100644 --- a/src/reducers/auth.js +++ b/src/reducers/auth.js @@ -1,4 +1,5 @@ import { FIRST_TIME, LOGOUT, UPDATE_STAGES, UPDATE_TOKEN } from '../constants'; +import { userIsJean } from '../utils/common'; import { REQUESTS } from '../actions/api'; const initialAuthState = { @@ -83,7 +84,7 @@ function authReducer(state = initialAuthState, action) { ...person, stage: state.person.id === person.id ? state.person.stage : null, // Add the stage if we're getting the same user again }, - isJean: person.organizational_permissions.length > 0, + isJean: userIsJean(person.organizational_permissions), }; case REQUESTS.GET_STAGES.SUCCESS: case UPDATE_STAGES: diff --git a/src/utils/common.js b/src/utils/common.js index 863d721a98..adb05fa952 100644 --- a/src/utils/common.js +++ b/src/utils/common.js @@ -67,6 +67,13 @@ export const refresh = (obj, method) => { export const isAuthenticated = authState => authState.token; +//If the user has permissions in a Cru Community (that is, user_created === false), they are Jean +export const userIsJean = orgPermissions => + orgPermissions.some(p => !p.organization.user_created); + +export const communityIsCru = organization => + organization && organization.id !== 'personal' && !organization.user_created; + const MHUB_PERMISSIONS = [ORG_PERMISSIONS.ADMIN, ORG_PERMISSIONS.USER]; export const isMissionhubUser = orgPermission => !!orgPermission && MHUB_PERMISSIONS.includes(orgPermission.permission_id); @@ -187,16 +194,22 @@ export function getPagination(action, currentLength) { } //showing assign/unassign buttons on side menu -export function showAssignButton(personIsCurrentUser, contactAssignment) { - return !personIsCurrentUser && !contactAssignment; +export function showAssignButton( + isCruOrg, + personIsCurrentUser, + contactAssignment, +) { + return isCruOrg && !personIsCurrentUser && !contactAssignment; +} +export function showUnassignButton(isCruOrg, contactAssignment) { + return isCruOrg && contactAssignment; } -export function showUnassignButton( +export function showDeleteButton( personIsCurrentUser, contactAssignment, - isJean, orgPermission, ) { - return !personIsCurrentUser && contactAssignment && isJean && orgPermission; + return !personIsCurrentUser && contactAssignment && !orgPermission; } export function getAssignedToName(myId, item) { diff --git a/yarn.lock b/yarn.lock index 5ab5db6797..8d20c4634c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2306,6 +2306,11 @@ ci-info@^1.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.1.tgz#47b44df118c48d2597b56d342e7e25791060171a" integrity sha512-vHDDF/bP9RYpTWtUhpJRhCFdvvp3iDWvEbuDbWgvjUrNGV1MXJrE0MPcwGtEled04m61iwdBLUIHZtDgzWS4ZQ== +ci-info@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== + circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" @@ -2600,6 +2605,15 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cosmiconfig@^5.0.6: + version "5.0.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" + integrity sha512-6DWfizHriCrFWURP1/qyhsiFvYdlJzbCzmtFWh744+KyWsJo5+kPzUZZaMRSSItoYc0pxFX7gEO7ZC1/gN/7AQ== + dependencies: + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^4.0.0" + create-react-class@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.2.tgz#cf1ed15f12aad7f14ef5f2dfe05e6c42f91ef02a" @@ -3054,6 +3068,13 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + error-stack-parser@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.2.tgz#4ae8dbaa2bf90a8b450707b9149dcabca135520d" @@ -3139,12 +3160,12 @@ escodegen@1.x.x, escodegen@^1.9.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" - integrity sha512-ag8YEyBXsm3nmOv1Hz991VtNNDMRa+MNy8cY47Pl4bw6iuzqKbJajXdqUpiw13STdLLrznxgm1hj9NhxeOYq0A== +eslint-config-prettier@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-3.1.0.tgz#2c26d2cdcfa3a05f0642cd7e6e4ef3316cdabfa2" + integrity sha512-QYGfmzuc4q4J6XIhlp8vRKdI/fI0tQfQPy1dME3UOLprE+v4ssH/3W9LM2Q7h5qBcy5m0ehCrBDU2YF8q6OY8w== dependencies: - get-stdin "^5.0.1" + get-stdin "^6.0.0" eslint-import-resolver-node@^0.3.1: version "0.3.1" @@ -3178,14 +3199,6 @@ eslint-plugin-import@^2.12.0: read-pkg-up "^2.0.0" resolve "^1.6.0" -eslint-plugin-prettier@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7" - integrity sha512-floiaI4F7hRkTrFe8V2ItOK97QYrX75DjmdzmVITZoAP6Cn06oEDPQRsO6MlHEP/u2SxI3xQ52Kpjw6j5WGfeQ== - dependencies: - fast-diff "^1.1.1" - jest-docblock "^21.0.0" - eslint-plugin-react-native-globals@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz#ee1348bc2ceb912303ce6bdbd22e2f045ea86ea2" @@ -3369,6 +3382,19 @@ execa@^0.8.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.9.0.tgz#adb7ce62cf985071f60580deb4a88b9e34712d01" + integrity sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA== + dependencies: + 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" + exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" @@ -3513,11 +3539,6 @@ fast-deep-equal@^1.0.0: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8= -fast-diff@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" - integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig== - fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -3670,6 +3691,13 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" @@ -3879,10 +3907,10 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" integrity sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U= -get-stdin@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" - integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g= +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== get-stream@^3.0.0: version "3.0.0" @@ -4286,14 +4314,21 @@ https-proxy-agent@^2.2.1: agent-base "^4.1.0" debug "^3.1.0" -husky@^0.14.3: - version "0.14.3" - resolved "https://registry.yarnpkg.com/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3" - integrity sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA== - dependencies: - is-ci "^1.0.10" - normalize-path "^1.0.0" - strip-indent "^2.0.0" +husky@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/husky/-/husky-1.1.2.tgz#574c2bb16958db8a8120b63306efaff110525c23" + integrity sha512-9TdkUpBeEOjz0AnFdUN4i3w8kEbOsVs9/WSeJqWLq2OO6bcKQhVW64Zi+pVd/AMRLpN3QTINb6ZXiELczvdmqQ== + dependencies: + cosmiconfig "^5.0.6" + execa "^0.9.0" + find-up "^3.0.0" + get-stdin "^6.0.0" + is-ci "^1.2.1" + pkg-dir "^3.0.0" + please-upgrade-node "^3.1.1" + read-pkg "^4.0.1" + run-node "^1.0.0" + slash "^2.0.0" i18next@^11.2.2: version "11.3.2" @@ -4509,6 +4544,13 @@ is-ci@^1.0.10: dependencies: ci-info "^1.0.0" +is-ci@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" + integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== + dependencies: + ci-info "^1.5.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -4546,6 +4588,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -4968,11 +5015,6 @@ jest-docblock@22.4.0: dependencies: detect-newline "^2.1.0" -jest-docblock@^21.0.0: - version "21.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" - integrity sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw== - jest-docblock@^22.4.0, jest-docblock@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-22.4.3.tgz#50886f132b42b280c903c592373bb6e93bb68b19" @@ -5221,6 +5263,14 @@ js-yaml@^3.7.0, js-yaml@^3.9.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.9.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsan@^3.1.9: version "3.1.10" resolved "https://registry.yarnpkg.com/jsan/-/jsan-3.1.10.tgz#ba9917b864defff567e0c990a34ae7a8d5eb1d90" @@ -5285,6 +5335,11 @@ json-edm-parser@0.1.2: dependencies: jsonparse "~1.2.0" +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" @@ -5509,6 +5564,14 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + lodash-es@^4.17.5: version "4.17.8" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.8.tgz#6fa8c8c5d337481df0bdf1c0d899d42473121e45" @@ -6220,11 +6283,6 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" - integrity sha1-MtDkcvkf80VwHBWoMRAY07CpA3k= - normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -6535,6 +6593,13 @@ p-limit@^1.0.0, p-limit@^1.1.0: dependencies: p-try "^1.0.0" +p-limit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" + integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -6542,6 +6607,13 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" @@ -6554,6 +6626,11 @@ p-try@^1.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= +p-try@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" + integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== + pac-proxy-agent@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-2.0.2.tgz#90d9f6730ab0f4d2607dcdcd4d3d641aa26c3896" @@ -6601,6 +6678,14 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + parse5@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" @@ -6748,6 +6833,20 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +please-upgrade-node@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac" + integrity sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ== + dependencies: + semver-compare "^1.0.0" + plist@1.2.0, plist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/plist/-/plist-1.2.0.tgz#084b5093ddc92506e259f874b8d9b1afb8c79593" @@ -6817,10 +6916,10 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= -prettier@^1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325" - integrity sha1-wa0g6APndJ+vkFpAnSNn4Gu+cyU= +prettier@^1.14.3: + version "1.14.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" + integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg== pretty-format@^22.4.0, pretty-format@^22.4.3: version "22.4.3" @@ -6835,10 +6934,10 @@ pretty-format@^4.2.1: resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-4.3.1.tgz#530be5c42b3c05b36414a7a2a4337aa80acd0e8d" integrity sha1-UwvlxCs8BbNkFKeipDN6qArNDo0= -pretty-quick@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-1.5.0.tgz#304853ece7f8cb56bec74ba3ccd978037e7f2117" - integrity sha512-sqSURtdYoHCN1665kxdzdmGQZTLYKhDfBZnBuj450xTwNNNZXh/zwee4161GlPmDn7tF8NBmRt1O6OcR4GPzhA== +pretty-quick@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-1.8.0.tgz#067ebe744ddb4e1ed4e1ee1af9648815121f78fc" + integrity sha512-qV25sQF/ivJpdZ5efwemQYkQJa7sp3HqT/Vf/7z5vGYMcq1VrT2lDpFKAxJPf6219N1YAdR8mGkIhPAZ1odTmQ== dependencies: chalk "^2.3.0" execa "^0.8.0" @@ -7449,6 +7548,15 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" +read-pkg@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237" + integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc= + dependencies: + normalize-package-data "^2.3.2" + parse-json "^4.0.0" + pify "^3.0.0" + readable-stream@1.1.x: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" @@ -7887,6 +7995,11 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +run-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e" + integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A== + rx-lite-aggregates@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" @@ -7962,6 +8075,11 @@ sax@~1.1.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240" integrity sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA= +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + "semver@2 || 3 || 4 || 5", semver@5.x, semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" @@ -8103,6 +8221,11 @@ slash@1.0.0, slash@^1.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" @@ -8490,11 +8613,6 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= -strip-indent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" - integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= - strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"