From c2586b7c52473cfe5e3b91049715e5d15243bfa0 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Wed, 20 Sep 2017 22:59:16 +0200 Subject: [PATCH 01/27] Started testing with tipsi-stripe This introduces a Podfile --- .gitignore | 2 +- README.md | 1 + android/app/build.gradle | 1 + .../java/no/neuf/chateau/MainApplication.java | 2 + android/build.gradle | 4 +- android/settings.gradle | 2 + env-example | 3 +- ios/Dusken.xcodeproj/project.pbxproj | 185 ++++++++++++++++++ .../contents.xcworkspacedata | 10 + ios/Podfile | 14 ++ ios/Podfile.lock | 12 ++ package.json | 3 +- src/modules/membership/Charge.js | 15 ++ yarn.lock | 6 + 14 files changed, 256 insertions(+), 4 deletions(-) create mode 100644 ios/Dusken.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Podfile create mode 100644 ios/Podfile.lock create mode 100644 src/modules/membership/Charge.js diff --git a/.gitignore b/.gitignore index dd22c9c..499a56f 100644 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,4 @@ fastlane/screenshots # Sentry android/sentry.properties ios/sentry.properties - +ios/Pods diff --git a/README.md b/README.md index 6c63216..0c556d7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ## Install # See https://facebook.github.io/react-native/docs/getting-started.html#content yarn + pod install # ios only # Environment settings cp env-example .env diff --git a/android/app/build.gradle b/android/app/build.gradle index 36a4c75..b709e51 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,6 +155,7 @@ android { } dependencies { + compile project(':tipsi-stripe') compile project(':react-native-sentry') compile project(':react-native-config') compile fileTree(dir: "libs", include: ["*.jar"]) diff --git a/android/app/src/main/java/no/neuf/chateau/MainApplication.java b/android/app/src/main/java/no/neuf/chateau/MainApplication.java index b02be0a..e490bbc 100644 --- a/android/app/src/main/java/no/neuf/chateau/MainApplication.java +++ b/android/app/src/main/java/no/neuf/chateau/MainApplication.java @@ -3,6 +3,7 @@ package no.neuf.chateau; import android.app.Application; import com.facebook.react.ReactApplication; +import com.gettipsi.stripe.StripeReactPackage; import io.sentry.RNSentryPackage; import com.lugg.ReactNativeConfig.ReactNativeConfigPackage; import com.facebook.react.ReactInstanceManager; @@ -26,6 +27,7 @@ public class MainApplication extends Application implements ReactApplication { protected List getPackages() { return Arrays.asList( new MainReactPackage(), + new StripeReactPackage(), new RNSentryPackage(MainApplication.this), new ReactNativeConfigPackage() ); diff --git a/android/build.gradle b/android/build.gradle index eed9972..776e352 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -13,7 +13,9 @@ buildscript { } allprojects { - repositories { + repositories { + // Add jitpack repository (added by tipsi-stripe) + maven { url "https://jitpack.io" } mavenLocal() jcenter() maven { diff --git a/android/settings.gradle b/android/settings.gradle index 24b641c..6a12348 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,4 +1,6 @@ rootProject.name = 'Dusken' +include ':tipsi-stripe' +project(':tipsi-stripe').projectDir = new File(rootProject.projectDir, '../node_modules/tipsi-stripe/android') include ':react-native-sentry' project(':react-native-sentry').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sentry/android') include ':react-native-config' diff --git a/env-example b/env-example index 4b08559..af40e08 100644 --- a/env-example +++ b/env-example @@ -2,4 +2,5 @@ EVENT_API_URL=https://studentersamfundet.no DUSKEN_API_URL=https://galtinn.neuf.no DUSKEN_PURCHASE_URL=https://galtinn.neuf.no/?utm_source=purchase-button&utm_medium=app DUSKEN_FORGOT_PASSWORD_URL=https://galtinn.neuf.no/auth/password_reset/ -SENTRY_DSN= \ No newline at end of file +SENTRY_DSN= +STRIPE_PUBLISHABLE_KEY= \ No newline at end of file diff --git a/ios/Dusken.xcodeproj/project.pbxproj b/ios/Dusken.xcodeproj/project.pbxproj index 67b0253..37d2a7d 100644 --- a/ios/Dusken.xcodeproj/project.pbxproj +++ b/ios/Dusken.xcodeproj/project.pbxproj @@ -39,7 +39,9 @@ 3E46ED82B1574BB598025413 /* EvilIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0A6DA7DAB38A43E2BF0FC37C /* EvilIcons.ttf */; }; 4306CBFD81DE4035B0AB4D30 /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C02D46B0229941F69264474C /* SimpleLineIcons.ttf */; }; 48652E97B0B04C15B3FA6FC3 /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D7A0431FBA3840039633FC3C /* MaterialIcons.ttf */; }; + 4AF5FEEA965E4967AA857546 /* libTPSStripe.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 95CBCD539DBA4AE7B3D73CD0 /* libTPSStripe.a */; }; 551E4CC640DB4E68A88730B5 /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4A651C47D6FC4ED2BAB4F197 /* Zocial.ttf */; }; + 55EF0DB62370FC7FACE6B61E /* libPods-DuskenTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 94E51283EFA6F590919438A3 /* libPods-DuskenTests.a */; }; 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; 65850D7E09F243FDB4F2B168 /* libRNSentry.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E3DF2205F5D4B34BF1CCCCF /* libRNSentry.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; @@ -53,6 +55,7 @@ C867C6D3ECB7499FA2F051D6 /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E926661F17B94D69B50A0BA5 /* FontAwesome.ttf */; }; CC801D520E86402F9AF28660 /* Foundation.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 390970DBF0FD44B0B4C8E2F0 /* Foundation.ttf */; }; D218B6D7605D4C17B6540D0B /* libReactNativeConfig.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 07B9F82FBB154C258C70E333 /* libReactNativeConfig.a */; }; + F27CE4F4AEFA492262BF93F8 /* libPods-Dusken.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 584192D9AB197F8F652E4481 /* libPods-Dusken.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -245,6 +248,13 @@ remoteGlobalIDString = 58B5119B1A9E6C1200147676; remoteInfo = RCTText; }; + 871D05431F7303CD0009775B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 32A55FD2F8DE47F3BC5443BB /* TPSStripe.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3A3A7F1A1DC27B520030F9DC; + remoteInfo = TPSStripe; + }; 87371BF41F6F25C200915105 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; @@ -313,6 +323,7 @@ 00E356EE1AD99517003FC87E /* DuskenTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DuskenTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 00E356F21AD99517003FC87E /* DuskenTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DuskenTests.m; sourceTree = ""; }; + 020374EEEA8B01E859226AEC /* Pods-Dusken.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Dusken.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Dusken/Pods-Dusken.debug.xcconfig"; sourceTree = ""; }; 07B9F82FBB154C258C70E333 /* libReactNativeConfig.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libReactNativeConfig.a; sourceTree = ""; }; 0A6DA7DAB38A43E2BF0FC37C /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/native-base/Fonts/EvilIcons.ttf"; sourceTree = ""; }; 0D8F73C46ADC4ABEBE691283 /* ReactNativeConfig.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = ReactNativeConfig.xcodeproj; path = "../node_modules/react-native-config/ios/ReactNativeConfig.xcodeproj"; sourceTree = ""; }; @@ -329,11 +340,14 @@ 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; 2D02E47B1E0B4A5D006451C7 /* Dusken-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Dusken-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D02E4901E0B4A5D006451C7 /* Dusken-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Dusken-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 32A55FD2F8DE47F3BC5443BB /* TPSStripe.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = TPSStripe.xcodeproj; path = "../node_modules/tipsi-stripe/ios/TPSStripe.xcodeproj"; sourceTree = ""; }; 390970DBF0FD44B0B4C8E2F0 /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/native-base/Fonts/Foundation.ttf"; sourceTree = ""; }; 4A651C47D6FC4ED2BAB4F197 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/native-base/Fonts/Zocial.ttf"; sourceTree = ""; }; 4E3DF2205F5D4B34BF1CCCCF /* libRNSentry.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNSentry.a; sourceTree = ""; }; + 584192D9AB197F8F652E4481 /* libPods-Dusken.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Dusken.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 59C3A3AC725E4DF083440735 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/native-base/Fonts/Ionicons.ttf"; sourceTree = ""; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; + 6C44CB8E861A480DD6BEA546 /* Pods-DuskenTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DuskenTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-DuskenTests/Pods-DuskenTests.release.xcconfig"; sourceTree = ""; }; 76F0B251D6DD45228CBC367B /* RNSentry.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSentry.xcodeproj; path = "../node_modules/react-native-sentry/ios/RNSentry.xcodeproj"; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; @@ -341,12 +355,16 @@ 87E5B29C1F225BD50051F809 /* dnslogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = dnslogo.png; path = Dusken/dnslogo.png; sourceTree = ""; }; 8CAEF677B8A643969E0294B7 /* Roboto_medium.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Roboto_medium.ttf; path = "../node_modules/native-base/Fonts/Roboto_medium.ttf"; sourceTree = ""; }; 923192359DEC49D085C78135 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 94E51283EFA6F590919438A3 /* libPods-DuskenTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-DuskenTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 95CBCD539DBA4AE7B3D73CD0 /* libTPSStripe.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libTPSStripe.a; sourceTree = ""; }; ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = ""; }; C02D46B0229941F69264474C /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/native-base/Fonts/SimpleLineIcons.ttf"; sourceTree = ""; }; C559033577D34FACA86020C1 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/native-base/Fonts/Octicons.ttf"; sourceTree = ""; }; D4F0955EA08E41F69EEE0DED /* Roboto.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Roboto.ttf; path = "../node_modules/native-base/Fonts/Roboto.ttf"; sourceTree = ""; }; D7A0431FBA3840039633FC3C /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = "../node_modules/native-base/Fonts/MaterialIcons.ttf"; sourceTree = ""; }; E926661F17B94D69B50A0BA5 /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = "../node_modules/native-base/Fonts/FontAwesome.ttf"; sourceTree = ""; }; + ED3E665425D2BF39C276B9FC /* Pods-Dusken.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Dusken.release.xcconfig"; path = "Pods/Target Support Files/Pods-Dusken/Pods-Dusken.release.xcconfig"; sourceTree = ""; }; + F99415EAE5AC3D08F4AD900B /* Pods-DuskenTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DuskenTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-DuskenTests/Pods-DuskenTests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -355,6 +373,7 @@ buildActionMask = 2147483647; files = ( 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */, + 55EF0DB62370FC7FACE6B61E /* libPods-DuskenTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -378,6 +397,8 @@ D218B6D7605D4C17B6540D0B /* libReactNativeConfig.a in Frameworks */, 65850D7E09F243FDB4F2B168 /* libRNSentry.a in Frameworks */, 83EBB8CA4CF842BA8C090802 /* libz.tbd in Frameworks */, + 4AF5FEEA965E4967AA857546 /* libTPSStripe.a in Frameworks */, + F27CE4F4AEFA492262BF93F8 /* libPods-Dusken.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -465,6 +486,17 @@ name = "Supporting Files"; sourceTree = ""; }; + 06140F8A90550C16A8941EFD /* Pods */ = { + isa = PBXGroup; + children = ( + 020374EEEA8B01E859226AEC /* Pods-Dusken.debug.xcconfig */, + ED3E665425D2BF39C276B9FC /* Pods-Dusken.release.xcconfig */, + F99415EAE5AC3D08F4AD900B /* Pods-DuskenTests.debug.xcconfig */, + 6C44CB8E861A480DD6BEA546 /* Pods-DuskenTests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; 139105B71AF99BAD00B5F7CC /* Products */ = { isa = PBXGroup; children = ( @@ -517,6 +549,15 @@ name = Products; sourceTree = ""; }; + 3B33B1721C77D1DC86BC30C3 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 584192D9AB197F8F652E4481 /* libPods-Dusken.a */, + 94E51283EFA6F590919438A3 /* libPods-DuskenTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; 5E91572E1DD0AC6500FF2AA8 /* Products */ = { isa = PBXGroup; children = ( @@ -552,6 +593,7 @@ 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, 0D8F73C46ADC4ABEBE691283 /* ReactNativeConfig.xcodeproj */, 76F0B251D6DD45228CBC367B /* RNSentry.xcodeproj */, + 32A55FD2F8DE47F3BC5443BB /* TPSStripe.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -574,6 +616,8 @@ 83CBBA001A601CBA00E9B192 /* Products */, 95AA103233A74A28A47B99B8 /* Resources */, 87995FD11F72F740005EB91D /* Recovered References */, + 06140F8A90550C16A8941EFD /* Pods */, + 3B33B1721C77D1DC86BC30C3 /* Frameworks */, ); indentWidth = 2; sourceTree = ""; @@ -591,12 +635,21 @@ name = Products; sourceTree = ""; }; + 871D05401F7303CD0009775B /* Products */ = { + isa = PBXGroup; + children = ( + 871D05441F7303CD0009775B /* libTPSStripe.a */, + ); + name = Products; + sourceTree = ""; + }; 87995FD11F72F740005EB91D /* Recovered References */ = { isa = PBXGroup; children = ( 07B9F82FBB154C258C70E333 /* libReactNativeConfig.a */, 4E3DF2205F5D4B34BF1CCCCF /* libRNSentry.a */, 923192359DEC49D085C78135 /* libz.tbd */, + 95CBCD539DBA4AE7B3D73CD0 /* libTPSStripe.a */, ); name = "Recovered References"; sourceTree = ""; @@ -652,9 +705,12 @@ isa = PBXNativeTarget; buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "DuskenTests" */; buildPhases = ( + 130DD4483861A16A773A7D0E /* [CP] Check Pods Manifest.lock */, 00E356EA1AD99517003FC87E /* Sources */, 00E356EB1AD99517003FC87E /* Frameworks */, 00E356EC1AD99517003FC87E /* Resources */, + 567CD65443C546CF1D70A27E /* [CP] Embed Pods Frameworks */, + E2056D6A32DDC89CA6D3EFCD /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -670,11 +726,14 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Dusken" */; buildPhases = ( + D97D7C388D1F900D9E524C3A /* [CP] Check Pods Manifest.lock */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 98D2BF556B534A3FBEC71C2F /* Upload Debug Symbols to Sentry */, + D038498A5851F0B62027363D /* [CP] Embed Pods Frameworks */, + D9A71B546BFA13DD10E69B91 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -816,6 +875,10 @@ ProductGroup = 87995FF41F72F741005EB91D /* Products */; ProjectRef = 76F0B251D6DD45228CBC367B /* RNSentry.xcodeproj */; }, + { + ProductGroup = 871D05401F7303CD0009775B /* Products */; + ProjectRef = 32A55FD2F8DE47F3BC5443BB /* TPSStripe.xcodeproj */; + }, ); projectRoot = ""; targets = ( @@ -1003,6 +1066,13 @@ remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 871D05441F7303CD0009775B /* libTPSStripe.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libTPSStripe.a; + remoteRef = 871D05431F7303CD0009775B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 87371BF51F6F25C200915105 /* libRCTBlob-tvOS.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1123,6 +1193,24 @@ shellPath = /bin/sh; shellScript = "export SENTRY_PROPERTIES=sentry.properties\nexport NODE_BINARY=node\n../node_modules/sentry-cli-binary/bin/sentry-cli react-native xcode ../node_modules/react-native/scripts/react-native-xcode.sh"; }; + 130DD4483861A16A773A7D0E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-DuskenTests-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; + }; 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1137,6 +1225,21 @@ shellPath = /bin/sh; shellScript = "export SENTRY_PROPERTIES=sentry.properties\nexport NODE_BINARY=node\n../node_modules/sentry-cli-binary/bin/sentry-cli react-native xcode ../node_modules/react-native/scripts/react-native-xcode.sh"; }; + 567CD65443C546CF1D70A27E /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-DuskenTests/Pods-DuskenTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 98D2BF556B534A3FBEC71C2F /* Upload Debug Symbols to Sentry */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1151,6 +1254,72 @@ shellPath = /bin/sh; shellScript = "export SENTRY_PROPERTIES=sentry.properties\n../node_modules/sentry-cli-binary/bin/sentry-cli upload-dsym"; }; + D038498A5851F0B62027363D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Dusken/Pods-Dusken-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + D97D7C388D1F900D9E524C3A /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Dusken-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; + }; + D9A71B546BFA13DD10E69B91 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-Dusken/Pods-Dusken-resources.sh", + $PODS_CONFIGURATION_BUILD_DIR/Stripe/Stripe.bundle, + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Dusken/Pods-Dusken-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + E2056D6A32DDC89CA6D3EFCD /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-DuskenTests/Pods-DuskenTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1218,6 +1387,7 @@ /* Begin XCBuildConfiguration section */ 00E356F61AD99517003FC87E /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = F99415EAE5AC3D08F4AD900B /* Pods-DuskenTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -1228,6 +1398,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-config/ios/ReactNativeConfig", "$(SRCROOT)/../node_modules/react-native-sentry/ios/**", + "$(SRCROOT)/../node_modules/tipsi-stripe/ios/TPSStripe", ); INFOPLIST_FILE = DuskenTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1236,6 +1407,7 @@ "$(inherited)", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1248,6 +1420,7 @@ }; 00E356F71AD99517003FC87E /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 6C44CB8E861A480DD6BEA546 /* Pods-DuskenTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; COPY_PHASE_STRIP = NO; @@ -1255,6 +1428,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-config/ios/ReactNativeConfig", "$(SRCROOT)/../node_modules/react-native-sentry/ios/**", + "$(SRCROOT)/../node_modules/tipsi-stripe/ios/TPSStripe", ); INFOPLIST_FILE = DuskenTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1263,6 +1437,7 @@ "$(inherited)", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1275,6 +1450,7 @@ }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 020374EEEA8B01E859226AEC /* Pods-Dusken.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = 1; @@ -1284,6 +1460,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-config/ios/ReactNativeConfig", "$(SRCROOT)/../node_modules/react-native-sentry/ios/**", + "$(SRCROOT)/../node_modules/tipsi-stripe/ios/TPSStripe", ); INFOPLIST_FILE = Dusken/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1300,6 +1477,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = ED3E665425D2BF39C276B9FC /* Pods-Dusken.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = 1; @@ -1308,6 +1486,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-config/ios/ReactNativeConfig", "$(SRCROOT)/../node_modules/react-native-sentry/ios/**", + "$(SRCROOT)/../node_modules/tipsi-stripe/ios/TPSStripe", ); INFOPLIST_FILE = Dusken/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1338,6 +1517,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-config/ios/ReactNativeConfig", "$(SRCROOT)/../node_modules/react-native-sentry/ios/**", + "$(SRCROOT)/../node_modules/tipsi-stripe/ios/TPSStripe", ); INFOPLIST_FILE = "Dusken-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1345,6 +1525,7 @@ "$(inherited)", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1374,6 +1555,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/react-native-config/ios/ReactNativeConfig", "$(SRCROOT)/../node_modules/react-native-sentry/ios/**", + "$(SRCROOT)/../node_modules/tipsi-stripe/ios/TPSStripe", ); INFOPLIST_FILE = "Dusken-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1381,6 +1563,7 @@ "$(inherited)", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1411,6 +1594,7 @@ "$(inherited)", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.Dusken-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1437,6 +1621,7 @@ "$(inherited)", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.Dusken-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/ios/Dusken.xcworkspace/contents.xcworkspacedata b/ios/Dusken.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..416606e --- /dev/null +++ b/ios/Dusken.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..e35b08d --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,14 @@ +platform :ios, '9.0' + +target 'Dusken' do + # use_frameworks! + + # Pods for Dusken + pod 'Stripe', '~> 10.1.0' + + target 'DuskenTests' do + inherit! :search_paths + # Pods for testing + end + +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..0b743a6 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,12 @@ +PODS: + - Stripe (10.1.0) + +DEPENDENCIES: + - Stripe (~> 10.1.0) + +SPEC CHECKSUMS: + Stripe: 1c7aa951a075cced500a919d92b687b35d410705 + +PODFILE CHECKSUM: f7eeb7918fcad1c2afbf24caacdddea228bf0609 + +COCOAPODS: 1.3.1 diff --git a/package.json b/package.json index 73b2550..6255e02 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "redux": "^3.7.2", "redux-logger": "^3.0.6", "redux-persist": "^4.9.1", - "redux-thunk": "^2.2.0" + "redux-thunk": "^2.2.0", + "tipsi-stripe": "^3.7.0" }, "devDependencies": { "babel-jest": "20.0.3", diff --git a/src/modules/membership/Charge.js b/src/modules/membership/Charge.js new file mode 100644 index 0000000..df8cf07 --- /dev/null +++ b/src/modules/membership/Charge.js @@ -0,0 +1,15 @@ +import stripe from 'tipsi-stripe' +import Config from 'react-native-config'; + +stripe.init({ + publishableKey: Config.STRIPE_PUBLISHABLE_KEY, +}); + +class Charge { + openStripe() { + stripe.createTokenWithCard().then((data) => { + // returns a token.tokenId which should be saved + + }) + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index a973df5..509d8eb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4432,6 +4432,12 @@ time-stamp@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.0.1.tgz#9f4bd23559c9365966f3302dbba2b07c6b99b151" +tipsi-stripe@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/tipsi-stripe/-/tipsi-stripe-3.7.0.tgz#9812ea9ffb9f1b8d08d3e86600195967021496ca" + dependencies: + prop-types "^15.5.10" + tmp@^0.0.31: version "0.0.31" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" From 351927f26deb581d126f46b00235cfc670785af5 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Sat, 30 Sep 2017 19:28:03 +0200 Subject: [PATCH 02/27] UserRegister: Started register form --- src/modules/login/Login.js | 4 +- src/modules/membership/Charge.js | 15 +- src/modules/membership/MembershipContainer.js | 4 +- src/modules/membership/UserRegister.js | 143 ++++++++++++++++++ .../membership/UserRegisterContainer.js | 11 ++ src/screens/MembershipScreen.js | 2 + 6 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 src/modules/membership/UserRegister.js create mode 100644 src/modules/membership/UserRegisterContainer.js diff --git a/src/modules/login/Login.js b/src/modules/login/Login.js index 49ff23f..1710717 100644 --- a/src/modules/login/Login.js +++ b/src/modules/login/Login.js @@ -82,7 +82,7 @@ export default class Login extends Component { {this.emailInput()} {this.passwordInput()} {this.showError()} - + {this.showSpinner()} + + + + ); + } +} +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + }, + input: { + width: 320, + fontSize: 20, + height: 52, + }, + registerButton: { + marginBottom: 16, + }, + errorBox: { + marginVertical: 10, + }, + errorMessage: { + textAlign: 'center', + color: 'red', + }, + card: { + borderColor: '#e1e8ee', + borderWidth: 1, + ...Platform.select({ + ios: { + shadowColor: 'rgba(0,0,0, .2)', + shadowOffset: {height: 0, width: 0}, + shadowOpacity: 1, + shadowRadius: 1, + }, + android: { + elevation: 1, + }, + }), + padding: 8, + margin: 8, + backgroundColor: '#fff', + }, +}); \ No newline at end of file diff --git a/src/modules/membership/UserRegisterContainer.js b/src/modules/membership/UserRegisterContainer.js new file mode 100644 index 0000000..674d28c --- /dev/null +++ b/src/modules/membership/UserRegisterContainer.js @@ -0,0 +1,11 @@ +import React, {Component} from 'react'; +import {connect} from "react-redux"; +import UserRegister from "./UserRegister"; + +class UserRegisterContainer extends Component { + render() { + return ; + } +} + +export default connect()(UserRegisterContainer); \ No newline at end of file diff --git a/src/screens/MembershipScreen.js b/src/screens/MembershipScreen.js index 12ada0c..9019167 100644 --- a/src/screens/MembershipScreen.js +++ b/src/screens/MembershipScreen.js @@ -3,6 +3,7 @@ import MembershipContainer from "../modules/membership/MembershipContainer"; import Icon from 'react-native-vector-icons/SimpleLineIcons'; import {StyleProvider} from "native-base"; import getTheme from '../../native-base-theme/components'; +import UserRegisterContainer from "../modules/membership/UserRegisterContainer"; export default class MembershipScreen extends Component { static navigationOptions = { @@ -30,6 +31,7 @@ export default class MembershipScreen extends Component { render() { return ( + {/**/} ) From be5c49fa0448bed81c3c4ea144b8e6589c452ffb Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Sun, 1 Oct 2017 15:12:37 +0200 Subject: [PATCH 03/27] Work on user register form --- src/Dusken.js | 2 +- src/actions.js | 66 ++++++++++++++++++- src/modules/events/EventList.js | 6 +- src/modules/login/Login.js | 4 +- src/modules/membership/MembershipContainer.js | 10 ++- src/modules/membership/UserRegister.js | 62 +++++++++++++---- .../membership/UserRegisterContainer.js | 18 ++++- src/reducers.js | 25 +++++++ src/screens/MembershipScreen.js | 4 +- 9 files changed, 170 insertions(+), 27 deletions(-) diff --git a/src/Dusken.js b/src/Dusken.js index 32d8065..1007d35 100644 --- a/src/Dusken.js +++ b/src/Dusken.js @@ -12,8 +12,8 @@ import MembershipScreen from "./screens/MembershipScreen"; /* Navigation */ const tabBarRoutes = { - EventList: { screen: EventListScreen }, Membership: { screen: MembershipScreen }, + EventList: { screen: EventListScreen }, About: { screen: AboutScreen }, }; diff --git a/src/actions.js b/src/actions.js index d8ca00c..930845c 100644 --- a/src/actions.js +++ b/src/actions.js @@ -7,6 +7,9 @@ const LOGOUT = 'LOGOUT'; const USER_DATA_REQUEST = 'USER_DATA_REQUEST'; const USER_DATA_SUCCESS = 'USER_DATA_SUCCESS'; const USER_DATA_FAILURE = 'USER_DATA_FAILURE'; +const REGISTER_USER_REQUEST = 'REGISTER_USER_REQUEST'; +const REGISTER_USER_SUCCESS = 'REGISTER_USER_SUCCESS'; +const REGISTER_USER_FAILURE = 'REGISTER_USER_FAILURE'; function loginRequest() { return { @@ -55,6 +58,26 @@ function userDataFailure(userError) { } } +function registerUserRequest() { + return { + type: REGISTER_USER_REQUEST + } +} + +function registerUserSuccess(data) { + return { + type: REGISTER_USER_SUCCESS, + data + } +} + +function registerUserFailure(registerError) { + return { + type: REGISTER_USER_FAILURE, + registerError + } +} + export { LOGIN_REQUEST, loginRequest, LOGIN_SUCCESS, loginSuccess, @@ -63,14 +86,16 @@ export { USER_DATA_REQUEST, userDataRequest, USER_DATA_SUCCESS, userDataSuccess, USER_DATA_FAILURE, userDataFailure, + REGISTER_USER_REQUEST, registerUserRequest, + REGISTER_USER_SUCCESS, registerUserSuccess, + REGISTER_USER_FAILURE, registerUserFailure, }; export function requestLogin(username, password) { return (dispatch) => { // We are now logging in dispatch(loginRequest()); - const apiURL = Config.DUSKEN_API_URL; - return fetch(`${apiURL}/auth/obtain-token/`, { + return fetch(`${Config.DUSKEN_API_URL}/auth/obtain-token/`, { method: 'POST', headers: { 'Accept': 'application/json', @@ -131,3 +156,40 @@ export function requestUserData(token) { ) } } + +export function requestRegisterUser(firstName, lastName, email, phoneNumber, password) { + return (dispatch) => { + dispatch(registerUserRequest()); + + return fetch(`${Config.DUSKEN_API_URL}/api/user/register`, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + 'first_name': firstName, + 'last_name': lastName, + 'email': email, + 'phone_number': phoneNumber, + 'password': password + }) + }) + .then(response => response.json().then(json => ({ json, response }))) + .then(({json, response}) => { + if (response.ok === false) { + return Promise.reject(json) + } + return json + }) + .then( + data => { + dispatch(registerUserSuccess(data)) + }, + data => { + dispatch(registerUserFailure(data || {'non_field_errors': ['Kunne ikke registrere bruker, prøv igjen']})) + } + ) + } +} + diff --git a/src/modules/events/EventList.js b/src/modules/events/EventList.js index 734f7e8..3b383fb 100644 --- a/src/modules/events/EventList.js +++ b/src/modules/events/EventList.js @@ -1,5 +1,5 @@ -import {StyleSheet, ActivityIndicator, View, SectionList} from "react-native"; -import {Card, ListItem, CardItem, Body, Text as Text, Left, Right, Icon, Button, Content} from 'native-base'; +import {StyleSheet, View, SectionList} from "react-native"; +import {Card, ListItem, CardItem, Body, Text as Text, Left, Right, Icon, Button, Content, Spinner} from 'native-base'; import React, { Component } from 'react'; import moment from "moment"; import 'moment/locale/nb'; @@ -33,7 +33,7 @@ export default class EventList extends Component { } return ( - + ); }; diff --git a/src/modules/login/Login.js b/src/modules/login/Login.js index 1710717..49ff23f 100644 --- a/src/modules/login/Login.js +++ b/src/modules/login/Login.js @@ -82,7 +82,7 @@ export default class Login extends Component { {this.emailInput()} {this.passwordInput()} {this.showError()} - {this.showSpinner()} @@ -101,6 +129,16 @@ export default class UserRegister extends Component { ); } + + onRegisterPress = () => { + this.props.onRegisterPress( + this.state.firstName, + this.state.lastName, + this.state.email, + this.state.phoneNumber, + this.state.password, + ); + } } const styles = StyleSheet.create({ container: { diff --git a/src/modules/membership/UserRegisterContainer.js b/src/modules/membership/UserRegisterContainer.js index 674d28c..bfe67f4 100644 --- a/src/modules/membership/UserRegisterContainer.js +++ b/src/modules/membership/UserRegisterContainer.js @@ -1,11 +1,25 @@ import React, {Component} from 'react'; import {connect} from "react-redux"; import UserRegister from "./UserRegister"; +import {requestRegisterUser} from "../../actions"; class UserRegisterContainer extends Component { + onRegisterPress = (firstName, lastName, email, phoneNumber, password) => { + this.props.requestRegisterUser(firstName, lastName, email, phoneNumber, password); + }; + render() { - return ; + return ; } } -export default connect()(UserRegisterContainer); \ No newline at end of file +function stateToProps(state) { + return { + isRegisteringUser: state.isRegisteringUser, + registerError: state.registerError + }; +} +export default connect( + stateToProps, + {requestRegisterUser} +)(UserRegisterContainer); \ No newline at end of file diff --git a/src/reducers.js b/src/reducers.js index 22b4cb2..5040895 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -6,20 +6,26 @@ import { USER_DATA_REQUEST, USER_DATA_SUCCESS, USER_DATA_FAILURE, + REGISTER_USER_REQUEST, + REGISTER_USER_FAILURE, + REGISTER_USER_SUCCESS, } from './actions'; const initialState = { isAuthenticated: false, isLoggingIn: false, isFetchingUserData: false, + isRegisteringUser: false, userToken: null, user: null, loginError: null, userError: null, + registerError: null, }; export default function duskenApp(state = initialState, action) { switch (action.type) { + /* Login */ case LOGIN_REQUEST: return Object.assign({}, state, { isLoggingIn: true, @@ -42,6 +48,7 @@ export default function duskenApp(state = initialState, action) { case LOGOUT: return initialState; + /* User data */ case USER_DATA_REQUEST: return Object.assign({}, state, { isFetchingUserData: true @@ -59,6 +66,24 @@ export default function duskenApp(state = initialState, action) { user: action.data }); + /* Register user */ + case REGISTER_USER_REQUEST: + return Object.assign({}, state, { + isRegisteringUser: true + }); + + case REGISTER_USER_FAILURE: + return Object.assign({}, state, { + isRegisteringUser: false, + registerError: action.registerError + }); + + case REGISTER_USER_SUCCESS: + return Object.assign({}, state, { + isRegisteringUser: false, + user: action.data + }); + default: return state } diff --git a/src/screens/MembershipScreen.js b/src/screens/MembershipScreen.js index 9019167..6c51d52 100644 --- a/src/screens/MembershipScreen.js +++ b/src/screens/MembershipScreen.js @@ -31,8 +31,8 @@ export default class MembershipScreen extends Component { render() { return ( - {/**/} - + + {/**/} ) } From 2d4d0b2cf4ec3cd6cf429785fedc2de2fff86134 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Mon, 2 Oct 2017 00:28:20 +0200 Subject: [PATCH 04/27] Mostly working user registration Refactor a bit Up next: card purchase --- .gitignore | 2 +- env-example | 1 - package.json | 2 +- src/Dusken.js | 4 ++ src/actions.js | 2 +- src/modules/membership/Charge.js | 1 + src/modules/membership/Membership.js | 9 +--- src/modules/membership/MembershipContainer.js | 17 +++++-- .../{MembershipProof.js => Proof.js} | 8 ++- src/modules/membership/ProofContainer.js | 15 ++++++ .../membership/UserRegisterContainer.js | 25 ---------- .../{membership => register}/UserRegister.js | 47 +++++++++++++---- src/modules/register/UserRegisterContainer.js | 50 +++++++++++++++++++ src/reducers.js | 16 ++++-- src/screens/ChargeScreen.js | 30 +++++++++++ src/screens/LoginScreen.js | 3 +- src/screens/MembershipScreen.js | 18 +++++-- src/screens/UserRegisterScreen.js | 30 +++++++++++ yarn.lock | 14 +++--- 19 files changed, 223 insertions(+), 71 deletions(-) rename src/modules/membership/{MembershipProof.js => Proof.js} (96%) create mode 100644 src/modules/membership/ProofContainer.js delete mode 100644 src/modules/membership/UserRegisterContainer.js rename src/modules/{membership => register}/UserRegister.js (84%) create mode 100644 src/modules/register/UserRegisterContainer.js create mode 100644 src/screens/ChargeScreen.js create mode 100644 src/screens/UserRegisterScreen.js diff --git a/.gitignore b/.gitignore index 499a56f..055b6e7 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,7 @@ fastlane/report.xml fastlane/Preview.html fastlane/screenshots -.env +.env* *.swp # Sentry diff --git a/env-example b/env-example index af40e08..f0cd498 100644 --- a/env-example +++ b/env-example @@ -1,6 +1,5 @@ EVENT_API_URL=https://studentersamfundet.no DUSKEN_API_URL=https://galtinn.neuf.no -DUSKEN_PURCHASE_URL=https://galtinn.neuf.no/?utm_source=purchase-button&utm_medium=app DUSKEN_FORGOT_PASSWORD_URL=https://galtinn.neuf.no/auth/password_reset/ SENTRY_DSN= STRIPE_PUBLISHABLE_KEY= \ No newline at end of file diff --git a/package.json b/package.json index 6255e02..d68841d 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "react-native-confetti": "^0.0.6", "react-native-config": "^0.6.1", "react-native-htmlview": "^0.12.0", - "react-native-sentry": "^0.23.2", + "react-native-sentry": "^0.25.0", "react-navigation": "^1.0.0-beta.11", "react-redux": "^5.0.6", "redux": "^3.7.2", diff --git a/src/Dusken.js b/src/Dusken.js index 1007d35..aa5c26a 100644 --- a/src/Dusken.js +++ b/src/Dusken.js @@ -8,6 +8,8 @@ import EventDetailScreen from "./screens/EventDetailScreen"; import EventListScreen from "./screens/EventListScreen"; import LoginScreen from "./screens/LoginScreen"; import MembershipScreen from "./screens/MembershipScreen"; +import UserRegisterScreen from "./screens/UserRegisterScreen"; +import ChargeScreen from "./screens/ChargeScreen"; /* Navigation */ @@ -46,6 +48,8 @@ const tabNav = TabNavigator(tabBarRoutes, tabBarOptions); const DuskenContainer = StackNavigator({ Root: { screen: tabNav }, Login: { screen: LoginScreen }, + UserRegister: { screen: UserRegisterScreen }, + Charge: { screen: ChargeScreen }, EventDetail: { screen: EventDetailScreen }, }); diff --git a/src/actions.js b/src/actions.js index 930845c..b2cf622 100644 --- a/src/actions.js +++ b/src/actions.js @@ -161,7 +161,7 @@ export function requestRegisterUser(firstName, lastName, email, phoneNumber, pas return (dispatch) => { dispatch(registerUserRequest()); - return fetch(`${Config.DUSKEN_API_URL}/api/user/register`, { + return fetch(`${Config.DUSKEN_API_URL}/api/user/register/`, { method: 'POST', headers: { 'Accept': 'application/json', diff --git a/src/modules/membership/Charge.js b/src/modules/membership/Charge.js index e5b5a69..eda16e2 100644 --- a/src/modules/membership/Charge.js +++ b/src/modules/membership/Charge.js @@ -10,6 +10,7 @@ stripe.init({ }); export default class Charge extends Component { + // TODO: You are here render() { return In charge view diff --git a/src/modules/membership/Membership.js b/src/modules/membership/Membership.js index 8aed2f0..7925a69 100644 --- a/src/modules/membership/Membership.js +++ b/src/modules/membership/Membership.js @@ -1,8 +1,6 @@ import React, {Component} from 'react'; import {ScrollView, Text, View, Linking, StyleSheet, Platform} from "react-native"; import {Button, Text as NBText} from "native-base"; -import Config from 'react-native-config'; - export default class Membership extends Component { render() { return ( @@ -11,7 +9,7 @@ export default class Membership extends Component { Hei 👋 Her kan du bli medlem i Det Norske Studentersamfund - Chateau Neuf og ha medlemsbeviset ditt på telefonen - + Hva får jeg? @@ -22,16 +20,13 @@ export default class Membership extends Component { - Mulighet til å delta i landets eldste studentdemokrati Allerede medlem? - + ) }; - onLoginPress = () => { - this.props.onLoginPress(); - }; } diff --git a/src/modules/membership/MembershipContainer.js b/src/modules/membership/MembershipContainer.js index d68b98c..729d403 100644 --- a/src/modules/membership/MembershipContainer.js +++ b/src/modules/membership/MembershipContainer.js @@ -2,7 +2,7 @@ import React, {Component} from 'react'; import {connect} from "react-redux"; import Membership from "./Membership"; -import MembershipProof from "./MembershipProof"; +import Proof from "./Proof"; import { requestUserData, logout } from "../../actions"; class MembershipContainer extends Component { @@ -42,20 +42,29 @@ class MembershipContainer extends Component { this.props.onLoginPress(); }; + onRegisterPress = () => { + this.props.onRegisterPress(); + }; + + onChargePress = () => { + this.props.onChargePress(); + }; + onLogoutPress = () => { this.props.logout(); - this.props.logoutNavigate(); + this.props.onLogoutPress(); }; render() { if (this.state.user) { - return ; } - return ; + return ; } } diff --git a/src/modules/membership/MembershipProof.js b/src/modules/membership/Proof.js similarity index 96% rename from src/modules/membership/MembershipProof.js rename to src/modules/membership/Proof.js index 7b6cdb2..3894c66 100644 --- a/src/modules/membership/MembershipProof.js +++ b/src/modules/membership/Proof.js @@ -1,10 +1,10 @@ import React, {Component} from 'react'; import {Image, Linking, StyleSheet, Platform, RefreshControl, TouchableOpacity, View} from "react-native"; import {Button, Body, Card, CardItem, Text, Content} from 'native-base'; -import Config from 'react-native-config'; import Confetti from 'react-native-confetti'; -export default class MembershipProof extends Component { +export default class Proof extends Component { + // FIXME: Move logic to container CONFETTI_TIMEOUT = 15000; constructor(props) { @@ -120,9 +120,7 @@ export default class MembershipProof extends Component { return + {this.registerbutton()} {this.showSpinner()} @@ -138,6 +144,27 @@ export default class UserRegister extends Component { this.state.phoneNumber, this.state.password, ); + }; + + registerbutton() { + if( this.props.isRegisteringUser || !this.canSubmitForm() ) { + return ( + ); + } + + return (); } } const styles = StyleSheet.create({ diff --git a/src/modules/register/UserRegisterContainer.js b/src/modules/register/UserRegisterContainer.js new file mode 100644 index 0000000..ff85fcf --- /dev/null +++ b/src/modules/register/UserRegisterContainer.js @@ -0,0 +1,50 @@ +import React, {Component} from 'react'; +import {connect} from "react-redux"; +import UserRegister from "./UserRegister"; +import {requestRegisterUser} from "../../actions"; + +class UserRegisterContainer extends Component { + + constructor(state) { + super(state); + this.state = { + isAuthenticated: false, + isRegisteringUser: false, + registerError: null + } + } + + componentWillReceiveProps(nextProps) { + if (this.state.isAuthenticated !== nextProps.isAuthenticated) { + if (nextProps.isAuthenticated) { + this.props.onRegister(); + } + } + if (this.state.isRegisteringUser !== nextProps.isRegisteringUser) { + this.setState({isRegisteringUser: nextProps.isRegisteringUser}); + } + if (this.state.registerError !== nextProps.registerError) { + this.setState({registerError: nextProps.registerError}); + } + } + + onRegisterPress = (firstName, lastName, email, phoneNumber, password) => { + this.props.requestRegisterUser(firstName, lastName, email, phoneNumber, password); + }; + + render() { + return ; + } +} + +function stateToProps(state) { + return { + isAuthenticated: state.isAuthenticated, + isRegisteringUser: state.isRegisteringUser, + registerError: state.registerError + }; +} +export default connect( + stateToProps, + {requestRegisterUser} +)(UserRegisterContainer); \ No newline at end of file diff --git a/src/reducers.js b/src/reducers.js index 5040895..943d4bc 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -51,7 +51,8 @@ export default function duskenApp(state = initialState, action) { /* User data */ case USER_DATA_REQUEST: return Object.assign({}, state, { - isFetchingUserData: true + isFetchingUserData: true, + userError: null }); case USER_DATA_FAILURE: @@ -63,13 +64,14 @@ export default function duskenApp(state = initialState, action) { case USER_DATA_SUCCESS: return Object.assign({}, state, { isFetchingUserData: false, - user: action.data + user: action.data, }); /* Register user */ case REGISTER_USER_REQUEST: return Object.assign({}, state, { - isRegisteringUser: true + isRegisteringUser: true, + registerError: null, }); case REGISTER_USER_FAILURE: @@ -79,9 +81,15 @@ export default function duskenApp(state = initialState, action) { }); case REGISTER_USER_SUCCESS: + let userData = action.data; + const token = action.data.auth_token; + delete userData['auth_token']; + return Object.assign({}, state, { isRegisteringUser: false, - user: action.data + isAuthenticated: true, + user: userData, + userToken: token, }); default: diff --git a/src/screens/ChargeScreen.js b/src/screens/ChargeScreen.js new file mode 100644 index 0000000..ab9d586 --- /dev/null +++ b/src/screens/ChargeScreen.js @@ -0,0 +1,30 @@ +import React, { Component } from 'react'; +import Charge from "../modules/membership/Charge"; +import {StyleProvider} from "native-base"; +import getTheme from '../../native-base-theme/components'; + +export default class ChargeScreen extends Component { + static navigationOptions = { + title: 'Kjøp medlemskap', + headerStyle: { + backgroundColor: '#f58220', + }, + headerTitleStyle: { + color: 'white', + }, + headerTintColor: 'white', + }; + + onCharged = () => { + // This works since ChargeScreen is allways navigated to from MembershipScreen + this.props.navigation.goBack(); + }; + + render() { + return ( + + + + ) + } +} \ No newline at end of file diff --git a/src/screens/LoginScreen.js b/src/screens/LoginScreen.js index 37fbf56..8bbe737 100644 --- a/src/screens/LoginScreen.js +++ b/src/screens/LoginScreen.js @@ -22,7 +22,8 @@ export default class LoginScreen extends Component { render() { return ( - + + ) } diff --git a/src/screens/MembershipScreen.js b/src/screens/MembershipScreen.js index 6c51d52..e46b6ce 100644 --- a/src/screens/MembershipScreen.js +++ b/src/screens/MembershipScreen.js @@ -3,7 +3,6 @@ import MembershipContainer from "../modules/membership/MembershipContainer"; import Icon from 'react-native-vector-icons/SimpleLineIcons'; import {StyleProvider} from "native-base"; import getTheme from '../../native-base-theme/components'; -import UserRegisterContainer from "../modules/membership/UserRegisterContainer"; export default class MembershipScreen extends Component { static navigationOptions = { @@ -20,7 +19,7 @@ export default class MembershipScreen extends Component { ), }; - onLoginPress = () => { + loginNavigate = () => { this.props.navigation.navigate('Login'); }; @@ -28,11 +27,22 @@ export default class MembershipScreen extends Component { this.props.navigation.navigate('Membership'); }; + registerNavigate = () => { + this.props.navigation.navigate('UserRegister'); + }; + + chargeNavigate = () => { + this.props.navigation.navigate('Charge'); + }; + render() { return ( - - {/**/} + ) } diff --git a/src/screens/UserRegisterScreen.js b/src/screens/UserRegisterScreen.js new file mode 100644 index 0000000..315a57d --- /dev/null +++ b/src/screens/UserRegisterScreen.js @@ -0,0 +1,30 @@ +import React, { Component } from 'react'; +import UserRegisterContainer from "../modules/register/UserRegisterContainer"; +import {StyleProvider} from "native-base"; +import getTheme from '../../native-base-theme/components'; + +export default class UserRegisterScreen extends Component { + static navigationOptions = { + title: 'Registrer', + headerStyle: { + backgroundColor: '#f58220', + }, + headerTitleStyle: { + color: 'white', + }, + headerTintColor: 'white', + }; + + onRegister = () => { + // This works since UserRegisterScreen is allways navigated to from MembershipScreen + this.props.navigation.goBack(); + }; + + render() { + return ( + + + + ) + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 509d8eb..5670795 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3582,15 +3582,15 @@ react-native-htmlview@^0.12.0: prop-types "^15.5.10" react-timer-mixin "^0.13.3" -react-native-sentry@^0.23.2: - version "0.23.2" - resolved "https://registry.yarnpkg.com/react-native-sentry/-/react-native-sentry-0.23.2.tgz#f9859263d5d274faa6d17604deae2adc94568234" +react-native-sentry@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/react-native-sentry/-/react-native-sentry-0.25.0.tgz#f7530aa2fc48d71e0088f808a83d72c356e2abd5" dependencies: chalk "^1.1.1" glob "7.1.1" inquirer "3.0.6" raven-js "^3.17.0" - sentry-cli-binary "^1.19.1" + sentry-cli-binary "^1.20.0" xcode "0.9.3" react-native-tab-view@^0.0.65: @@ -4110,9 +4110,9 @@ send@0.13.2: range-parser "~1.0.3" statuses "~1.2.1" -sentry-cli-binary@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/sentry-cli-binary/-/sentry-cli-binary-1.19.1.tgz#0abc210ed7f35d7ec0680963e612b15bd2bc14c0" +sentry-cli-binary@^1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/sentry-cli-binary/-/sentry-cli-binary-1.20.0.tgz#a620145863fde98c398adcc2166cf17c0738d513" dependencies: progress "2.0.0" From 9ab8061cc3f49544c7b1fdc611d6482327a9938d Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Tue, 3 Oct 2017 02:07:04 +0200 Subject: [PATCH 05/27] First working stripe charge Refactored Proof, ProofContainer and MembershipContainer Minor fixes --- src/Dusken.js | 2 - src/actions.js | 132 ++++------------ src/api.js | 146 ++++++++++++++++++ src/modules/login/LoginContainer.js | 2 +- src/modules/membership/Charge.js | 27 ---- src/modules/membership/MembershipContainer.js | 30 ++-- src/modules/membership/Proof.js | 56 ++----- src/modules/membership/ProofContainer.js | 71 ++++++++- src/modules/register/UserRegister.js | 2 +- src/modules/register/UserRegisterContainer.js | 2 +- src/reducers.js | 24 ++- src/screens/ChargeScreen.js | 30 ---- src/screens/MembershipScreen.js | 7 +- src/screens/UserRegisterScreen.js | 2 +- 14 files changed, 297 insertions(+), 236 deletions(-) create mode 100644 src/api.js delete mode 100644 src/modules/membership/Charge.js delete mode 100644 src/screens/ChargeScreen.js diff --git a/src/Dusken.js b/src/Dusken.js index aa5c26a..df46362 100644 --- a/src/Dusken.js +++ b/src/Dusken.js @@ -9,7 +9,6 @@ import EventListScreen from "./screens/EventListScreen"; import LoginScreen from "./screens/LoginScreen"; import MembershipScreen from "./screens/MembershipScreen"; import UserRegisterScreen from "./screens/UserRegisterScreen"; -import ChargeScreen from "./screens/ChargeScreen"; /* Navigation */ @@ -49,7 +48,6 @@ const DuskenContainer = StackNavigator({ Root: { screen: tabNav }, Login: { screen: LoginScreen }, UserRegister: { screen: UserRegisterScreen }, - Charge: { screen: ChargeScreen }, EventDetail: { screen: EventDetailScreen }, }); diff --git a/src/actions.js b/src/actions.js index b2cf622..55f4c85 100644 --- a/src/actions.js +++ b/src/actions.js @@ -1,5 +1,3 @@ -import Config from 'react-native-config'; - const LOGIN_REQUEST = 'LOGIN_REQUEST'; const LOGIN_SUCCESS = 'LOGIN_SUCCESS'; const LOGIN_FAILURE = 'LOGIN_FAILURE'; @@ -10,6 +8,9 @@ const USER_DATA_FAILURE = 'USER_DATA_FAILURE'; const REGISTER_USER_REQUEST = 'REGISTER_USER_REQUEST'; const REGISTER_USER_SUCCESS = 'REGISTER_USER_SUCCESS'; const REGISTER_USER_FAILURE = 'REGISTER_USER_FAILURE'; +const MEMBERSHIP_CHARGE_REQUEST = 'MEMBERSHIP_CHARGE_REQUEST'; +const MEMBERSHIP_CHARGE_SUCCESS = 'MEMBERSHIP_CHARGE_SUCCESS'; +const MEMBERSHIP_CHARGE_FAILURE = 'MEMBERSHIP_CHARGE_FAILURE'; function loginRequest() { return { @@ -77,6 +78,25 @@ function registerUserFailure(registerError) { registerError } } +function membershipChargeRequest() { + return { + type: MEMBERSHIP_CHARGE_REQUEST + } +} + +function membershipChargeSuccess(data) { + return { + type: MEMBERSHIP_CHARGE_SUCCESS, + data + } +} + +function membershipChargeFailure(chargeError) { + return { + type: MEMBERSHIP_CHARGE_FAILURE, + chargeError + } +} export { LOGIN_REQUEST, loginRequest, @@ -89,107 +109,7 @@ export { REGISTER_USER_REQUEST, registerUserRequest, REGISTER_USER_SUCCESS, registerUserSuccess, REGISTER_USER_FAILURE, registerUserFailure, -}; - -export function requestLogin(username, password) { - return (dispatch) => { - // We are now logging in - dispatch(loginRequest()); - return fetch(`${Config.DUSKEN_API_URL}/auth/obtain-token/`, { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - 'username': username, - 'password': password - }) - }) - .then(response => response.json().then(json => ({ json, response }))) - .then(({json, response}) => { - if (response.ok === false) { - return Promise.reject(json) - } - return json - }) - .then( - data => { - dispatch(loginSuccess(username, data.token)) - }, - data => { - console.log(data); - dispatch(loginFailure(data || {'non_field_errors': ['Kunne ikke logge inn, prøv igjen']})) - } - ) - } -} - -export function requestUserData(token) { - return (dispatch) => { - // We are now fetching user data - dispatch(userDataRequest()); - - const apiURL = Config.DUSKEN_API_URL; - return fetch(`${apiURL}/api/me/`, { - method: 'GET', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - 'Authorization': 'Token ' + token - } - }) - .then(response => response.json().then(json => ({ json, response }))) - .then(({json, response}) => { - if (response.ok === false) { - return Promise.reject(json) - } - return json - }) - .then( - data => { - dispatch(userDataSuccess(data)) - }, - data => { - dispatch(userDataFailure('Det funka ikke :-(')) - } - ) - } -} - -export function requestRegisterUser(firstName, lastName, email, phoneNumber, password) { - return (dispatch) => { - dispatch(registerUserRequest()); - - return fetch(`${Config.DUSKEN_API_URL}/api/user/register/`, { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - 'first_name': firstName, - 'last_name': lastName, - 'email': email, - 'phone_number': phoneNumber, - 'password': password - }) - }) - .then(response => response.json().then(json => ({ json, response }))) - .then(({json, response}) => { - if (response.ok === false) { - return Promise.reject(json) - } - return json - }) - .then( - data => { - dispatch(registerUserSuccess(data)) - }, - data => { - dispatch(registerUserFailure(data || {'non_field_errors': ['Kunne ikke registrere bruker, prøv igjen']})) - } - ) - } -} - + MEMBERSHIP_CHARGE_REQUEST, membershipChargeRequest, + MEMBERSHIP_CHARGE_SUCCESS, membershipChargeSuccess, + MEMBERSHIP_CHARGE_FAILURE, membershipChargeFailure, +}; \ No newline at end of file diff --git a/src/api.js b/src/api.js new file mode 100644 index 0000000..133c5ca --- /dev/null +++ b/src/api.js @@ -0,0 +1,146 @@ +import Config from 'react-native-config'; + +import { + loginFailure, loginRequest, loginSuccess, + registerUserFailure, registerUserRequest, registerUserSuccess, + userDataFailure, userDataRequest, userDataSuccess, + membershipChargeFailure, membershipChargeRequest, membershipChargeSuccess, +} from "./actions"; + +export function requestLogin(username, password) { + return (dispatch) => { + // We are now logging in + dispatch(loginRequest()); + return fetch(`${Config.DUSKEN_API_URL}/auth/obtain-token/`, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + 'username': username, + 'password': password + }) + }) + .then(response => response.json().then(json => ({ json, response }))) + .then(({json, response}) => { + if (response.ok === false) { + return Promise.reject(json) + } + return json + }) + .then( + data => { + dispatch(loginSuccess(username, data.token)) + }, + data => { + console.log(data); + dispatch(loginFailure(data || {'non_field_errors': ['Kunne ikke logge inn, prøv igjen']})) + } + ) + } +} + +export function requestUserData(auth_token) { + return (dispatch) => { + // We are now fetching user data + dispatch(userDataRequest()); + + return fetch(`${Config.DUSKEN_API_URL}/api/me/`, { + method: 'GET', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': `Token ${auth_token}` + } + }) + .then(response => response.json().then(json => ({ json, response }))) + .then(({json, response}) => { + if (response.ok === false) { + return Promise.reject(json) + } + return json + }) + .then( + data => { + dispatch(userDataSuccess(data)) + }, + data => { + dispatch(userDataFailure('Det funka ikke :-(')) + } + ) + } +} + +export function requestRegisterUser(firstName, lastName, email, phoneNumber, password) { + return (dispatch) => { + dispatch(registerUserRequest()); + + return fetch(`${Config.DUSKEN_API_URL}/api/user/register/`, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + 'first_name': firstName, + 'last_name': lastName, + 'email': email, + 'phone_number': phoneNumber, + 'password': password + }) + }) + .then(response => response.json().then(json => ({ json, response }))) + .then(({json, response}) => { + if (response.ok === false) { + return Promise.reject(json) + } + return json + }) + .then( + data => { + dispatch(registerUserSuccess(data)) + }, + data => { + dispatch(registerUserFailure(data || {'non_field_errors': ['Kunne ikke registrere bruker, prøv igjen']})) + } + ) + } +} + +export function requestMembershipCharge(auth_token, stripe_token, membership_type) { + return (dispatch) => { + dispatch(membershipChargeRequest()); + + return fetch(`${Config.DUSKEN_API_URL}/api/membership/charge/`, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': `Token ${auth_token}` + }, + body: JSON.stringify({ + 'stripe_token': stripe_token, + 'membership_type': membership_type, + 'payment_method': 'app', + }) + }) + .then(response => response.json().then(json => ({ json, response }))) + .then(({json, response}) => { + if (response.ok === false) { + return Promise.reject(json) + } + return json + }) + .then( + data => { + dispatch(membershipChargeSuccess(data)) + }, + data => { + dispatch(membershipChargeFailure(data || {'non_field_errors': ['Kunne ikke belaste kort, prøv igjen']})) + } + ) + } +} + + diff --git a/src/modules/login/LoginContainer.js b/src/modules/login/LoginContainer.js index 55f61cb..0eb40fc 100644 --- a/src/modules/login/LoginContainer.js +++ b/src/modules/login/LoginContainer.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import {connect} from "react-redux"; import Login from "./Login"; -import {requestLogin} from "../../actions"; +import {requestLogin} from "../../api"; class LoginContainer extends Component { constructor(state) { diff --git a/src/modules/membership/Charge.js b/src/modules/membership/Charge.js deleted file mode 100644 index eda16e2..0000000 --- a/src/modules/membership/Charge.js +++ /dev/null @@ -1,27 +0,0 @@ -import stripe from 'tipsi-stripe' -import React, {Component} from 'react'; -import Config from 'react-native-config'; -import {ActivityIndicator, Text, View} from "react-native"; -// import {ScrollView, Text, View, Linking, StyleSheet, Platform} from "react-native"; -// import {Button, Text as NBText} from "native-base"; - -stripe.init({ - publishableKey: Config.STRIPE_PUBLISHABLE_KEY, -}); - -export default class Charge extends Component { - // TODO: You are here - render() { - return - In charge view - - - } - - openStripe() { - stripe.createTokenWithCard().then((data) => { - // returns a token.tokenId which should be saved - - }) - } -} diff --git a/src/modules/membership/MembershipContainer.js b/src/modules/membership/MembershipContainer.js index 729d403..9017461 100644 --- a/src/modules/membership/MembershipContainer.js +++ b/src/modules/membership/MembershipContainer.js @@ -2,8 +2,9 @@ import React, {Component} from 'react'; import {connect} from "react-redux"; import Membership from "./Membership"; -import Proof from "./Proof"; -import { requestUserData, logout } from "../../actions"; +import { logout } from "../../actions"; +import {requestUserData} from "../../api"; +import ProofContainer from "./ProofContainer"; class MembershipContainer extends Component { constructor(props) { @@ -11,9 +12,9 @@ class MembershipContainer extends Component { this.state = { isAuthenticated: props.isAuthenticated, - userToken: props.userToken, isFetchingUserData: props.isFetchingUserData, - user: props.user, + userToken: props.userToken, + lastOrder: props.lastOrder, } } @@ -29,8 +30,12 @@ class MembershipContainer extends Component { }); } - if(this.state.user !== nextProps.user) { - this.setState({user: nextProps.user}) + if(this.state.lastOrder !== nextProps.lastOrder) { + this.setState({lastOrder: nextProps.lastOrder}, () => { + if(nextProps.userToken) { + this.fetchUser(); + } + }); } } @@ -46,22 +51,18 @@ class MembershipContainer extends Component { this.props.onRegisterPress(); }; - onChargePress = () => { - this.props.onChargePress(); - }; - onLogoutPress = () => { this.props.logout(); this.props.onLogoutPress(); }; render() { - if (this.state.user) { - return ; } return ; @@ -74,6 +75,7 @@ function stateToProps(state) { isFetchingUserData: state.isFetchingUserData, userToken: state.userToken, user: state.user, + lastOrder: state.lastOrder }; } diff --git a/src/modules/membership/Proof.js b/src/modules/membership/Proof.js index 3894c66..f536e55 100644 --- a/src/modules/membership/Proof.js +++ b/src/modules/membership/Proof.js @@ -1,27 +1,18 @@ import React, {Component} from 'react'; -import {Image, Linking, StyleSheet, Platform, RefreshControl, TouchableOpacity, View} from "react-native"; +import {Image, StyleSheet, TouchableOpacity, View} from "react-native"; import {Button, Body, Card, CardItem, Text, Content} from 'native-base'; import Confetti from 'react-native-confetti'; export default class Proof extends Component { - // FIXME: Move logic to container CONFETTI_TIMEOUT = 15000; constructor(props) { super(props); this.state = { - user: props.user, - refreshing: false, stopConfetti: false, } }; - componentWillReceiveProps(nextProps) { - if(this.state.user !== nextProps.user) { - this.setState({user: nextProps.user}) - } - } - componentDidUpdate () { if (this._confettiView && this.state.stopConfetti) { this._confettiView.stopConfetti(); @@ -35,26 +26,6 @@ export default class Proof extends Component { } } - // fetchUser = () => { - // this.props.fetchUser().then(() => { - // this.setState({refreshing: false}); - // }); - // }; - - // _onRefresh() { - // console.log('onRefresh') - // this.setState({refreshing: true}); - // this.fetchUser() - // } - - // refreshControl() { - // return ( - // ) - // } - onMembershipPress = () => { this.setState({showConfetti: true}, () => { if(this._confettiView) { @@ -67,12 +38,12 @@ export default class Proof extends Component { }; membershipValidTo() { - if( !this.state.user.last_membership) { + if( !this.props.user.last_membership) { return; } - let validTo = this.state.user.last_membership.end_date; - if (this.state.user.last_membership.membership_type === 'lifelong') { + let validTo = this.props.user.last_membership.end_date; + if (this.props.user.last_membership.membership_type === 'lifelong') { validTo = 'Livsvarig' } @@ -87,8 +58,8 @@ export default class Proof extends Component { } membershipStatus() { - if (!this.state.user.is_member) { - if ( !this.state.user.last_membership ) { + if (!this.props.user.is_member) { + if ( !this.props.user.last_membership ) { return ( @@ -101,7 +72,7 @@ export default class Proof extends Component { } let statusText = 'Medlem'; - if (this.state.user.is_volunteer) { + if (this.props.user.is_volunteer) { statusText = 'Aktiv'; } @@ -114,7 +85,7 @@ export default class Proof extends Component { } purchaseButton() { - if (this.state.user.is_member) { + if (this.props.user.is_member) { return; } return @@ -131,14 +102,14 @@ export default class Proof extends Component { } confetti() { - if (this.state.user.is_member) { + if (this.props.user.is_member) { // FIXME: allmost infinite confetti. Are the animations paused when not visible, if not power hog? return this._confettiView = node} confettiCount={Number.MAX_SAFE_INTEGER} /> } } logo() { - if (!this.state.user.is_member) { + if (!this.props.user.is_member) { return; } // FIXME: URL to config @@ -149,9 +120,6 @@ export default class Proof extends Component { /> } - fetchUser = () => { - this.props.fetchUser() - }; render() { return ( @@ -174,9 +142,9 @@ export default class Proof extends Component { }; membershipName() { - let name = `${this.state.user.first_name} ${this.state.user.last_name}`; + let name = `${this.props.user.first_name} ${this.props.user.last_name}`; if(name === ' ') { - name = this.state.user.email; + name = this.props.user.email; } return {name} diff --git a/src/modules/membership/ProofContainer.js b/src/modules/membership/ProofContainer.js index 7ca641d..53afa9d 100644 --- a/src/modules/membership/ProofContainer.js +++ b/src/modules/membership/ProofContainer.js @@ -1,15 +1,82 @@ import React, {Component} from 'react'; import {connect} from "react-redux"; +import stripe from 'tipsi-stripe' +import Config from 'react-native-config'; import Proof from "./Proof"; +import {requestMembershipCharge} from "../../api"; + + +stripe.init({ + publishableKey: Config.STRIPE_PUBLISHABLE_KEY, +}); class ProofContainer extends Component { constructor(props) { super(props); + + this.state = { + refreshing: false, + } } + + componentWillReceiveProps(nextProps) { + if(this.state.user !== nextProps.user) { + this.setState({user: nextProps.user}) + } + } + render() { - return + return } + + openStripe = () => { + const options = { + prefilledInformation: { + email: this.props.user.email, + }, + smsAutofillDisabled: true, + }; + + stripe.paymentRequestWithCardForm(options).then( + (token) => { + // returns a token.tokenId which should be saved + this.props.requestMembershipCharge( + this.props.userToken, + {id: token.tokenId, email: this.props.user.email}, + 'standard'); + }, + (error) => { + // TODO: display error + console.log(error); + } + ); + }; + + // fetchUser = () => { + // this.props.fetchUser().then(() => { + // this.setState({refreshing: false}); + // }); + // }; + + // _onRefresh() { + // console.log('onRefresh') + // this.setState({refreshing: true}); + // this.fetchUser() + // } + + // refreshControl() { + // return ( + // ) + // } } -export default connect()(ProofContainer); +export default connect( + (state) => ({ + userToken: state.userToken + }), + {requestMembershipCharge} +)(ProofContainer); diff --git a/src/modules/register/UserRegister.js b/src/modules/register/UserRegister.js index e018f5f..0d89db8 100644 --- a/src/modules/register/UserRegister.js +++ b/src/modules/register/UserRegister.js @@ -163,7 +163,7 @@ export default class UserRegister extends Component { onPress={this.onRegisterPress} style={styles.registerButton} > - Registrer + Registrer meg ); } } diff --git a/src/modules/register/UserRegisterContainer.js b/src/modules/register/UserRegisterContainer.js index ff85fcf..aa6c47a 100644 --- a/src/modules/register/UserRegisterContainer.js +++ b/src/modules/register/UserRegisterContainer.js @@ -1,7 +1,7 @@ import React, {Component} from 'react'; import {connect} from "react-redux"; import UserRegister from "./UserRegister"; -import {requestRegisterUser} from "../../actions"; +import {requestRegisterUser} from "../../api"; class UserRegisterContainer extends Component { diff --git a/src/reducers.js b/src/reducers.js index 943d4bc..abf1dac 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -8,7 +8,7 @@ import { USER_DATA_FAILURE, REGISTER_USER_REQUEST, REGISTER_USER_FAILURE, - REGISTER_USER_SUCCESS, + REGISTER_USER_SUCCESS, MEMBERSHIP_CHARGE_REQUEST, MEMBERSHIP_CHARGE_FAILURE, MEMBERSHIP_CHARGE_SUCCESS, } from './actions'; const initialState = { @@ -16,11 +16,14 @@ const initialState = { isLoggingIn: false, isFetchingUserData: false, isRegisteringUser: false, + isChargingMembership: false, userToken: null, user: null, loginError: null, userError: null, registerError: null, + chargeError: null, + lastOrder: null, }; export default function duskenApp(state = initialState, action) { @@ -92,6 +95,25 @@ export default function duskenApp(state = initialState, action) { userToken: token, }); + /* User data */ + case MEMBERSHIP_CHARGE_REQUEST: + return Object.assign({}, state, { + isChargingMembership: true, + chargeError: null + }); + + case MEMBERSHIP_CHARGE_FAILURE: + return Object.assign({}, state, { + isChargingMembership: false, + chargeError: action.chargeError + }); + + case MEMBERSHIP_CHARGE_SUCCESS: + return Object.assign({}, state, { + isChargingMembership: false, + lastOrder: action.data, + }); + default: return state } diff --git a/src/screens/ChargeScreen.js b/src/screens/ChargeScreen.js deleted file mode 100644 index ab9d586..0000000 --- a/src/screens/ChargeScreen.js +++ /dev/null @@ -1,30 +0,0 @@ -import React, { Component } from 'react'; -import Charge from "../modules/membership/Charge"; -import {StyleProvider} from "native-base"; -import getTheme from '../../native-base-theme/components'; - -export default class ChargeScreen extends Component { - static navigationOptions = { - title: 'Kjøp medlemskap', - headerStyle: { - backgroundColor: '#f58220', - }, - headerTitleStyle: { - color: 'white', - }, - headerTintColor: 'white', - }; - - onCharged = () => { - // This works since ChargeScreen is allways navigated to from MembershipScreen - this.props.navigation.goBack(); - }; - - render() { - return ( - - - - ) - } -} \ No newline at end of file diff --git a/src/screens/MembershipScreen.js b/src/screens/MembershipScreen.js index e46b6ce..2de3deb 100644 --- a/src/screens/MembershipScreen.js +++ b/src/screens/MembershipScreen.js @@ -31,18 +31,13 @@ export default class MembershipScreen extends Component { this.props.navigation.navigate('UserRegister'); }; - chargeNavigate = () => { - this.props.navigation.navigate('Charge'); - }; - render() { return ( + onRegisterPress={this.registerNavigate} /> ) } diff --git a/src/screens/UserRegisterScreen.js b/src/screens/UserRegisterScreen.js index 315a57d..0b16965 100644 --- a/src/screens/UserRegisterScreen.js +++ b/src/screens/UserRegisterScreen.js @@ -5,7 +5,7 @@ import getTheme from '../../native-base-theme/components'; export default class UserRegisterScreen extends Component { static navigationOptions = { - title: 'Registrer', + title: 'Bli medlem', headerStyle: { backgroundColor: '#f58220', }, From c0d677bab06426a05525e3f8fa6e410a46f0f8ae Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Wed, 4 Oct 2017 23:18:13 +0200 Subject: [PATCH 06/27] Don't crash on empty sentry DSN --- index.android.js | 4 +++- index.ios.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/index.android.js b/index.android.js index 31a205d..0ea5d65 100644 --- a/index.android.js +++ b/index.android.js @@ -3,6 +3,8 @@ import { AppRegistry } from "react-native"; import { Sentry } from 'react-native-sentry'; import Config from 'react-native-config'; -Sentry.config(Config.SENTRY_DSN).install(); +if(Config.SENTRY_DSN) { + Sentry.config(Config.SENTRY_DSN).install(); +} AppRegistry.registerComponent('Dusken', () => App); \ No newline at end of file diff --git a/index.ios.js b/index.ios.js index 31a205d..0ea5d65 100644 --- a/index.ios.js +++ b/index.ios.js @@ -3,6 +3,8 @@ import { AppRegistry } from "react-native"; import { Sentry } from 'react-native-sentry'; import Config from 'react-native-config'; -Sentry.config(Config.SENTRY_DSN).install(); +if(Config.SENTRY_DSN) { + Sentry.config(Config.SENTRY_DSN).install(); +} AppRegistry.registerComponent('Dusken', () => App); \ No newline at end of file From be18b022e4a1f74d938139178a0dff42863ccf95 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Mon, 9 Oct 2017 00:15:58 +0200 Subject: [PATCH 07/27] Minor improvements - Android: Add bottom navigation border - chore: fix yarn run warning - Fix logout button regression --- package.json | 1 + src/Dusken.js | 10 +- src/modules/membership/ProofContainer.js | 7 +- yarn.lock | 142 ++++++++++++++++++++++- 4 files changed, 154 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index d68841d..5fdfa4c 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "react-native-config": "^0.6.1", "react-native-htmlview": "^0.12.0", "react-native-sentry": "^0.25.0", + "react-native-vector-icons": "~4.3.0", "react-navigation": "^1.0.0-beta.11", "react-redux": "^5.0.6", "redux": "^3.7.2", diff --git a/src/Dusken.js b/src/Dusken.js index df46362..2109436 100644 --- a/src/Dusken.js +++ b/src/Dusken.js @@ -1,6 +1,6 @@ import React from 'react'; import {connect} from "react-redux"; -import {Platform} from 'react-native'; +import {Platform, StyleSheet} from 'react-native'; import {TabNavigator, StackNavigator} from "react-navigation"; import AboutScreen from "./screens/AboutScreen"; @@ -22,7 +22,13 @@ const tabBarOptions = { tabBarPosition: 'bottom', tabBarOptions: { style: { - backgroundColor: "#fff" + ...Platform.select({ + android: { + backgroundColor: "#fff", + borderTopWidth: StyleSheet.hairlineWidth, + borderTopColor: 'rgba(0, 0, 0, 0.1)' + } + }) }, indicatorStyle: { backgroundColor: "#f58220" diff --git a/src/modules/membership/ProofContainer.js b/src/modules/membership/ProofContainer.js index 53afa9d..257271a 100644 --- a/src/modules/membership/ProofContainer.js +++ b/src/modules/membership/ProofContainer.js @@ -27,7 +27,12 @@ class ProofContainer extends Component { } render() { - return + return } openStripe = () => { diff --git a/yarn.lock b/yarn.lock index 5670795..825d153 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1036,6 +1036,10 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + caseless@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" @@ -1305,6 +1309,14 @@ cross-spawn@^3.0.1: lru-cache "^4.0.1" which "^1.2.9" +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" @@ -1567,6 +1579,18 @@ exec-sh@^0.2.0: dependencies: merge "^1.1.3" +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + 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" + expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -1714,7 +1738,7 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.1.0: +find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" dependencies: @@ -1826,6 +1850,10 @@ get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + getpass@^0.1.1: version "0.1.6" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" @@ -2221,7 +2249,7 @@ is-property@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" -is-stream@^1.0.1: +is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -2727,6 +2755,15 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -2876,6 +2913,12 @@ media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + merge-stream@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" @@ -3157,6 +3200,12 @@ normalize-path@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + npmlog@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692" @@ -3261,6 +3310,14 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + os-name@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/os-name/-/os-name-2.0.1.tgz#b9a386361c17ae3a21736ef0599405c9a8c5dc5e" @@ -3279,6 +3336,10 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + p-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" @@ -3330,6 +3391,10 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" @@ -3348,6 +3413,12 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + pause@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/pause/-/pause-0.1.0.tgz#ebc8a4a8619ff0b8a81ac1513c3434ff469fdb74" @@ -3607,6 +3678,14 @@ react-native-vector-icons@~4.1.1: prop-types "^15.5.8" yargs "^6.3.0" +react-native-vector-icons@~4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-4.3.0.tgz#49eab845fbcde6354cb3dbcb62c1abd1f6abc866" + dependencies: + lodash "^4.0.0" + prop-types "^15.5.10" + yargs "^8.0.2" + react-native@0.48.3: version "0.48.3" resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.48.3.tgz#ec17a66929eb292512b14c091cf260b25e2fba18" @@ -3767,6 +3846,13 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -3775,6 +3861,14 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.1.5, readable-stream@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" @@ -4153,6 +4247,16 @@ setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + shell-quote@1.6.1, shell-quote@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" @@ -4333,7 +4437,7 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-bom@3.0.0: +strip-bom@3.0.0, strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -4343,6 +4447,10 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + 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" @@ -4641,6 +4749,10 @@ which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + which@^1.2.12, which@^1.2.9: version "1.2.14" resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" @@ -4781,6 +4893,12 @@ yargs-parser@^5.0.0: dependencies: camelcase "^3.0.0" +yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + dependencies: + camelcase "^4.1.0" + yargs@^6.3.0, yargs@^6.4.0: version "6.6.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" @@ -4817,6 +4935,24 @@ yargs@^7.0.2: y18n "^3.2.1" yargs-parser "^5.0.0" +yargs@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + dependencies: + 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@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" From 6ff10ae06b86c88877bc6a73fa6bcd6f628e94cc Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Mon, 9 Oct 2017 01:35:28 +0200 Subject: [PATCH 08/27] Start improving error handling in register form Also move navigation code to own file --- src/Dusken.js | 63 ++--------- src/modules/register/UserRegister.js | 161 ++++++++++++++++----------- src/navigation.js | 56 ++++++++++ 3 files changed, 164 insertions(+), 116 deletions(-) create mode 100644 src/navigation.js diff --git a/src/Dusken.js b/src/Dusken.js index 2109436..c88f052 100644 --- a/src/Dusken.js +++ b/src/Dusken.js @@ -1,60 +1,15 @@ -import React from 'react'; +import React, {Component} from 'react'; import {connect} from "react-redux"; -import {Platform, StyleSheet} from 'react-native'; -import {TabNavigator, StackNavigator} from "react-navigation"; - -import AboutScreen from "./screens/AboutScreen"; -import EventDetailScreen from "./screens/EventDetailScreen"; -import EventListScreen from "./screens/EventListScreen"; -import LoginScreen from "./screens/LoginScreen"; -import MembershipScreen from "./screens/MembershipScreen"; -import UserRegisterScreen from "./screens/UserRegisterScreen"; +import {Root} from 'native-base'; +import DuskenNavigation from "./navigation"; -/* Navigation */ -const tabBarRoutes = { - Membership: { screen: MembershipScreen }, - EventList: { screen: EventListScreen }, - About: { screen: AboutScreen }, -}; - -const tabBarOptions = { - tabBarPosition: 'bottom', - tabBarOptions: { - style: { - ...Platform.select({ - android: { - backgroundColor: "#fff", - borderTopWidth: StyleSheet.hairlineWidth, - borderTopColor: 'rgba(0, 0, 0, 0.1)' - } - }) - }, - indicatorStyle: { - backgroundColor: "#f58220" - }, - activeTintColor: '#f58220', - inactiveTintColor: '#333333', - showIcon: true, - labelStyle: { - fontSize: 10, - marginBottom: 0, - ...Platform.select({ - android: { - fontWeight: 'bold', - } - }), - }, +class DuskenContainer extends Component { + render() { + return ( + + ) } -}; - -const tabNav = TabNavigator(tabBarRoutes, tabBarOptions); - -const DuskenContainer = StackNavigator({ - Root: { screen: tabNav }, - Login: { screen: LoginScreen }, - UserRegister: { screen: UserRegisterScreen }, - EventDetail: { screen: EventDetailScreen }, -}); +} export default connect()(DuskenContainer); \ No newline at end of file diff --git a/src/modules/register/UserRegister.js b/src/modules/register/UserRegister.js index 0d89db8..f73c8a9 100644 --- a/src/modules/register/UserRegister.js +++ b/src/modules/register/UserRegister.js @@ -1,5 +1,5 @@ import React, {Component} from 'react'; -import {Container, Header, Content, Form, Item, Input, Label, Spinner, Button, Text, Icon} from 'native-base'; +import {Container, Header, Content, Form, Item, Input, Label, Spinner, Button, Text, Icon, Toast} from 'native-base'; import {Platform, StyleSheet, View} from "react-native"; export default class UserRegister extends Component { @@ -11,23 +11,75 @@ export default class UserRegister extends Component { lastName: '', email: '', phoneNumber: '', - password: '' + password: '', + errors: {}, + touched: new Set() } - } + }; + + validateForm(triggeredBy) { + const fieldNames = ['firstName', 'lastName', 'email', 'phoneNumber', 'password']; + + let errors = Object.assign({}, this.state.errors); + let touched = new Set(this.state.touched).add(triggeredBy); - canSubmitForm() { /* No empty fields */ - for([key, value] of Object.entries(this.state)) { + for(let key of fieldNames) { + const value = this.state[key]; if(value === '') { - return false; + errors[key] = 'Feltet kan ikke være tomt'; + } else { + delete errors[key]; } } - return true; + this.setState({errors: errors, touched}); }; + fieldHasError(field) { + return this.state.touched.has(field) && field in this.state.errors; + } + + canSubmitForm() { + return Object.keys(this.state.errors).length === 0; + } + + firstNameInput() { + return + + { + this.setState({firstName: text}, () => { this.validateForm('firstName'); }); + }} + onSubmitEditing={() => { + this.refs.lastNameInput._root.focus() + }} + /> + {this.fieldHasError('firstName') && } + ; + } + + lastNameInput() { + return + + { + this.setState({lastName: text}, () => { this.validateForm('lastName'); }); + }} + onSubmitEditing={() => { + this.refs.emailInput._root.focus() + }} + /> + {this.fieldHasError('lastName') && } + ; + } + emailInput() { - return + return { - this.setState({email: text}); + this.setState({email: text}, () => { this.validateForm('email'); }); }} onSubmitEditing={() => { this.refs.phoneInput._root.focus() }} /> + {this.fieldHasError('email') && } + ; + } + + phoneNumberInput() { + return + + { + this.setState({phoneNumber: text}, () => { this.validateForm('phoneNumber'); }); + }} + onSubmitEditing={() => { + this.refs.passwordInput._root.focus() + }} + /> + {this.fieldHasError('phoneNumber') && } ; } passwordInput() { - // FIXME: How to dynamicly set error attribute? replace component, what? - return + return { - this.setState({password: text}); + this.setState({password: text}, () => { this.validateForm('password'); }); }} onSubmitEditing={this.onRegisterPress} /> + {this.fieldHasError('password') && } } showError = () => { + // TODO: Move these from prop to state in componentWillRecieveProps // TODO: Format these and highlight error fields if (this.props.registerError && Object.keys(this.props.registerError).length !== 0) { const err = this.props.registerError.non_field_errors; @@ -85,47 +157,10 @@ export default class UserRegister extends Component {
- - - { - this.setState({firstName: text}); - }} - onSubmitEditing={() => { - this.refs.lastNameInput._root.focus() - }} - /> - - - - { - this.setState({lastName: text}); - }} - onSubmitEditing={() => { - this.refs.emailInput._root.focus() - }} - /> - + {this.firstNameInput()} + {this.lastNameInput()} {this.emailInput()} - - - { - this.setState({phoneNumber: text}); - }} - onSubmitEditing={() => { - this.refs.passwordInput._root.focus() - }} - /> - + {this.phoneNumberInput()} {this.passwordInput()} {this.showError()} {this.registerbutton()} @@ -137,6 +172,16 @@ export default class UserRegister extends Component { } onRegisterPress = () => { + if( !this.validateForm() ) { + Toast.show({ + text: 'Noen av feltene er ikke fylt ut riktig', + position: 'bottom', + buttonText: 'OK', + duration: 1500, + }); + return; + } + this.props.onRegisterPress( this.state.firstName, this.state.lastName, @@ -147,19 +192,11 @@ export default class UserRegister extends Component { }; registerbutton() { - if( this.props.isRegisteringUser || !this.canSubmitForm() ) { - return ( - ); - } + const isDisabled = this.props.isRegisteringUser || !this.canSubmitForm(); return (
-
+ ) }; diff --git a/src/modules/membership/ProofContainer.js b/src/modules/membership/ProofContainer.js index 257271a..f174c6c 100644 --- a/src/modules/membership/ProofContainer.js +++ b/src/modules/membership/ProofContainer.js @@ -8,7 +8,7 @@ import {requestMembershipCharge} from "../../api"; stripe.init({ - publishableKey: Config.STRIPE_PUBLISHABLE_KEY, + publishableKey: Config.STRIPE_PUBLISHABLE_KEY || '', }); class ProofContainer extends Component { diff --git a/yarn.lock b/yarn.lock index e28eb67..a884b68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -66,15 +66,11 @@ amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" -ansi-escapes@^1.1.0, ansi-escapes@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - ansi-escapes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" -ansi-regex@^2.0.0, ansi-regex@^2.1.1: +ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -86,7 +82,7 @@ ansi-styles@^2.1.0, ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.0.0, ansi-styles@^3.1.0: +ansi-styles@^3.1.0, ansi-styles@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" dependencies: @@ -188,6 +184,10 @@ assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + async@^1.4.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -198,10 +198,6 @@ async@^2.1.4, async@^2.4.0: dependencies: lodash "^4.14.0" -async@~0.2.6: - version "0.2.10" - resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -356,13 +352,12 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-jest@20.0.3, babel-jest@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-20.0.3.tgz#e4a03b13dc10389e140fc645d09ffc4ced301671" +babel-jest@21.2.0, babel-jest@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-21.2.0.tgz#2ce059519a9374a2c46f2455b6fbef5ad75d863e" dependencies: - babel-core "^6.0.0" babel-plugin-istanbul "^4.0.0" - babel-preset-jest "^20.0.3" + babel-preset-jest "^21.2.0" babel-messages@^6.23.0: version "6.23.0" @@ -390,13 +385,13 @@ babel-plugin-istanbul@^4.0.0: istanbul-lib-instrument "^1.7.5" test-exclude "^4.1.1" -babel-plugin-jest-hoist@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-20.0.3.tgz#afedc853bd3f8dc3548ea671fbe69d03cc2c1767" +babel-plugin-jest-hoist@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.2.0.tgz#2cef637259bd4b628a6cace039de5fcd14dbb006" -babel-plugin-react-transform@2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-react-transform/-/babel-plugin-react-transform-2.0.2.tgz#515bbfa996893981142d90b1f9b1635de2995109" +babel-plugin-react-transform@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-react-transform/-/babel-plugin-react-transform-3.0.0.tgz#402f25137b7bb66e9b54ead75557dfbc7ecaaa74" dependencies: lodash "^4.6.1" @@ -408,6 +403,10 @@ babel-plugin-syntax-class-properties@^6.5.0, babel-plugin-syntax-class-propertie version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + babel-plugin-syntax-flow@^6.18.0, babel-plugin-syntax-flow@^6.5.0, babel-plugin-syntax-flow@^6.8.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" @@ -416,7 +415,7 @@ babel-plugin-syntax-jsx@^6.5.0, babel-plugin-syntax-jsx@^6.8.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" -babel-plugin-syntax-object-rest-spread@^6.8.0: +babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest-spread@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" @@ -692,54 +691,22 @@ babel-preset-fbjs@^2.1.2, babel-preset-fbjs@^2.1.4: babel-plugin-transform-react-display-name "^6.8.0" babel-plugin-transform-react-jsx "^6.8.0" -babel-preset-jest@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-20.0.3.tgz#cbacaadecb5d689ca1e1de1360ebfc66862c178a" +babel-preset-jest@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-21.2.0.tgz#ff9d2bce08abd98e8a36d9a8a5189b9173b85638" dependencies: - babel-plugin-jest-hoist "^20.0.3" + babel-plugin-jest-hoist "^21.2.0" + babel-plugin-syntax-object-rest-spread "^6.13.0" -babel-preset-react-native@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/babel-preset-react-native/-/babel-preset-react-native-1.9.2.tgz#b22addd2e355ff3b39671b79be807e52dfa145f2" +babel-preset-react-native@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/babel-preset-react-native/-/babel-preset-react-native-4.0.0.tgz#3df80dd33a453888cdd33bdb87224d17a5d73959" dependencies: 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" - -babel-preset-react-native@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-react-native/-/babel-preset-react-native-2.1.0.tgz#9013ebd82da1c88102bf588810ff59e209ca2b8a" - dependencies: - babel-plugin-check-es2015-constants "^6.5.0" - babel-plugin-react-transform "2.0.2" + babel-plugin-react-transform "^3.0.0" babel-plugin-syntax-async-functions "^6.5.0" babel-plugin-syntax-class-properties "^6.5.0" + babel-plugin-syntax-dynamic-import "^6.18.0" babel-plugin-syntax-flow "^6.5.0" babel-plugin-syntax-jsx "^6.5.0" babel-plugin-syntax-trailing-function-commas "^6.5.0" @@ -764,6 +731,7 @@ babel-preset-react-native@^2.0.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" + babel-template "^6.24.1" react-transform-hmr "^1.0.4" babel-register@^6.24.1, babel-register@^6.26.0: @@ -944,12 +912,6 @@ browser-resolve@^1.11.2: dependencies: resolve "1.1.7" -bser@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169" - dependencies: - node-int64 "^0.4.0" - bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" @@ -976,10 +938,6 @@ camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -1023,6 +981,14 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^2.0.1, chalk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + ci-info@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.1.tgz#47b44df118c48d2597b56d342e7e25791060171a" @@ -1103,7 +1069,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@^2.9.0: +commander@^2.9.0, commander@~2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" @@ -1531,6 +1497,17 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" +expect@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-21.2.1.tgz#003ac2ac7005c3c29e73b38a272d4afadd6d1d7b" + dependencies: + ansi-styles "^3.2.0" + jest-diff "^21.2.1" + jest-get-type "^21.2.0" + jest-matcher-utils "^21.2.1" + jest-message-util "^21.2.1" + jest-regex-util "^21.2.0" + express-session@~1.11.3: version "1.11.3" resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.11.3.tgz#5cc98f3f5ff84ed835f91cbf0aabd0c7107400af" @@ -1549,7 +1526,7 @@ extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" -external-editor@^2.0.1, external-editor@^2.0.4: +external-editor@^2.0.4: version "2.0.5" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.5.tgz#52c249a3981b9ba187c7cacf5beb50bf1d91a6bc" dependencies: @@ -1582,12 +1559,6 @@ fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" -fb-watchman@^1.8.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-1.9.2.tgz#a24cf47827f82d38fb59a69ad70b76e3b6ae7383" - dependencies: - bser "1.0.2" - fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" @@ -1607,19 +1578,7 @@ fbjs-scripts@^0.8.1: semver "^5.1.0" through2 "^2.0.0" -fbjs@0.8.14: - version "0.8.14" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.14.tgz#d1dbe2be254c35a91e09f31f9cd50a40b2a0ed1c" - dependencies: - 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.9" - -fbjs@^0.8.16, fbjs@^0.8.9: +fbjs@^0.8.14, fbjs@^0.8.16, fbjs@^0.8.9: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" dependencies: @@ -1807,18 +1766,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: +glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -1990,7 +1938,7 @@ html-encoding-sniffer@^1.0.1: dependencies: whatwg-encoding "^1.0.1" -htmlparser2-without-node-native@^3.9.0: +htmlparser2-without-node-native@^3.9.2: version "3.9.2" resolved "https://registry.yarnpkg.com/htmlparser2-without-node-native/-/htmlparser2-without-node-native-3.9.2.tgz#b3ed050d877d0ff3465969e339877b7f9f6631f6" dependencies: @@ -2060,25 +2008,7 @@ ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" -inquirer@3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" - dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.1" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - -inquirer@^3.0.6: +inquirer@^3.0.6, inquirer@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" dependencies: @@ -2299,231 +2229,230 @@ istanbul-reports@^1.1.2: dependencies: handlebars "^4.0.3" -jest-changed-files@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-20.0.3.tgz#9394d5cc65c438406149bef1bf4d52b68e03e3f8" - -jest-cli@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-20.0.4.tgz#e532b19d88ae5bc6c417e8b0593a6fe954b1dc93" +jest-changed-files@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-21.2.0.tgz#5dbeecad42f5d88b482334902ce1cba6d9798d29" dependencies: - ansi-escapes "^1.4.0" - callsites "^2.0.0" - chalk "^1.1.3" + throat "^4.0.0" + +jest-cli@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-21.2.1.tgz#9c528b6629d651911138d228bdb033c157ec8c00" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.1" + glob "^7.1.2" graceful-fs "^4.1.11" is-ci "^1.0.10" istanbul-api "^1.1.1" istanbul-lib-coverage "^1.0.1" istanbul-lib-instrument "^1.4.2" istanbul-lib-source-maps "^1.1.0" - jest-changed-files "^20.0.3" - jest-config "^20.0.4" - jest-docblock "^20.0.3" - jest-environment-jsdom "^20.0.3" - jest-haste-map "^20.0.4" - jest-jasmine2 "^20.0.4" - jest-message-util "^20.0.3" - jest-regex-util "^20.0.3" - jest-resolve-dependencies "^20.0.3" - jest-runtime "^20.0.4" - jest-snapshot "^20.0.3" - jest-util "^20.0.3" + jest-changed-files "^21.2.0" + jest-config "^21.2.1" + jest-environment-jsdom "^21.2.1" + jest-haste-map "^21.2.0" + jest-message-util "^21.2.1" + jest-regex-util "^21.2.0" + jest-resolve-dependencies "^21.2.0" + jest-runner "^21.2.1" + jest-runtime "^21.2.1" + jest-snapshot "^21.2.1" + jest-util "^21.2.1" micromatch "^2.3.11" node-notifier "^5.0.2" - pify "^2.3.0" + pify "^3.0.0" slash "^1.0.0" - string-length "^1.0.1" - throat "^3.0.0" + string-length "^2.0.0" + strip-ansi "^4.0.0" which "^1.2.12" worker-farm "^1.3.1" - yargs "^7.0.2" + yargs "^9.0.0" -jest-config@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-20.0.4.tgz#e37930ab2217c913605eff13e7bd763ec48faeea" +jest-config@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-21.2.1.tgz#c7586c79ead0bcc1f38c401e55f964f13bf2a480" dependencies: - chalk "^1.1.3" + chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^20.0.3" - jest-environment-node "^20.0.3" - jest-jasmine2 "^20.0.4" - jest-matcher-utils "^20.0.3" - jest-regex-util "^20.0.3" - jest-resolve "^20.0.4" - jest-validate "^20.0.3" - pretty-format "^20.0.3" + jest-environment-jsdom "^21.2.1" + jest-environment-node "^21.2.1" + jest-get-type "^21.2.0" + jest-jasmine2 "^21.2.1" + jest-regex-util "^21.2.0" + jest-resolve "^21.2.0" + jest-util "^21.2.1" + jest-validate "^21.2.1" + pretty-format "^21.2.1" -jest-diff@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-20.0.3.tgz#81f288fd9e675f0fb23c75f1c2b19445fe586617" +jest-diff@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-21.2.1.tgz#46cccb6cab2d02ce98bc314011764bb95b065b4f" dependencies: - chalk "^1.1.3" + chalk "^2.0.1" diff "^3.2.0" - jest-matcher-utils "^20.0.3" - pretty-format "^20.0.3" + jest-get-type "^21.2.0" + pretty-format "^21.2.1" -jest-docblock@20.1.0-echo.1: - version "20.1.0-echo.1" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.1.0-echo.1.tgz#be02f43ee019f97e6b83267c746ac7b40d290fe8" +jest-docblock@^21, jest-docblock@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" -jest-docblock@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712" - -jest-environment-jsdom@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-20.0.3.tgz#048a8ac12ee225f7190417713834bb999787de99" +jest-environment-jsdom@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-21.2.1.tgz#38d9980c8259b2a608ec232deee6289a60d9d5b4" dependencies: - jest-mock "^20.0.3" - jest-util "^20.0.3" + jest-mock "^21.2.0" + jest-util "^21.2.1" jsdom "^9.12.0" -jest-environment-node@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-20.0.3.tgz#d488bc4612af2c246e986e8ae7671a099163d403" +jest-environment-node@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-21.2.1.tgz#98c67df5663c7fbe20f6e792ac2272c740d3b8c8" dependencies: - jest-mock "^20.0.3" - jest-util "^20.0.3" + jest-mock "^21.2.0" + jest-util "^21.2.1" -jest-haste-map@20.1.0-echo.1: - version "20.1.0-echo.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.1.0-echo.1.tgz#6dfd0c97bb51a68a35dd98326e04f994157dce81" +jest-get-type@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.2.0.tgz#f6376ab9db4b60d81e39f30749c6c466f40d4a23" + +jest-haste-map@^21, jest-haste-map@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-21.2.0.tgz#1363f0a8bb4338f24f001806571eff7a4b2ff3d8" dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" - jest-docblock "20.1.0-echo.1" + jest-docblock "^21.2.0" micromatch "^2.3.11" sane "^2.0.0" worker-farm "^1.3.1" -jest-haste-map@^20.0.4: - version "20.0.5" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.0.5.tgz#abad74efb1a005974a7b6517e11010709cab9112" +jest-jasmine2@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-21.2.1.tgz#9cc6fc108accfa97efebce10c4308548a4ea7592" dependencies: - fb-watchman "^2.0.0" + chalk "^2.0.1" + expect "^21.2.1" graceful-fs "^4.1.11" - jest-docblock "^20.0.3" - micromatch "^2.3.11" - sane "~1.6.0" - worker-farm "^1.3.1" + jest-diff "^21.2.1" + jest-matcher-utils "^21.2.1" + jest-message-util "^21.2.1" + jest-snapshot "^21.2.1" + p-cancelable "^0.3.0" -jest-jasmine2@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-20.0.4.tgz#fcc5b1411780d911d042902ef1859e852e60d5e1" +jest-matcher-utils@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-21.2.1.tgz#72c826eaba41a093ac2b4565f865eb8475de0f64" dependencies: - chalk "^1.1.3" - graceful-fs "^4.1.11" - jest-diff "^20.0.3" - jest-matcher-utils "^20.0.3" - jest-matchers "^20.0.3" - jest-message-util "^20.0.3" - jest-snapshot "^20.0.3" - once "^1.4.0" - p-map "^1.1.1" + chalk "^2.0.1" + jest-get-type "^21.2.0" + pretty-format "^21.2.1" -jest-matcher-utils@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-20.0.3.tgz#b3a6b8e37ca577803b0832a98b164f44b7815612" +jest-message-util@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-21.2.1.tgz#bfe5d4692c84c827d1dcf41823795558f0a1acbe" dependencies: - chalk "^1.1.3" - pretty-format "^20.0.3" - -jest-matchers@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-matchers/-/jest-matchers-20.0.3.tgz#ca69db1c32db5a6f707fa5e0401abb55700dfd60" - dependencies: - jest-diff "^20.0.3" - jest-matcher-utils "^20.0.3" - jest-message-util "^20.0.3" - jest-regex-util "^20.0.3" - -jest-message-util@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-20.0.3.tgz#6aec2844306fcb0e6e74d5796c1006d96fdd831c" - dependencies: - chalk "^1.1.3" + chalk "^2.0.1" micromatch "^2.3.11" slash "^1.0.0" -jest-mock@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-20.0.3.tgz#8bc070e90414aa155c11a8d64c869a0d5c71da59" +jest-mock@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-21.2.0.tgz#7eb0770e7317968165f61ea2a7281131534b3c0f" -jest-regex-util@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-20.0.3.tgz#85bbab5d133e44625b19faf8c6aa5122d085d762" +jest-regex-util@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-21.2.0.tgz#1b1e33e63143babc3e0f2e6c9b5ba1eb34b2d530" -jest-resolve-dependencies@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-20.0.3.tgz#6e14a7b717af0f2cb3667c549de40af017b1723a" +jest-resolve-dependencies@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-21.2.0.tgz#9e231e371e1a736a1ad4e4b9a843bc72bfe03d09" dependencies: - jest-regex-util "^20.0.3" + jest-regex-util "^21.2.0" -jest-resolve@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-20.0.4.tgz#9448b3e8b6bafc15479444c6499045b7ffe597a5" +jest-resolve@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-21.2.0.tgz#068913ad2ba6a20218e5fd32471f3874005de3a6" dependencies: browser-resolve "^1.11.2" + chalk "^2.0.1" is-builtin-module "^1.0.0" - resolve "^1.3.2" -jest-runtime@^20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-20.0.4.tgz#a2c802219c4203f754df1404e490186169d124d8" +jest-runner@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-21.2.1.tgz#194732e3e518bfb3d7cbfc0fd5871246c7e1a467" + dependencies: + jest-config "^21.2.1" + jest-docblock "^21.2.0" + jest-haste-map "^21.2.0" + jest-jasmine2 "^21.2.1" + jest-message-util "^21.2.1" + jest-runtime "^21.2.1" + jest-util "^21.2.1" + pify "^3.0.0" + throat "^4.0.0" + worker-farm "^1.3.1" + +jest-runtime@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-21.2.1.tgz#99dce15309c670442eee2ebe1ff53a3cbdbbb73e" dependencies: babel-core "^6.0.0" - babel-jest "^20.0.3" + babel-jest "^21.2.0" babel-plugin-istanbul "^4.0.0" - chalk "^1.1.3" + chalk "^2.0.1" convert-source-map "^1.4.0" graceful-fs "^4.1.11" - jest-config "^20.0.4" - jest-haste-map "^20.0.4" - jest-regex-util "^20.0.3" - jest-resolve "^20.0.4" - jest-util "^20.0.3" + jest-config "^21.2.1" + jest-haste-map "^21.2.0" + jest-regex-util "^21.2.0" + jest-resolve "^21.2.0" + jest-util "^21.2.1" json-stable-stringify "^1.0.1" micromatch "^2.3.11" + slash "^1.0.0" strip-bom "3.0.0" - yargs "^7.0.2" + write-file-atomic "^2.1.0" + yargs "^9.0.0" -jest-snapshot@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-20.0.3.tgz#5b847e1adb1a4d90852a7f9f125086e187c76566" +jest-snapshot@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-21.2.1.tgz#29e49f16202416e47343e757e5eff948c07fd7b0" dependencies: - chalk "^1.1.3" - jest-diff "^20.0.3" - jest-matcher-utils "^20.0.3" - jest-util "^20.0.3" + chalk "^2.0.1" + jest-diff "^21.2.1" + jest-matcher-utils "^21.2.1" + mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^20.0.3" + pretty-format "^21.2.1" -jest-util@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-20.0.3.tgz#0c07f7d80d82f4e5a67c6f8b9c3fe7f65cfd32ad" +jest-util@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-21.2.1.tgz#a274b2f726b0897494d694a6c3d6a61ab819bb78" dependencies: - chalk "^1.1.3" + callsites "^2.0.0" + chalk "^2.0.1" graceful-fs "^4.1.11" - jest-message-util "^20.0.3" - jest-mock "^20.0.3" - jest-validate "^20.0.3" - leven "^2.1.0" + jest-message-util "^21.2.1" + jest-mock "^21.2.0" + jest-validate "^21.2.1" mkdirp "^0.5.1" -jest-validate@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-20.0.3.tgz#d0cfd1de4f579f298484925c280f8f1d94ec3cab" +jest-validate@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.2.1.tgz#cc0cbca653cd54937ba4f2a111796774530dd3c7" dependencies: - chalk "^1.1.3" - jest-matcher-utils "^20.0.3" + chalk "^2.0.1" + jest-get-type "^21.2.0" leven "^2.1.0" - pretty-format "^20.0.3" + pretty-format "^21.2.1" -jest@20.0.4: - version "20.0.4" - resolved "https://registry.yarnpkg.com/jest/-/jest-20.0.4.tgz#3dd260c2989d6dad678b1e9cc4d91944f6d602ac" +jest@21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-21.2.1.tgz#c964e0b47383768a1438e3ccf3c3d470327604e1" dependencies: - jest-cli "^20.0.4" + jest-cli "^21.2.1" js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" @@ -2861,9 +2790,9 @@ methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -metro-bundler@^0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/metro-bundler/-/metro-bundler-0.13.0.tgz#a1510eaecfc3db8ef46d2a936a3cc18f651e26f7" +metro-bundler@^0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/metro-bundler/-/metro-bundler-0.20.0.tgz#a2faef20ba7f566484a6c5bd585f590f8640c183" dependencies: absolute-path "^0.0.0" async "^2.4.0" @@ -2872,7 +2801,7 @@ metro-bundler@^0.13.0: babel-plugin-external-helpers "^6.18.0" babel-preset-es2015-node "^6.1.1" babel-preset-fbjs "^2.1.4" - babel-preset-react-native "^2.0.0" + babel-preset-react-native "^4.0.0" babel-register "^6.24.1" babylon "^6.18.0" chalk "^1.1.1" @@ -2880,11 +2809,11 @@ metro-bundler@^0.13.0: core-js "^2.2.2" debug "^2.2.0" denodeify "^1.2.1" - fbjs "0.8.14" + fbjs "^0.8.14" graceful-fs "^4.1.3" image-size "^0.6.0" - jest-docblock "20.1.0-echo.1" - jest-haste-map "20.1.0-echo.1" + jest-docblock "^21" + jest-haste-map "^21" json-stable-stringify "^1.0.1" json5 "^0.4.0" left-pad "^1.1.3" @@ -2897,7 +2826,7 @@ metro-bundler@^0.13.0: source-map "^0.5.6" temp "0.8.3" throat "^4.1.0" - uglify-js "2.7.5" + uglify-es "^3.1.0" write-file-atomic "^1.2.0" xpipe "^1.0.5" @@ -3036,9 +2965,9 @@ native-base-shoutem-theme@0.2.1: lodash "^4.10.1" prop-types "^15.5.10" -native-base@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/native-base/-/native-base-2.3.2.tgz#4cc837cf240f2e8a981952c14085acb280ab45d0" +native-base@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/native-base/-/native-base-2.3.3.tgz#de35234cf9cf8d24b5ce5e1720f8330dd5f3c96a" dependencies: blueimp-md5 "^2.5.0" clamp "^1.0.1" @@ -3051,7 +2980,7 @@ native-base@^2.3.2: react-native-drawer "https://github.com/GeekyAnts/react-native-drawer" react-native-easy-grid "0.1.15" react-native-keyboard-aware-scroll-view "https://github.com/GeekyAnts/react-native-keyboard-aware-scroll-view" - react-native-vector-icons "~4.1.1" + react-native-vector-icons "~4.4.2" react-tween-state "^0.1.5" tween-functions "^1.0.1" @@ -3078,7 +3007,7 @@ node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" -node-notifier@^5.0.2: +node-notifier@^5.0.2, node-notifier@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.1.2.tgz#2fa9e12605fa10009d44549d6fcd8a63dde0e4ff" dependencies: @@ -3228,12 +3157,6 @@ os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - dependencies: - lcid "^1.0.0" - os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" @@ -3260,6 +3183,10 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -3274,10 +3201,6 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" -p-map@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -3359,10 +3282,14 @@ performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" -pify@^2.0.0, pify@^2.3.0: +pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -3398,12 +3325,12 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -pretty-format@^20.0.3: - version "20.0.3" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-20.0.3.tgz#020e350a560a1fe1a98dc3beb6ccffb386de8b14" +pretty-format@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.2.1.tgz#ae5407f3cf21066cd011aa1ba5fce7b6a2eddb36" dependencies: - ansi-regex "^2.1.1" - ansi-styles "^3.0.0" + ansi-regex "^3.0.0" + ansi-styles "^3.2.0" pretty-format@^4.2.1: version "4.3.1" @@ -3437,7 +3364,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.5.8: +prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" dependencies: @@ -3490,9 +3417,9 @@ range-parser@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" -raven-js@^3.17.0: - version "3.18.1" - resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.18.1.tgz#746339c08fca75c3f402d7e6b633687c3ffc6ee8" +raven-js@^3.19.1: + version "3.19.1" + resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.19.1.tgz#a5d25646556fc2c86d2b188ae4f425c144c08dd8" raw-body@~2.1.2: version "2.1.7" @@ -3530,9 +3457,9 @@ react-native-confetti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/react-native-confetti/-/react-native-confetti-0.0.6.tgz#a505e4e5a23bcb2cf554ba51362dfaf3ac17a100" -react-native-config@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/react-native-config/-/react-native-config-0.6.1.tgz#0a4c0a6ef8d086aeac9902ac4c3c9d9d19fa888a" +react-native-config@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/react-native-config/-/react-native-config-0.9.0.tgz#5a82874a2f75a44c3c421e03d8910228f17cea35" react-native-dismiss-keyboard@1.0.0: version "1.0.0" @@ -3563,12 +3490,12 @@ react-native-easy-grid@0.1.15: dependencies: lodash "^4.11.1" -react-native-htmlview@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/react-native-htmlview/-/react-native-htmlview-0.12.0.tgz#9b19a7dccd38586c0aebf975e6083184685013a6" +react-native-htmlview@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/react-native-htmlview/-/react-native-htmlview-0.12.1.tgz#4b987f1f34fae89f7bbd3c478f8f20d601019639" dependencies: entities "^1.1.1" - htmlparser2-without-node-native "^3.9.0" + htmlparser2-without-node-native "^3.9.2" "react-native-keyboard-aware-scroll-view@https://github.com/GeekyAnts/react-native-keyboard-aware-scroll-view": version "0.2.9" @@ -3578,42 +3505,34 @@ react-native-htmlview@^0.12.0: prop-types "^15.5.10" react-timer-mixin "^0.13.3" -react-native-sentry@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/react-native-sentry/-/react-native-sentry-0.25.0.tgz#f7530aa2fc48d71e0088f808a83d72c356e2abd5" +react-native-sentry@^0.30.2: + version "0.30.2" + resolved "https://registry.yarnpkg.com/react-native-sentry/-/react-native-sentry-0.30.2.tgz#6e432954db24d541c2810bfb386cd7adbad4497e" dependencies: - chalk "^1.1.1" - glob "7.1.1" - inquirer "3.0.6" - raven-js "^3.17.0" - sentry-cli-binary "^1.20.0" - xcode "0.9.3" + chalk "^2.3.0" + glob "^7.1.1" + inquirer "^3.3.0" + raven-js "^3.19.1" + sentry-cli-binary "^1.21.0" + xcode "^1.0.0" -react-native-tab-view@^0.0.69: - version "0.0.69" - resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-0.0.69.tgz#f52d4354a98a382f10eb5fcf61db5216c91dc7e7" +react-native-tab-view@^0.0.70: + version "0.0.70" + resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-0.0.70.tgz#1dd2ded32acd0cb6bfef38d26e53675db733b37b" dependencies: - prop-types "^15.5.8" + prop-types "^15.5.10" -react-native-vector-icons@~4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-4.1.1.tgz#9ac75bde77d9243346668c51dca7756775428087" - dependencies: - lodash "^4.0.0" - prop-types "^15.5.8" - yargs "^6.3.0" - -react-native-vector-icons@~4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-4.3.0.tgz#49eab845fbcde6354cb3dbcb62c1abd1f6abc866" +react-native-vector-icons@~4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-4.4.2.tgz#090f42ee0396c4cc4eae0ddaa518028ba8df40c7" dependencies: lodash "^4.0.0" prop-types "^15.5.10" yargs "^8.0.2" -react-native@0.49.1: - version "0.49.1" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.49.1.tgz#cf11575d823525d64bf31360d7f64b8fbcd11c1a" +react-native@0.50.1: + version "0.50.1" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.50.1.tgz#3d8bb7c96dd3151788e795a22155d305f15abfd1" dependencies: absolute-path "^0.0.0" art "^0.10.0" @@ -3634,18 +3553,19 @@ react-native@0.49.1: denodeify "^1.2.1" envinfo "^3.0.0" event-target-shim "^1.0.5" - fbjs "0.8.14" + fbjs "^0.8.14" fbjs-scripts "^0.8.1" fs-extra "^1.0.0" glob "^7.1.1" graceful-fs "^4.1.3" inquirer "^3.0.6" lodash "^4.16.6" - metro-bundler "^0.13.0" + metro-bundler "^0.20.0" mime "^1.3.4" minimist "^1.2.0" mkdirp "^0.5.1" node-fetch "^1.3.3" + node-notifier "^5.1.2" npmlog "^2.0.4" opn "^3.0.2" optimist "^0.6.1" @@ -3665,11 +3585,11 @@ react-native@0.49.1: ws "^1.1.0" xcode "^0.9.1" xmldoc "^0.4.0" - yargs "^6.4.0" + yargs "^9.0.0" -react-navigation@^1.0.0-beta.11: - version "1.0.0-beta.13" - resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-1.0.0-beta.13.tgz#77521f7080e5755906a3483a28baedbbc66f763c" +react-navigation@^1.0.0-beta.19: + version "1.0.0-beta.19" + resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-1.0.0-beta.19.tgz#96e159c4b6760f51fc92d5c1c3690790cff4dbcf" dependencies: babel-plugin-transform-define "^1.3.0" clamp "^1.0.1" @@ -3677,7 +3597,7 @@ react-navigation@^1.0.0-beta.11: path-to-regexp "^1.7.0" prop-types "^15.5.10" react-native-drawer-layout-polyfill "^1.3.2" - react-native-tab-view "^0.0.69" + react-native-tab-view "^0.0.70" react-proxy@^1.1.7: version "1.1.8" @@ -3697,12 +3617,12 @@ react-redux@^5.0.6: loose-envify "^1.1.0" prop-types "^15.5.10" -react-test-renderer@16.0.0-alpha.12: - version "16.0.0-alpha.12" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.0.0-alpha.12.tgz#9e4cc5d8ce8bfca72778340de3e1454b9d6c0cc5" +react-test-renderer@16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.0.0.tgz#9fe7b8308f2f71f29fc356d4102086f131c9cb15" dependencies: - fbjs "^0.8.9" - object-assign "^4.1.0" + fbjs "^0.8.16" + object-assign "^4.1.1" react-timer-mixin@^0.13.2, react-timer-mixin@^0.13.3: version "0.13.3" @@ -3722,14 +3642,14 @@ react-tween-state@^0.1.5: raf "^3.1.0" tween-functions "^1.0.1" -react@16.0.0-beta.5: - version "16.0.0-beta.5" - resolved "https://registry.yarnpkg.com/react/-/react-16.0.0-beta.5.tgz#b4abba9bce7db72c30633db54a148614b6574e79" +react@16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.0.0.tgz#ce7df8f1941b036f02b2cca9dbd0cb1f0e855e2d" dependencies: - fbjs "^0.8.9" + fbjs "^0.8.16" loose-envify "^1.1.0" - object-assign "^4.1.0" - prop-types "^15.5.6" + object-assign "^4.1.1" + prop-types "^15.6.0" read-pkg-up@^1.0.1: version "1.0.1" @@ -3788,9 +3708,9 @@ redux-logger@^3.0.6: dependencies: deep-diff "^0.3.5" -redux-persist@^4.9.1: - version "4.10.1" - resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-4.10.1.tgz#4fb2b789942f10f56d51cc7ad068d9d6beb46124" +redux-persist@^4.10.2: + version "4.10.2" + resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-4.10.2.tgz#8efdb16cfe882c521a78a6d0bfdfef2437f49f96" dependencies: json-stringify-safe "^5.0.1" lodash "^4.17.4" @@ -3941,12 +3861,6 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.3.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" - dependencies: - path-parse "^1.0.5" - response-time@~2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/response-time/-/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a" @@ -3997,10 +3911,6 @@ rx-lite@*, rx-lite@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" -rx@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -4023,18 +3933,6 @@ sane@^2.0.0: optionalDependencies: fsevents "^1.1.1" -sane@~1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/sane/-/sane-1.6.0.tgz#9610c452307a135d29c1fdfe2547034180c46775" - dependencies: - anymatch "^1.3.0" - exec-sh "^0.2.0" - fb-watchman "^1.8.0" - minimatch "^3.0.2" - minimist "^1.1.1" - walker "~1.0.5" - watch "~0.10.0" - sax@^1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -4064,9 +3962,9 @@ send@0.13.2: range-parser "~1.0.3" statuses "~1.2.1" -sentry-cli-binary@^1.20.0: - version "1.21.0" - resolved "https://registry.yarnpkg.com/sentry-cli-binary/-/sentry-cli-binary-1.21.0.tgz#3752563994d9a1c23828d61165ffa3b074cf6bb7" +sentry-cli-binary@^1.21.0: + version "1.22.0" + resolved "https://registry.yarnpkg.com/sentry-cli-binary/-/sentry-cli-binary-1.22.0.tgz#25f0e6784a467d287abb09d32b9e2e946aad2cd8" dependencies: progress "2.0.0" @@ -4184,6 +4082,10 @@ source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + sparkles@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" @@ -4242,11 +4144,12 @@ stream-counter@~0.2.0: dependencies: readable-stream "~1.1.8" -string-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac" +string-length@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" dependencies: - strip-ansi "^3.0.0" + astral-regex "^1.0.0" + strip-ansi "^4.0.0" string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" @@ -4369,11 +4272,7 @@ test-exclude@^4.1.1: read-pkg-up "^1.0.1" require-main-filename "^1.0.1" -throat@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836" - -throat@^4.1.0: +throat@^4.0.0, throat@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" @@ -4392,9 +4291,9 @@ time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" -tipsi-stripe@^3.7.0: - version "3.7.4" - resolved "https://registry.yarnpkg.com/tipsi-stripe/-/tipsi-stripe-3.7.4.tgz#a023c2060b876f56c6d1cdfdb0a2396c376945de" +tipsi-stripe@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/tipsi-stripe/-/tipsi-stripe-4.1.0.tgz#ed3b151fdbd6ca846f3e4c2bca193f71328124ec" dependencies: prop-types "^15.5.10" @@ -4469,14 +4368,12 @@ ua-parser-js@^0.7.9: version "0.7.14" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.14.tgz#110d53fa4c3f326c121292bbeac904d2e03387ca" -uglify-js@2.7.5: - version "2.7.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" +uglify-es@^3.1.0: + version "3.1.7" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.7.tgz#4994b6d7dee6ae0b05bd4fb5d18c9ae2023b6d58" dependencies: - async "~0.2.6" - source-map "~0.5.1" - uglify-to-browserify "~1.0.0" - yargs "~3.10.0" + commander "~2.11.0" + source-map "~0.6.1" uglify-js@^2.6: version "2.8.29" @@ -4576,10 +4473,6 @@ walker@~1.0.5: dependencies: makeerror "1.0.x" -watch@~0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/watch/-/watch-0.10.0.tgz#77798b2da0f9910d595f1ace5b0c2258521f21dc" - watch@~0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" @@ -4616,10 +4509,6 @@ whatwg-url@^4.3.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -4684,6 +4573,14 @@ write-file-atomic@^1.2.0: imurmurhash "^0.1.4" slide "^1.1.5" +write-file-atomic@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + ws@^1.1.0: version "1.1.4" resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.4.tgz#57f40d036832e5f5055662a397c4de76ed66bf61" @@ -4698,7 +4595,7 @@ ws@^2.0.3: safe-buffer "~5.0.1" ultron "~1.1.0" -xcode@0.9.3, xcode@^0.9.1: +xcode@^0.9.1: version "0.9.3" resolved "https://registry.yarnpkg.com/xcode/-/xcode-0.9.3.tgz#910a89c16aee6cc0b42ca805a6d0b4cf87211cf3" dependencies: @@ -4706,6 +4603,14 @@ xcode@0.9.3, xcode@^0.9.1: simple-plist "^0.2.1" uuid "3.0.1" +xcode@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/xcode/-/xcode-1.0.0.tgz#e1f5b1443245ded38c180796df1a10fdeda084ec" + dependencies: + pegjs "^0.10.0" + simple-plist "^0.2.1" + uuid "3.0.1" + xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" @@ -4746,60 +4651,12 @@ yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" -yargs-parser@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" - dependencies: - camelcase "^3.0.0" - -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - dependencies: - camelcase "^3.0.0" - yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" dependencies: camelcase "^4.1.0" -yargs@^6.3.0, yargs@^6.4.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^4.2.0" - -yargs@^7.0.2: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.0" - yargs@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" @@ -4818,6 +4675,24 @@ yargs@^8.0.2: y18n "^3.2.1" yargs-parser "^7.0.0" +yargs@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c" + dependencies: + 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@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" From 101a4143fde0b3753fe0070bc4382f8274d2fdd0 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Mon, 6 Nov 2017 00:36:32 +0100 Subject: [PATCH 12/27] refactor: Extract card style to theme file --- src/modules/about/About.js | 20 +------ src/modules/events/EventDetail.js | 43 +++----------- src/modules/events/EventList.js | 9 ++- src/modules/login/Login.js | 20 +------ src/modules/membership/Membership.js | 20 +------ src/modules/membership/Proof.js | 87 +++++++++++++++------------- src/modules/register/UserRegister.js | 20 +------ src/theme.js | 21 +++++++ 8 files changed, 87 insertions(+), 153 deletions(-) create mode 100644 src/theme.js diff --git a/src/modules/about/About.js b/src/modules/about/About.js index 2688bef..8301c7d 100644 --- a/src/modules/about/About.js +++ b/src/modules/about/About.js @@ -3,6 +3,7 @@ import {Text, ScrollView, View, Platform, StyleSheet, Image, Linking, TouchableO // import HTMLView from 'react-native-htmlview'; import {Button, Text as NBText, Icon} from 'native-base'; +import theme from "../../theme"; const CHATEAU_NEUF_ADDRESS = 'Det Norske Studentersamfund, Slemdalsveien 15, 0369 Oslo'; @@ -125,24 +126,7 @@ const styles = StyleSheet.create({ paddingBottom: 10, lineHeight: 25, }, - card: { - borderColor: '#e1e8ee', - borderWidth: 1, - ...Platform.select({ - ios: { - shadowColor: 'rgba(0,0,0, .2)', - shadowOffset: {height: 0, width: 0}, - shadowOpacity: 1, - shadowRadius: 1, - }, - android: { - elevation: 1, - }, - }), - padding: 8, - margin: 8, - backgroundColor: '#fff', - }, + card: theme.card, featuredImage: { height: 230, width: null, diff --git a/src/modules/events/EventDetail.js b/src/modules/events/EventDetail.js index 5c37622..0d69ed1 100644 --- a/src/modules/events/EventDetail.js +++ b/src/modules/events/EventDetail.js @@ -1,9 +1,9 @@ import React, { Component } from 'react'; -import {Linking, StyleSheet, ScrollView, Text, Platform, View, Image, TouchableHighlight, - TouchableOpacity} from "react-native"; +import {Linking, StyleSheet, ScrollView, Text, Platform, View, Image, TouchableOpacity} from "react-native"; import HTMLView from 'react-native-htmlview'; import moment from "moment"; -import {Button, Icon, Text as NBText} from "native-base"; +import {Icon} from "native-base"; +import theme from "../../theme"; moment.locale('nb'); @@ -172,7 +172,7 @@ export default class EventDetail extends Component { {/* Date and title */} - + {this._formatDay(item.start_time)} {this._formatMonth(item.start_time)} {this.showYear()} @@ -222,24 +222,7 @@ const styles = StyleSheet.create({ fontWeight: 'bold', color: '#000', }, - card: { - borderColor: '#e1e8ee', - borderWidth: 1, - ...Platform.select({ - ios: { - shadowColor: 'rgba(0,0,0, .2)', - shadowOffset: {height: 0, width: 0}, - shadowOpacity: 1, - shadowRadius: 1, - }, - android: { - elevation: 1, - }, - }), - padding: 8, - margin: 8, - backgroundColor: '#fff', - }, + card: theme.card, image: { height: 260, width: null @@ -275,20 +258,8 @@ const styles = StyleSheet.create({ justifyContent: 'center', }, dateCard: { - borderColor: '#e1e8ee', - borderWidth: 1, - ...Platform.select({ - ios: { - shadowColor: 'rgba(0,0,0, .2)', - shadowOffset: {height: 0, width: 0}, - shadowOpacity: 2, - shadowRadius: 2, - }, - android: { - elevation: 1, - }, - }), - backgroundColor: '#fff', + margin: 0, + padding: 0, paddingBottom: 6, width: 62, }, diff --git a/src/modules/events/EventList.js b/src/modules/events/EventList.js index 3b383fb..4d89d2b 100644 --- a/src/modules/events/EventList.js +++ b/src/modules/events/EventList.js @@ -3,6 +3,7 @@ import {Card, ListItem, CardItem, Body, Text as Text, Left, Right, Icon, Button, import React, { Component } from 'react'; import moment from "moment"; import 'moment/locale/nb'; +import theme from "../../theme"; moment.locale('nb'); @@ -20,7 +21,7 @@ export default class EventList extends Component { ); _renderSectionHeader = ({section}) => { - return ( + return ( {section.title} @@ -71,7 +72,7 @@ export default class EventList extends Component { onEndReachedThreshould={10} initialNumToRender={10} ListFooterComponent={this._renderFooter} - style={styles.list} + style={[styles.list, {paddingRight: 0}]} />); } } @@ -96,7 +97,5 @@ const styles = StyleSheet.create({ textAlign: 'center', paddingBottom: 8 }, - list: { - backgroundColor: 'white' - } + list: theme.card, }); \ No newline at end of file diff --git a/src/modules/login/Login.js b/src/modules/login/Login.js index 49ff23f..90c2ed2 100644 --- a/src/modules/login/Login.js +++ b/src/modules/login/Login.js @@ -3,6 +3,7 @@ import {Linking, StyleSheet, View, Platform} from 'react-native'; import {Container, Header, Content, Form, Item, Input, Label, Spinner, Button, Text, Icon} from 'native-base'; import Config from 'react-native-config'; +import theme from "../../theme"; export default class Login extends Component { constructor(props) { @@ -157,22 +158,5 @@ const styles = StyleSheet.create({ textAlign: 'center', color: 'red', }, - card: { - borderColor: '#e1e8ee', - borderWidth: 1, - ...Platform.select({ - ios: { - shadowColor: 'rgba(0,0,0, .2)', - shadowOffset: {height: 0, width: 0}, - shadowOpacity: 1, - shadowRadius: 1, - }, - android: { - elevation: 1, - }, - }), - padding: 8, - margin: 8, - backgroundColor: '#fff', - }, + card: theme.card, }); \ No newline at end of file diff --git a/src/modules/membership/Membership.js b/src/modules/membership/Membership.js index 7925a69..3454958 100644 --- a/src/modules/membership/Membership.js +++ b/src/modules/membership/Membership.js @@ -1,6 +1,7 @@ import React, {Component} from 'react'; import {ScrollView, Text, View, Linking, StyleSheet, Platform} from "react-native"; import {Button, Text as NBText} from "native-base"; +import theme from "../../theme"; export default class Membership extends Component { render() { return ( @@ -31,24 +32,7 @@ export default class Membership extends Component { const styles = StyleSheet.create({ - card: { - borderColor: '#e1e8ee', - borderWidth: 1, - ...Platform.select({ - ios: { - shadowColor: 'rgba(0,0,0, .2)', - shadowOffset: {height: 0, width: 0}, - shadowOpacity: 1, - shadowRadius: 1, - }, - android: { - elevation: 1, - }, - }), - padding: 8, - margin: 8, - backgroundColor: '#fff', - }, + card: theme.card, paragraph: { textAlign: 'center', fontSize: 16, diff --git a/src/modules/membership/Proof.js b/src/modules/membership/Proof.js index 2950ac2..16d2f3b 100644 --- a/src/modules/membership/Proof.js +++ b/src/modules/membership/Proof.js @@ -1,7 +1,8 @@ import React, {Component} from 'react'; -import {Image, StyleSheet, TouchableOpacity, View} from "react-native"; -import {Button, Body, Card, CardItem, Container, Content, Text} from 'native-base'; +import {Image, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, View} from "react-native"; +import {Button, Text as NBText} from 'native-base'; import Confetti from 'react-native-confetti'; +import theme from "../../theme"; export default class Proof extends Component { CONFETTI_TIMEOUT = 15000; @@ -48,57 +49,52 @@ export default class Proof extends Component { } return ( - - - Gyldig til: - {validTo} - - + + Gyldig til: + {validTo} + ) } membershipStatus() { if (!this.props.user.is_member) { if ( !this.props.user.last_membership ) { - return ( - - - Ikke medlem - - ) + return; } - return Utløpt + return ( + + Utløpt + ) } - let statusText = 'Medlem'; - if (this.props.user.is_volunteer) { - statusText = 'Aktiv'; - } + const statusText = this.props.user.is_volunteer ? 'Aktiv' : 'Medlem'; return ( - + {statusText} - ); + ); } purchaseButton() { if (this.props.user.is_member) { return; } - return - + return ( + - - + + Medlemskapet er gyldig i ett år + + ) } confetti() { @@ -123,21 +119,21 @@ export default class Proof extends Component { render() { return ( - + {this.confetti()} - - - {this.membershipName()} - {this.logo()} - {this.membershipStatus()} - {this.purchaseButton()} - {this.membershipValidTo()} - + + {this.membershipName()} + {this.logo()} + {this.membershipStatus()} + {this.purchaseButton()} + {this.membershipValidTo()} + + - - + + ) }; @@ -146,13 +142,14 @@ export default class Proof extends Component { if(name === ' ') { name = this.props.user.email; } - return + return {name} - + } } const styles = StyleSheet.create({ + card: theme.card, nameText: { flex: 1, textAlign: 'center', @@ -203,4 +200,14 @@ const styles = StyleSheet.create({ alignSelf: 'center', marginVertical: 20, }, + purchaseText: { + alignItems: 'center' + }, + purchaseTextInner: { + fontStyle: 'italic', + fontSize: 16, + textAlign: 'center', + paddingTop: 10, + paddingBottom: 8 + } }); \ No newline at end of file diff --git a/src/modules/register/UserRegister.js b/src/modules/register/UserRegister.js index c7a8e3e..315b1e6 100644 --- a/src/modules/register/UserRegister.js +++ b/src/modules/register/UserRegister.js @@ -3,6 +3,7 @@ import {Container, Header, Content, Form, Item, Input, Label, Spinner, Button, T import {Platform, StyleSheet, View} from "react-native"; import EmailValidator from 'email-validator'; import platform from "native-base/src/theme/variables/platform"; +import theme from "../../theme"; export default class UserRegister extends Component { constructor(props) { @@ -250,24 +251,7 @@ const styles = StyleSheet.create({ color: platform.btnDangerBg, fontSize: 14, }, - card: { - borderColor: '#e1e8ee', - borderWidth: 1, - ...Platform.select({ - ios: { - shadowColor: 'rgba(0,0,0, .2)', - shadowOffset: {height: 0, width: 0}, - shadowOpacity: 1, - shadowRadius: 1, - }, - android: { - elevation: 1, - }, - }), - padding: 8, - margin: 8, - backgroundColor: '#fff', - }, + card: theme.card, errorText: { paddingTop: 2, paddingBottom: 12, diff --git a/src/theme.js b/src/theme.js new file mode 100644 index 0000000..fdde701 --- /dev/null +++ b/src/theme.js @@ -0,0 +1,21 @@ +import { Platform } from "react-native"; + +const card = { + borderColor: '#e1e8ee', + borderWidth: 1, + ...Platform.select({ + ios: { + shadowColor: 'rgba(0,0,0, .2)', + shadowOffset: {height: 0, width: 0}, + shadowOpacity: 1, + shadowRadius: 1, + }, + android: { + elevation: 1, + }, + }), + padding: 8, + margin: 8, + backgroundColor: '#fff', +}; +export default {card}; \ No newline at end of file From 18936797aaa1390fb28df3f5b13db922def17b98 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Mon, 6 Nov 2017 01:12:32 +0100 Subject: [PATCH 13/27] Proof: Add spinner if charging++ --- src/modules/login/LoginContainer.js | 27 +++--------- src/modules/membership/Proof.js | 56 ++++++++++++++---------- src/modules/membership/ProofContainer.js | 19 +++----- 3 files changed, 47 insertions(+), 55 deletions(-) diff --git a/src/modules/login/LoginContainer.js b/src/modules/login/LoginContainer.js index 0eb40fc..181d17a 100644 --- a/src/modules/login/LoginContainer.js +++ b/src/modules/login/LoginContainer.js @@ -4,39 +4,24 @@ import Login from "./Login"; import {requestLogin} from "../../api"; class LoginContainer extends Component { - constructor(state) { - super(state); - this.state = { - isAuthenticated: false, - isLoggingIn: false, - loginError: null, - } - } - componentWillReceiveProps(nextProps) { - if (this.state.isAuthenticated !== nextProps.isAuthenticated) { + if (this.props.isAuthenticated !== nextProps.isAuthenticated) { if (nextProps.isAuthenticated) { this.props.onLogin(); } } - if (this.state.isLoggingIn !== nextProps.isLoggingIn) { - this.setState({isLoggingIn: nextProps.isLoggingIn}) - } - if (this.state.loginError !== nextProps.loginError) { - this.setState({loginError: nextProps.loginError}) - } } render() { - return + return } } export default connect( - (state) => ({ - isAuthenticated: state.isAuthenticated, - isLoggingIn: state.isLoggingIn, - loginError: state.loginError, + (store) => ({ + isAuthenticated: store.isAuthenticated, + isLoggingIn: store.isLoggingIn, + loginError: store.loginError, }), {requestLogin} )(LoginContainer); diff --git a/src/modules/membership/Proof.js b/src/modules/membership/Proof.js index 16d2f3b..9be9c43 100644 --- a/src/modules/membership/Proof.js +++ b/src/modules/membership/Proof.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import {Image, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, View} from "react-native"; -import {Button, Text as NBText} from 'native-base'; +import {Button, Text as NBText, Spinner} from 'native-base'; import Confetti from 'react-native-confetti'; import theme from "../../theme"; @@ -71,7 +71,7 @@ export default class Proof extends Component { const statusText = this.props.user.is_volunteer ? 'Aktiv' : 'Medlem'; return ( - + {statusText} @@ -84,9 +84,11 @@ export default class Proof extends Component { } return ( + {this.props.isChargingMembership && } - - + + + {this.membershipName()} + {this.logo()} + {this.membershipStatus()} + {this.purchaseButton()} + {this.membershipValidTo()} + + + + + + ) }; @@ -150,6 +158,9 @@ export default class Proof extends Component { const styles = StyleSheet.create({ card: theme.card, + membershipStatus: { + marginVertical: 16, + }, nameText: { flex: 1, textAlign: 'center', @@ -171,7 +182,8 @@ const styles = StyleSheet.create({ backgroundColor: '#d9534f', flex: 1, marginHorizontal: -16, - padding: 16 + padding: 16, + marginVertical: 16, }, expiredText: { color: 'white', diff --git a/src/modules/membership/ProofContainer.js b/src/modules/membership/ProofContainer.js index f174c6c..bb67697 100644 --- a/src/modules/membership/ProofContainer.js +++ b/src/modules/membership/ProofContainer.js @@ -20,16 +20,12 @@ class ProofContainer extends Component { } } - componentWillReceiveProps(nextProps) { - if(this.state.user !== nextProps.user) { - this.setState({user: nextProps.user}) - } - } - render() { return @@ -51,10 +47,7 @@ class ProofContainer extends Component { {id: token.tokenId, email: this.props.user.email}, 'standard'); }, - (error) => { - // TODO: display error - console.log(error); - } + (error) => { /* FIXME: Happens only if card dialog is canceled? */ } ); }; @@ -80,8 +73,10 @@ class ProofContainer extends Component { } export default connect( - (state) => ({ - userToken: state.userToken + (store) => ({ + userToken: store.userToken, + isChargingMembership: store.isChargingMembership, + chargeError: store.chargeError }), {requestMembershipCharge} )(ProofContainer); From a0e976ee1f2b787fc0cb9794c644e0520a1c3744 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Mon, 6 Nov 2017 01:20:36 +0100 Subject: [PATCH 14/27] Minor --- src/api.js | 2 +- src/modules/membership/Proof.js | 2 +- src/modules/membership/ProofContainer.js | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/api.js b/src/api.js index 2c3644a..a8125e1 100644 --- a/src/api.js +++ b/src/api.js @@ -67,7 +67,7 @@ export function requestUserData(auth_token) { dispatch(userDataSuccess(data)) }, data => { - dispatch(userDataFailure('Det funka ikke :-(')) + dispatch(userDataFailure(data || {'non_field_errors': ['Kunne ikke hente brukerdata']})) } ) } diff --git a/src/modules/membership/Proof.js b/src/modules/membership/Proof.js index 9be9c43..96abf4b 100644 --- a/src/modules/membership/Proof.js +++ b/src/modules/membership/Proof.js @@ -91,7 +91,7 @@ export default class Proof extends Component { disabled={this.props.isChargingMembership} style={styles.purchaseButton} > - Kjøp medlemskap (200 NOK) + {`Kjøp medlemskap (${this.props.membershipPrice} NOK)`} Medlemskapet er gyldig i ett år diff --git a/src/modules/membership/ProofContainer.js b/src/modules/membership/ProofContainer.js index bb67697..14da8fd 100644 --- a/src/modules/membership/ProofContainer.js +++ b/src/modules/membership/ProofContainer.js @@ -12,6 +12,8 @@ stripe.init({ }); class ProofContainer extends Component { + price = 200; // TODO: fetch from backend + constructor(props) { super(props); @@ -28,6 +30,7 @@ class ProofContainer extends Component { chargeError={this.props.chargeError} onChargePress={this.openStripe} onLogoutPress={this.props.onLogoutPress} + membershipPrice={this.price} /> } From 6511a4422f6761dc6f627eaedf74e0c4971d56e6 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Wed, 8 Nov 2017 00:02:31 +0100 Subject: [PATCH 15/27] Fetch default membership price from dusken This uses apollo-client to connect and fetch from the graphql API --- package.json | 6 ++ src/App.js | 24 +++-- src/modules/membership/Proof.js | 2 +- src/modules/membership/ProofContainer.js | 33 +++++-- yarn.lock | 106 ++++++++++++++++++++++- 5 files changed, 158 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 8ca9eec..aaa9f6a 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,17 @@ "release-android": "cd android && fastlane beta" }, "dependencies": { + "apollo-cache-inmemory": "^1.1.0", + "apollo-client": "^2.0.2", + "apollo-link-http": "^1.1.0", "email-validator": "^1.1.1", + "graphql": "^0.11.7", + "graphql-tag": "^2.5.0", "moment": "^2.19.1", "native-base": "^2.3.3", "prop-types": "^15.5.10", "react": "16.0.0", + "react-apollo": "^2.0.0", "react-native": "0.50.1", "react-native-confetti": "^0.0.6", "react-native-config": "^0.9.0", diff --git a/src/App.js b/src/App.js index 021afa2..f8ce82b 100644 --- a/src/App.js +++ b/src/App.js @@ -1,24 +1,38 @@ -import Dusken from "./Dusken"; import React, {Component} from 'react'; -import { Provider } from 'react-redux'; -import { createStore, applyMiddleware } from 'redux'; +import {Provider} from 'react-redux'; +import {applyMiddleware, createStore} from 'redux'; import logger from 'redux-logger'; import thunk from 'redux-thunk'; -import {persistStore, autoRehydrate} from 'redux-persist' +import {autoRehydrate, persistStore} from 'redux-persist' import {AsyncStorage} from 'react-native' +import Config from 'react-native-config'; +import {ApolloClient} from 'apollo-client'; +import {HttpLink} from 'apollo-link-http'; +import {InMemoryCache} from 'apollo-cache-inmemory'; +import {ApolloProvider} from "react-apollo"; + +import Dusken from "./Dusken"; import duskenApp from "./reducers"; + let store = createStore( duskenApp, applyMiddleware(...[logger, thunk]), autoRehydrate() ); +const apolloClient = new ApolloClient({ + link: new HttpLink({uri: `${Config.DUSKEN_API_URL}/api/graphql/`}), + cache: new InMemoryCache() +}); + export default class App extends Component { render() { return ( - + + + ) } diff --git a/src/modules/membership/Proof.js b/src/modules/membership/Proof.js index 96abf4b..0a40a50 100644 --- a/src/modules/membership/Proof.js +++ b/src/modules/membership/Proof.js @@ -1,5 +1,5 @@ import React, {Component} from 'react'; -import {Image, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, View} from "react-native"; +import {Image, ScrollView, StyleSheet, Text, TouchableOpacity, View} from "react-native"; import {Button, Text as NBText, Spinner} from 'native-base'; import Confetti from 'react-native-confetti'; import theme from "../../theme"; diff --git a/src/modules/membership/ProofContainer.js b/src/modules/membership/ProofContainer.js index 14da8fd..eb4d78e 100644 --- a/src/modules/membership/ProofContainer.js +++ b/src/modules/membership/ProofContainer.js @@ -2,6 +2,8 @@ import React, {Component} from 'react'; import {connect} from "react-redux"; import stripe from 'tipsi-stripe' import Config from 'react-native-config'; +import { graphql } from 'react-apollo'; +import gql from 'graphql-tag'; import Proof from "./Proof"; import {requestMembershipCharge} from "../../api"; @@ -11,17 +13,23 @@ stripe.init({ publishableKey: Config.STRIPE_PUBLISHABLE_KEY || '', }); -class ProofContainer extends Component { - price = 200; // TODO: fetch from backend +class ProofContainer extends Component { constructor(props) { super(props); - this.state = { refreshing: false, } } + getPrice(membershipTypes) { + if (!membershipTypes || membershipTypes.length !== 1) { + return 0; + } + + return membershipTypes[0].price / 100; + } + render() { return } @@ -75,7 +83,20 @@ class ProofContainer extends Component { // } } -export default connect( +const PROOF_QUERY = gql`{ + membershipTypes(isDefault: true) { + id + slug + price + expiryType + duration + isActive + name + isDefault + } +}`; + +const proofContainerWithState = connect( (store) => ({ userToken: store.userToken, isChargingMembership: store.isChargingMembership, @@ -83,3 +104,5 @@ export default connect( }), {requestMembershipCharge} )(ProofContainer); + +export default graphql(PROOF_QUERY)(proofContainerWithState); diff --git a/yarn.lock b/yarn.lock index a884b68..bf8d306 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,14 @@ # yarn lockfile v1 +"@types/async@2.0.45": + version "2.0.45" + resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.45.tgz#0cfe971d7ed5542695740338e0455c91078a0e83" + +"@types/zen-observable@^0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.5.3.tgz#91b728599544efbb7386d8b6633693a3c2e7ade5" + abab@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -99,6 +107,57 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +apollo-cache-inmemory@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.1.0.tgz#8b35f21da142419f0d68b6fff908f8ed4370ac8d" + dependencies: + apollo-cache "^1.0.0" + apollo-utilities "^1.0.0" + graphql-anywhere "^4.0.0" + +apollo-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.0.0.tgz#8579cf70073410b3594164a21c5afb847a8eed1f" + dependencies: + apollo-utilities "^1.0.0" + +apollo-client@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.0.2.tgz#f2b01898c404c867fc2bd8edf7c3ccded2b96fc6" + dependencies: + "@types/zen-observable" "^0.5.3" + apollo-cache "^1.0.0" + apollo-link "1.0.0" + apollo-link-dedup "1.0.0" + apollo-utilities "^1.0.0" + symbol-observable "^1.0.2" + zen-observable "^0.6.0" + optionalDependencies: + "@types/async" "2.0.45" + +apollo-link-dedup@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.0.tgz#f0134ac495cc42e7e43dfafe7126645baa1e03bc" + +apollo-link-http@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.1.0.tgz#a85cc43d9a5286bb54ac32213f7a16bef3554ae4" + +apollo-link@1.0.0, apollo-link@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.0.0.tgz#3d334285789c217f95712ebce434d56ce7f3e991" + dependencies: + apollo-utilities "^0.2.0-beta.0" + zen-observable "^0.6.0" + +apollo-utilities@^0.2.0-beta.0: + version "0.2.0-rc.3" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-0.2.0-rc.3.tgz#7bd93be0f587f20c5b46e21880272e305759fdc2" + +apollo-utilities@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.1.tgz#34b4df0bd6ed71d0afaa7c62489173dca5d07e92" + append-transform@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" @@ -1798,6 +1857,22 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" +graphql-anywhere@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.0.0.tgz#4cf7ae7ed93aabeb95d329caa08c3867ddaef45e" + dependencies: + apollo-utilities "^1.0.0" + +graphql-tag@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.5.0.tgz#b43bfd8b5babcd2c205ad680c03e98b238934e0f" + +graphql@^0.11.7: + version "0.11.7" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.7.tgz#e5abaa9cb7b7cccb84e9f0836bf4370d268750c6" + dependencies: + iterall "1.1.3" + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -2027,7 +2102,7 @@ inquirer@^3.0.6, inquirer@^3.3.0: strip-ansi "^4.0.0" through "^2.3.6" -invariant@^2.0.0, invariant@^2.2.2: +invariant@^2.0.0, invariant@^2.2.1, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: @@ -2229,6 +2304,10 @@ istanbul-reports@^1.1.2: dependencies: handlebars "^4.0.3" +iterall@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.3.tgz#1cbbff96204056dde6656e2ed2e2226d0e6d72c9" + jest-changed-files@^21.2.0: version "21.2.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-21.2.0.tgz#5dbeecad42f5d88b482334902ce1cba6d9798d29" @@ -2665,6 +2744,10 @@ lodash.escape@^3.0.0: dependencies: lodash._root "^3.0.0" +lodash.flowright@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/lodash.flowright/-/lodash.flowright-3.5.0.tgz#2b5fff399716d7e7dc5724fe9349f67065184d67" + lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -2693,6 +2776,10 @@ lodash.padstart@^4.1.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" +lodash.pick@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" @@ -3438,6 +3525,17 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-apollo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-2.0.0.tgz#c9cbda2956585d422800f1686d870258637170f8" + dependencies: + apollo-link "^1.0.0" + hoist-non-react-statics "^2.2.0" + invariant "^2.2.1" + lodash.flowright "^3.5.0" + lodash.pick "^4.4.0" + prop-types "^15.5.8" + react-clone-referenced-element@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.0.1.tgz#2bba8c69404c5e4a944398600bcc4c941f860682" @@ -4226,7 +4324,7 @@ supports-color@^4.0.0: dependencies: has-flag "^2.0.0" -symbol-observable@^1.0.3: +symbol-observable@^1.0.2, symbol-observable@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" @@ -4701,3 +4799,7 @@ yargs@~3.10.0: cliui "^2.1.0" decamelize "^1.0.0" window-size "0.1.0" + +zen-observable@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.6.0.tgz#8a6157ed15348d185d948cfc4a59d90a2c0f70ee" From de301712805fec9b5272f7c728ba2cecbe146afc Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Wed, 8 Nov 2017 00:13:15 +0100 Subject: [PATCH 16/27] Proof: Use MembershipType.slug from API --- src/modules/membership/ProofContainer.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/modules/membership/ProofContainer.js b/src/modules/membership/ProofContainer.js index eb4d78e..766b733 100644 --- a/src/modules/membership/ProofContainer.js +++ b/src/modules/membership/ProofContainer.js @@ -15,6 +15,7 @@ stripe.init({ class ProofContainer extends Component { + // TODO: Prevent charge if we do not have a default membership type constructor(props) { super(props); this.state = { @@ -23,7 +24,7 @@ class ProofContainer extends Component { } getPrice(membershipTypes) { - if (!membershipTypes || membershipTypes.length !== 1) { + if (!membershipTypes) { return 0; } @@ -50,13 +51,15 @@ class ProofContainer extends Component { smsAutofillDisabled: true, }; + const membershipTypeSlug = this.props.data.membershipTypes ? this.props.data.membershipTypes[0].slug : 'standard'; + stripe.paymentRequestWithCardForm(options).then( (token) => { // returns a token.tokenId which should be saved this.props.requestMembershipCharge( this.props.userToken, {id: token.tokenId, email: this.props.user.email}, - 'standard'); + membershipTypeSlug); }, (error) => { /* FIXME: Happens only if card dialog is canceled? */ } ); @@ -85,14 +88,8 @@ class ProofContainer extends Component { const PROOF_QUERY = gql`{ membershipTypes(isDefault: true) { - id slug price - expiryType - duration - isActive - name - isDefault } }`; From 064255fe1ee7a32c9f5563dc6c07a6046460e669 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Wed, 8 Nov 2017 00:33:58 +0100 Subject: [PATCH 17/27] Fix tests --- __tests__/index.js | 1 - package.json | 1 + src/App.js | 1 + yarn.lock | 9 +++++++++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/__tests__/index.js b/__tests__/index.js index efc5d0b..9da8020 100644 --- a/__tests__/index.js +++ b/__tests__/index.js @@ -4,7 +4,6 @@ import App from '../src/App'; // Note: test renderer must be required after react-native. import renderer from 'react-test-renderer'; -import 'isomorphic-fetch'; it('renders correctly', () => { const tree = renderer.create( diff --git a/package.json b/package.json index aaa9f6a..a830494 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "devDependencies": { "babel-jest": "21.2.0", "jest": "21.2.1", + "react-dom": "^16.0.0", "react-test-renderer": "16.0.0" }, "jest": { diff --git a/src/App.js b/src/App.js index f8ce82b..acf245a 100644 --- a/src/App.js +++ b/src/App.js @@ -10,6 +10,7 @@ import {ApolloClient} from 'apollo-client'; import {HttpLink} from 'apollo-link-http'; import {InMemoryCache} from 'apollo-cache-inmemory'; import {ApolloProvider} from "react-apollo"; +import 'isomorphic-fetch'; import Dusken from "./Dusken"; import duskenApp from "./reducers"; diff --git a/yarn.lock b/yarn.lock index bf8d306..36ff9be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3551,6 +3551,15 @@ react-devtools-core@^2.5.0: shell-quote "^1.6.1" ws "^2.0.3" +react-dom@^16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.0.0.tgz#9cc3079c3dcd70d4c6e01b84aab2a7e34c303f58" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.0" + react-native-confetti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/react-native-confetti/-/react-native-confetti-0.0.6.tgz#a505e4e5a23bcb2cf554ba51362dfaf3ac17a100" From 7175336465fc1f4a0623476ec393023c43b97cab Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Wed, 8 Nov 2017 00:39:38 +0100 Subject: [PATCH 18/27] chore: Run tests on node 8 for now --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8852e5b..9aa473f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: node:latest +image: node:carbon cache: paths: From a329dd023935f54c1235e6ebfe453f02848291e5 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Sun, 12 Nov 2017 18:58:04 +0100 Subject: [PATCH 19/27] EventList: Style fixes --- __tests__/index.js | 1 + src/App.js | 1 - src/modules/events/EventList.js | 30 ++++++++++++++++++++++++------ src/theme.js | 6 +++--- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/__tests__/index.js b/__tests__/index.js index 9da8020..02e3775 100644 --- a/__tests__/index.js +++ b/__tests__/index.js @@ -1,6 +1,7 @@ import 'react-native'; import React from 'react'; import App from '../src/App'; +import 'isomorphic-fetch'; // Note: test renderer must be required after react-native. import renderer from 'react-test-renderer'; diff --git a/src/App.js b/src/App.js index acf245a..f8ce82b 100644 --- a/src/App.js +++ b/src/App.js @@ -10,7 +10,6 @@ import {ApolloClient} from 'apollo-client'; import {HttpLink} from 'apollo-link-http'; import {InMemoryCache} from 'apollo-cache-inmemory'; import {ApolloProvider} from "react-apollo"; -import 'isomorphic-fetch'; import Dusken from "./Dusken"; import duskenApp from "./reducers"; diff --git a/src/modules/events/EventList.js b/src/modules/events/EventList.js index 4d89d2b..8c448cc 100644 --- a/src/modules/events/EventList.js +++ b/src/modules/events/EventList.js @@ -21,9 +21,9 @@ export default class EventList extends Component { ); _renderSectionHeader = ({section}) => { - return ( + return ( - {section.title} + {section.title} ); }; @@ -72,7 +72,8 @@ export default class EventList extends Component { onEndReachedThreshould={10} initialNumToRender={10} ListFooterComponent={this._renderFooter} - style={[styles.list, {paddingRight: 0}]} + style={[styles.card, styles.list]} + ListHeaderComponent={() => { return }} />); } } @@ -80,6 +81,7 @@ export default class EventList extends Component { const styles = StyleSheet.create({ listItem: { + backgroundColor: 'white', marginLeft: 0 }, listItemTitle: { @@ -89,13 +91,29 @@ const styles = StyleSheet.create({ fontSize: 14, color: '#666' }, - listItemSectionTitle: { - fontSize: 14, + sectionHeader: { + backgroundColor: 'white', + marginLeft: 0, + marginBottom: -8, + paddingBottom: 0, + borderBottomWidth: 0, + }, + sectionTitle: { + fontSize: 16, fontWeight: 'bold', }, loadingText: { textAlign: 'center', paddingBottom: 8 }, - list: theme.card, + card: theme.card, + list: { + padding: 0, + marginTop: 0, + marginBottom: 0, + backgroundColor: 'transparent', + }, + listHeader: { + paddingTop: 8, + } }); \ No newline at end of file diff --git a/src/theme.js b/src/theme.js index fdde701..729db2a 100644 --- a/src/theme.js +++ b/src/theme.js @@ -1,8 +1,8 @@ import { Platform } from "react-native"; +const colors = {}; + const card = { - borderColor: '#e1e8ee', - borderWidth: 1, ...Platform.select({ ios: { shadowColor: 'rgba(0,0,0, .2)', @@ -18,4 +18,4 @@ const card = { margin: 8, backgroundColor: '#fff', }; -export default {card}; \ No newline at end of file +export default {card, colors}; \ No newline at end of file From 39a163010be28b60d4a52f3c87f9b259fe7c906f Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Sat, 18 Nov 2017 17:59:06 +0100 Subject: [PATCH 20/27] =?UTF-8?q?=F0=9F=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 6 +-- yarn.lock | 133 +++++++++++++++++++++++++-------------------------- 2 files changed, 69 insertions(+), 70 deletions(-) diff --git a/package.json b/package.json index a830494..69837c6 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "prop-types": "^15.5.10", "react": "16.0.0", "react-apollo": "^2.0.0", - "react-native": "0.50.1", + "react-native": "0.50.3", "react-native-confetti": "^0.0.6", - "react-native-config": "^0.9.0", + "react-native-config": "^0.10.0", "react-native-htmlview": "^0.12.1", "react-native-sentry": "^0.30.2", "react-native-vector-icons": "~4.4.2", @@ -39,7 +39,7 @@ "babel-jest": "21.2.0", "jest": "21.2.1", "react-dom": "^16.0.0", - "react-test-renderer": "16.0.0" + "react-test-renderer": "16.1.1" }, "jest": { "preset": "react-native", diff --git a/yarn.lock b/yarn.lock index 36ff9be..3a5b226 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6,7 +6,7 @@ version "2.0.45" resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.45.tgz#0cfe971d7ed5542695740338e0455c91078a0e83" -"@types/zen-observable@^0.5.3": +"@types/zen-observable@0.5.3", "@types/zen-observable@^0.5.3": version "0.5.3" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.5.3.tgz#91b728599544efbb7386d8b6633693a3c2e7ade5" @@ -108,55 +108,52 @@ anymatch@^1.3.0: normalize-path "^2.0.0" apollo-cache-inmemory@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.1.0.tgz#8b35f21da142419f0d68b6fff908f8ed4370ac8d" + version "1.1.1" + resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.1.1.tgz#1511f00eb845da88504abf867f408c3026a909ba" dependencies: - apollo-cache "^1.0.0" - apollo-utilities "^1.0.0" - graphql-anywhere "^4.0.0" + apollo-cache "^1.0.1" + apollo-utilities "^1.0.2" + graphql-anywhere "^4.0.1" -apollo-cache@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.0.0.tgz#8579cf70073410b3594164a21c5afb847a8eed1f" +apollo-cache@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.0.1.tgz#66c16141173bc752d3ad3dce990310c10dfc4076" dependencies: - apollo-utilities "^1.0.0" + apollo-utilities "^1.0.2" apollo-client@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.0.2.tgz#f2b01898c404c867fc2bd8edf7c3ccded2b96fc6" + version "2.0.3" + resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.0.3.tgz#f99f32e2c851bbd52da1e1b113ce8f6a0cf94945" dependencies: "@types/zen-observable" "^0.5.3" - apollo-cache "^1.0.0" - apollo-link "1.0.0" - apollo-link-dedup "1.0.0" - apollo-utilities "^1.0.0" + apollo-cache "^1.0.1" + apollo-link "^1.0.0" + apollo-link-dedup "^1.0.0" + apollo-utilities "^1.0.2" symbol-observable "^1.0.2" zen-observable "^0.6.0" optionalDependencies: "@types/async" "2.0.45" -apollo-link-dedup@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.0.tgz#f0134ac495cc42e7e43dfafe7126645baa1e03bc" +apollo-link-dedup@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.2.tgz#bab659dde41f8dd627839142d4dad90e55251110" apollo-link-http@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.1.0.tgz#a85cc43d9a5286bb54ac32213f7a16bef3554ae4" + version "1.2.0" + resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.2.0.tgz#48464c2ebfa6474f7a89908696827d66b2deb5cc" -apollo-link@1.0.0, apollo-link@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.0.0.tgz#3d334285789c217f95712ebce434d56ce7f3e991" +apollo-link@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.0.3.tgz#759c36abeeb99e227eca45f919ee07fb8fee911e" dependencies: - apollo-utilities "^0.2.0-beta.0" + "@types/zen-observable" "0.5.3" + apollo-utilities "^1.0.0" zen-observable "^0.6.0" -apollo-utilities@^0.2.0-beta.0: - version "0.2.0-rc.3" - resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-0.2.0-rc.3.tgz#7bd93be0f587f20c5b46e21880272e305759fdc2" - -apollo-utilities@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.1.tgz#34b4df0bd6ed71d0afaa7c62489173dca5d07e92" +apollo-utilities@^1.0.0, apollo-utilities@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.2.tgz#bcf348a7e613e82e2624ddb5be2b9f6bf1259c6d" append-transform@^0.4.0: version "0.4.0" @@ -1857,11 +1854,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -graphql-anywhere@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.0.0.tgz#4cf7ae7ed93aabeb95d329caa08c3867ddaef45e" +graphql-anywhere@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.0.1.tgz#eb53ed5c56ef42e21d34dc22951e3da38f88a342" dependencies: - apollo-utilities "^1.0.0" + apollo-utilities "^1.0.2" graphql-tag@^2.5.0: version "2.5.0" @@ -2877,9 +2874,9 @@ methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -metro-bundler@^0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/metro-bundler/-/metro-bundler-0.20.0.tgz#a2faef20ba7f566484a6c5bd585f590f8640c183" +metro-bundler@^0.20.1: + version "0.20.3" + resolved "https://registry.yarnpkg.com/metro-bundler/-/metro-bundler-0.20.3.tgz#0ded01b64e8963117017b106f75b83cfc34f3656" dependencies: absolute-path "^0.0.0" async "^2.4.0" @@ -2913,7 +2910,8 @@ metro-bundler@^0.20.0: source-map "^0.5.6" temp "0.8.3" throat "^4.1.0" - uglify-es "^3.1.0" + uglify-es "^3.1.8" + wordwrap "^1.0.0" write-file-atomic "^1.2.0" xpipe "^1.0.5" @@ -2998,8 +2996,8 @@ minimist@~0.0.1: minimist "0.0.8" moment@^2.19.1: - version "2.19.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.1.tgz#56da1a2d1cbf01d38b7e1afc31c10bcfa1929167" + version "2.19.2" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.2.tgz#8a7f774c95a64550b4c7ebd496683908f9419dbe" morgan@~1.6.1: version "1.6.1" @@ -3526,8 +3524,8 @@ rc@^1.1.7: strip-json-comments "~2.0.1" react-apollo@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-2.0.0.tgz#c9cbda2956585d422800f1686d870258637170f8" + version "2.0.1" + resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-2.0.1.tgz#43997db9f294d81bd229eb705944fb36d5164607" dependencies: apollo-link "^1.0.0" hoist-non-react-statics "^2.2.0" @@ -3552,8 +3550,8 @@ react-devtools-core@^2.5.0: ws "^2.0.3" react-dom@^16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.0.0.tgz#9cc3079c3dcd70d4c6e01b84aab2a7e34c303f58" + version "16.1.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.1.1.tgz#b2e331b6d752faf1a2d31399969399a41d8d45f8" dependencies: fbjs "^0.8.16" loose-envify "^1.1.0" @@ -3564,9 +3562,9 @@ react-native-confetti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/react-native-confetti/-/react-native-confetti-0.0.6.tgz#a505e4e5a23bcb2cf554ba51362dfaf3ac17a100" -react-native-config@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/react-native-config/-/react-native-config-0.9.0.tgz#5a82874a2f75a44c3c421e03d8910228f17cea35" +react-native-config@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/react-native-config/-/react-native-config-0.10.0.tgz#7ecabfcdc5f8fe34ba42b56b043626eb72d232fe" react-native-dismiss-keyboard@1.0.0: version "1.0.0" @@ -3637,9 +3635,9 @@ react-native-vector-icons@~4.4.2: prop-types "^15.5.10" yargs "^8.0.2" -react-native@0.50.1: - version "0.50.1" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.50.1.tgz#3d8bb7c96dd3151788e795a22155d305f15abfd1" +react-native@0.50.3: + version "0.50.3" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.50.3.tgz#91282bd5356cc7d794969cdc443cc764389b9af4" dependencies: absolute-path "^0.0.0" art "^0.10.0" @@ -3667,7 +3665,7 @@ react-native@0.50.1: graceful-fs "^4.1.3" inquirer "^3.0.6" lodash "^4.16.6" - metro-bundler "^0.20.0" + metro-bundler "^0.20.1" mime "^1.3.4" minimist "^1.2.0" mkdirp "^0.5.1" @@ -3724,12 +3722,13 @@ react-redux@^5.0.6: loose-envify "^1.1.0" prop-types "^15.5.10" -react-test-renderer@16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.0.0.tgz#9fe7b8308f2f71f29fc356d4102086f131c9cb15" +react-test-renderer@16.1.1: + version "16.1.1" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.1.1.tgz#a05184688d564be799f212449262525d1e350537" dependencies: fbjs "^0.8.16" object-assign "^4.1.1" + prop-types "^15.6.0" react-timer-mixin@^0.13.2, react-timer-mixin@^0.13.3: version "0.13.3" @@ -4399,8 +4398,8 @@ time-stamp@^1.0.0: resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" tipsi-stripe@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/tipsi-stripe/-/tipsi-stripe-4.1.0.tgz#ed3b151fdbd6ca846f3e4c2bca193f71328124ec" + version "4.1.2" + resolved "https://registry.yarnpkg.com/tipsi-stripe/-/tipsi-stripe-4.1.2.tgz#f0f09c838707c4a584a45c174961122cd55656b5" dependencies: prop-types "^15.5.10" @@ -4472,12 +4471,12 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" ua-parser-js@^0.7.9: - version "0.7.14" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.14.tgz#110d53fa4c3f326c121292bbeac904d2e03387ca" + version "0.7.17" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" -uglify-es@^3.1.0: - version "3.1.7" - resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.7.tgz#4994b6d7dee6ae0b05bd4fb5d18c9ae2023b6d58" +uglify-es@^3.1.8: + version "3.1.9" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.9.tgz#6c82df628ac9eb7af9c61fd70c744a084abe6161" dependencies: commander "~2.11.0" source-map "~0.6.1" @@ -4646,14 +4645,14 @@ wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" +wordwrap@^1.0.0, wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - worker-farm@^1.3.1: version "1.5.0" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.0.tgz#adfdf0cd40581465ed0a1f648f9735722afd5c8d" From f65f29a0f31f8dbac6b1dad22d11b19c0c962c3c Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Sat, 18 Nov 2017 18:07:43 +0100 Subject: [PATCH 21/27] EventList: Fix section header padding on android --- src/modules/events/EventList.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/modules/events/EventList.js b/src/modules/events/EventList.js index 8c448cc..93423fd 100644 --- a/src/modules/events/EventList.js +++ b/src/modules/events/EventList.js @@ -1,4 +1,4 @@ -import {StyleSheet, View, SectionList} from "react-native"; +import {StyleSheet, View, SectionList, Platform} from "react-native"; import {Card, ListItem, CardItem, Body, Text as Text, Left, Right, Icon, Button, Content, Spinner} from 'native-base'; import React, { Component } from 'react'; import moment from "moment"; @@ -94,7 +94,10 @@ const styles = StyleSheet.create({ sectionHeader: { backgroundColor: 'white', marginLeft: 0, - marginBottom: -8, + ...Platform.select({ + 'ios': {marginBottom: -8}, + 'android': {marginBottom: -4} + }), paddingBottom: 0, borderBottomWidth: 0, }, From d4b81ff8e85db9b4990be643c7d10824d7e054cc Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Sat, 18 Nov 2017 18:54:16 +0100 Subject: [PATCH 22/27] Proof: Prevent charge if no membershiptype --- src/modules/membership/Membership.js | 8 ++++++++ src/modules/membership/MembershipContainer.js | 6 +++++- src/modules/membership/Proof.js | 2 +- src/modules/membership/ProofContainer.js | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/modules/membership/Membership.js b/src/modules/membership/Membership.js index 3454958..a24cf2c 100644 --- a/src/modules/membership/Membership.js +++ b/src/modules/membership/Membership.js @@ -4,6 +4,14 @@ import {Button, Text as NBText} from "native-base"; import theme from "../../theme"; export default class Membership extends Component { render() { + if (this.props.isFetchingUserData) { + return ( + + + + ); + } + return ( diff --git a/src/modules/membership/MembershipContainer.js b/src/modules/membership/MembershipContainer.js index 8a4b2ff..fae9bf5 100644 --- a/src/modules/membership/MembershipContainer.js +++ b/src/modules/membership/MembershipContainer.js @@ -62,7 +62,11 @@ class MembershipContainer extends Component { onLogoutPress={this.onLogoutPress} />; } - return ; + return ; } } diff --git a/src/modules/membership/Proof.js b/src/modules/membership/Proof.js index 0a40a50..edf4e1b 100644 --- a/src/modules/membership/Proof.js +++ b/src/modules/membership/Proof.js @@ -88,7 +88,7 @@ export default class Proof extends Component {