diff --git a/.env.sample b/.env.sample index 68e50ae..6b1bff5 100644 --- a/.env.sample +++ b/.env.sample @@ -1,8 +1,8 @@ -REACT_APP_FIREBASE_API_KEY= -REACT_APP_DEV_AUTH_DOMAIN=.firebaseapp.com -REACT_APP_DEV_DATABASE_URL=https://.firebaseio.com -REACT_APP_DEV_PROJECT_ID= -REACT_APP_DEV_STORAGE_BUCKET=.appspot.com -REACT_APP_DEV_MESSAGING_SENDER_ID=############ +GATSBY_FIREBASE_API_KEY= +GATSBY_DEV_AUTH_DOMAIN=.firebaseapp.com +GATSBY_DEV_DATABASE_URL=https://.firebaseio.com +GATSBY_DEV_PROJECT_ID= +GATSBY_DEV_STORAGE_BUCKET=.appspot.com +GATSBY_DEV_MESSAGING_SENDER_ID=############ -REACT_APP_CONFIRMATION_EMAIL_REDIRECT=https://.firebaseapp.com \ No newline at end of file +GATSBY_CONFIRMATION_EMAIL_REDIRECT=https://.firebaseapp.com \ No newline at end of file diff --git a/.firebase/hosting.YnVpbGQ.cache b/.firebase/hosting.YnVpbGQ.cache index 544d2e3..c55c1da 100644 --- a/.firebase/hosting.YnVpbGQ.cache +++ b/.firebase/hosting.YnVpbGQ.cache @@ -1,17 +1,17 @@ asset-manifest.json,1556898463490,f723129505a2111ca263ef5479bd10b1f0efc470c951b596f13dcf48d8649c7e -index.html,1556898463490,d2791f63e8652b46a6a92df716e200ef6670799c079df85344ad44c0732a0338 -precache-manifest.a096a268b779b4480b9a46727f75551b.js,1556898463490,3ee2e9cfd0185210ebe9c8fe3dd342b86254c667c2e9b51369438728c9f7e324 manifest.json,1555998067072,20792c911b58103a520ddb6b0f7bcc7ce3bceaa15480cbfd913f8b3620864341 +precache-manifest.a096a268b779b4480b9a46727f75551b.js,1556898463490,3ee2e9cfd0185210ebe9c8fe3dd342b86254c667c2e9b51369438728c9f7e324 +index.html,1556898463490,d2791f63e8652b46a6a92df716e200ef6670799c079df85344ad44c0732a0338 icon.png,1555998067072,40bb863e95a5ea2c01be6eba0beb6801183746f99d40eb393a6b4776a11d8636 service-worker.js,1556898463490,de05f8df6933f0d1ff232f36ce73e94b0faafe0ac3ce9882fbbacc7fc608fc2d +static/css/main.1716334c.chunk.css,1556898463519,dadd472a021e6f3502d58df7b11455a233a9a25f87ce536e693c18db20036e09 reactfavicon.ico,1555998067072,b72f7455f00e4e58792d2bca892abb068e2213838c0316d6b7a0d6d16acd1955 static/css/main.1716334c.chunk.css.map,1556898463519,c50d028b9046b1664c1a246227bee082eaf7a5f46f8857aad8963283c298dacd -static/css/main.1716334c.chunk.css,1556898463519,dadd472a021e6f3502d58df7b11455a233a9a25f87ce536e693c18db20036e09 -favicon.ico,1555998067071,229055d54fe1f70f3d835e9d723ea2fef78f2af82ed7ce45efa2f4623c1c1131 static/js/runtime~main.a8a9905a.js,1556898463519,e1af5f94fdd13901b2e433d0d7607e27c01458151c35b1fe4b7feda2a32b7aa9 -static/js/runtime~main.a8a9905a.js.map,1556898463519,c337bf8b58896da637a6e50ab8cfc779eb1ec42c55f8ec429030a03454a549db -static/js/main.a10ab5ea.chunk.js,1556898463491,04608cac454dbaa153b80f00064f3cb33edc8aad4a2710d56a385fd8e86a3bc5 splash.png,1555998067072,e06cb28b9a2a8275ce53eb5eead2851f684f537a6a30f0f0bf360b8813fa273f +favicon.ico,1555998067071,229055d54fe1f70f3d835e9d723ea2fef78f2af82ed7ce45efa2f4623c1c1131 +static/js/main.a10ab5ea.chunk.js,1556898463491,04608cac454dbaa153b80f00064f3cb33edc8aad4a2710d56a385fd8e86a3bc5 +static/js/runtime~main.a8a9905a.js.map,1556898463519,c337bf8b58896da637a6e50ab8cfc779eb1ec42c55f8ec429030a03454a549db static/js/main.a10ab5ea.chunk.js.map,1556898463521,777ecf9469d772313dec6ecc4b5d7de7425b13cf8529747c21e02254c9251081 static/js/2.3f4eb03d.chunk.js,1556898463520,47a71ca572b94638afd405721c3ef6fb4aef5962dd0db71eb6ff9f284be1cd48 static/js/2.3f4eb03d.chunk.js.map,1556898463521,79d34370558394348a525ac8b13043f85a4b8ba81ecc94a4d7ed54ebb1b33bcd diff --git a/.firebase/hosting.cHVibGlj.cache b/.firebase/hosting.cHVibGlj.cache new file mode 100644 index 0000000..cd29dc8 --- /dev/null +++ b/.firebase/hosting.cHVibGlj.cache @@ -0,0 +1,259 @@ +1-e637d8c9742134eeed9a.js,1559191150475,d773519988e3ed95001136377d9c3daa0bb66c8d05ad1b6348505b438faff072 +chunk-map.json,1559191150480,fb1fd11cd2955b8a5626d470cba151ba68735df822ef21977fcb5360452650f1 +component---node-modules-gatsby-plugin-offline-app-shell-js-4df7b9cc57a68e118679.js,1557813278931,48f5df7bf9940bc34de5a07796f504ae7e8a4e4a136f55a628b54d6c92a99783 +component---node-modules-gatsby-plugin-offline-app-shell-js-4df7b9cc57a68e118679.js.map,1557813278929,8ef60e63ba5ad56d598db9b9298f5fa24bb065225193f09dca53153f86fa641b +component---node-modules-gatsby-plugin-offline-app-shell-js-87b2b9037874577fa624.js,1557877612117,776c67e827973c39d9add084f5c602205ba3c449bb422f7a1c5f97144de5ab01 +component---node-modules-gatsby-plugin-offline-app-shell-js-87b2b9037874577fa624.js.map,1557877612117,2e1b8f7c386954b6f07f838e8947423f111a4ad3dff3e62af544862b3c13e867 +component---node-modules-gatsby-plugin-offline-app-shell-js-987953a5e480edd8b12e.js,1559191150475,b8e5cb85d96d4eca56929f940371b51c4239360d905d13c54ecda25bb2c496be +component---node-modules-gatsby-plugin-offline-app-shell-js-987953a5e480edd8b12e.js.map,1559191150475,d8c9fe7ad0dd182449f3ab560c7f9fd26e1fe8ea9e7978579304f6519bc5da0f +component---node-modules-gatsby-plugin-offline-app-shell-js-a5adf491a4b51b678ab4.js,1557813216313,e6f7d784763351c637ca695438635900ede18ddf16b66a4bc225f16423cb042f +12-621a4fab8181238d89d1.js,1559191150474,060b1f5b0e3a304782b0cff43acec7d12913fdb26076dc7081b0fd196b8fecbd +6-7cd46754f59c438121c6.js,1557809399806,424f2cee551dec444421bb78ae3b4533c2151c4b68f919618663f188fa187207 +7-48de5896cc12a0770376.js,1557811597005,a8c0867f17831389f02aee5a07ed13156325d2e2392a711e1c2a5e3476878344 +7-5ac312645a29bf1fdd6e.js,1557813216311,ed6c365c5b1751de24bdb5e38e5484cef38487ed81c63fbda8c626ac989b6222 +7-6e2f1d702590008337ab.js,1557877612116,89244d69b84a3af3042427da487981d5b0caac814f01ab1d3fb354963f636d18 +component---node-modules-gatsby-plugin-offline-app-shell-js-a5adf491a4b51b678ab4.js.map,1557813216313,63dd693cee3393293c73a004c41eae51f56e1c429e0379e9bb46880d403ca96a +component---src-pages-app-js-11514e76c0925398c882.js,1557811909955,a7c3e7b7b5cf57e88aebd17ee39372e8a1370e9d14fc95a1ab44d1004626af0e +component---src-pages-app-js-16fe4e3d65cc37c78c96.js,1557809399807,b1e5d4565eca9b861dd1f2da45d174d70e044f7da6014e2137f2b3ef2b2b3364 +component---src-pages-app-js-64bfe6508afc2cd91848.js,1557810051653,8e1c2b557e6cadb78f9c44518a4fcaed1dbe394634258bd4d560b94d2f7383b7 +0-7ff3ca7547845a6eef79.js,1557811597004,c0936b373315e803a5e622b6473ac8261940d765a55c9a086017b83016c746f8 +0-9f9a6583e4c048f127d3.js,1557877612116,dfdcfefa102a72ee16c3592c9ac93d92de025bd676d543c5e4b50c3d9d55e8c3 +0-ab041ef2e6d4095125c2.js,1559191150474,dd97c5b802bfbe89a6b6c23cd5ee7dba7ca95784d4de31d1e851b817d8edd1da +component---src-pages-app-js-7b489f7de785c20384cb.js,1559191150474,0bdae9aeec4f420b96a9ea3b3cde3da4af168a431ddd60199e50465c4f52ad0d +0-1d5e926418bee134ae0c.js,1557813216311,8af847ec9607f090f98defb7769e4d95a30df93d81c72c5055cf3d2a5c11b821 +0-3920b011ae88884f1e53.js,1557811909954,f7dabbe23155a95b0ab3bf6407520b2b31cbf8f75235ce3a746d96337fbe65f6 +0-de6d673a626f526f2349.js,1557809399806,a7576b62a4d4b153353783d83631ddd2d96d5ebb0d0506c4e64c9b4f9a8ce3a1 +component---src-pages-app-js-91da5dd68de736a15f66.js,1557877612118,b93126fd53acf1f24edd6bb0cf38e468d05ddf9e2c898117b9030b618df761b9 +component---src-pages-app-js-92fe68136ca22600651c.js,1557813216312,8ca1d90b2b578f532ef57585885a8a93560be02a7dc9d91d7a8653790f174315 +1-e637d8c9742134eeed9a.js.map,1559191150475,403f871d4eb99079539771d0f86cdef38557bc425b3c282ab5ecdb704e37658f +component---src-pages-app-js-121b0cd7c31a75bd0edd.js,1557813278929,c447094dee450c5c2c70f14bc66d1a5cad61d738ca49a97b88e257e1e7ff0215 +component---src-pages-app-js-11514e76c0925398c882.js.map,1557811909955,8e69424910b314123d7f0b32d92d075195f23d66f768c25c0bc16ef32d8750fe +component---src-pages-app-js-16fe4e3d65cc37c78c96.js.map,1557809399807,eb7a85a5825ed52210c195f8f609eece01eee90ea74ebd419e25791d6bab5b7a +component---src-pages-app-js-121b0cd7c31a75bd0edd.js.map,1557813278929,06fd1d0564287da0da7d70b5ce3b11f91970b69302a432cb38da12a2e6a3692b +component---src-pages-app-js-64bfe6508afc2cd91848.js.map,1557810051652,86417b73a0ddb1f7f22eb1139a28ecb7d41b633eef45c3795ef3d3e83b23a771 +component---src-pages-app-js-a76fdea18f43b1a178f5.js,1557811597005,ecc4000202fc3dcd1be338c93a6fbd6a8b8369c231a055a867ad4cda1c90254d +component---src-pages-app-js-af1366e225e5376a01fb.js,1557811050241,3d6a830876df721ff19a6789e8850a153e8748f30e1d2574b9aac8af16a533b9 +component---src-pages-app-js-bdc761eeb8883dcaf92a.js,1557810007758,39945b55212c034bfe05a87e5619ba249bc80fc4cc203cd1b5f7ad5fba302b21 +component---src-pages-app-js-d107a6e61077ad7586d3.js,1557811141801,b3231eebfbe19c9e918e52c1e54587645a679cc0549e1358e5a1ecd274d06d99 +component---src-pages-app-js-7b489f7de785c20384cb.js.map,1559191150475,0a7dfec8297e82a6f1072966b83ab02f298414e1ad24af38bda507a8a054c4db +component---src-pages-app-js-91da5dd68de736a15f66.js.map,1557877612117,aaac7290461de3d087be8f25db73a4ea39e267870901973e931950aa12763037 +7-c42318b2b0377cf8e28a.js,1557813278929,4ead356810f3595119dcc428684f173a25bf918690baa215a8d58acc93b2b93a +component---src-pages-index-js-33762b085d58d5b79183.js,1557811909954,a2e057f2537b951ae8c8c6c71d959bfce16c8ca161d92ea76cf2bda5ce1a3fd3 +component---src-pages-index-js-33762b085d58d5b79183.js.map,1557811909955,a7cc6e27f9fb25aea07404619c2c23e0a0b1749a71e4b11b5482db5acd3d0f11 +component---src-pages-index-js-3ede77932f1232b52454.js,1557811597004,dd98bbb30c6f71d26b022ddbe84ec667c4a10b8164f131b46b79d637b933c6ef +component---src-pages-app-js-92fe68136ca22600651c.js.map,1557813216312,8a492143fd955d1876ba4d150e6a4becaef61689f2d30ee6b71db2a6337d9665 +component---src-pages-index-js-3ede77932f1232b52454.js.map,1557811597005,d602dfb5969134a90f1f2db2f983d38788e126cb2e824eca7a16ccb1888bddeb +12-621a4fab8181238d89d1.js.map,1559191150476,9bb09fa12dc8f1ad3ef95cf955afb10d4d1f742fa6befce7dac0d934aea24fac +component---src-pages-index-js-6438e06fb1d67b4e3708.js,1557809399807,149bc70e32c37609c5f07e52a8794c190b0847e1ca2039f18d8b13ee4e73358e +component---src-pages-app-js-a76fdea18f43b1a178f5.js.map,1557811597005,77d87689cf8d8d28223457a71a13fbb695dcb8250725b53c0fe653c549bb970f +component---src-pages-app-js-af1366e225e5376a01fb.js.map,1557811050241,a487d92a97bbc142b9e650a76a0a8f86578916a4f1eb3c91728356b1169678fe +component---src-pages-app-js-bdc761eeb8883dcaf92a.js.map,1557810007757,2e706f7d36cea5dcd091dbb5b8ea6245cab10c5b60d160c1073e99e95b78fd7b +component---src-pages-index-js-afd3974173a9f520ca8e.js,1557813278928,1830bc93b51dbb80c899a3851d954b55535f296927a706f00e482dc59592b3be +component---src-pages-index-js-afd3974173a9f520ca8e.js.map,1557813278931,f10a3d084249a23614177379cfa7905deccaf89e06348b3b5447745cf3b19627 +component---src-pages-index-js-6438e06fb1d67b4e3708.js.map,1557809399807,3272a2b613c4da0b44957c4144665e4e74aba875e49b8b1a7b590a68e55b08d4 +component---src-pages-index-js-73ba9f81d523e25221d8.js,1559191150474,314fcd639ace8093e39b187094f17c2a160dcf64047f6b176ebca4994a530544 +component---src-pages-app-js-d107a6e61077ad7586d3.js.map,1557811141801,8ad10232fdc319ca7dae6f817d0526bd6aa0445f2d4bcfceaaffa72553c398df +0-ffd58bca1c1d419808cb.js,1557813278928,bcae49aae328a5d854849040795b4bea811ce3308abed67f765b4d9dc81d16f3 +component---src-pages-index-js-b5c05671b8f1e94dbf09.js,1557813216311,e6f0c7dd39f4c9270b2866ada671f692783b2968a918f22841e6b5c444f6ae92 +component---src-pages-index-js-b5c05671b8f1e94dbf09.js.map,1557813216312,5469666e0b0203652d87896f84bd025cd0385a8123f7aa42ef1e3fa4224108dc +component---src-pages-index-js-eff01f6896a59a2d7c53.js,1557877612116,b2085ca07625d8ce9e6990aee305f484da7db76779f227625b7cb34252ca48ba +component---src-pages-index-js-eff01f6896a59a2d7c53.js.map,1557877612117,0d03ece318a95d2acd1d9c002a9603bd477227cce722c6012912cd6f49f0a978 +component---src-pages-login-js-2bd423148f09d42974a8.js,1559191150474,a7bc7ee356a571edaaeea234c04df8ad72b30aa3f78197b53cefbfd7cb597cd6 +component---src-pages-login-js-2bd423148f09d42974a8.js.map,1559191150475,aef8c24e6439eb0b0bf8651f523bb4d28959321e20c0d9f6318816bba114c26c +component---src-pages-privacy-js-7455142186b1fb391cfb.js,1559191150474,1c50ad66ebbe295ee6ade1e1710e6f1dfdc2f2a318c60f128248794b97884ed1 +component---src-pages-privacy-js-7455142186b1fb391cfb.js.map,1559191150475,38d500f6151173acb4caa8482ee1139c4ba7d7017f2bd49c9b2c0de1baf7f8f6 +component---src-pages-register-js-807ae98fc7ee9ce582ce.js,1559191150474,c6d2ffad67d4bff8cd74a9f32efe334cc10c67699dc4e4eb59697fcce2d18824 +component---src-pages-register-js-807ae98fc7ee9ce582ce.js.map,1559191150476,a83be1b0fe237dc89949c5f79f6a60380e09f8fc060881d6df15b55efc6005b0 +component---src-pages-terms-js-b061df86d1349e23ef0f.js,1559191150474,714a7b2f5ed732ee120d4f567e647d9bd6edb24654754f1cd6be79bfa8ef7c9f +component---src-pages-terms-js-b061df86d1349e23ef0f.js.map,1559191150475,9fa6ceedcbe9d779c26613ecbb6a899641d9f3da44eda88c6260ef887eb084a5 +component---src-pages-index-js-73ba9f81d523e25221d8.js.map,1559191150475,cbaf4270f052d4c2744daac7293d6ea612174f4911294210a5d46c63b071aa5a +favicon.ico,1555998067071,229055d54fe1f70f3d835e9d723ea2fef78f2af82ed7ce45efa2f4623c1c1131 +icon.png,1555998067072,40bb863e95a5ea2c01be6eba0beb6801183746f99d40eb393a6b4776a11d8636 +idb-keyval-iife.min.js,1559191154709,9c4125183adfe3e08e424eed0f3f811c0c512af9ce287ab17b375656a0a4873c +index.html,1559191154665,74de5c7e94e5f0799822a0b9e3f354dde5e19df734efbd7dbd67c9284264f0fb +manifest.json,1555998067072,20792c911b58103a520ddb6b0f7bcc7ce3bceaa15480cbfd913f8b3620864341 +manifest.webmanifest,1559191135607,ca070aceb9b306afe6b908b63b264a7356955552172c49bdf58805050c0a013e +pages-manifest-121566f92b19b2952737.js,1559191150474,bf7e19860670a6dccca494c61ec0405ab80e5182bb676f4e14a9c451befd83aa +pages-manifest-121566f92b19b2952737.js.map,1559191150475,487251b34a7371d969facd05520f2a2ab81c4e2d93b3eeeeed60a227723208c7 +0-ffd58bca1c1d419808cb.js.map,1557813278929,bbe47b2a02fe210665ace9744b05ef02649b64bbf7f927b0598d62d6eef345e5 +pages-manifest-3ceff0312593811de18d.js,1557813216311,f139e9f032774fa0af2a3cb80e7f0ef99df619ca6e8ef8c07406d4f9e3ec211f +pages-manifest-3ceff0312593811de18d.js.map,1557813216312,a784318fdede6f5673debd63195401650400424e1f79c10b9c38dc24e2c378e9 +pages-manifest-81118a764c3e6e30d44a.js,1557809399806,4bbe7147c22b8cad92ce5d0e8af6be61467d7e34cf1735b836a43908450b534a +pages-manifest-81118a764c3e6e30d44a.js.map,1557809399807,6f30bde9776e193d6a6af1ea806fbe9f71490fb67bd889a94a700da0b25fcb04 +pages-manifest-8509e70eda082230a7ba.js,1557811909954,10563ffe7ad63205e8b2ba40ade8a8396249bee0cd53f1ed0274cae6a677bb1c +pages-manifest-8509e70eda082230a7ba.js.map,1557811909955,4fee75d4ff2ff9df7a0e1d9d6c3aee60ef06d2e77165977857f5400e07901471 +7-c42318b2b0377cf8e28a.js.map,1557813278930,e770d051445bf67785537e9f87183c85a044d1d600df05a7e709038b9cf616e4 +pages-manifest-aa19bb1317098ff68e7e.js,1557813278928,fd25d37d6bedb33c6b08ff39bbb85ae10289045004c7b059e9f74f3b4f696a21 +pages-manifest-aa19bb1317098ff68e7e.js.map,1557813278930,4b13daa2f616df52d3b638fb802c351cf81c2df55c1b8d51648d13ce0488f6f3 +pages-manifest-e2ee64996c474b49ea09.js,1557877612116,acd632ec43db64084c9b8ffaf5e2ef51e0b61e311e7fd981ba8d09650452614b +pages-manifest-e2ee64996c474b49ea09.js.map,1557877612117,68fb144a220a193ebf11535b23e9084e670fd905dfd779347f4c5856123abb1b +6-7cd46754f59c438121c6.js.map,1557809399807,98f28a349454c079d7ebbfb78771634f52c4f6ffec47f2d29ddacbf5d4d02ba6 +reactfavicon.ico,1555998067072,b72f7455f00e4e58792d2bca892abb068e2213838c0316d6b7a0d6d16acd1955 +sw.js,1559191154742,4ac5f3e5e281ed35452daa0e1d8b8d9b20fde6b280edf5549e234e9f139df568 +splash.png,1555998067072,e06cb28b9a2a8275ce53eb5eead2851f684f537a6a30f0f0bf360b8813fa273f +webpack-runtime-16d3d5c6c8f562bea7bb.js,1557877612116,d51a0fba8c8ffebcc257da377f022360c37134a3b94d7722c5aabd4a646fc248 +webpack-runtime-16d3d5c6c8f562bea7bb.js.map,1557877612117,fb08c32ecebf8a5f824862e39be3d2afb9f9873392048fc119d3316ac19cfe9c +webpack-runtime-232977f20ebd1288102f.js,1557811597004,34b5958fd4171f2ea2eccd9d47379436ebf4bb2921f7aad01e5e7bf72c3a0438 +webpack-runtime-232977f20ebd1288102f.js.map,1557811597006,f77ce094ad617f99ff2ded5c86d442c74b5c4eaafe4b6a291b273ddf891aa377 +webpack-runtime-3bbe49222b61394661af.js,1557810051651,1da6d945c59c54b3c140ec0706b1c62f0346854ca7754e0808d650c618325c32 +0-9f9a6583e4c048f127d3.js.map,1557877612116,1d3027ae5649795eee4fe684395ba8e341f50cfc658a1dea627779fae452852f +webpack-runtime-3bbe49222b61394661af.js.map,1557810051652,33bd5e7eb44b28d505ecd97f83d7f496caa2ca2cb0288147ea4fd77b7671a6b7 +7-5ac312645a29bf1fdd6e.js.map,1557813216313,6e0ef24b1ec1c56454cadf4c46fe13520636868a179481a64a38514c93a0083c +webpack-runtime-71b1de03f480e8a05b86.js,1557813278928,75e01d5f87df1a9176f52448edd9de0e7e8192438f62101866291fff6b98f6ae +webpack-runtime-71b1de03f480e8a05b86.js.map,1557813278929,1c201fa72239a89d4695bbf362bd70653158fadcfceca260ddcee0702fde5fa6 +webpack-runtime-730f869f42b97ecf0111.js,1557809399806,348e3496f5d3c7f62197522c1a66d17c1fa341578d7a4c4be77160f67b4d4343 +webpack-runtime-730f869f42b97ecf0111.js.map,1557809399807,629ad7214e8fb9cebb6bac1f5ebe674243703a29300026d553f367cc11e2cb22 +webpack-runtime-87a76d3c03698d51092c.js,1559191150474,6c899d0e0d103d1b8e50121c70c06da8672a9747e2ffe331e9b2972e95ddb4e3 +webpack-runtime-87a76d3c03698d51092c.js.map,1559191150476,3ec44450f02d9b3229f28ad55bd8f9d221fe06f2200b3cd9b76dfb9fe0cb6dda +webpack-runtime-90cd096772b6aa22a87e.js,1557813216311,da1ea42c05fa0b95f66d9d058f673ac98f7c396065c8623392f02da949bc65cb +webpack-runtime-90cd096772b6aa22a87e.js.map,1557813216312,d958be870d9edea0fa0dbb8f75322c60a5ac59443c1db7c8d3d02d26925233cc +webpack-runtime-9ab98137c8d259164d47.js,1557811909955,f69a4381fba54866917cec54e1bc5ecf652674df36cc361ed9b3d0a40c459660 +webpack-runtime-9ab98137c8d259164d47.js.map,1557811909955,d53efc503817af7dda11ab5627fdd1fa0707ac38cbfd928661605a001da3a1d5 +webpack-runtime-b67f32eecccd6f4df46a.js,1557811050241,ad0561ae294e6798427ea0ab19bd35a0c218b35758a6a771292fbbf1522acd45 +7-6e2f1d702590008337ab.js.map,1557877612117,7b9471190ece31effc7f2b5152654bd366350b75d56ff559849838ce3f10219b +webpack-runtime-b67f32eecccd6f4df46a.js.map,1557811050241,21f2836575f163fb393f8e5d84bdc84ae70d8bf04f4477182d8c4258d4b642b7 +webpack-runtime-bc44a0a762f560bf5409.js,1557811141799,24e2349a4f5007de1d12713681eba0abab7e820a391078d5bf79d94d395cd142 +webpack-runtime-fbc6a54768345aa362a9.js,1557810007756,5d99469d4243a82bb4ffd275016ee20e51a67e72c751c5720be30500b80199f6 +webpack-runtime-bc44a0a762f560bf5409.js.map,1557811141801,296d7901183e1fa2114d4f0496b17c21266f4909f92198658356697554fdf46a +webpack-runtime-fbc6a54768345aa362a9.js.map,1557810007757,b949e1b3c207244a1fb6848f2569d63b47755e0e8addab8be95e82a5a8665976 +webpack.stats.json,1559191150481,1d89aacd1d82bfd41bb10491bffbb145c16e62e76c89c6681efc95e2155c4624 +0-ab041ef2e6d4095125c2.js.map,1559191150474,9f8580210a0589b8a0441f2f48d419bb99b4d8917745dbcc5ba311c91cc34882 +app/index.html,1559191154665,729c7d09effe5857e14880dee28ed047ce3007f55fbe45d858ec3f10800e9e4f +0-de6d673a626f526f2349.js.map,1557809399808,21d12e191499dc0b0b89acace0d0dad2029e3158e727bb0f1d81f1809f7ae280 +icons/icon-144x144.png,1559191135548,b15ffb4ec2a0a0c3b94fec11ee0eb9c979bce08539e6d2643955c0a79253f858 +icons/icon-192x192.png,1559191135564,bb1c5ddc47a848a01393c61fa518ea870f852c92ccc779e9dcbd86c85e2a74aa +0-7ff3ca7547845a6eef79.js.map,1557811597005,6606b3d016eb59cc84d29abbe412bd0df2bce0c58b7b943fdec5b141e304af00 +icons/icon-48x48.png,1559191135527,e6f681244044cc32ddbdd5475113e6c69b1b897c82ca86fdbe99ef8bc7734be7 +icons/icon-512x512.png,1559191135576,2c57aa583e667577bb1895d8b7c1d0d8894645aa1336576718ca26449fd5d02a +icons/icon-72x72.png,1559191135536,aba2399ff54f53ec86eb6aaea94c56024b5590c549c71675f993f84ce30c931d +icons/icon-96x96.png,1559191135542,01a29c55127108c1cb649e568e0746f610828b910db0beacc925eadba64eacd0 +login/index.html,1559191154667,f48e485fc30ad9b0bf36a7941f4ae5c7da9e744a5ddf81061ac85e4c16dc9cb0 +google-fonts/s/montserrat/v13/JTURjIg1_i6t8kCHKm45_dJE3gnD-A.woff,1559184315809,daeb49428c9086a93fbd9fd5c4b788c1f609dd76e61a79eb6bb263414c41a2e9 +google-fonts/s/montserrat/v13/JTURjIg1_i6t8kCHKm45_dJE3gnD_g.woff2,1559184315896,ff876f7e3a23118dd4e74aedbe78472aa3316268aebee52ee408c96e60920cc1 +offline-plugin-app-shell-fallback/index.html,1559191154665,a28b87d8f4dd9e4dcae048b8fbc38fe278512e81e74d2deecf15e085f71c06d2 +privacy/index.html,1559191154668,72adb08ca4d0130448fb9986d24d323ee37e76b9ce960579347344de1646465f +google-fonts/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459WlhzQ.woff,1559184315994,2786ba68a3c0b7323ed9a5b5199435f3186c0677459edb68a58359d156fa52c1 +0-3920b011ae88884f1e53.js.map,1557811909955,ccd4e005310a5f7f37dcdcbfb78636b717f5f608462fa178741f9da59a6f343f +7-48de5896cc12a0770376.js.map,1557811597006,65389dfd7f9dfb8401d6a730ae2c29f9c6c7f98e521b6af80452f0a437efde88 +icons/icon-256x256.png,1559191135579,851415406ee67057fa625de5b6072bf0fb4b4e26c04bf65993de6c8bdd678382 +register/index.html,1559191154668,2d977d0dc7a0d07eebed5c414bf56d088b279da05357afa78096ae116f653cd6 +0-1d5e926418bee134ae0c.js.map,1557813216312,ca87eb43611e9432755bd51ffbdab2173a4ad4099cff7095fd2c0e24c73dd08c +static/84b155cbc6291cd983595a8bc1ba4360/1f686/landing-graphic-dark.png,1558210993774,3226c17652cb835baea5db1628b77d93b2810789cba0454cb20bf669aefb0490 +static/84b155cbc6291cd983595a8bc1ba4360/a79b5/landing-graphic-dark.png,1558210993799,4fd9ec33da04e98ebf840d453d2567f323adc933c41d9217110e56d856145b49 +static/84b155cbc6291cd983595a8bc1ba4360/af214/landing-graphic-dark.png,1558210993794,66909fa88ba86ff3d85973cca3f798c88bec847f62a39e0400b62e203cf99f83 +google-fonts/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459Wlhyw.woff2,1559184316101,fbd3baccdf94dd3595a3b259c5d917ebdd6508501b18d09bfb81cffd21b0f7c3 +static/8c1ce00c604ffec2de59d6b88ea38bf5/1f686/landing-graphic-light.png,1558210993702,4c443c2ab4cc2619a4a040529349194f1dedbbe383c818c4ba5eba60eef8d8c9 +icons/icon-384x384.png,1559191135604,351f5a1534c56febf22093d49eed3cbe35ecf63032bfdfe0cc777a43b30eefc7 +static/8c1ce00c604ffec2de59d6b88ea38bf5/a79b5/landing-graphic-light.png,1558210993716,1d743d97a5da0b16afd4dc9620d8f56e6ed2a5956b0da55b70079a54e82167dc +static/8c1ce00c604ffec2de59d6b88ea38bf5/af214/landing-graphic-light.png,1558210993716,35af3e55d7e54247e907d6a4ea576f03416d7b22df563ea0d54c0435297cf474 +static/d/1671509314.json,1558210681132,9bffff23084e1fa4827aaf8ada09e5c35255f45a7cc78390a157b85997905513 +static/d/3828651140.json,1559191135474,6cfb20d081a8779573c9f17d748692baa5fc50459facd9b785e2c879ce39bea8 +static/d/107/path---dev-404-page-5-f-9-fab-Oe6ArANhU8Vz5qTmGlUMUTGz0k.json,1557812561298,d73c632a5ce5b4f2a3660f396c3e9c864b4f3f91d6c37b799907ef64864f4fd8 +static/d/109/path---user-50-d-1f4-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1557791272922,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/140/path---index-6a9-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1559191135480,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/142/path---dev-404-page-5-f-9-fab-bfDVx85rKBSZKYobhh0xz8NXpN8.json,1558143810414,e173975cc9463a37680e56a0b7c346abac36c1d4d92f756790366e94511cc994 +static/d/156/path---dev-404-page-5-f-9-fab-0lHfmoILn29P5B3VzoKMRN0MGQ.json,1557812408750,ed41989158051bcf6c05c2627471057240158bc036f81cc4561f2655fa09d417 +static/d/256/path---app-user-2-f-0-9a2-EL1Va90kR4oqYPhXw5v5axaD3JQ.json,1557812404221,8d87d70b92fdb651f5428d9a53d1213f9956c477655b9ec5393fe5f74ed67c83 +app-895d651bee860628b349.js,1557811597004,802cca0a5571d08249597d7c15e22a5f18ad4ad6f884e9475cc08562d89afa81 +static/d/266/path---app-f-4-d-201-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1557794915702,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/274/path---dev-404-page-5-f-9-fab-g7SNJLoOWmRhQGZS7AT9qXVmis.json,1557960913927,ded6b64295f9bc0286c3afbbf2e43dea75630429517b601bb0acf9299129df9c +static/d/275/path---dev-404-page-5-f-9-fab-7lHBP7GsKlZkMPCTRxgKxLrkxBM.json,1557791394482,575176c53b51672ae3e669e3e2c88676647d4945d4ce637c1ba9b1abf56d7ffa +app-fb394d03a36f4752b604.js,1557809399806,49d83bbb318fa9f029d012879e9994634c4e4ac7aea60e668ce0729f023ea5bb +static/d/285/path---dev-404-page-5-f-9-fab-PpN8VPOAUwhi0z7MBHklrX1I.json,1559184316660,1a16a9eeacd5dab2ea68c50ce8fd503655c0ae403645605a6d3ebfa4560af33b +static/d/296/path---terms-8-c-4-c6a-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1559191135482,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/329/path---dev-404-page-5-f-9-fab-ypDXSKzc49eH9uf0n35qJvC7Zqo.json,1557585087142,4ed19f97246e3a4558314e3a2dc15bf718720d14380d985b27015f5e4924c9f9 +app-eadb88dc3e8f941f2ae9.js,1557813216312,ed2e35ad3dde974fe175460987912be736281fd672d22b2603a2738bcf7d0b0f +static/d/330/path---dev-404-page-5-f-9-fab-eOYp6h7SVMiZ3XWAglV9JDgWjCc.json,1557961609064,e4d04a5ac60cdf8242130174f8a908c3ce41009441ffed81d96e7c8948f645a3 +static/d/386/path---dev-404-page-5-f-9-fab-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1558210629760,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/403/path---user-00-d-0c4-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1557793005559,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/456/path---dev-404-page-5-f-9-fab-oq8bWxqDOoqJ57xcxUwyedhpfrQ.json,1558144315175,818197c97bfe0f373fdbbdb61330c4595294e78c36693962e6359936e3e39630 +static/d/482/path---year-30-b-72f-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1557791262554,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/511/path---privacy-4-ed-e67-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1557962570873,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/53/path---app-f-4-d-201-EL1Va90kR4oqYPhXw5v5axaD3JQ.json,1559191135480,8d87d70b92fdb651f5428d9a53d1213f9956c477655b9ec5393fe5f74ed67c83 +static/d/535/path---dev-404-page-5-f-9-fab-JZOWdQRbQwXKp05LLHAfc8WxTg.json,1557962570874,b10e7a36265a8e5bcf6e0328e85878f358105921e1eee8bb0c6cd6ded5f0b185 +static/d/543/path---login-829-9b2-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1558144315175,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/562/path---register-ab-5-675-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1559191135482,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/566/path---app-user-8-cc-07f-EL1Va90kR4oqYPhXw5v5axaD3JQ.json,1557812561297,8d87d70b92fdb651f5428d9a53d1213f9956c477655b9ec5393fe5f74ed67c83 +static/d/603/path---privacy-06-e-82f-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1559191135482,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/604/path---offline-plugin-app-shell-fallback-a-30-c5a-BawJvyh36KKFwbrWPg4a4aYuc8.json,1559191135481,56d9a0c519587d158bf2b14c3e85d85c5058fc2c417584d0aed283a32efe7c3c +static/d/66/path---dev-404-page-5-f-9-fab-tmTaVcQPdlVyr5nMFZ3AD2ZsnIQ.json,1558144324418,334d166a0ea0f86485684e01575fd9e1aae74ba7f6698e32e6b2479934d401cc +static/d/7/path---register-233-7b8-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1558144320503,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/710/path---dev-404-page-5-f-9-fab-0afLBjpmUk0liuixjBX4a6ggE.json,1557960918411,3839fd636684fcaa7c7cd26f445f4d9028dd7c772b12be48e890820af2c430a5 +static/d/750/path---dev-404-page-5-f-9-fab-KqGoYC24nNalnT08MydFwo8PN8.json,1557791262554,8608bb7fa02f6af4f181d5e2b8dfd5378c8dcfa82b35eec702fbd3911b415eda +app-fda3ed7d59bc2e65cbed.js,1559191150476,7610f92a7c8843a26880c54b21412476da0f72f82d26d5557776fef3c18780db +static/d/750/path---dev-404-page-5-f-9-fab-olHuxZO3hbLTEnU5n89Yy1aON0M.json,1558144320503,7c20fca2a82b18be6295c2099f390ec39dd64f28f29a059106cbe4d4c1909219 +static/d/754/path---terms-c-57-a14-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1557960913927,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +app-c7f161e371102bbd741c.js,1557877612118,648944d783a48ee240ad3a5c8ab0fb949976115aea0ff2cc1adf1acda6faca33 +static/d/776/path---dev-404-page-5-f-9-fab-nA29NXyrUxPizjd0q3r6q4UsXVQ.json,1557793409115,032ba8e508f5a5a287afa363786a8b627f2debaa014f3d6efa410957f23a12e8 +static/d/792/path---dev-404-page-5-f-9-fab-7spOoyDeLUxd48g5NTqrcPngVMw.json,1558144328419,884ac15a5d8505b779821497b4d0e98d5a7fce270e2952624158d2df7395812c +static/d/812/path---dev-404-page-5-f-9-fab-fdIM0MsRHSYfhFLvj6uTgXL93RA.json,1557791397877,22a2395e99b6a91e91517d55855511f32e08e3272809f149319fc7811a838d20 +static/d/829/path---dev-404-page-5-f-9-fab-o7af702RpOxvpRo1x1JR8NttFI.json,1557790335151,f4d17034ad75fb79d4df9cf46d875f09d1964c8d84637a8c5968425e61b55f62 +static/d/851/path---dev-404-page-5-f-9-fab-SiQrH1RpDdAQNsRvRvTTlCkTa9Q.json,1557812404221,9d4b15f1a4008cbbc7211ff3190db5809869bbff55b6022aaf032fd0e6bdffc6 +static/d/852/path---dev-404-page-5-f-9-fab-ckUv9SblqtFNnH2wT0VK4F8I.json,1557793401208,8a7c1d5486304983a72e629436ea85081baa09e7620c982290fee1078d5a13df +static/d/854/path---dev-404-page-5-f-9-fab-RYlGcedJe6I3R75B3YCt93ZfpRA.json,1557962577713,848c6ce156c02f20f3805b8767b82d133acd12dfac177a3a6ad717886ff6861c +static/d/86/path---dev-404-page-5-f-9-fab-pkUqVDZsKmlJGIKI1kXB5UaDw.json,1557793417755,b61656ca79670f8030e83735b63a7022a04d76e40c9c6668320706a5ad2c4ff7 +static/d/89/path---dev-404-page-5-f-9-fab-e0fJdkAO2HvW9LcacfoFl8DTXfI.json,1557959468569,2500e17b9026f43ec09d8f10c7371e82466b8f6eee8230b434131e83e8314f5a +static/d/936/path---year-8-dc-5b4-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1557793005559,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/944/path---login-557-29c-0SUcWyAf8ecbYDsMhQkEfPzV8.json,1559191135480,3c6f21270f201243aeb6103344b0c9b7fbcdfe7684d48ad45f54ef9c74287673 +static/d/953/path---dev-404-page-5-f-9-fab-XPHjMMR3cHucHYiNAKDAM1g22w.json,1557793005559,09290bbe063bcf24e0fa983cdb5708ec806fc4dd3b4fa896cdad938e5915a61a +static/d/970/path---dev-404-page-5-f-9-fab-avTDW6yAYqjQnpQf8FHK6Ay9OZs.json,1557791272922,2ffa3c1950ede19556cb5e12d87f8645fa7e8564ef43d8533c6d5338a52b03a1 +app-c5b938aeccd7fc80368e.js,1557810933019,2ef1cbf070eee83297a5cfd52657ada5aa32effea00af6b25f7f0bd56089e9a6 +terms/index.html,1559191154668,5ecf9f4b31e4795d759034aeef8cd292ee537a8ed8c03b2f8b18ffec9482d3e7 +workbox-v3.6.3/workbox-background-sync.dev.js,1559191154719,ac804438e84e5510f7af402494af59b8d3e366073e931a47585058c6ff2b6415 +workbox-v3.6.3/workbox-background-sync.prod.js,1559191154727,b500ff18680a9041f2e3a90166fb2cbc76ae34fcc4a7add25d9cf098bb83b800 +workbox-v3.6.3/workbox-background-sync.dev.js.map,1559191154719,00ee13919bc4d5f6d75cc4779cfea5c1cb8ae54528d05f35c1bf52da0687eeea +workbox-v3.6.3/workbox-background-sync.prod.js.map,1559191154719,e62a639ab7416db8a8aedebd1d70521de44b9282f0bbc686598789839ce7f9c7 +workbox-v3.6.3/workbox-broadcast-cache-update.dev.js,1559191154720,a82f9b92bc6364e6c19aef4061137baa5f0018b186095c5bb7c6b80d6c5dd80f +workbox-v3.6.3/workbox-broadcast-cache-update.dev.js.map,1559191154719,bcde8c74931fe0ce9d4c198665fcf64faf1ad1018c5d8f7606117139f72fb1fa +workbox-v3.6.3/workbox-broadcast-cache-update.prod.js,1559191154719,b573854c912b9327790d35b0b33150b620fb74b15ff2fbe592f9da1c258c2894 +workbox-v3.6.3/workbox-broadcast-cache-update.prod.js.map,1559191154720,a5c68b36e3ae09571e7162f2568520bf2575f6ab31d73aeb017f93e530d7089a +workbox-v3.6.3/workbox-cache-expiration.dev.js,1559191154719,48f75ddb3c9f2cd7d19d3d1315c5dede05a41e6f66b729edb396e3cb3b653709 +workbox-v3.6.3/workbox-cache-expiration.dev.js.map,1559191154719,d1f035224e4b6e46c68c9b94d9bbcd7e20f10714a8bb372e5b5dcc8c8bff0248 +workbox-v3.6.3/workbox-cache-expiration.prod.js,1559191154719,3099f5d0a38688d0192daba6a066fcf8f6872e0f828e8035d05d9c705fcf27e0 +workbox-v3.6.3/workbox-cache-expiration.prod.js.map,1559191154719,4748da4b302ce375413faff0aa145964bd851a1e756e0e507123326ad2cd32cc +workbox-v3.6.3/workbox-cacheable-response.dev.js,1559191154719,8e074782705c28c0b116946a027163ab9dc81f7a955330f4a23915c7d773e4d2 +workbox-v3.6.3/workbox-cacheable-response.dev.js.map,1559191154719,6baf8b5f9be8df30a29e568574cc70d55e26b725226d134736f5e9fe0db7039c +workbox-v3.6.3/workbox-cacheable-response.prod.js,1559191154719,02b3c02c3e4b172065cc363f549522a467f1193e8932fc1c73cb3ea96e6b43ce +workbox-v3.6.3/workbox-cacheable-response.prod.js.map,1559191154719,6a39e7c4d29693321d6a8aca0142638b33a4df779bca0d6264d97598c479defa +workbox-v3.6.3/workbox-core.prod.js,1559191154719,93ee32c25bf6a164429f1c5d6c82c0ca0b903bc19374ba11e427976c3b75f6b2 +workbox-v3.6.3/workbox-core.dev.js.map,1559191154719,8b2dd6c35646bcec6c0398334285ffc0b8988a9f4d128b4fc135a9eccc29c561 +workbox-v3.6.3/workbox-core.prod.js.map,1559191154719,9434c6eae79466484110e0feb20d76647b2992e35dddd2facf9b1fb9a87baa4b +workbox-v3.6.3/workbox-google-analytics.dev.js,1559191154719,8aa7efc7901a56a6eaba5e79e03ef600cf4506b1300cff7ff8ddb1cabe4c75ce +workbox-v3.6.3/workbox-google-analytics.dev.js.map,1559191154719,24eeb53b75980b683532c462a161d46f45f8e0ed06dde2e2e25cbabc37d9ee05 +workbox-v3.6.3/workbox-google-analytics.prod.js,1559191154719,7002e3236691685f59f38903a3077627ac780a3c8e68441e6580879d1af10ac4 +workbox-v3.6.3/workbox-google-analytics.prod.js.map,1559191154719,ab0982e5eb954127a5d56b72c90203072c0b392127c2397b871d0822daeab8ed +workbox-v3.6.3/workbox-navigation-preload.dev.js,1559191154719,b010c30a8487588d296e11c082fd9072593810abc1ee4abf810f6ce8fb703e54 +workbox-v3.6.3/workbox-navigation-preload.dev.js.map,1559191154719,8255c995f30096fa4f3dc33d5b7f0b9a127f5496b373b2efde57015faf3a3fb9 +workbox-v3.6.3/workbox-navigation-preload.prod.js,1559191154720,914ba19f33a24e0d3cca58281d1d22bc948b3136332756184c7497142773f751 +workbox-v3.6.3/workbox-core.dev.js,1559191154719,e97174cd772178c3f0d6d4cfaafd39fa2ee4da2789e09e5d98c02771c46178d9 +workbox-v3.6.3/workbox-navigation-preload.prod.js.map,1559191154719,94b8af64cf134df1196eac25dd95d614b5877be1147f374953c5978909b2e8ae +workbox-v3.6.3/workbox-precaching.dev.js.map,1559191154720,c765d71f4c125e1c8757a7017276e6df3f5dfd31d1fc598d4323d9780382b0e8 +workbox-v3.6.3/workbox-precaching.dev.js,1559191154720,3c0dc543e36cd60908d638d3805b6abe16df6be77e926657a44beccbf3f0f582 +workbox-v3.6.3/workbox-precaching.prod.js,1559191154720,474d3dcb24c8a1432f4cdd2b825193b63df6df9341a331553c415c2f834b02c7 +workbox-v3.6.3/workbox-precaching.prod.js.map,1559191154720,b9e82010a346e1a02ce1d9d3a7fe6087caec916490b8fea9fc0ce49157828846 +workbox-v3.6.3/workbox-range-requests.dev.js,1559191154720,11c6b6bbf381791984dff07de8a55f8cc6f4233b4f189266140193314f776a38 +workbox-v3.6.3/workbox-range-requests.dev.js.map,1559191154720,e4942562c7a00de4b4244d286763373cf084f8ce108bf48a9bc90ae98e3424e6 +workbox-v3.6.3/workbox-range-requests.prod.js,1559191154720,6c54ba842d1142ad630554cd43b716d0e1967779486d08db2c9055cbd98735a3 +workbox-v3.6.3/workbox-range-requests.prod.js.map,1559191154720,14934216d94d1709106833144eb0ea6d93038594d6435c39f7d30af5e7919d04 +workbox-v3.6.3/workbox-routing.dev.js,1559191154720,2c628cfbb0d319651064e7b3d2bac0937cfb6bfa4a0a125db38f32784c0b0796 +workbox-v3.6.3/workbox-routing.prod.js,1559191154720,21a3e3ec3bc1876aa28bc5002986bd0a286dc3d1dd7025d8d29dfced05bc6414 +workbox-v3.6.3/workbox-routing.dev.js.map,1559191154720,47456496d22cdcd260cb2fae01d832bb24c62be9af477872368fe1de5730b6a7 +workbox-v3.6.3/workbox-routing.prod.js.map,1559191154720,bb5aa00b3c144bbf42ca81cd089f2b52f623a9b015b8a5ca3be4e86e15fec7a8 +workbox-v3.6.3/workbox-strategies.dev.js,1559191154720,dc7656e0bc31e36c5a216732ed5dd69612a2591e281e3271af265bfd27afe916 +workbox-v3.6.3/workbox-strategies.dev.js.map,1559191154721,4b930ea0b0ce1c979e0233fba40a0ed7587c5cbfc310b7b213545ae566cda12c +workbox-v3.6.3/workbox-strategies.prod.js,1559191154720,66cb572656c6f67c8ccfa9ed50fd0ef5f43812460a8e66ec5e1331bd35e74fb4 +workbox-v3.6.3/workbox-strategies.prod.js.map,1559191154720,bd614f0a7c9f746a5711c80701afd5fbd1f9a4badaa3d41a9b6d2209e964c94b +workbox-v3.6.3/workbox-streams.dev.js,1559191154721,ebd9ce89ba8783a9c7cedbb649fd2c0e72d16c0e49fc75c55af3cbc2a06f6229 +workbox-v3.6.3/workbox-streams.dev.js.map,1559191154727,db0ab4193f8fd5f3cb46000c464d0812534eb593830fe6f209edbdf444aba391 +workbox-v3.6.3/workbox-streams.prod.js,1559191154720,a38b6330c98447b0f6046fef7432bcae71ca64d112bf9e4d0c97f91f6585a74a +workbox-v3.6.3/workbox-streams.prod.js.map,1559191154721,74d4cde66c4cfef524824fc286f178d8670de1aadd1d559be4ca1cd0a2942f24 +workbox-v3.6.3/workbox-sw.js,1559191154727,e07638726911853e795bbd8a2172e49ed788f456d9ebaf2412a3e894139b76fc +workbox-v3.6.3/workbox-sw.js.map,1559191154721,12bddb94b59cc432f8db0760cf49fdfcff462b966305d09fd265be5b267a10d5 +app-5240259ae487bdf09f0d.js,1557813278931,04da3d4832ac13a4e860903d0b70486f8314373a6b76fe49f2cfb82a75758912 +app-5240259ae487bdf09f0d.js.map,1557813278929,358adcb70befc58d69ee8b6700450752e6dcb4f0ca17a4bbeb6f5c97cc8ac0f3 +app-eadb88dc3e8f941f2ae9.js.map,1557813216314,bed2226123bc1ed270d12afb04fad8d873a88d2adda2676229e02dfe8d7ee2b3 +app-c7f161e371102bbd741c.js.map,1557877612117,1b103871e0ddb305a5a4d53b021107d30acb4053d2fd2f14be0b8507129197c3 +app-895d651bee860628b349.js.map,1557811597005,6b37ec886fab84a7eb072c67913cf7eff6c45f5e9f9d4596759b19fb734966ee +app-c5b938aeccd7fc80368e.js.map,1557810933019,1522deeb95c35d6bc4ed00c542c91288e0f57f835cfc1c94865b1e3eec590ec3 +app-fda3ed7d59bc2e65cbed.js.map,1559191150475,37bd1b78efd536b053c0d1134aa109891b6059eba318652aa990c8ea6d18ea20 +app-fb394d03a36f4752b604.js.map,1557809399807,f356f070bf4e3e581c4c044cb4e707e368c45eddcbc785c8b22bcbfaa14e6733 diff --git a/.firebaserc b/.firebaserc index 2dbce2f..9f3b617 100644 --- a/.firebaserc +++ b/.firebaserc @@ -2,5 +2,14 @@ "projects": { "default": "journal-app-service", "prod": "sol-journal" + }, + "targets": { + "sol-journal": { + "hosting": { + "soljournal": [ + "soljournal" + ] + } + } } -} +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index a83a0b5..0c8cc55 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ npm-debug.log* yarn-debug.log* yarn-error.log* + +.cache +public \ No newline at end of file diff --git a/README.md b/README.md index 379efc4..79a8199 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,13 @@ Personal Journaling Platform -Sol Journal is a simple, minimal, journaling platform that works offline and across all devices. It can be self-hosted through Firebase and then installed as a PWA, on mobile devices for easy access on a phone, or on Desktops. +Sol Journal is a simple, minimal, journaling platform that works offline and across all devices. It can be hosted yourself on Firebase and then installed as a PWA, on mobile devices for easy access on a phone, or on Desktops.

- preview of page + preview of page

## Introduction @@ -21,7 +24,7 @@ Having a journal that is available on any device makes journaling easier. Being There are 2 ways to get started using Sol Journal: -1. You can use the hosted version (this is the simplest way to use the product) +1. You can use the hosted version (this is the simplest way to use the product) at [soljournal.netlify.com](soljournal.netlify.com) 2. You can host your own version and manage it yourself Sol Journal uses firebase to support offline functionality and authentication, meaning a new Firebase app will need to be setup with Firestore as a database if you wish to host it yourself. Be sure to add documents for `users` and `entries`, as well as enabling email for user authentication. @@ -31,13 +34,25 @@ Sol Journal uses firebase to support offline functionality and authentication, m In the spirit of minimalism, key features are what are in place for a quick, lightweight journaling experience that can work across devices, including: - 🔥 Authentication: Cloud firestore persists registered users to a users document and saved journal entries to an entries document -- 🎨 Dark Theme: the `src/styles/theme.js` file contains a set of colors and default styles that are applied to components with Emotion. A default light and dark theme are already in the file +- 🎨 Theming: the `src/styles/theme.js` file contains a set of colors and default styles that are applied to components with Emotion. A default light and dark theme are already in the file - 🔍 Search: full-text search of a user's entries stored in Firestore for quick access to past entries - 🖥 Mobile Friendly: designed to look great on mobile as well as desktop, with easy navigation on both - 💡 PWA: being a progressive web app makes it installable from Chrome/Safari on desktop, or be added to the homescreen on iOS/Android -- 🔌 Offline Support: read/write when you're offline and let the updates happen when your connection is restored +- 🔌 Offline Support: read/write when you're offline and let the updates happen when your connection is restored - 🗄 Export: backup all of your entries at any time to save your data +## Project setup + +Files are organized into these folders: + +`/components`: user interface pieces to construct the design and layout of the site +`/data`: local data transformed by gatsby to become queryable by Gatsby's GraphQL data layer +`/img`: images used by places like landing pages that are optimized by gatsby-image and then queryable in the GraphQL layer +`/pages`: public pages that can be seen by unauthenticated users and are completely server side rendered by Gatsby during `gatsby build` +`/routes`: private, client only routes only visible to authenticated users that are used by the app section of the journal +`/styles`: role based design tokens and theme definitions +`/util`: simple utility functions, for things like formatting dates + ## Developing Clone the project: @@ -59,24 +74,25 @@ yarn ``` Then configure a file in a new `.env` file (using the `.env.sample` file as a reference) with the following keys from the firebase console: -```env -REACT_APP_FIREBASE_API_KEY= -REACT_APP_DEV_AUTH_DOMAIN=.firebaseapp.com -REACT_APP_DEV_DATABASE_URL=https://.firebaseio.com -REACT_APP_DEV_PROJECT_ID= -REACT_APP_DEV_STORAGE_BUCKET=.appspot.com -REACT_APP_DEV_MESSAGING_SENDER_ID=############ -REACT_APP_CONFIRMATION_EMAIL_REDIRECT=https://.firebaseapp.com +```env +GATSBY_FIREBASE_API_KEY= +GATSBY_DEV_AUTH_DOMAIN=.firebaseapp.com +GATSBY_DEV_DATABASE_URL=https://.firebaseio.com +GATSBY_DEV_PROJECT_ID= +GATSBY_DEV_STORAGE_BUCKET=.appspot.com +GATSBY_DEV_MESSAGING_SENDER_ID=############ + +GATSBY_CONFIRMATION_EMAIL_REDIRECT=https://.firebaseapp.com ``` Navigate into the project directory, and then launch the site with this command: ```bash -yarn develop +gatsby develop ``` -The site will be opened up in your default browser on http://localhost:3000 +The site will be opened up in your default browser on http://localhost:8000 Edit code in the `/src`, save your changes, and they'll reload instantly in the browser. @@ -85,13 +101,15 @@ Edit code in the `/src`, save your changes, and they'll reload instantly in the To create an optimized build of the site run this command: ```bash -yarn build +gatsby build ``` -A `/build` folder will be assembled that can be deployed with this command: +A `/public` folder will be assembled that can be deployed to any static file hosting service like Netlify or surge. + +It can be deployed to firebase with this command: ```bash -firebase deploy +firebase deploy -p public ``` ## Inspiration diff --git a/SETUP.md b/SETUP.md index 4a4bfcd..1845cfd 100644 --- a/SETUP.md +++ b/SETUP.md @@ -2,7 +2,6 @@ Setting up Sol Journal requires a free Firebase account since many of the features rely on built in Firebase capabilities to allow functionality offline. The free plan gives you 50,000 reads and 20,000 writes per day, meaning you can easily run a personal version for yourself. - ## Setting up Firebase You will need a Google account to create a Firebase project, then navigate to the Firebase Console: https://console.firebase.google.com/ @@ -71,7 +70,7 @@ In order to prevent would be hackers or nefarious folks from messing with data i ##### Configuration -## Code Setup +## Setting up Code Having node installed is a prerequistie, you can follow instructions to get it setup yourself. @@ -88,3 +87,30 @@ firebase login ``` Follow the prompted instructions to connect your account. + +Clone the repository: + +```bash +git clone https://github.com/gillkyle/sol-journal +``` + +Then change the name of the `.env.sample` file to `.env` (or `.env.production`/`.env.development` if you would like to run the app in different environments) and fill it in, mapping your own keys from your Firebase project to the corresponding names in the file. + +```env +GATSBY_FIREBASE_API_KEY= +GATSBY_DEV_AUTH_DOMAIN=.firebaseapp.com +GATSBY_DEV_DATABASE_URL=https://.firebaseio.com +GATSBY_DEV_PROJECT_ID= +GATSBY_DEV_STORAGE_BUCKET=.appspot.com +GATSBY_DEV_MESSAGING_SENDER_ID=############ + +GATSBY_CONFIRMATION_EMAIL_REDIRECT=https://.firebaseapp.com +``` + +Then run the build command to generate an optimized build in the public directory. + +```bash +gatsby build +``` + +You can upload your `/public` folder to S3, or run the surge command inside the directory to deploy it to a free subdomain. diff --git a/firebase.json b/firebase.json index 1c4cbc0..81da9d5 100644 --- a/firebase.json +++ b/firebase.json @@ -4,6 +4,7 @@ "indexes": "firestore.indexes.json" }, "hosting": { + "target": "soljournal", "public": "build", "ignore": [ "firebase.json", diff --git a/gatsby-browser.js b/gatsby-browser.js new file mode 100644 index 0000000..68d5438 --- /dev/null +++ b/gatsby-browser.js @@ -0,0 +1,21 @@ +import React from "react" +import { ThemeProvider as EmotionThemeProvider } from "emotion-theming" +import Firebase, { FirebaseContext } from "components/firebase" +import theme from "styles/theme" +import ThemeTogglerContext, { ThemeToggler } from "components/context/theme" + +export const wrapRootElement = ({ element }) => { + return ( + + + + {({ themeName }) => ( + + {element} + + )} + + + + ) +} diff --git a/gatsby-config.js b/gatsby-config.js new file mode 100644 index 0000000..820c88a --- /dev/null +++ b/gatsby-config.js @@ -0,0 +1,71 @@ +module.exports = { + plugins: [ + `gatsby-plugin-react-helmet`, + `gatsby-plugin-emotion`, + // create routes for client side routing + { + resolve: `gatsby-plugin-create-client-paths`, + options: { prefixes: [`/app/*`] }, + }, + // provide fonts from Google fonts + { + resolve: `gatsby-plugin-prefetch-google-fonts`, + options: { + fonts: [ + { + family: `Montserrat`, + variants: [`400`, `700`], + }, + ], + }, + }, + // plugins for PWA support + `gatsby-plugin-offline`, + { + resolve: `gatsby-plugin-manifest`, + options: { + name: `Sol Journal`, + short_name: `Sol Journal`, + start_url: `/app`, + background_color: `#FFF`, + theme_color: `#FFF`, + display: `standalone`, + icon: `src/img/splash.png`, + }, + }, + // plugins for optimized images + `gatsby-transformer-sharp`, + `gatsby-plugin-sharp`, + { + resolve: `gatsby-source-filesystem`, + options: { + name: `images`, + path: `${__dirname}/src/img`, + }, + }, + // parse data from /src/data as Javascrip objects + `gatsby-transformer-json`, + { + resolve: `gatsby-source-filesystem`, + options: { + path: `./src/data/`, + }, + }, + // easier imports and exports by defining aliases + // for commonly used folders + { + resolve: "gatsby-plugin-module-resolver", + options: { + root: "./src", + aliases: { + components: "./components", + data: "./data", + img: "./img", + routes: "./routes", + styles: "./styles", + utils: "./utils", + }, + }, + }, + ], +} diff --git a/gatsby-node.js b/gatsby-node.js new file mode 100644 index 0000000..582e026 --- /dev/null +++ b/gatsby-node.js @@ -0,0 +1,9 @@ +exports.onCreatePage = async ({ page, actions }) => { + const { createPage } = actions + + if (page.path.match(/^\/app/)) { + page.matchPath = "/app/*" + + createPage(page) + } +} diff --git a/gatsby-ssr.js b/gatsby-ssr.js new file mode 100644 index 0000000..4cba3d0 --- /dev/null +++ b/gatsby-ssr.js @@ -0,0 +1,10 @@ +import React from "react" +import { ThemeProvider } from "emotion-theming" +import Firebase, { FirebaseContext } from "./src/components/firebase" +import theme from "./src/styles/theme" + +export const wrapRootElement = ({ element }) => ( + + {element} + +) diff --git a/package.json b/package.json index f3d35b1..5e14318 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,23 @@ "date-fns": "^1.30.1", "emotion-theming": "^10.0.10", "firebase": "^5.9.0", + "gatsby": "^2.4.3", + "gatsby-image": "^2.1.0", + "gatsby-plugin-create-client-paths": "^2.0.5", + "gatsby-plugin-emotion": "^4.0.6", + "gatsby-plugin-manifest": "^2.1.1", + "gatsby-plugin-module-resolver": "^1.0.3", + "gatsby-plugin-offline": "^2.1.0", + "gatsby-plugin-prefetch-google-fonts": "^1.4.2", + "gatsby-plugin-react-helmet": "^3.0.12", + "gatsby-plugin-sharp": "^2.0.37", + "gatsby-source-filesystem": "^2.0.36", + "gatsby-transformer-json": "^2.1.11", + "gatsby-transformer-sharp": "^2.1.19", "react": "^16.8.4", "react-dom": "^16.8.4", "react-feather": "^1.1.6", + "react-helmet": "^5.2.1", "react-router-dom": "^5.0.0", "react-scripts": "2.1.8", "react-spinners": "^0.5.3", diff --git a/public/index.html b/public/index.html index 0dc662b..a365e8c 100644 --- a/public/index.html +++ b/public/index.html @@ -1,45 +1 @@ - - - - - - - - - - - - Sol Journal - - - -
- - - +
\ No newline at end of file diff --git a/src/App.js b/src/App.js deleted file mode 100644 index 5c601ba..0000000 --- a/src/App.js +++ /dev/null @@ -1,145 +0,0 @@ -import React, { Component } from "react" -import { BrowserRouter as Router, Route } from "react-router-dom" -import { compose } from "recompose" -import styled from "@emotion/styled" -import { ThemeProvider } from "emotion-theming" - -import { SIZES } from "./styles/constants" - -import theme from "./styles/theme" -import Navbar from "./components/Navbar" -import Day from "./components/screens/Day" -import Month from "./components/screens/Month" -import Year from "./components/screens/Year" -import User from "./components/screens/User" -import Login from "./components/screens/Login" -import Search from "./components/screens/Search" -import Register from "./components/screens/Register" -import Start from "./components/screens/Start" -import Terms from "./components/screens/Terms" -import Privacy from "./components/screens/Privacy" -import PrivateRoute from "./components/PrivateRoute" - -import { OnlineContext } from "./components/context/online" -import { withAuthentication } from "./components/session" -import { withFirebase } from "./components/firebase" - -const FullscreenLayout = styled.div` - background-color: ${props => props.theme.colors.bodyBackground}; -` -const RouteLayout = styled.div` - display: flex; - flex-direction: column; - height: 100%; - margin: 0 auto; - padding: 0 10px; - max-width: ${SIZES.maxWidth}; - min-height: calc(100vh - 60px); - background-color: ${props => props.theme.colors.bodyBackground}; -` - -class App extends Component { - state = { - authUser: JSON.parse(localStorage.getItem("authUser")), - selectedTheme: - new Date().getHours() >= 7 && new Date().getHours() <= 21 - ? "LIGHT" - : "DARK", - online: navigator.onLine, - } - - componentDidMount() { - window.addEventListener("online", () => { - this.setState({ online: true }) - }) - - window.addEventListener("offline", () => { - this.setState({ online: false }) - }) - } - - onChangeTheme = () => { - const { selectedTheme } = this.state - const body = document.body - const newTheme = selectedTheme === "LIGHT" ? "DARK" : "LIGHT" - body.style.setProperty( - "background-color", - theme[newTheme].colors.bodyBackground - ) - this.setState({ selectedTheme: newTheme }) - } - - saveUserSettings = newTheme => { - const { authUser, firebase } = this.props - firebase.db - .collection("users") - .doc(authUser.uid) - .update({ - theme: newTheme, - }) - .then(function() { - console.log("Updated theme settings") - }) - } - - render() { - const { selectedTheme, authUser, online } = this.state - const { authUser: propAuthUser } = this.props - const authed = !!propAuthUser || !!authUser - - const currentTheme = theme[selectedTheme] - return ( - - - - - - - - - - - - - - - - - - - - - - ) - } -} - -export default compose( - withAuthentication, - withFirebase -)(App) diff --git a/src/App.test.js b/src/App.test.js deleted file mode 100644 index 7deaa42..0000000 --- a/src/App.test.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from "react" -import ReactDOM from "react-dom" -import App from "./App" - -it("renders without crashing", () => { - const div = document.createElement("div") - ReactDOM.render(, div) - ReactDOM.unmountComponentAtNode(div) -}) diff --git a/src/components/App.js b/src/components/App.js new file mode 100644 index 0000000..f320bcd --- /dev/null +++ b/src/components/App.js @@ -0,0 +1,115 @@ +import React, { Component } from "react" +import { Router } from "@reach/router" +import { compose } from "recompose" +import styled from "@emotion/styled" +import { withTheme } from "emotion-theming" + +import { SIZES } from "styles/constants" + +// import theme from "./styles/theme" +import Day from "routes/Day" +import Month from "routes/Month" +import Year from "routes/Year" +import User from "routes/User" +import Search from "routes/Search" +import Welcome from "routes/Welcome" + +import Navbar from "components/Navbar" +import PrivateRoute from "components/PrivateRoute" +import { OnlineContext } from "components/context/online" +import { withAuthentication } from "components/session" +import { withFirebase } from "components/firebase" +import ThemeTogglerContext from "components/context/theme" + +const FullscreenBgColor = styled.div` + background-color: ${props => props.theme.colors.bodyBackground}; +` +const RouteLayout = styled.div` + display: flex; + flex-direction: column; + height: 100%; + margin: 0 auto; + padding: 0 10px; + max-width: ${SIZES.maxWidth}; + min-height: calc(100vh - 60px); +` + +class App extends Component { + state = { + selectedTheme: this.props.theme.name, + } + + componentDidMount() { + window.addEventListener("online", () => { + this.setState({ online: true }) + }) + + window.addEventListener("offline", () => { + this.setState({ online: false }) + }) + + this.setState({ + authUser: JSON.parse(localStorage.getItem("authUser")), + online: navigator.onLine, + }) + } + + render() { + const { authUser, online } = this.state + const { authUser: propAuthUser } = this.props + const authed = !!propAuthUser || !!authUser + + return ( + + {({ toggle }) => ( + + + + + + + + + + + + + + + + )} + + ) + } +} + +export default compose( + withAuthentication, + withFirebase, + withTheme +)(App) diff --git a/src/components/Footer.js b/src/components/Footer.js new file mode 100644 index 0000000..dddc34a --- /dev/null +++ b/src/components/Footer.js @@ -0,0 +1,55 @@ +import React from "react" +import { Link } from "gatsby" +import { css } from "@emotion/core" +import styled from "@emotion/styled" +import { withTheme } from "emotion-theming" + +import Logo from "components/Logo" + +const FooterBlock = styled.footer` + margin-top: 120px; + padding: 30px 0px; + text-align: center; + color: ${props => props.theme.colors.secondary}; +` +const linkStyles = css` + cursor: pointer; + text-decoration: none; + margin: 10px; +` +const FooterLink = styled(Link)` + ${linkStyles} + color: ${props => props.theme.colors.secondary}; + &:hover { + color: ${props => props.theme.colors.tertiary}; + } + ` +const FooterAnchor = styled.a` + ${linkStyles} + color: ${props => props.theme.colors.secondary}; + &:hover { + color: ${props => props.theme.colors.tertiary}; + } +` + +const Footer = ({ theme }) => ( + +
+ +
+
+ + View on GitHub + + Terms of Service + Privacy Policy +
+
© 2019
+
+) + +export default withTheme(Footer) diff --git a/src/components/Icon/Icon.js b/src/components/Icon.js similarity index 100% rename from src/components/Icon/Icon.js rename to src/components/Icon.js diff --git a/src/components/Icon/index.js b/src/components/Icon/index.js deleted file mode 100644 index dd4586c..0000000 --- a/src/components/Icon/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import Icon from "./Icon" -export default Icon diff --git a/src/components/Layout.js b/src/components/Layout.js new file mode 100644 index 0000000..48105ad --- /dev/null +++ b/src/components/Layout.js @@ -0,0 +1,47 @@ +import React from "react" +import { Helmet } from "react-helmet" +import { Global, css } from "@emotion/core" +import styled from "@emotion/styled" + +import { withTheme } from "emotion-theming" + +const Layout = ({ children, theme }) => ( + <> + + {/* some styles should applied globally via the layout */} + + {children} + +) + +export default withTheme(Layout) diff --git a/src/components/Logo/index.js b/src/components/Logo.js similarity index 100% rename from src/components/Logo/index.js rename to src/components/Logo.js diff --git a/src/components/Navbar.js b/src/components/Navbar.js new file mode 100644 index 0000000..0c1e7ff --- /dev/null +++ b/src/components/Navbar.js @@ -0,0 +1,158 @@ +import React from "react" +import { navigate, Link } from "gatsby" +import { StyledLink } from "components/elements" +import styled from "@emotion/styled" +/** @jsx jsx */ +import { jsx } from "@emotion/core" +import { compose } from "recompose" +import { withTheme } from "emotion-theming" + +import { SIZES } from "styles/constants" +import { todayUrl, yearUrl } from "utils/date" + +import Logo from "components/Logo" +import Icon from "components/Icon" +import { withAuthentication } from "components/session" +import ThemeTogglerContext from "components/context/theme" + +const Header = styled.div` + background-color: ${props => props.theme.colors.headerBackground}; + height: 60px; + display: grid; + grid-template-areas: "... nav ..."; + grid-template-columns: 1fr minmax(240px, ${SIZES.maxWidth}) 1fr; + grid-gap: 10px; + align-items: center; + border-width: 1px; + border-color: ${props => props.theme.colors.quarternary}; + border-style: solid; +` +const Nav = styled.div` + grid-area: nav; + max-width: ${SIZES.maxWidth}; + display: flex; + flex-direction: row; + justify-content: space-between; + align-content: center; +` +const LogoSection = styled.div` + height: 40px; + display: flex; + flex-direction: row; + align-items: center; + font-family: "Montserrat", sans-serif; + font-weight: 700; + font-size: 18px; + &:hover { + cursor: pointer; + } +` +const LogoText = styled.span` + color: ${props => props.color}; + margin-left: 5px; + @media (max-width: 400px) { + display: none; + } +` +const NavIcons = styled.div` + display: flex; + flex-direction: row; + align-items: center; + * + * { + margin-left: 10px; + } +` + +const Navbar = ({ authUser, theme, toggleTheme }) => ( +
+ +
+) + +// on langing page and simple pages outside the app, simplify link options +const SimpleNav = ({ authUser, theme }) => ( +
+ +
+) + +const SimpleNavbar = compose( + withAuthentication, + withTheme +)(SimpleNav) + +export { SimpleNavbar } + +export default compose( + withAuthentication, + withTheme +)(Navbar) diff --git a/src/components/Navbar/Navbar.js b/src/components/Navbar/Navbar.js deleted file mode 100644 index 2fb8986..0000000 --- a/src/components/Navbar/Navbar.js +++ /dev/null @@ -1,113 +0,0 @@ -import React from "react" -import { withRouter } from "react-router-dom" -import { StyledLink as Link } from "../elements" -import styled from "@emotion/styled" -/** @jsx jsx */ -import { jsx } from "@emotion/core" -import { compose } from "recompose" -import { withTheme } from "emotion-theming" - -import { SIZES } from "../../styles/constants" -import { todayUrl, yearUrl } from "../../utils/date" - -import Logo from "../Logo" -import Icon from "../Icon" -import { withAuthentication } from "../session" - -const Header = styled.div` - background-color: ${props => props.theme.colors.headerBackground}; - height: 60px; - display: grid; - grid-template-areas: "... nav ..."; - grid-template-columns: 1fr minmax(240px, ${SIZES.maxWidth}) 1fr; - grid-gap: 10px; - align-items: center; - border-width: 1px; - border-color: ${props => props.theme.colors.quarternary}; - border-style: solid; -` -const Nav = styled.div` - grid-area: nav; - max-width: ${SIZES.maxWidth}; - display: flex; - flex-direction: row; - justify-content: space-between; - align-content: center; -` -const LogoSection = styled.div` - height: 40px; - display: flex; - flex-direction: row; - align-items: center; - font-family: "Montserrat", sans-serif; - font-weight: 700; - font-size: 18px; - &:hover { - cursor: pointer; - } -` -const LogoText = styled.span` - color: ${props => props.color}; - margin-left: 5px; - @media (max-width: 400px) { - display: none; - } -` -const NavIcons = styled.div` - display: flex; - flex-direction: row; - align-items: center; - * + * { - margin-left: 10px; - } -` - -const Navbar = ({ authUser, theme, toggleTheme, history }) => ( -
- -
-) - -export default compose( - withAuthentication, - withTheme, - withRouter -)(Navbar) diff --git a/src/components/Navbar/index.js b/src/components/Navbar/index.js deleted file mode 100644 index 27f2a37..0000000 --- a/src/components/Navbar/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import Navbar from "./Navbar" -export default Navbar diff --git a/src/components/PrivateRoute.js b/src/components/PrivateRoute.js new file mode 100644 index 0000000..a024264 --- /dev/null +++ b/src/components/PrivateRoute.js @@ -0,0 +1,19 @@ +import React from "react" +import { Redirect, Location } from "@reach/router" + +// when a user isn't logged in, force a redirect +const PrivateRoute = ({ component: Component, authed, ...rest }) => { + return ( + + {({ location }) => + authed === true ? ( + + ) : ( + + ) + } + + ) +} + +export default PrivateRoute diff --git a/src/components/PrivateRoute/PrivateRoute.js b/src/components/PrivateRoute/PrivateRoute.js deleted file mode 100644 index 42720e8..0000000 --- a/src/components/PrivateRoute/PrivateRoute.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from "react" -import { Route, Redirect } from "react-router-dom" - -const PrivateRoute = ({ component: Component, authed, ...rest }) => { - return ( - - authed === true ? ( - - ) : ( - - ) - } - /> - ) -} - -export default PrivateRoute diff --git a/src/components/PrivateRoute/index.js b/src/components/PrivateRoute/index.js deleted file mode 100644 index 345d794..0000000 --- a/src/components/PrivateRoute/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import PrivateRoute from "./PrivateRoute" -export default PrivateRoute diff --git a/src/components/Seek/Seek.js b/src/components/Seek.js similarity index 90% rename from src/components/Seek/Seek.js rename to src/components/Seek.js index f24ccb5..4575b52 100644 --- a/src/components/Seek/Seek.js +++ b/src/components/Seek.js @@ -2,9 +2,9 @@ import React from "react" import styled from "@emotion/styled" import { withTheme } from "emotion-theming" -import Icon from "../Icon" -import { H1 } from "../elements" -import { StyledLink as Link } from "../elements" +import Icon from "components/Icon" +import { H1 } from "components/elements" +import { StyledLink as Link } from "components/elements" const SeekHeader = styled.header` display: flex; diff --git a/src/components/Seek/index.js b/src/components/Seek/index.js deleted file mode 100644 index 232bb19..0000000 --- a/src/components/Seek/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import Seek from "./Seek" -export default Seek diff --git a/src/components/SignOut/SignOut.js b/src/components/SignOut.js similarity index 79% rename from src/components/SignOut/SignOut.js rename to src/components/SignOut.js index 3f572ed..f04bf60 100644 --- a/src/components/SignOut/SignOut.js +++ b/src/components/SignOut.js @@ -2,9 +2,9 @@ import React from "react" import { compose } from "recompose" import { withTheme } from "emotion-theming" -import { Button } from "../elements" +import { Button } from "components/elements" -import { withFirebase } from "../firebase" +import { withFirebase } from "components/firebase" const SignOutButton = ({ firebase, theme }) => ( - {error &&

{error.message}

} + {error &&

{error.message}

} ) } } -const LoginForm = compose( - withTheme, - withRouter -)(LoginFormBase) +const LoginForm = compose(withTheme)(LoginFormBase) export default withTheme(LoginPage) diff --git a/src/pages/privacy.js b/src/pages/privacy.js new file mode 100644 index 0000000..76bf83f --- /dev/null +++ b/src/pages/privacy.js @@ -0,0 +1,94 @@ +import React from "react" + +import { SimpleH1, SimpleH2, P, Em } from "components/elements" +import Layout from "components/Layout" +import Container from "components/container" +import { SimpleNavbar } from "components/Navbar" +import { withTheme } from "emotion-theming" + +const Terms = ({ theme }) => ( + + + + Privacy Policy + Last update: April 30, 2019{" "} +

+ Sol Journal supports the following browsers: Chrome (latest), Safari + (latest), Firefox (50+) +

+ Rights +

+ You don't have to provide your real name when you register to an + account, but you need to use a valid/verifiable email address. +
+
+ You have the right to export your data at any time, in JSON format. +
+
+ Your data will not be intentionally shown to other users or shared with + third parties. +
+
+ Your personal data will not be shared with anyone without your consent. +
+
+ Data saved on the hosted version of Sol Journal is encrypted as it is + transmitted and stored. However, data is not salted or hashed when it is + stored on Google servers so database administrators (me) can view the + data as plaintext. I won't view or use the data of other users for any + reason but if you would like to have more ownership of your data you can + setup the code on your own. +
+
+ If the site ceases operation, you will receive an opportunity to export + all your data before the site dies. +
+
+ Any new features that affect privacy will be strictly opt-in. +

+ Responsibilites +

+ You will not use the site to store illegal information or data under + United States law (or any law). +
+
+ You have to be at least 18+ to create an account and use the site. +
+
+ You must not abuse the site by knowingly posting malicious code that + could harm you or the other users. +
+
+ You may not make automated requests to the site. +
+
+ You may not abuse the registration system. +
+
+ You are responsible for keeping your account secure. +
+
I reserve the right to close accounts that abuse the system + (millions of entries or overloading services with requests) or use it in + an unreasonable manner. +

+ Other +

+ Other important legal stuff Though I want to provide a great service, + there are certain things about the service I cannot promise. For + example, the services and software are provided “as-is”, at your own + risk, without express or implied warranty or condition of any kind. I + also disclaim any warranties of merchantability, fitness for a + particular purpose or non-infringement. Sol Journal will have no + responsibility for any harm to your computer system, loss or corruption + of data, or other harm that results from your access to or use of the + Services or Software. +
+
+ These Terms can change at any time, but I'll try to be reasonable. This + is a service I've always and hope to be able to run it for a long time. +

+
+
+) + +export default withTheme(Terms) diff --git a/src/components/screens/Register/Register.js b/src/pages/register.js similarity index 70% rename from src/components/screens/Register/Register.js rename to src/pages/register.js index a848251..773e2f4 100644 --- a/src/components/screens/Register/Register.js +++ b/src/pages/register.js @@ -1,14 +1,14 @@ import React, { Component } from "react" -import { withRouter } from "react-router-dom" import styled from "@emotion/styled" +import { navigate, Link } from "gatsby" import { compose } from "recompose" import { withTheme } from "emotion-theming" -import { Input, Button, P } from "../../elements" -import { SIZES } from "../../../styles/constants" -import { StyledLink as Link } from "../../elements" - -import { FirebaseContext } from "../../firebase" +import { SimpleNavbar } from "components/Navbar" +import { Input, Button, P } from "components/elements" +import Layout from "components/Layout" +import { FirebaseContext } from "components/firebase" +import { SIZES } from "styles/constants" const RegisterGrid = styled.div` display: grid; @@ -18,19 +18,30 @@ const RegisterGrid = styled.div` const RegisterLayout = styled.div` max-width: ${SIZES.smallWidth}; width: 100%; - align-self: center; - margin-top: 20px; + margin: 20px auto; ` -const RegisterPage = ({ history, theme }) => ( - - - {firebase => } - -

- Already have an account? Login -

-
+const RegisterPage = ({ theme }) => ( + + + + + {firebase => } + +

+ By registering for this site you are agreeing to the{" "} + + Terms of Service + +

+

+ Already have an account?{" "} + + Login + +

+
+
) class RegisterFormBase extends Component { @@ -69,7 +80,7 @@ class RegisterFormBase extends Component { .set({ email: user.email, }) - this.props.history.push("/") + navigate("app/") }) .catch(error => { this.setState({ error }) @@ -131,16 +142,13 @@ class RegisterFormBase extends Component { - {error &&

{error.message}

} + {error &&

{error.message}

} ) } } -const RegisterForm = compose( - withTheme, - withRouter -)(RegisterFormBase) +const RegisterForm = compose(withTheme)(RegisterFormBase) export default withTheme(RegisterPage) diff --git a/src/pages/terms.js b/src/pages/terms.js new file mode 100644 index 0000000..d9470dc --- /dev/null +++ b/src/pages/terms.js @@ -0,0 +1,88 @@ +import React from "react" + +import { SimpleH1, SimpleH2, P, Em } from "components/elements" +import Layout from "components/Layout" +import Container from "components/container" +import { SimpleNavbar } from "components/Navbar" +import { withTheme } from "emotion-theming" + +const Terms = ({ theme }) => ( + + + + Terms of Service + Last update: April 30, 2019 + Scope of Service +

+ Sol Journal supports the following browsers: Chrome (latest), Safari + (latest), Firefox (50+) +

+ Rights +

+ You don't have to provide your real name when you register to an + account, but you need to use a valid/verifiable email address. +
+
+ You have the right to export your data at any time, in JSON format. +
+
+ Your data will not be intentionally shown to other users or shared with + third parties. +
+
+ Your personal data will not be shared with anyone without your consent. +
+
+ We reserve the right to discontinue any feature of the service at any + time. If the site ceases operation, you will receive an opportunity to + export all your data before the site dies. +
+
+ Any new features that affect privacy will be strictly opt-in. +

+ Responsibilites +

+ You will not use the site to store illegal information or data under + United States law (or any law). +
+
+ You have to be at least 18+ to create an account and use the site. +
+
+ You must not abuse the site by knowingly posting malicious code that + could harm you or the other users. +
+
+ You may not make automated requests to the site. +
+
+ You may not abuse the registration system. +
+
+ You are responsible for keeping your account secure. +
+
I reserve the right to close accounts that abuse the system + (millions of entries or overloading services with requests) or use it in + an unreasonable manner. +

+ Other +

+ Other important legal stuff Though I want to provide a great service, + there are certain things about the service I cannot promise. For + example, the services and software are provided “as-is”, at your own + risk, without express or implied warranty or condition of any kind. I + also disclaim any warranties of merchantability, fitness for a + particular purpose or non-infringement. Sol Journal will have no + responsibility for any harm to your computer system, loss or corruption + of data, or other harm that results from your access to or use of the + Services or Software. +
+
+ These Terms can change at any time, but I'll try to be reasonable. This + is a service I've always and hope to be able to run it for a long time. +

+
+
+) + +export default withTheme(Terms) diff --git a/src/components/screens/Day/Day.js b/src/routes/Day.js similarity index 87% rename from src/components/screens/Day/Day.js rename to src/routes/Day.js index ea79ff4..e49f075 100644 --- a/src/components/screens/Day/Day.js +++ b/src/routes/Day.js @@ -1,21 +1,20 @@ import React from "react" +import { addDays, subDays, format, isAfter, startOfYesterday } from "date-fns" +import { BeatLoader } from "react-spinners" import styled from "@emotion/styled" /** @jsx jsx */ import { jsx, css, keyframes } from "@emotion/core" import { compose } from "recompose" -import { Prompt } from "react-router" -import { withRouter } from "react-router-dom" import { withTheme } from "emotion-theming" -import { withFirebase } from "../../firebase" -import { withAuthentication } from "../../session" -import { OnlineContext } from "../../context/online" -import { addDays, subDays, format, isAfter, startOfYesterday } from "date-fns" -import { BeatLoader } from "react-spinners" -import { SIZES } from "../../../styles/constants" +import { withFirebase } from "components/firebase" +import { withAuthentication } from "components/session" +import { OnlineContext } from "components/context/online" -import Seek from "../../Seek" -import Icon from "../../Icon" +import { SIZES } from "styles/constants" + +import Seek from "components/Seek" +import Icon from "components/Icon" const EntryHeading = styled.div` display: flex; @@ -48,6 +47,7 @@ const OfflineNotice = styled.div` color: ${props => props.theme.colors.secondary}; border: 1px solid; border-color: ${props => props.theme.colors.tertiary}; + font-size: ${SIZES.tiny}; border-radius: 3px; ` const JournalEntryArea = styled.textarea` @@ -58,6 +58,7 @@ const JournalEntryArea = styled.textarea` background-color: transparent; line-height: 1.5; letter-spacing: 0.5px; + height: calc(100vh - 300px); width: 100%; border: none; resize: none; @@ -106,24 +107,31 @@ class Day extends React.Component { lastEditedAt: new Date(), } timeout = 0 - retrievedFromServer = false static contextType = OnlineContext componentDidMount() { - const { - history, - match: { - params: { year, month, day }, - }, - } = this.props - history.listen((location, action) => { - const [, year, month, day] = location.pathname.split("/") - this.onRouteChanged(year, month, day) - }) + const { year, month, day } = this.props this.getDocRef(year, month, day, false) } + componentDidUpdate(prevProps) { + // check if a new route was hit, to save the entry and load the next one + if (this.props.uri !== prevProps.uri) { + const [ + , + , + prevYear, + prevMonth, + prevDay, + ] = prevProps.location.pathname.split("/") + const { text } = this.state + this.saveText(text, prevYear, prevMonth, prevDay) + const [, , year, month, day] = this.props.location.pathname.split("/") + this.onRouteChanged(year, month, day) + } + } + onRouteChanged = (year, month, day) => { this.setState({ loading: true }) this.getDocRef(year, month, day, false) @@ -168,11 +176,7 @@ class Day extends React.Component { onChangeText = e => { if (this.timeout) clearTimeout(this.timeout) const text = e.target.value - const { - match: { - params: { year, month, day }, - }, - } = this.props + const { year, month, day } = this.props this.setState({ text, lastEditedAt: new Date() }) this.timeout = setTimeout(() => { @@ -184,11 +188,7 @@ class Day extends React.Component { const entryTextArea = document.getElementById("entry-text-area") const cursorIndex = entryTextArea.selectionStart const { text } = this.state - const { - match: { - params: { year, month, day }, - }, - } = this.props + const { year, month, day } = this.props const insertAt = (str, sub, pos) => `${str.slice(0, pos)}${sub}${str.slice(pos)}` const newText = insertAt(text, format(new Date(), "h:mma "), cursorIndex) @@ -227,12 +227,7 @@ class Day extends React.Component { } render() { - const { - match: { - params: { year, month, day }, - }, - theme, - } = this.props + const { year, month, day, theme } = this.props const online = this.context const { text, loading, saving, lastSavedAt, lastEditedAt } = this.state const currentDay = new Date(year, month - 1, day) @@ -241,10 +236,6 @@ class Day extends React.Component { return ( <> - { const { firebase, authUser } = this.props const entriesRef = await firebase.db @@ -87,13 +88,7 @@ class Search extends Component { .where("userId", "==", authUser.uid) .get() const entries = entriesRef.docs.map(doc => doc.data()).reverse() - // const sortedEntries = entries.sort((a, b) => { - // return ( - // new Date(b.year, b.month - 1, b.day) - - // new Date(a.year, a.month - 1, a.day) - // ) - // }) - // console.log(sortedEntries) + this.setState({ entries, allEntries: entries, loading: false }) } diff --git a/src/components/screens/Start/Start.js b/src/routes/Start.js similarity index 54% rename from src/components/screens/Start/Start.js rename to src/routes/Start.js index 4ccd532..c6d3af9 100644 --- a/src/components/screens/Start/Start.js +++ b/src/routes/Start.js @@ -1,22 +1,26 @@ import React, { Component } from "react" -import { Link } from "react-router-dom" +import { Helmet } from "react-helmet" +import { Link, StaticQuery, graphql } from "gatsby" +import Img from "gatsby-image" import styled from "@emotion/styled" import { withTheme } from "emotion-theming" -import { SIZES } from "../../../styles/constants" -import { Button, P } from "../../elements" -import { todayUrl } from "../../../utils/date" -import Icon from "../../Icon" -import Logo from "../../Logo" +import { SIZES } from "styles/constants" +import { Button, P } from "components/elements" +import Icon from "components/Icon" +import Footer from "components/Footer" +import { todayUrl } from "utils/date" const StartGrid = styled.div` margin-top: 30px; + text-align: center; line-height: 1.5; color: ${props => props.theme.colors.primary}; height: 100%; ` const FeatureGrid = styled.div` display: grid; + text-align: left; grid-template-rows: 1fr; grid-gap: 30px; ` @@ -36,21 +40,6 @@ const FeatureTitle = styled.div` const FeatureDescription = styled.div` color: ${props => props.theme.colors.secondary}; ` -const Footer = styled.footer` - margin-top: 120px; - padding: 30px 0px; - text-align: center; - color: ${props => props.theme.colors.secondary}; -` -const FooterLink = styled(Link)` - cursor: pointer; - color: ${props => props.theme.colors.secondary}; - text-decoration: none; - margin: 10px; - &:hover { - color: ${props => props.theme.colors.tertiary}; - } -` const features = [ { @@ -83,6 +72,12 @@ const features = [ desc: "Download all of your journal entries at any time for back-up or safe keeping ", }, + { + icon: "Moon", + title: "Dark Mode", + desc: + "Take it easy on your eyes, with an easily accessible toggle from all screens and detection of night hours to turn on automatically", + }, ] class Start extends Component { @@ -90,15 +85,78 @@ class Start extends Component { const { theme } = this.props return ( + + +

Record what's on your mind, from anywhere

Journaling can improve your health and help you take inventory of your day. Sol Journal works offline and from any device. Use it as a place to record thoughts and events from the day.

- - + + +
+ { + return theme.name === "LIGHT" ? ( + + ) : ( + + ) + }} + /> +
))} -
-
- -
-
- View on GitHub - Terms of Service - Privacy Policy -
-
© 2019
-
+