14
.env.sample
14
.env.sample
@@ -1,8 +1,8 @@
|
|||||||
REACT_APP_FIREBASE_API_KEY=<BUNCHofRandomNumbersAndChars>
|
GATSBY_FIREBASE_API_KEY=<BUNCHofRandomNumbersAndChars>
|
||||||
REACT_APP_DEV_AUTH_DOMAIN=<name>.firebaseapp.com
|
GATSBY_DEV_AUTH_DOMAIN=<name>.firebaseapp.com
|
||||||
REACT_APP_DEV_DATABASE_URL=https://<name>.firebaseio.com
|
GATSBY_DEV_DATABASE_URL=https://<name>.firebaseio.com
|
||||||
REACT_APP_DEV_PROJECT_ID=<name>
|
GATSBY_DEV_PROJECT_ID=<name>
|
||||||
REACT_APP_DEV_STORAGE_BUCKET=<name>.appspot.com
|
GATSBY_DEV_STORAGE_BUCKET=<name>.appspot.com
|
||||||
REACT_APP_DEV_MESSAGING_SENDER_ID=############
|
GATSBY_DEV_MESSAGING_SENDER_ID=############
|
||||||
|
|
||||||
REACT_APP_CONFIRMATION_EMAIL_REDIRECT=https://<name>.firebaseapp.com
|
GATSBY_CONFIRMATION_EMAIL_REDIRECT=https://<name>.firebaseapp.com
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
asset-manifest.json,1556898463490,f723129505a2111ca263ef5479bd10b1f0efc470c951b596f13dcf48d8649c7e
|
asset-manifest.json,1556898463490,f723129505a2111ca263ef5479bd10b1f0efc470c951b596f13dcf48d8649c7e
|
||||||
index.html,1556898463490,d2791f63e8652b46a6a92df716e200ef6670799c079df85344ad44c0732a0338
|
|
||||||
precache-manifest.a096a268b779b4480b9a46727f75551b.js,1556898463490,3ee2e9cfd0185210ebe9c8fe3dd342b86254c667c2e9b51369438728c9f7e324
|
|
||||||
manifest.json,1555998067072,20792c911b58103a520ddb6b0f7bcc7ce3bceaa15480cbfd913f8b3620864341
|
manifest.json,1555998067072,20792c911b58103a520ddb6b0f7bcc7ce3bceaa15480cbfd913f8b3620864341
|
||||||
|
precache-manifest.a096a268b779b4480b9a46727f75551b.js,1556898463490,3ee2e9cfd0185210ebe9c8fe3dd342b86254c667c2e9b51369438728c9f7e324
|
||||||
|
index.html,1556898463490,d2791f63e8652b46a6a92df716e200ef6670799c079df85344ad44c0732a0338
|
||||||
icon.png,1555998067072,40bb863e95a5ea2c01be6eba0beb6801183746f99d40eb393a6b4776a11d8636
|
icon.png,1555998067072,40bb863e95a5ea2c01be6eba0beb6801183746f99d40eb393a6b4776a11d8636
|
||||||
service-worker.js,1556898463490,de05f8df6933f0d1ff232f36ce73e94b0faafe0ac3ce9882fbbacc7fc608fc2d
|
service-worker.js,1556898463490,de05f8df6933f0d1ff232f36ce73e94b0faafe0ac3ce9882fbbacc7fc608fc2d
|
||||||
|
static/css/main.1716334c.chunk.css,1556898463519,dadd472a021e6f3502d58df7b11455a233a9a25f87ce536e693c18db20036e09
|
||||||
reactfavicon.ico,1555998067072,b72f7455f00e4e58792d2bca892abb068e2213838c0316d6b7a0d6d16acd1955
|
reactfavicon.ico,1555998067072,b72f7455f00e4e58792d2bca892abb068e2213838c0316d6b7a0d6d16acd1955
|
||||||
static/css/main.1716334c.chunk.css.map,1556898463519,c50d028b9046b1664c1a246227bee082eaf7a5f46f8857aad8963283c298dacd
|
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,1556898463519,e1af5f94fdd13901b2e433d0d7607e27c01458151c35b1fe4b7feda2a32b7aa9
|
||||||
static/js/runtime~main.a8a9905a.js.map,1556898463519,c337bf8b58896da637a6e50ab8cfc779eb1ec42c55f8ec429030a03454a549db
|
|
||||||
static/js/main.a10ab5ea.chunk.js,1556898463491,04608cac454dbaa153b80f00064f3cb33edc8aad4a2710d56a385fd8e86a3bc5
|
|
||||||
splash.png,1555998067072,e06cb28b9a2a8275ce53eb5eead2851f684f537a6a30f0f0bf360b8813fa273f
|
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/main.a10ab5ea.chunk.js.map,1556898463521,777ecf9469d772313dec6ecc4b5d7de7425b13cf8529747c21e02254c9251081
|
||||||
static/js/2.3f4eb03d.chunk.js,1556898463520,47a71ca572b94638afd405721c3ef6fb4aef5962dd0db71eb6ff9f284be1cd48
|
static/js/2.3f4eb03d.chunk.js,1556898463520,47a71ca572b94638afd405721c3ef6fb4aef5962dd0db71eb6ff9f284be1cd48
|
||||||
static/js/2.3f4eb03d.chunk.js.map,1556898463521,79d34370558394348a525ac8b13043f85a4b8ba81ecc94a4d7ed54ebb1b33bcd
|
static/js/2.3f4eb03d.chunk.js.map,1556898463521,79d34370558394348a525ac8b13043f85a4b8ba81ecc94a4d7ed54ebb1b33bcd
|
||||||
|
|||||||
259
.firebase/hosting.cHVibGlj.cache
Normal file
259
.firebase/hosting.cHVibGlj.cache
Normal file
@@ -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
|
||||||
@@ -2,5 +2,14 @@
|
|||||||
"projects": {
|
"projects": {
|
||||||
"default": "journal-app-service",
|
"default": "journal-app-service",
|
||||||
"prod": "sol-journal"
|
"prod": "sol-journal"
|
||||||
|
},
|
||||||
|
"targets": {
|
||||||
|
"sol-journal": {
|
||||||
|
"hosting": {
|
||||||
|
"soljournal": [
|
||||||
|
"soljournal"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -25,3 +25,6 @@
|
|||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
|
.cache
|
||||||
|
public
|
||||||
52
README.md
52
README.md
@@ -5,10 +5,13 @@
|
|||||||
Personal Journaling Platform
|
Personal Journaling Platform
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="preview of page" src="https://raw.githubusercontent.com/gillkyle/images/master/hero-mixed.png" />
|
<img
|
||||||
|
alt="preview of page"
|
||||||
|
src="https://raw.githubusercontent.com/gillkyle/images/master/hero-mixed.png"
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Introduction
|
## 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:
|
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
|
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.
|
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:
|
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
|
- 🔥 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
|
- 🔍 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
|
- 🖥 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
|
- 💡 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
|
- 🗄 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
|
## Developing
|
||||||
|
|
||||||
Clone the project:
|
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:
|
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=<BUNCHofRandomNumbersAndChars>
|
|
||||||
REACT_APP_DEV_AUTH_DOMAIN=<name>.firebaseapp.com
|
|
||||||
REACT_APP_DEV_DATABASE_URL=https://<name>.firebaseio.com
|
|
||||||
REACT_APP_DEV_PROJECT_ID=<name>
|
|
||||||
REACT_APP_DEV_STORAGE_BUCKET=<name>.appspot.com
|
|
||||||
REACT_APP_DEV_MESSAGING_SENDER_ID=############
|
|
||||||
|
|
||||||
REACT_APP_CONFIRMATION_EMAIL_REDIRECT=https://<name>.firebaseapp.com
|
```env
|
||||||
|
GATSBY_FIREBASE_API_KEY=<BUNCHofRandomNumbersAndChars>
|
||||||
|
GATSBY_DEV_AUTH_DOMAIN=<name>.firebaseapp.com
|
||||||
|
GATSBY_DEV_DATABASE_URL=https://<name>.firebaseio.com
|
||||||
|
GATSBY_DEV_PROJECT_ID=<name>
|
||||||
|
GATSBY_DEV_STORAGE_BUCKET=<name>.appspot.com
|
||||||
|
GATSBY_DEV_MESSAGING_SENDER_ID=############
|
||||||
|
|
||||||
|
GATSBY_CONFIRMATION_EMAIL_REDIRECT=https://<name>.firebaseapp.com
|
||||||
```
|
```
|
||||||
|
|
||||||
Navigate into the project directory, and then launch the site with this command:
|
Navigate into the project directory, and then launch the site with this command:
|
||||||
|
|
||||||
```bash
|
```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.
|
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:
|
To create an optimized build of the site run this command:
|
||||||
|
|
||||||
```bash
|
```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
|
```bash
|
||||||
firebase deploy
|
firebase deploy -p public
|
||||||
```
|
```
|
||||||
|
|
||||||
## Inspiration
|
## Inspiration
|
||||||
|
|||||||
30
SETUP.md
30
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 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
|
## 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/
|
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
|
##### Configuration
|
||||||
|
|
||||||
## Code Setup
|
## Setting up Code
|
||||||
|
|
||||||
Having node installed is a prerequistie, you can follow instructions to get it setup yourself.
|
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.
|
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=<BUNCHofRandomNumbersAndChars>
|
||||||
|
GATSBY_DEV_AUTH_DOMAIN=<name>.firebaseapp.com
|
||||||
|
GATSBY_DEV_DATABASE_URL=https://<name>.firebaseio.com
|
||||||
|
GATSBY_DEV_PROJECT_ID=<name>
|
||||||
|
GATSBY_DEV_STORAGE_BUCKET=<name>.appspot.com
|
||||||
|
GATSBY_DEV_MESSAGING_SENDER_ID=############
|
||||||
|
|
||||||
|
GATSBY_CONFIRMATION_EMAIL_REDIRECT=https://<name>.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.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"indexes": "firestore.indexes.json"
|
"indexes": "firestore.indexes.json"
|
||||||
},
|
},
|
||||||
"hosting": {
|
"hosting": {
|
||||||
|
"target": "soljournal",
|
||||||
"public": "build",
|
"public": "build",
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"firebase.json",
|
"firebase.json",
|
||||||
|
|||||||
21
gatsby-browser.js
Normal file
21
gatsby-browser.js
Normal file
@@ -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 (
|
||||||
|
<FirebaseContext.Provider value={new Firebase()}>
|
||||||
|
<ThemeToggler>
|
||||||
|
<ThemeTogglerContext.Consumer>
|
||||||
|
{({ themeName }) => (
|
||||||
|
<EmotionThemeProvider theme={theme[themeName]}>
|
||||||
|
{element}
|
||||||
|
</EmotionThemeProvider>
|
||||||
|
)}
|
||||||
|
</ThemeTogglerContext.Consumer>
|
||||||
|
</ThemeToggler>
|
||||||
|
</FirebaseContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
71
gatsby-config.js
Normal file
71
gatsby-config.js
Normal file
@@ -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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
9
gatsby-node.js
Normal file
9
gatsby-node.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
exports.onCreatePage = async ({ page, actions }) => {
|
||||||
|
const { createPage } = actions
|
||||||
|
|
||||||
|
if (page.path.match(/^\/app/)) {
|
||||||
|
page.matchPath = "/app/*"
|
||||||
|
|
||||||
|
createPage(page)
|
||||||
|
}
|
||||||
|
}
|
||||||
10
gatsby-ssr.js
Normal file
10
gatsby-ssr.js
Normal file
@@ -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 }) => (
|
||||||
|
<FirebaseContext.Provider value={new Firebase()}>
|
||||||
|
<ThemeProvider theme={theme.LIGHT}>{element}</ThemeProvider>
|
||||||
|
</FirebaseContext.Provider>
|
||||||
|
)
|
||||||
14
package.json
14
package.json
@@ -9,9 +9,23 @@
|
|||||||
"date-fns": "^1.30.1",
|
"date-fns": "^1.30.1",
|
||||||
"emotion-theming": "^10.0.10",
|
"emotion-theming": "^10.0.10",
|
||||||
"firebase": "^5.9.0",
|
"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": "^16.8.4",
|
||||||
"react-dom": "^16.8.4",
|
"react-dom": "^16.8.4",
|
||||||
"react-feather": "^1.1.6",
|
"react-feather": "^1.1.6",
|
||||||
|
"react-helmet": "^5.2.1",
|
||||||
"react-router-dom": "^5.0.0",
|
"react-router-dom": "^5.0.0",
|
||||||
"react-scripts": "2.1.8",
|
"react-scripts": "2.1.8",
|
||||||
"react-spinners": "^0.5.3",
|
"react-spinners": "^0.5.3",
|
||||||
|
|||||||
@@ -1,45 +1 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="ie=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><title data-react-helmet="true"></title><link rel="preload" as="font" type="font/woff2" crossorigin="anonymous" href="/google-fonts/s/montserrat/v13/JTURjIg1_i6t8kCHKm45_dJE3gnD_g.woff2"/><link rel="preload" as="font" type="font/woff2" crossorigin="anonymous" href="/google-fonts/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459Wlhyw.woff2"/><style type="text/css">@font-face{font-family:Montserrat;font-style:normal;font-weight:400;src:local('Montserrat Regular'),local('Montserrat-Regular'),url(/google-fonts/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459Wlhyw.woff2) format('woff2'),url(/google-fonts/s/montserrat/v13/JTUSjIg1_i6t8kCHKm459WlhzQ.woff) format('woff');font-display: swap;}@font-face{font-family:Montserrat;font-style:normal;font-weight:700;src:local('Montserrat Bold'),local('Montserrat-Bold'),url(/google-fonts/s/montserrat/v13/JTURjIg1_i6t8kCHKm45_dJE3gnD_g.woff2) format('woff2'),url(/google-fonts/s/montserrat/v13/JTURjIg1_i6t8kCHKm45_dJE3gnD-A.woff) format('woff');font-display: swap;}</style><link rel="shortcut icon" href="/icons/icon-48x48.png?v=54c7134a7e5384a7327f957c04754c6d"/><link rel="manifest" href="/manifest.webmanifest"/><meta name="theme-color" content="#FFF"/><link rel="apple-touch-icon" sizes="48x48" href="/icons/icon-48x48.png?v=54c7134a7e5384a7327f957c04754c6d"/><link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png?v=54c7134a7e5384a7327f957c04754c6d"/><link rel="apple-touch-icon" sizes="96x96" href="/icons/icon-96x96.png?v=54c7134a7e5384a7327f957c04754c6d"/><link rel="apple-touch-icon" sizes="144x144" href="/icons/icon-144x144.png?v=54c7134a7e5384a7327f957c04754c6d"/><link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192x192.png?v=54c7134a7e5384a7327f957c04754c6d"/><link rel="apple-touch-icon" sizes="256x256" href="/icons/icon-256x256.png?v=54c7134a7e5384a7327f957c04754c6d"/><link rel="apple-touch-icon" sizes="384x384" href="/icons/icon-384x384.png?v=54c7134a7e5384a7327f957c04754c6d"/><link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512x512.png?v=54c7134a7e5384a7327f957c04754c6d"/><script src="/socket.io/socket.io.js"></script></head><body><noscript id="gatsby-noscript">This app works best with JavaScript enabled.</noscript><div id="___gatsby"></div><script src="/commons.js"></script></body></html>
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
||||||
<meta
|
|
||||||
name="viewport"
|
|
||||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
|
||||||
/>
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<!--
|
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
||||||
-->
|
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css?family=Montserrat:400,700"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<!--
|
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
|
||||||
Only files inside the `public` folder can be referenced from the HTML.
|
|
||||||
|
|
||||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
||||||
work correctly both with client-side routing and a non-root public URL.
|
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
|
||||||
-->
|
|
||||||
<title>Sol Journal</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<div id="root"></div>
|
|
||||||
<!--
|
|
||||||
This HTML file is a template.
|
|
||||||
If you open it directly in the browser, you will see an empty page.
|
|
||||||
|
|
||||||
You can add webfonts, meta tags, or analytics to this file.
|
|
||||||
The build step will place the bundled scripts into the <body> tag.
|
|
||||||
|
|
||||||
To begin the development, run `npm start` or `yarn start`.
|
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
|
||||||
-->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
145
src/App.js
145
src/App.js
@@ -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 (
|
|
||||||
<ThemeProvider theme={currentTheme}>
|
|
||||||
<OnlineContext.Provider value={online}>
|
|
||||||
<Router>
|
|
||||||
<FullscreenLayout>
|
|
||||||
<Navbar toggleTheme={this.onChangeTheme} />
|
|
||||||
<RouteLayout>
|
|
||||||
<PrivateRoute
|
|
||||||
authed={authed}
|
|
||||||
path="/:year(\d+)"
|
|
||||||
component={Year}
|
|
||||||
exact
|
|
||||||
/>
|
|
||||||
<PrivateRoute
|
|
||||||
authed={authed}
|
|
||||||
path="/:year(\d+)/:month(0[1-9]|1[0-2]+)"
|
|
||||||
component={Month}
|
|
||||||
exact
|
|
||||||
/>
|
|
||||||
<PrivateRoute
|
|
||||||
authed={authed}
|
|
||||||
path="/:year(\d+)/:month(0[1-9]|1[0-2]+)/:day(\d+)"
|
|
||||||
component={Day}
|
|
||||||
exact
|
|
||||||
/>
|
|
||||||
<PrivateRoute
|
|
||||||
authed={authed}
|
|
||||||
path="/search"
|
|
||||||
component={Search}
|
|
||||||
exact
|
|
||||||
/>
|
|
||||||
<PrivateRoute
|
|
||||||
authed={authed}
|
|
||||||
path="/user"
|
|
||||||
component={User}
|
|
||||||
exact
|
|
||||||
/>
|
|
||||||
<Route path="/login" component={Login} exact />
|
|
||||||
<Route path="/register" component={Register} exact />
|
|
||||||
<Route path="/terms" component={Terms} exact />
|
|
||||||
<Route path="/privacy" component={Privacy} exact />
|
|
||||||
<Route path="/" component={Start} exact />
|
|
||||||
</RouteLayout>
|
|
||||||
</FullscreenLayout>
|
|
||||||
</Router>
|
|
||||||
</OnlineContext.Provider>
|
|
||||||
</ThemeProvider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withAuthentication,
|
|
||||||
withFirebase
|
|
||||||
)(App)
|
|
||||||
@@ -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(<App />, div)
|
|
||||||
ReactDOM.unmountComponentAtNode(div)
|
|
||||||
})
|
|
||||||
115
src/components/App.js
Normal file
115
src/components/App.js
Normal file
@@ -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 (
|
||||||
|
<ThemeTogglerContext.Consumer>
|
||||||
|
{({ toggle }) => (
|
||||||
|
<OnlineContext.Provider value={online}>
|
||||||
|
<FullscreenBgColor>
|
||||||
|
<Navbar toggleTheme={toggle} />
|
||||||
|
<RouteLayout>
|
||||||
|
<Router style={{ height: "100%" }}>
|
||||||
|
<PrivateRoute
|
||||||
|
authed={authed}
|
||||||
|
path="/app/:year"
|
||||||
|
component={Year}
|
||||||
|
exact
|
||||||
|
/>
|
||||||
|
<PrivateRoute
|
||||||
|
authed={authed}
|
||||||
|
path="/app/:year/:month"
|
||||||
|
component={Month}
|
||||||
|
exact
|
||||||
|
/>
|
||||||
|
<PrivateRoute
|
||||||
|
authed={authed}
|
||||||
|
path="/app/:year/:month/:day"
|
||||||
|
component={Day}
|
||||||
|
exact
|
||||||
|
/>
|
||||||
|
<PrivateRoute
|
||||||
|
authed={authed}
|
||||||
|
path="/app/search"
|
||||||
|
component={Search}
|
||||||
|
exact
|
||||||
|
/>
|
||||||
|
<PrivateRoute
|
||||||
|
authed={authed}
|
||||||
|
path="/app/user"
|
||||||
|
component={User}
|
||||||
|
exact
|
||||||
|
/>
|
||||||
|
<Welcome authed={authed} path="/app" exact />
|
||||||
|
</Router>
|
||||||
|
</RouteLayout>
|
||||||
|
</FullscreenBgColor>
|
||||||
|
</OnlineContext.Provider>
|
||||||
|
)}
|
||||||
|
</ThemeTogglerContext.Consumer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withAuthentication,
|
||||||
|
withFirebase,
|
||||||
|
withTheme
|
||||||
|
)(App)
|
||||||
55
src/components/Footer.js
Normal file
55
src/components/Footer.js
Normal file
@@ -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 }) => (
|
||||||
|
<FooterBlock>
|
||||||
|
<div>
|
||||||
|
<Logo color={theme.colors.secondary} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<FooterAnchor
|
||||||
|
href="https://github.com/gillkyle/sol-journal"
|
||||||
|
rel="target noopener"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
View on GitHub
|
||||||
|
</FooterAnchor>
|
||||||
|
<FooterLink to="terms">Terms of Service</FooterLink>
|
||||||
|
<FooterLink to="privacy">Privacy Policy</FooterLink>
|
||||||
|
</div>
|
||||||
|
<div>© 2019</div>
|
||||||
|
</FooterBlock>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default withTheme(Footer)
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Icon from "./Icon"
|
|
||||||
export default Icon
|
|
||||||
47
src/components/Layout.js
Normal file
47
src/components/Layout.js
Normal file
@@ -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 }) => (
|
||||||
|
<>
|
||||||
|
<Helmet title="Sol Journal" />
|
||||||
|
{/* some styles should applied globally via the layout */}
|
||||||
|
<Global
|
||||||
|
styles={css`
|
||||||
|
* {
|
||||||
|
transition: 0.2s border-color ease-in-out, 0.2s fill ease-in-out,
|
||||||
|
0.2s box-shadow ease-in-out, 0.2s background-color ease-in-out,
|
||||||
|
0.2s color ease-in-out;
|
||||||
|
overflow: -moz-scrollbars-none;
|
||||||
|
}
|
||||||
|
*::-webkit-scrollbar {
|
||||||
|
width: 0 !important;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
background-color: ${theme.colors.bodyBackground};
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-family: "Montserrat", -apple-system, BlinkMacSystemFont,
|
||||||
|
"Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans",
|
||||||
|
"Droid Sans", "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
|
||||||
|
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
|
||||||
|
"Helvetica Neue", sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default withTheme(Layout)
|
||||||
158
src/components/Navbar.js
Normal file
158
src/components/Navbar.js
Normal file
@@ -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 }) => (
|
||||||
|
<Header>
|
||||||
|
<Nav>
|
||||||
|
<LogoSection onClick={() => navigate("/app")}>
|
||||||
|
<Logo color={theme.colors.logo} />
|
||||||
|
<LogoText color={theme.colors.primary}>SOL</LogoText>{" "}
|
||||||
|
<LogoText color={theme.colors.secondary}>JOURNAL</LogoText>
|
||||||
|
</LogoSection>
|
||||||
|
<NavIcons>
|
||||||
|
{authUser ? (
|
||||||
|
<React.Fragment>
|
||||||
|
<StyledLink to={todayUrl()}>
|
||||||
|
<Icon name="Edit2" />
|
||||||
|
</StyledLink>
|
||||||
|
<StyledLink to={yearUrl()}>
|
||||||
|
<Icon name="Calendar" />
|
||||||
|
</StyledLink>
|
||||||
|
<StyledLink to={"/search"}>
|
||||||
|
<Icon name="Search" />
|
||||||
|
</StyledLink>
|
||||||
|
<StyledLink to={"/user"}>
|
||||||
|
<Icon name="User" />
|
||||||
|
</StyledLink>
|
||||||
|
<Icon
|
||||||
|
tabindex={0}
|
||||||
|
onClick={() => toggleTheme()}
|
||||||
|
onKeyPress={() => toggleTheme()}
|
||||||
|
name={theme.name === "Dark" ? "Sun" : "Moon"}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Link to={"/login"} style={{ textDecoration: "none" }}>
|
||||||
|
<Icon name="ArrowRight" label="Login" size={20} />
|
||||||
|
</Link>
|
||||||
|
<Icon
|
||||||
|
tabindex={0}
|
||||||
|
onClick={() => toggleTheme()}
|
||||||
|
onKeyPress={() => toggleTheme()}
|
||||||
|
name={theme.name === "Dark" ? "Sun" : "Moon"}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</NavIcons>
|
||||||
|
</Nav>
|
||||||
|
</Header>
|
||||||
|
)
|
||||||
|
|
||||||
|
// on langing page and simple pages outside the app, simplify link options
|
||||||
|
const SimpleNav = ({ authUser, theme }) => (
|
||||||
|
<Header>
|
||||||
|
<Nav>
|
||||||
|
<LogoSection onClick={() => navigate("/")}>
|
||||||
|
<Logo color={theme.colors.logo} />
|
||||||
|
<LogoText color={theme.colors.primary}>SOL</LogoText>{" "}
|
||||||
|
<LogoText color={theme.colors.secondary}>JOURNAL</LogoText>
|
||||||
|
</LogoSection>
|
||||||
|
<NavIcons>
|
||||||
|
{authUser ? (
|
||||||
|
<StyledLink to={"/"}>
|
||||||
|
<Icon name="Circle" />
|
||||||
|
</StyledLink>
|
||||||
|
) : (
|
||||||
|
<Link to={"/login"} style={{ textDecoration: "none" }}>
|
||||||
|
<Icon name="ArrowRight" label="Login" size={20} />
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
<ThemeTogglerContext.Consumer>
|
||||||
|
{({ toggle }) => (
|
||||||
|
<Icon
|
||||||
|
tabindex={0}
|
||||||
|
onClick={() => toggle()}
|
||||||
|
onKeyPress={() => toggle()}
|
||||||
|
name={theme.name === "Dark" ? "Sun" : "Moon"}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ThemeTogglerContext.Consumer>
|
||||||
|
</NavIcons>
|
||||||
|
</Nav>
|
||||||
|
</Header>
|
||||||
|
)
|
||||||
|
|
||||||
|
const SimpleNavbar = compose(
|
||||||
|
withAuthentication,
|
||||||
|
withTheme
|
||||||
|
)(SimpleNav)
|
||||||
|
|
||||||
|
export { SimpleNavbar }
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withAuthentication,
|
||||||
|
withTheme
|
||||||
|
)(Navbar)
|
||||||
@@ -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 }) => (
|
|
||||||
<Header>
|
|
||||||
<Nav>
|
|
||||||
<LogoSection onClick={() => history.push("/")}>
|
|
||||||
<Logo color={theme.colors.logo} />
|
|
||||||
<LogoText color={theme.colors.primary}>SOL</LogoText>{" "}
|
|
||||||
<LogoText color={theme.colors.secondary}>JOURNAL</LogoText>
|
|
||||||
</LogoSection>
|
|
||||||
<NavIcons>
|
|
||||||
{authUser ? (
|
|
||||||
<React.Fragment>
|
|
||||||
<Link to={todayUrl()}>
|
|
||||||
<Icon name="Edit2" />
|
|
||||||
</Link>
|
|
||||||
<Link to={yearUrl()}>
|
|
||||||
<Icon name="Calendar" />
|
|
||||||
</Link>
|
|
||||||
<Link to={"/search"}>
|
|
||||||
<Icon name="Search" />
|
|
||||||
</Link>
|
|
||||||
<Link to={"/user"}>
|
|
||||||
<Icon name="User" />
|
|
||||||
</Link>
|
|
||||||
<Icon
|
|
||||||
tabindex={0}
|
|
||||||
onClick={() => toggleTheme()}
|
|
||||||
onKeyPress={() => toggleTheme()}
|
|
||||||
name={theme.name === "Dark" ? "Sun" : "Moon"}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
|
||||||
) : (
|
|
||||||
<React.Fragment>
|
|
||||||
{/* <Link to={"/"}>Landing</Link> */}
|
|
||||||
<Link to={"/login"}>
|
|
||||||
<Icon name="LogIn" label="Get Started" />
|
|
||||||
</Link>
|
|
||||||
{/* <Link to={"/register"}>Register</Link> */}
|
|
||||||
</React.Fragment>
|
|
||||||
)}
|
|
||||||
</NavIcons>
|
|
||||||
</Nav>
|
|
||||||
</Header>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withAuthentication,
|
|
||||||
withTheme,
|
|
||||||
withRouter
|
|
||||||
)(Navbar)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Navbar from "./Navbar"
|
|
||||||
export default Navbar
|
|
||||||
19
src/components/PrivateRoute.js
Normal file
19
src/components/PrivateRoute.js
Normal file
@@ -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>
|
||||||
|
{({ location }) =>
|
||||||
|
authed === true ? (
|
||||||
|
<Component {...rest} />
|
||||||
|
) : (
|
||||||
|
<Redirect to="/login" from={location.pathname} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Location>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PrivateRoute
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import React from "react"
|
|
||||||
import { Route, Redirect } from "react-router-dom"
|
|
||||||
|
|
||||||
const PrivateRoute = ({ component: Component, authed, ...rest }) => {
|
|
||||||
return (
|
|
||||||
<Route
|
|
||||||
{...rest}
|
|
||||||
render={props =>
|
|
||||||
authed === true ? (
|
|
||||||
<Component {...props} />
|
|
||||||
) : (
|
|
||||||
<Redirect
|
|
||||||
to={{ pathname: "/login", state: { from: props.location } }}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PrivateRoute
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import PrivateRoute from "./PrivateRoute"
|
|
||||||
export default PrivateRoute
|
|
||||||
@@ -2,9 +2,9 @@ import React from "react"
|
|||||||
import styled from "@emotion/styled"
|
import styled from "@emotion/styled"
|
||||||
import { withTheme } from "emotion-theming"
|
import { withTheme } from "emotion-theming"
|
||||||
|
|
||||||
import Icon from "../Icon"
|
import Icon from "components/Icon"
|
||||||
import { H1 } from "../elements"
|
import { H1 } from "components/elements"
|
||||||
import { StyledLink as Link } from "../elements"
|
import { StyledLink as Link } from "components/elements"
|
||||||
|
|
||||||
const SeekHeader = styled.header`
|
const SeekHeader = styled.header`
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Seek from "./Seek"
|
|
||||||
export default Seek
|
|
||||||
@@ -2,9 +2,9 @@ import React from "react"
|
|||||||
import { compose } from "recompose"
|
import { compose } from "recompose"
|
||||||
import { withTheme } from "emotion-theming"
|
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 }) => (
|
const SignOutButton = ({ firebase, theme }) => (
|
||||||
<Button
|
<Button
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import SignOut from "./SignOut"
|
|
||||||
export default SignOut
|
|
||||||
16
src/components/container.js
Normal file
16
src/components/container.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import React from "react"
|
||||||
|
import styled from "@emotion/styled"
|
||||||
|
|
||||||
|
import { SIZES } from "styles/constants"
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 10px;
|
||||||
|
max-width: ${SIZES.maxWidth};
|
||||||
|
min-height: calc(100vh - 60px);
|
||||||
|
`
|
||||||
|
|
||||||
|
export default Container
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react'
|
import React from "react"
|
||||||
|
|
||||||
|
// when navigator is available outside of the build phase, provide it through Context
|
||||||
export const OnlineContext = React.createContext({
|
export const OnlineContext = React.createContext({
|
||||||
online: navigator.onLine,
|
online: typeof window !== "undefined" && navigator && navigator.onLine,
|
||||||
});
|
})
|
||||||
|
|||||||
67
src/components/context/theme.js
Normal file
67
src/components/context/theme.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { Helmet } from "react-helmet"
|
||||||
|
import theme from "styles/theme"
|
||||||
|
|
||||||
|
// create an app-wide context for the theme being used as
|
||||||
|
// well as a function to toggle it back and forth
|
||||||
|
const ThemeTogglerContext = React.createContext({
|
||||||
|
themeName: "LIGHT",
|
||||||
|
toggle: () => {},
|
||||||
|
})
|
||||||
|
|
||||||
|
class ThemeToggler extends React.Component {
|
||||||
|
state = {
|
||||||
|
themeName:
|
||||||
|
new Date().getHours() >= 7 && new Date().getHours() <= 21
|
||||||
|
? "LIGHT"
|
||||||
|
: "DARK",
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
// set the body style property on mount so routes don't flash between transitions
|
||||||
|
const { themeName } = this.state
|
||||||
|
this.toggle(themeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle = newThemeName => {
|
||||||
|
const { themeName } = this.state
|
||||||
|
const body = document.body
|
||||||
|
let newTheme
|
||||||
|
if (newThemeName) {
|
||||||
|
newTheme = newThemeName
|
||||||
|
} else {
|
||||||
|
newTheme = themeName === "LIGHT" ? "DARK" : "LIGHT"
|
||||||
|
}
|
||||||
|
body.style.setProperty(
|
||||||
|
"background-color",
|
||||||
|
theme[newTheme].colors.bodyBackground
|
||||||
|
)
|
||||||
|
|
||||||
|
this.setState({ themeName: newTheme })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { children } = this.props
|
||||||
|
const { themeName } = this.state
|
||||||
|
return (
|
||||||
|
<ThemeTogglerContext.Provider
|
||||||
|
value={{
|
||||||
|
themeName,
|
||||||
|
toggle: this.toggle,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Helmet>
|
||||||
|
<meta
|
||||||
|
name="theme-color"
|
||||||
|
content={theme[themeName].colors.bodyBackground}
|
||||||
|
/>
|
||||||
|
</Helmet>
|
||||||
|
{children}
|
||||||
|
</ThemeTogglerContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThemeTogglerContext
|
||||||
|
|
||||||
|
export { ThemeToggler }
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
|
import React from "react"
|
||||||
import { withTheme } from "emotion-theming"
|
import { withTheme } from "emotion-theming"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "gatsby"
|
||||||
import styled from "@emotion/styled"
|
import styled from "@emotion/styled"
|
||||||
|
|
||||||
import { SIZES } from "../../styles/constants"
|
import { SIZES } from "styles/constants"
|
||||||
|
|
||||||
export const H1 = styled.h1`
|
export const H1 = styled.h1`
|
||||||
display: block;
|
display: block;
|
||||||
@@ -10,6 +11,18 @@ export const H1 = styled.h1`
|
|||||||
color: ${props => props.color};
|
color: ${props => props.color};
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const SimpleH1 = styled.h1`
|
||||||
|
color: ${props => props.color};
|
||||||
|
`
|
||||||
|
|
||||||
|
export const SimpleH2 = styled.h1`
|
||||||
|
color: ${props => props.color};
|
||||||
|
`
|
||||||
|
|
||||||
|
export const Em = styled.em`
|
||||||
|
color: ${props => props.color};
|
||||||
|
`
|
||||||
|
|
||||||
export const Input = styled.input`
|
export const Input = styled.input`
|
||||||
color: ${props => props.colors.primary};
|
color: ${props => props.colors.primary};
|
||||||
background-color: ${props => props.colors.headerBackground};
|
background-color: ${props => props.colors.headerBackground};
|
||||||
@@ -33,23 +46,24 @@ export const Input = styled.input`
|
|||||||
|
|
||||||
export const Button = styled.button`
|
export const Button = styled.button`
|
||||||
display: inline;
|
display: inline;
|
||||||
background-color: ${props => props.colors.primary};
|
color: ${props => props.colors.primary};
|
||||||
|
background-color: ${props => props.colors.button};
|
||||||
|
border-color: ${props => props.colors.quarternary};
|
||||||
padding: 12px 50px;
|
padding: 12px 50px;
|
||||||
min-height: 45px;
|
min-height: 45px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 0px solid;
|
border: 0px solid;
|
||||||
border-color: ${props => props.colors.quarternary};
|
font-family: Montserrat;
|
||||||
color: ${props => props.colors.quarternary};
|
|
||||||
font-size: ${props => SIZES[props.fontSize || "normal"]};
|
font-size: ${props => SIZES[props.fontSize || "normal"]};
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
outline: none;
|
outline: none;
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: ${props => props.colors.secondary};
|
background-color: ${props => props.colors.hover};
|
||||||
|
box-shadow: 0 0 0 3px ${props => props.colors.bodyBackground},
|
||||||
|
0 0 0 5px ${props => props.colors.button};
|
||||||
}
|
}
|
||||||
&:focus {
|
&:focus {
|
||||||
box-shadow: 0 0 0 3px ${props => props.colors.bodyBackground},
|
|
||||||
0 0 0 5px ${props => props.colors.secondary};
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -57,7 +71,10 @@ export const P = styled.p`
|
|||||||
color: ${props => props.theme.colors.secondary};
|
color: ${props => props.theme.colors.secondary};
|
||||||
`
|
`
|
||||||
|
|
||||||
export const StyledLink = withTheme(styled(Link)`
|
// prepend links used within the app section with app
|
||||||
|
export const AppLink = props => <Link {...props} to={"/app" + props.to} />
|
||||||
|
|
||||||
|
export const StyledLink = withTheme(styled(AppLink)`
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * from "./elements"
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
|
|
||||||
|
// create context of firebase instance
|
||||||
const FirebaseContext = React.createContext(null)
|
const FirebaseContext = React.createContext(null)
|
||||||
|
|
||||||
export const withFirebase = Component => props => (
|
export const withFirebase = Component => props => (
|
||||||
|
|||||||
@@ -2,48 +2,61 @@ import app from "firebase/app"
|
|||||||
import "firebase/auth"
|
import "firebase/auth"
|
||||||
import "firebase/firestore"
|
import "firebase/firestore"
|
||||||
|
|
||||||
|
// store private keys in .env file
|
||||||
|
// the prefix GATSBY_ is necessary here
|
||||||
const config = {
|
const config = {
|
||||||
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
|
apiKey: process.env.GATSBY_FIREBASE_API_KEY,
|
||||||
authDomain: process.env.REACT_APP_DEV_AUTH_DOMAIN,
|
authDomain: process.env.GATSBY_DEV_AUTH_DOMAIN,
|
||||||
databaseURL: process.env.REACT_APP_DEV_DATABASE_URL,
|
databaseURL: process.env.GATSBY_DEV_DATABASE_URL,
|
||||||
projectId: process.env.REACT_APP_DEV_PROJECT_ID,
|
projectId: process.env.GATSBY_DEV_PROJECT_ID,
|
||||||
storageBucket: process.env.REACT_APP_DEV_STORAGE_BUCKET,
|
storageBucket: process.env.GATSBY_DEV_STORAGE_BUCKET,
|
||||||
messagingSenderId: process.env.REACT_APP_DEV_MESSAGING_SENDER_ID,
|
messagingSenderId: process.env.GATSBY_DEV_MESSAGING_SENDER_ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
class Firebase {
|
class Firebase {
|
||||||
constructor() {
|
constructor() {
|
||||||
app.initializeApp(config)
|
// protect with conditional so gatsby build doesn't have
|
||||||
this.auth = app.auth()
|
// issues trying to access the window object
|
||||||
this.db = app.firestore()
|
if (typeof window !== "undefined") {
|
||||||
app
|
app.initializeApp(config)
|
||||||
.firestore()
|
this.auth = app.auth()
|
||||||
.enablePersistence()
|
this.db = app.firestore()
|
||||||
.catch(function(err) {
|
app
|
||||||
if (err.code === "failed-precondition") {
|
.firestore()
|
||||||
console.error("firestore won't work offline with multiple tabs open")
|
.enablePersistence()
|
||||||
} else if (err.code === "unimplemented") {
|
.catch(function(err) {
|
||||||
console.error(
|
if (err.code === "failed-precondition") {
|
||||||
"current browser can't take advantage of firestore offline"
|
console.error(
|
||||||
)
|
"firestore won't work offline with multiple tabs open"
|
||||||
}
|
)
|
||||||
})
|
} else if (err.code === "unimplemented") {
|
||||||
|
console.error(
|
||||||
|
"current browser can't take advantage of firestore offline"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth
|
// authentication
|
||||||
|
// create user in the database
|
||||||
doCreateUserWithEmailAndPassword = (email, password) =>
|
doCreateUserWithEmailAndPassword = (email, password) =>
|
||||||
this.auth.createUserWithEmailAndPassword(email, password)
|
this.auth.createUserWithEmailAndPassword(email, password)
|
||||||
|
|
||||||
|
// login already existing user
|
||||||
doSignInWithEmailAndPassword = (email, password) =>
|
doSignInWithEmailAndPassword = (email, password) =>
|
||||||
this.auth.signInWithEmailAndPassword(email, password)
|
this.auth.signInWithEmailAndPassword(email, password)
|
||||||
|
|
||||||
|
// sign out user
|
||||||
doSignOut = () => {
|
doSignOut = () => {
|
||||||
this.auth.signOut()
|
this.auth.signOut()
|
||||||
window.location.replace("/login")
|
window.location.replace("/login")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send email reset to email provided
|
||||||
doPasswordReset = email => this.auth.sendPasswordResetEmail(email)
|
doPasswordReset = email => this.auth.sendPasswordResetEmail(email)
|
||||||
|
|
||||||
|
// change password to password provided
|
||||||
doPasswordUpdate = password => this.auth.currentUser.updatePassword(password)
|
doPasswordUpdate = password => this.auth.currentUser.updatePassword(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
import Day from "./Day"
|
|
||||||
export default Day
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Login from "./Login"
|
|
||||||
export default Login
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Month from "./Month"
|
|
||||||
export default Month
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
import React, { Component } from "react"
|
|
||||||
import { withRouter } from "react-router-dom"
|
|
||||||
import styled from "@emotion/styled"
|
|
||||||
import { compose } from "recompose"
|
|
||||||
import { format } from "date-fns"
|
|
||||||
import { withTheme } from "emotion-theming"
|
|
||||||
|
|
||||||
import { Input, Button, P } from "../../elements"
|
|
||||||
import { SIZES } from "../../../styles/constants"
|
|
||||||
import { StyledLink as Link } from "../../elements"
|
|
||||||
|
|
||||||
const Terms = ({}) => (
|
|
||||||
<>
|
|
||||||
<h1>Privacy Policy</h1>
|
|
||||||
<em>Last update: April 30, 2019</em>
|
|
||||||
<P>
|
|
||||||
Sol Journal supports the following browsers: Chrome (latest), Safari
|
|
||||||
(latest), Firefox (50+)
|
|
||||||
</P>
|
|
||||||
<h2>Rights</h2>
|
|
||||||
<P>
|
|
||||||
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.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You have the right to export your data at any time, in JSON format.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
Your data will not be intentionally shown to other users or shared with
|
|
||||||
third parties.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
Your personal data will not be shared with anyone without your consent.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
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.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
If the site ceases operation, you will receive an opportunity to export
|
|
||||||
all your data before the site dies.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
Any new features that affect privacy will be strictly opt-in.
|
|
||||||
</P>
|
|
||||||
<h2>Responsibilites</h2>
|
|
||||||
<P>
|
|
||||||
You will not use the site to store illegal information or data under
|
|
||||||
United States law (or any law).
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You have to be at least 18+ to create an account and use the site.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You must not abuse the site by knowingly posting malicious code that could
|
|
||||||
harm you or the other users.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You may not make automated requests to the site.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You may not abuse the registration system.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You are responsible for keeping your account secure.
|
|
||||||
<br />
|
|
||||||
<br />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.
|
|
||||||
</P>
|
|
||||||
<h2>Other</h2>
|
|
||||||
<P>
|
|
||||||
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.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
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.
|
|
||||||
</P>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default withTheme(Terms)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Privacy from "./Privacy"
|
|
||||||
export default Privacy
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Register from "./Register"
|
|
||||||
export default Register
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Search from "./Search"
|
|
||||||
export default Search
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Start from "./Start"
|
|
||||||
export default Start
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
import React from "react"
|
|
||||||
|
|
||||||
import { P } from "../../elements"
|
|
||||||
|
|
||||||
const Terms = () => (
|
|
||||||
<>
|
|
||||||
<h1>Terms of Service</h1>
|
|
||||||
<em>Last update: April 30, 2019</em>
|
|
||||||
<h2>Scope of Service</h2>
|
|
||||||
<P>
|
|
||||||
Sol Journal supports the following browsers: Chrome (latest), Safari
|
|
||||||
(latest), Firefox (50+)
|
|
||||||
</P>
|
|
||||||
<h2>Rights</h2>
|
|
||||||
<P>
|
|
||||||
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.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You have the right to export your data at any time, in JSON format.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
Your data will not be intentionally shown to other users or shared with
|
|
||||||
third parties.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
Your personal data will not be shared with anyone without your consent.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
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.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
Any new features that affect privacy will be strictly opt-in.
|
|
||||||
</P>
|
|
||||||
<h2>Responsibilites</h2>
|
|
||||||
<P>
|
|
||||||
You will not use the site to store illegal information or data under
|
|
||||||
United States law (or any law).
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You have to be at least 18+ to create an account and use the site.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You must not abuse the site by knowingly posting malicious code that could
|
|
||||||
harm you or the other users.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You may not make automated requests to the site.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You may not abuse the registration system.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
You are responsible for keeping your account secure.
|
|
||||||
<br />
|
|
||||||
<br />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.
|
|
||||||
</P>
|
|
||||||
<h2>Other</h2>
|
|
||||||
<P>
|
|
||||||
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.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
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.
|
|
||||||
</P>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default Terms
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Terms from "./Terms"
|
|
||||||
export default Terms
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import User from "./User"
|
|
||||||
export default User
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import Year from "./Year"
|
|
||||||
export default Year
|
|
||||||
@@ -1,29 +1,39 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
|
|
||||||
import AuthUserContext from "./context"
|
import AuthUserContext from "./context"
|
||||||
import { withFirebase } from "../firebase"
|
import { withFirebase } from "components/firebase"
|
||||||
|
|
||||||
|
// use context to provide all app components with information about
|
||||||
|
// the authUser if it's been put in localStorage
|
||||||
const withAuthentication = Component => {
|
const withAuthentication = Component => {
|
||||||
class WithAuthentication extends React.Component {
|
class WithAuthentication extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.state = {
|
// protect browser API's like localStorage so Gatsby builds don't fail
|
||||||
authUser: JSON.parse(localStorage.getItem("authUser")),
|
if (typeof window !== "undefined") {
|
||||||
|
this.state = {
|
||||||
|
authUser: JSON.parse(localStorage.getItem("authUser")),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.state = { authUser: null }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.listener = this.props.firebase.auth.onAuthStateChanged(
|
this.listener = this.props.firebase.auth.onAuthStateChanged(
|
||||||
authUser => {
|
authUser => {
|
||||||
|
// accessing localStorage in componentDidMount is fine in Gatsby
|
||||||
localStorage.setItem("authUser", JSON.stringify(authUser))
|
localStorage.setItem("authUser", JSON.stringify(authUser))
|
||||||
this.setState({
|
if (authUser) {
|
||||||
authUser: {
|
this.setState({
|
||||||
uid: authUser.uid,
|
authUser: {
|
||||||
email: authUser.email,
|
uid: authUser.uid,
|
||||||
emailVerified: authUser.emailVerified,
|
email: authUser.email,
|
||||||
},
|
emailVerified: authUser.emailVerified,
|
||||||
})
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
localStorage.removeItem("authUser")
|
localStorage.removeItem("authUser")
|
||||||
|
|||||||
74
src/data/quotes.json
Normal file
74
src/data/quotes.json
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"quote": "Dude, sucking at something is the first step to being sorta good at something.",
|
||||||
|
"author": "Jake the Dog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "Journal writing is a voyage to the interior.",
|
||||||
|
"author": "Christina Baldwin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "Blessed is he who keeps daily diary and compares the work of this week with that of the last, for he will realize God quickly!",
|
||||||
|
"author": "Sivananda Saraswati"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "Each Bullet Journal becomes another volume in the story of your life. Does it represent the life you want to live? If not, then leverage the lessons you've learned to change the narrative in the next volume.",
|
||||||
|
"author": "Ryder Carroll"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "Authentic writing cannot be coerced.",
|
||||||
|
"author": "Ernst Jünger"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "If kids reflect on their days, they will become better problem-solvers of life.",
|
||||||
|
"author": "Trevor Carss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "The best time to begin keeping a journal is whenever you decide to.",
|
||||||
|
"author": "Hannah Hinchman"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "He said, You'll write it not because there's no possibility it'll be found but because it costs too much to not write it.",
|
||||||
|
"author": "China Miéville"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "In the diary you find proof that in situations which today would seem unbearable, you lived, looked around and wrote down observations, that this right hand moved then as it does today...",
|
||||||
|
"author": "Franz Kafka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "In the journal I do not just express myself more openly than I could to any person; I create myself.",
|
||||||
|
"author": "Susan Sontag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "But what am I to do? I must have some drug, and reading isn’t a strong enough drug now.",
|
||||||
|
"author": "C.S. Lewis"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "What a comfort is this journal. I tell myself to myself and throw the burden on my book and feel relieved.",
|
||||||
|
"author": "Anne Lister"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "If there was no other motive in view [except] to have the privilege of reading over our journals and for our children to read, it would pay for the time spent in writing it.",
|
||||||
|
"author": "Wilford Woodruff"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "As there are a thousand thoughts lying within a man that he does not know till he takes up the pen to write.",
|
||||||
|
"author": "William Makepeace Thackeray"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "I want to write, but more than that, I want to bring out all kinds of things that lie buried deep in my heart.",
|
||||||
|
"author": "Anne Frank"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "A diary is useful during conscious, intentional, and painful spiritual evolutions.",
|
||||||
|
"author": "André Gide"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "Most folks are about as happy as they make up their minds to be.",
|
||||||
|
"author": "Abraham Lincoln"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quote": "It takes no more time to see the good side of life than it takes to see the bad.",
|
||||||
|
"author": "Jimmy Buffet"
|
||||||
|
}
|
||||||
|
]
|
||||||
BIN
src/img/landing-graphic-dark.png
Normal file
BIN
src/img/landing-graphic-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
src/img/landing-graphic-light.png
Normal file
BIN
src/img/landing-graphic-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
src/img/splash.png
Normal file
BIN
src/img/splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -1,12 +0,0 @@
|
|||||||
* {
|
|
||||||
transition: 0.2s all ease-in-out;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
|
||||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
19
src/index.js
19
src/index.js
@@ -1,19 +0,0 @@
|
|||||||
import React from "react"
|
|
||||||
import ReactDOM from "react-dom"
|
|
||||||
|
|
||||||
import "./index.css"
|
|
||||||
import App from "./App"
|
|
||||||
import * as serviceWorker from "./serviceWorker"
|
|
||||||
import Firebase, { FirebaseContext } from "./components/firebase"
|
|
||||||
|
|
||||||
ReactDOM.render(
|
|
||||||
<FirebaseContext.Provider value={new Firebase()}>
|
|
||||||
<App />
|
|
||||||
</FirebaseContext.Provider>,
|
|
||||||
document.getElementById("root")
|
|
||||||
)
|
|
||||||
|
|
||||||
// If you want your app to work offline and load faster, you can change
|
|
||||||
// unregister() to register() below. Note this comes with some pitfalls.
|
|
||||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
|
||||||
serviceWorker.register()
|
|
||||||
15
src/pages/app.js
Normal file
15
src/pages/app.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import React from "react"
|
||||||
|
|
||||||
|
import App from "components/App"
|
||||||
|
import Layout from "components/Layout"
|
||||||
|
|
||||||
|
/* similar to create-react-app, the App.js is like the
|
||||||
|
entrypoint to the protected/client only content,
|
||||||
|
Context providers are moved to gatsby-browser.js
|
||||||
|
to wrap the root element with necessary providers
|
||||||
|
and context */
|
||||||
|
export default () => (
|
||||||
|
<Layout>
|
||||||
|
<App />
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
17
src/pages/index.js
Normal file
17
src/pages/index.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { SimpleNavbar } from "components/Navbar"
|
||||||
|
import Index from "routes/Start"
|
||||||
|
import Layout from "components/Layout"
|
||||||
|
import Container from "components/container"
|
||||||
|
|
||||||
|
// the landing page is generated like other Gatsby pages
|
||||||
|
// other unprotected routes like /login, /privacy, etc
|
||||||
|
// are completely server side rendered by gatsby build
|
||||||
|
export default () => (
|
||||||
|
<Layout>
|
||||||
|
<SimpleNavbar />
|
||||||
|
<Container>
|
||||||
|
<Index />
|
||||||
|
</Container>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import { withRouter } from "react-router-dom"
|
import { navigate, Link } from "gatsby"
|
||||||
import styled from "@emotion/styled"
|
import styled from "@emotion/styled"
|
||||||
import { compose } from "recompose"
|
import { compose } from "recompose"
|
||||||
import { format } from "date-fns"
|
import { format } from "date-fns"
|
||||||
import { withTheme } from "emotion-theming"
|
import { withTheme } from "emotion-theming"
|
||||||
|
|
||||||
import { Input, Button, P } from "../../elements"
|
import { SimpleNavbar } from "components/Navbar"
|
||||||
import { SIZES } from "../../../styles/constants"
|
import { Input, Button, P } from "components/elements"
|
||||||
import { StyledLink as Link } from "../../elements"
|
import Layout from "components/Layout"
|
||||||
|
import { FirebaseContext } from "components/firebase"
|
||||||
import { FirebaseContext } from "../../firebase"
|
import { SIZES } from "styles/constants"
|
||||||
|
|
||||||
const LoginGrid = styled.div`
|
const LoginGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -19,19 +19,24 @@ const LoginGrid = styled.div`
|
|||||||
const LoginLayout = styled.div`
|
const LoginLayout = styled.div`
|
||||||
max-width: ${SIZES.smallWidth};
|
max-width: ${SIZES.smallWidth};
|
||||||
width: 100%;
|
width: 100%;
|
||||||
align-self: center;
|
margin: 20px auto;
|
||||||
margin-top: 20px;
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const LoginPage = ({ history, theme }) => (
|
const LoginPage = ({ theme }) => (
|
||||||
<LoginLayout>
|
<Layout>
|
||||||
<FirebaseContext.Consumer>
|
<SimpleNavbar />
|
||||||
{firebase => <LoginForm history={history} firebase={firebase} />}
|
<LoginLayout>
|
||||||
</FirebaseContext.Consumer>
|
<FirebaseContext.Consumer>
|
||||||
<P colors={theme.colors} style={{ fontStyle: "italic" }}>
|
{firebase => <LoginForm firebase={firebase} />}
|
||||||
Don't have an account? <Link to={"/register"}>Sign Up</Link>
|
</FirebaseContext.Consumer>
|
||||||
</P>
|
<P colors={theme.colors} style={{ fontStyle: "italic" }}>
|
||||||
</LoginLayout>
|
Don't have an account?{" "}
|
||||||
|
<Link style={{ color: theme.colors.primary }} to={"/register"}>
|
||||||
|
Sign Up
|
||||||
|
</Link>
|
||||||
|
</P>
|
||||||
|
</LoginLayout>
|
||||||
|
</Layout>
|
||||||
)
|
)
|
||||||
|
|
||||||
class LoginFormBase extends Component {
|
class LoginFormBase extends Component {
|
||||||
@@ -49,7 +54,7 @@ class LoginFormBase extends Component {
|
|||||||
.doSignInWithEmailAndPassword(email, password)
|
.doSignInWithEmailAndPassword(email, password)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.setState({ email: "", password: "", error: null })
|
this.setState({ email: "", password: "", error: null })
|
||||||
this.props.history.push(format(new Date(), "/"))
|
navigate(`app/${format(new Date(), "/")}`)
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.setState({ error })
|
this.setState({ error })
|
||||||
@@ -89,16 +94,13 @@ class LoginFormBase extends Component {
|
|||||||
Login
|
Login
|
||||||
</Button>
|
</Button>
|
||||||
</LoginGrid>
|
</LoginGrid>
|
||||||
{error && <p>{error.message}</p>}
|
{error && <P colors={theme.colors}>{error.message}</P>}
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LoginForm = compose(
|
const LoginForm = compose(withTheme)(LoginFormBase)
|
||||||
withTheme,
|
|
||||||
withRouter
|
|
||||||
)(LoginFormBase)
|
|
||||||
|
|
||||||
export default withTheme(LoginPage)
|
export default withTheme(LoginPage)
|
||||||
|
|
||||||
94
src/pages/privacy.js
Normal file
94
src/pages/privacy.js
Normal file
@@ -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 }) => (
|
||||||
|
<Layout>
|
||||||
|
<SimpleNavbar />
|
||||||
|
<Container>
|
||||||
|
<SimpleH1 color={theme.colors.primary}>Privacy Policy</SimpleH1>
|
||||||
|
<Em color={theme.colors.secondary}>Last update: April 30, 2019</Em>{" "}
|
||||||
|
<P>
|
||||||
|
Sol Journal supports the following browsers: Chrome (latest), Safari
|
||||||
|
(latest), Firefox (50+)
|
||||||
|
</P>
|
||||||
|
<SimpleH2 color={theme.colors.secondary}>Rights</SimpleH2>
|
||||||
|
<P>
|
||||||
|
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.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You have the right to export your data at any time, in JSON format.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Your data will not be intentionally shown to other users or shared with
|
||||||
|
third parties.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Your personal data will not be shared with anyone without your consent.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
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.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
If the site ceases operation, you will receive an opportunity to export
|
||||||
|
all your data before the site dies.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Any new features that affect privacy will be strictly opt-in.
|
||||||
|
</P>
|
||||||
|
<SimpleH2 color={theme.colors.secondary}>Responsibilites</SimpleH2>
|
||||||
|
<P>
|
||||||
|
You will not use the site to store illegal information or data under
|
||||||
|
United States law (or any law).
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You have to be at least 18+ to create an account and use the site.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You must not abuse the site by knowingly posting malicious code that
|
||||||
|
could harm you or the other users.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You may not make automated requests to the site.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You may not abuse the registration system.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You are responsible for keeping your account secure.
|
||||||
|
<br />
|
||||||
|
<br />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.
|
||||||
|
</P>
|
||||||
|
<SimpleH2 color={theme.colors.secondary}>Other</SimpleH2>
|
||||||
|
<P>
|
||||||
|
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.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
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.
|
||||||
|
</P>
|
||||||
|
</Container>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default withTheme(Terms)
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import { withRouter } from "react-router-dom"
|
|
||||||
import styled from "@emotion/styled"
|
import styled from "@emotion/styled"
|
||||||
|
import { navigate, Link } from "gatsby"
|
||||||
import { compose } from "recompose"
|
import { compose } from "recompose"
|
||||||
import { withTheme } from "emotion-theming"
|
import { withTheme } from "emotion-theming"
|
||||||
|
|
||||||
import { Input, Button, P } from "../../elements"
|
import { SimpleNavbar } from "components/Navbar"
|
||||||
import { SIZES } from "../../../styles/constants"
|
import { Input, Button, P } from "components/elements"
|
||||||
import { StyledLink as Link } from "../../elements"
|
import Layout from "components/Layout"
|
||||||
|
import { FirebaseContext } from "components/firebase"
|
||||||
import { FirebaseContext } from "../../firebase"
|
import { SIZES } from "styles/constants"
|
||||||
|
|
||||||
const RegisterGrid = styled.div`
|
const RegisterGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -18,19 +18,30 @@ const RegisterGrid = styled.div`
|
|||||||
const RegisterLayout = styled.div`
|
const RegisterLayout = styled.div`
|
||||||
max-width: ${SIZES.smallWidth};
|
max-width: ${SIZES.smallWidth};
|
||||||
width: 100%;
|
width: 100%;
|
||||||
align-self: center;
|
margin: 20px auto;
|
||||||
margin-top: 20px;
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const RegisterPage = ({ history, theme }) => (
|
const RegisterPage = ({ theme }) => (
|
||||||
<RegisterLayout>
|
<Layout>
|
||||||
<FirebaseContext.Consumer>
|
<SimpleNavbar />
|
||||||
{firebase => <RegisterForm history={history} firebase={firebase} />}
|
<RegisterLayout>
|
||||||
</FirebaseContext.Consumer>
|
<FirebaseContext.Consumer>
|
||||||
<P colors={theme.colors} style={{ fontStyle: "italic" }}>
|
{firebase => <RegisterForm firebase={firebase} />}
|
||||||
Already have an account? <Link to={"/login"}>Login</Link>
|
</FirebaseContext.Consumer>
|
||||||
</P>
|
<P colors={theme.colors} style={{ fontStyle: "italic" }}>
|
||||||
</RegisterLayout>
|
By registering for this site you are agreeing to the{" "}
|
||||||
|
<Link style={{ color: theme.colors.primary }} to={"/terms"}>
|
||||||
|
Terms of Service
|
||||||
|
</Link>
|
||||||
|
</P>
|
||||||
|
<P colors={theme.colors} style={{ fontStyle: "italic" }}>
|
||||||
|
Already have an account?{" "}
|
||||||
|
<Link style={{ color: theme.colors.primary }} to={"/login"}>
|
||||||
|
Login
|
||||||
|
</Link>
|
||||||
|
</P>
|
||||||
|
</RegisterLayout>
|
||||||
|
</Layout>
|
||||||
)
|
)
|
||||||
|
|
||||||
class RegisterFormBase extends Component {
|
class RegisterFormBase extends Component {
|
||||||
@@ -69,7 +80,7 @@ class RegisterFormBase extends Component {
|
|||||||
.set({
|
.set({
|
||||||
email: user.email,
|
email: user.email,
|
||||||
})
|
})
|
||||||
this.props.history.push("/")
|
navigate("app/")
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.setState({ error })
|
this.setState({ error })
|
||||||
@@ -131,16 +142,13 @@ class RegisterFormBase extends Component {
|
|||||||
</Button>
|
</Button>
|
||||||
</RegisterGrid>
|
</RegisterGrid>
|
||||||
|
|
||||||
{error && <p>{error.message}</p>}
|
{error && <P colors={theme.colors}>{error.message}</P>}
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RegisterForm = compose(
|
const RegisterForm = compose(withTheme)(RegisterFormBase)
|
||||||
withTheme,
|
|
||||||
withRouter
|
|
||||||
)(RegisterFormBase)
|
|
||||||
|
|
||||||
export default withTheme(RegisterPage)
|
export default withTheme(RegisterPage)
|
||||||
|
|
||||||
88
src/pages/terms.js
Normal file
88
src/pages/terms.js
Normal file
@@ -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 }) => (
|
||||||
|
<Layout>
|
||||||
|
<SimpleNavbar />
|
||||||
|
<Container>
|
||||||
|
<SimpleH1 color={theme.colors.primary}>Terms of Service</SimpleH1>
|
||||||
|
<Em color={theme.colors.secondary}>Last update: April 30, 2019</Em>
|
||||||
|
<SimpleH2 color={theme.colors.secondary}>Scope of Service</SimpleH2>
|
||||||
|
<P>
|
||||||
|
Sol Journal supports the following browsers: Chrome (latest), Safari
|
||||||
|
(latest), Firefox (50+)
|
||||||
|
</P>
|
||||||
|
<SimpleH2 color={theme.colors.secondary}>Rights</SimpleH2>
|
||||||
|
<P>
|
||||||
|
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.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You have the right to export your data at any time, in JSON format.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Your data will not be intentionally shown to other users or shared with
|
||||||
|
third parties.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Your personal data will not be shared with anyone without your consent.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
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.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Any new features that affect privacy will be strictly opt-in.
|
||||||
|
</P>
|
||||||
|
<SimpleH2 color={theme.colors.secondary}>Responsibilites</SimpleH2>
|
||||||
|
<P>
|
||||||
|
You will not use the site to store illegal information or data under
|
||||||
|
United States law (or any law).
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You have to be at least 18+ to create an account and use the site.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You must not abuse the site by knowingly posting malicious code that
|
||||||
|
could harm you or the other users.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You may not make automated requests to the site.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You may not abuse the registration system.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
You are responsible for keeping your account secure.
|
||||||
|
<br />
|
||||||
|
<br />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.
|
||||||
|
</P>
|
||||||
|
<SimpleH2 color={theme.colors.secondary}>Other</SimpleH2>
|
||||||
|
<P>
|
||||||
|
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.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
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.
|
||||||
|
</P>
|
||||||
|
</Container>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default withTheme(Terms)
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
|
import { addDays, subDays, format, isAfter, startOfYesterday } from "date-fns"
|
||||||
|
import { BeatLoader } from "react-spinners"
|
||||||
import styled from "@emotion/styled"
|
import styled from "@emotion/styled"
|
||||||
/** @jsx jsx */
|
/** @jsx jsx */
|
||||||
import { jsx, css, keyframes } from "@emotion/core"
|
import { jsx, css, keyframes } from "@emotion/core"
|
||||||
import { compose } from "recompose"
|
import { compose } from "recompose"
|
||||||
import { Prompt } from "react-router"
|
|
||||||
import { withRouter } from "react-router-dom"
|
|
||||||
import { withTheme } from "emotion-theming"
|
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 { SIZES } from "styles/constants"
|
||||||
import Icon from "../../Icon"
|
|
||||||
|
import Seek from "components/Seek"
|
||||||
|
import Icon from "components/Icon"
|
||||||
|
|
||||||
const EntryHeading = styled.div`
|
const EntryHeading = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -48,6 +47,7 @@ const OfflineNotice = styled.div`
|
|||||||
color: ${props => props.theme.colors.secondary};
|
color: ${props => props.theme.colors.secondary};
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
border-color: ${props => props.theme.colors.tertiary};
|
border-color: ${props => props.theme.colors.tertiary};
|
||||||
|
font-size: ${SIZES.tiny};
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
`
|
`
|
||||||
const JournalEntryArea = styled.textarea`
|
const JournalEntryArea = styled.textarea`
|
||||||
@@ -58,6 +58,7 @@ const JournalEntryArea = styled.textarea`
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
|
height: calc(100vh - 300px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: none;
|
border: none;
|
||||||
resize: none;
|
resize: none;
|
||||||
@@ -106,24 +107,31 @@ class Day extends React.Component {
|
|||||||
lastEditedAt: new Date(),
|
lastEditedAt: new Date(),
|
||||||
}
|
}
|
||||||
timeout = 0
|
timeout = 0
|
||||||
retrievedFromServer = false
|
|
||||||
|
|
||||||
static contextType = OnlineContext
|
static contextType = OnlineContext
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {
|
const { year, month, day } = this.props
|
||||||
history,
|
|
||||||
match: {
|
|
||||||
params: { year, month, day },
|
|
||||||
},
|
|
||||||
} = this.props
|
|
||||||
history.listen((location, action) => {
|
|
||||||
const [, year, month, day] = location.pathname.split("/")
|
|
||||||
this.onRouteChanged(year, month, day)
|
|
||||||
})
|
|
||||||
this.getDocRef(year, month, day, false)
|
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) => {
|
onRouteChanged = (year, month, day) => {
|
||||||
this.setState({ loading: true })
|
this.setState({ loading: true })
|
||||||
this.getDocRef(year, month, day, false)
|
this.getDocRef(year, month, day, false)
|
||||||
@@ -168,11 +176,7 @@ class Day extends React.Component {
|
|||||||
onChangeText = e => {
|
onChangeText = e => {
|
||||||
if (this.timeout) clearTimeout(this.timeout)
|
if (this.timeout) clearTimeout(this.timeout)
|
||||||
const text = e.target.value
|
const text = e.target.value
|
||||||
const {
|
const { year, month, day } = this.props
|
||||||
match: {
|
|
||||||
params: { year, month, day },
|
|
||||||
},
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
this.setState({ text, lastEditedAt: new Date() })
|
this.setState({ text, lastEditedAt: new Date() })
|
||||||
this.timeout = setTimeout(() => {
|
this.timeout = setTimeout(() => {
|
||||||
@@ -184,11 +188,7 @@ class Day extends React.Component {
|
|||||||
const entryTextArea = document.getElementById("entry-text-area")
|
const entryTextArea = document.getElementById("entry-text-area")
|
||||||
const cursorIndex = entryTextArea.selectionStart
|
const cursorIndex = entryTextArea.selectionStart
|
||||||
const { text } = this.state
|
const { text } = this.state
|
||||||
const {
|
const { year, month, day } = this.props
|
||||||
match: {
|
|
||||||
params: { year, month, day },
|
|
||||||
},
|
|
||||||
} = this.props
|
|
||||||
const insertAt = (str, sub, pos) =>
|
const insertAt = (str, sub, pos) =>
|
||||||
`${str.slice(0, pos)}${sub}${str.slice(pos)}`
|
`${str.slice(0, pos)}${sub}${str.slice(pos)}`
|
||||||
const newText = insertAt(text, format(new Date(), "h:mma "), cursorIndex)
|
const newText = insertAt(text, format(new Date(), "h:mma "), cursorIndex)
|
||||||
@@ -227,12 +227,7 @@ class Day extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { year, month, day, theme } = this.props
|
||||||
match: {
|
|
||||||
params: { year, month, day },
|
|
||||||
},
|
|
||||||
theme,
|
|
||||||
} = this.props
|
|
||||||
const online = this.context
|
const online = this.context
|
||||||
const { text, loading, saving, lastSavedAt, lastEditedAt } = this.state
|
const { text, loading, saving, lastSavedAt, lastEditedAt } = this.state
|
||||||
const currentDay = new Date(year, month - 1, day)
|
const currentDay = new Date(year, month - 1, day)
|
||||||
@@ -241,10 +236,6 @@ class Day extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Prompt
|
|
||||||
when={!hasSavedChanges}
|
|
||||||
message="You have unsaved changes, are you sure you want to leave?"
|
|
||||||
/>
|
|
||||||
<Seek
|
<Seek
|
||||||
title={format(currentDay, "YYYY MMM DD - dddd")}
|
title={format(currentDay, "YYYY MMM DD - dddd")}
|
||||||
prev={format(subDays(currentDay, 1), "/YYYY/MM/DD")}
|
prev={format(subDays(currentDay, 1), "/YYYY/MM/DD")}
|
||||||
@@ -318,6 +309,5 @@ class Day extends React.Component {
|
|||||||
export default compose(
|
export default compose(
|
||||||
withFirebase,
|
withFirebase,
|
||||||
withTheme,
|
withTheme,
|
||||||
withAuthentication,
|
withAuthentication
|
||||||
withRouter
|
|
||||||
)(Day)
|
)(Day)
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import { Link } from "react-router-dom"
|
|
||||||
import styled from "@emotion/styled"
|
import styled from "@emotion/styled"
|
||||||
import {
|
import {
|
||||||
isAfter,
|
isAfter,
|
||||||
@@ -12,7 +11,8 @@ import {
|
|||||||
startOfMonth,
|
startOfMonth,
|
||||||
} from "date-fns"
|
} from "date-fns"
|
||||||
|
|
||||||
import Seek from "../../Seek"
|
import { AppLink as Link } from "components/elements"
|
||||||
|
import Seek from "components/Seek"
|
||||||
|
|
||||||
const YearCardGrid = styled.div`
|
const YearCardGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -38,11 +38,7 @@ const YearCard = styled.div`
|
|||||||
|
|
||||||
class Month extends Component {
|
class Month extends Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { year, month } = this.props
|
||||||
match: {
|
|
||||||
params: { year, month },
|
|
||||||
},
|
|
||||||
} = this.props
|
|
||||||
const currentDay = new Date(year, month - 1)
|
const currentDay = new Date(year, month - 1)
|
||||||
|
|
||||||
// include all months unless it's this year
|
// include all months unless it's this year
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Component } from "react"
|
import { Component } from "react"
|
||||||
import { Link } from "react-router-dom"
|
|
||||||
/** @jsx jsx */
|
/** @jsx jsx */
|
||||||
import { jsx, css, keyframes } from "@emotion/core"
|
import { jsx, css, keyframes } from "@emotion/core"
|
||||||
import styled from "@emotion/styled"
|
import styled from "@emotion/styled"
|
||||||
@@ -7,11 +6,11 @@ import { compose } from "recompose"
|
|||||||
import { withTheme } from "emotion-theming"
|
import { withTheme } from "emotion-theming"
|
||||||
import { BeatLoader } from "react-spinners"
|
import { BeatLoader } from "react-spinners"
|
||||||
|
|
||||||
import { Input } from "../../elements"
|
import { AppLink as Link } from "components/elements"
|
||||||
import { pad } from "../../../utils/date"
|
import { Input } from "components/elements"
|
||||||
|
import { withFirebase } from "components/firebase"
|
||||||
import { withFirebase } from "../../firebase"
|
import { withAuthentication } from "components/session"
|
||||||
import { withAuthentication } from "../../session"
|
import { pad } from "utils/date"
|
||||||
|
|
||||||
const SearchGrid = styled.div`
|
const SearchGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -80,6 +79,8 @@ class Search extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all entries for a user are fetched this scales poorly but is much
|
||||||
|
// simpler than an API key and setting up an index for Algolia
|
||||||
getEntries = async _ => {
|
getEntries = async _ => {
|
||||||
const { firebase, authUser } = this.props
|
const { firebase, authUser } = this.props
|
||||||
const entriesRef = await firebase.db
|
const entriesRef = await firebase.db
|
||||||
@@ -87,13 +88,7 @@ class Search extends Component {
|
|||||||
.where("userId", "==", authUser.uid)
|
.where("userId", "==", authUser.uid)
|
||||||
.get()
|
.get()
|
||||||
const entries = entriesRef.docs.map(doc => doc.data()).reverse()
|
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 })
|
this.setState({ entries, allEntries: entries, loading: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,22 +1,26 @@
|
|||||||
import React, { Component } from "react"
|
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 styled from "@emotion/styled"
|
||||||
import { withTheme } from "emotion-theming"
|
import { withTheme } from "emotion-theming"
|
||||||
|
|
||||||
import { SIZES } from "../../../styles/constants"
|
import { SIZES } from "styles/constants"
|
||||||
import { Button, P } from "../../elements"
|
import { Button, P } from "components/elements"
|
||||||
import { todayUrl } from "../../../utils/date"
|
import Icon from "components/Icon"
|
||||||
import Icon from "../../Icon"
|
import Footer from "components/Footer"
|
||||||
import Logo from "../../Logo"
|
import { todayUrl } from "utils/date"
|
||||||
|
|
||||||
const StartGrid = styled.div`
|
const StartGrid = styled.div`
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
|
text-align: center;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: ${props => props.theme.colors.primary};
|
color: ${props => props.theme.colors.primary};
|
||||||
height: 100%;
|
height: 100%;
|
||||||
`
|
`
|
||||||
const FeatureGrid = styled.div`
|
const FeatureGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
|
text-align: left;
|
||||||
grid-template-rows: 1fr;
|
grid-template-rows: 1fr;
|
||||||
grid-gap: 30px;
|
grid-gap: 30px;
|
||||||
`
|
`
|
||||||
@@ -36,21 +40,6 @@ const FeatureTitle = styled.div`
|
|||||||
const FeatureDescription = styled.div`
|
const FeatureDescription = styled.div`
|
||||||
color: ${props => props.theme.colors.secondary};
|
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 = [
|
const features = [
|
||||||
{
|
{
|
||||||
@@ -83,6 +72,12 @@ const features = [
|
|||||||
desc:
|
desc:
|
||||||
"Download all of your journal entries at any time for back-up or safe keeping ",
|
"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 {
|
class Start extends Component {
|
||||||
@@ -90,15 +85,78 @@ class Start extends Component {
|
|||||||
const { theme } = this.props
|
const { theme } = this.props
|
||||||
return (
|
return (
|
||||||
<StartGrid>
|
<StartGrid>
|
||||||
|
<Helmet>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
label="Connect with your soul through a simple, beautiful journaling experience from any of your devices."
|
||||||
|
/>
|
||||||
|
</Helmet>
|
||||||
<h1>Record what's on your mind, from anywhere</h1>
|
<h1>Record what's on your mind, from anywhere</h1>
|
||||||
<P style={{ letterSpacing: 1.1, marginBottom: 30 }}>
|
<P style={{ letterSpacing: 1.1, marginBottom: 30 }}>
|
||||||
Journaling can improve your health and help you take inventory of your
|
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
|
day. Sol Journal works offline and from any device. Use it as a place
|
||||||
to record thoughts and events from the day.
|
to record thoughts and events from the day.
|
||||||
</P>
|
</P>
|
||||||
<Link to={todayUrl()} style={{ textDecoration: "none" }}>
|
<Link to={`/app${todayUrl()}`} style={{ textDecoration: "none" }}>
|
||||||
<Button colors={theme.colors}>Write about today</Button>
|
<Button colors={theme.colors}>Start Writing</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
marginTop: 30,
|
||||||
|
maxHeight: 350,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StaticQuery
|
||||||
|
query={graphql`
|
||||||
|
query {
|
||||||
|
landingGraphicLight: file(
|
||||||
|
relativePath: { eq: "landing-graphic-light.png" }
|
||||||
|
) {
|
||||||
|
childImageSharp {
|
||||||
|
fluid(maxWidth: 320) {
|
||||||
|
...GatsbyImageSharpFluid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
landingGraphicDark: file(
|
||||||
|
relativePath: { eq: "landing-graphic-dark.png" }
|
||||||
|
) {
|
||||||
|
childImageSharp {
|
||||||
|
fluid(maxWidth: 320) {
|
||||||
|
...GatsbyImageSharpFluid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
render={data => {
|
||||||
|
return theme.name === "LIGHT" ? (
|
||||||
|
<Img
|
||||||
|
style={{
|
||||||
|
maxWidth: 320,
|
||||||
|
width: "100%",
|
||||||
|
maxHeight: 350,
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
fluid={data.landingGraphicLight.childImageSharp.fluid}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Img
|
||||||
|
style={{
|
||||||
|
maxWidth: 320,
|
||||||
|
width: "100%",
|
||||||
|
maxHeight: 350,
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
fluid={data.landingGraphicDark.childImageSharp.fluid}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
margin: "60px 0px",
|
margin: "60px 0px",
|
||||||
@@ -129,17 +187,7 @@ class Start extends Component {
|
|||||||
</FeatureRow>
|
</FeatureRow>
|
||||||
))}
|
))}
|
||||||
</FeatureGrid>
|
</FeatureGrid>
|
||||||
<Footer>
|
<Footer />
|
||||||
<div>
|
|
||||||
<Logo color={theme.colors.logo} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<FooterLink>View on GitHub</FooterLink>
|
|
||||||
<FooterLink to="terms">Terms of Service</FooterLink>
|
|
||||||
<FooterLink to="privacy">Privacy Policy</FooterLink>
|
|
||||||
</div>
|
|
||||||
<div>© 2019</div>
|
|
||||||
</Footer>
|
|
||||||
</StartGrid>
|
</StartGrid>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3,14 +3,13 @@ import styled from "@emotion/styled"
|
|||||||
import { withTheme } from "emotion-theming"
|
import { withTheme } from "emotion-theming"
|
||||||
import { compose } from "recompose"
|
import { compose } from "recompose"
|
||||||
import { format } from "date-fns"
|
import { format } from "date-fns"
|
||||||
import { withFirebase } from "../../firebase"
|
|
||||||
import { withAuthentication } from "../../session"
|
|
||||||
import { BeatLoader } from "react-spinners"
|
import { BeatLoader } from "react-spinners"
|
||||||
|
|
||||||
import { SIZES } from "../../../styles/constants"
|
import { SIZES } from "styles/constants"
|
||||||
|
import { withFirebase } from "components/firebase"
|
||||||
import SignOut from "../../SignOut"
|
import { withAuthentication } from "components/session"
|
||||||
import { Button } from "../../elements"
|
import SignOut from "components/SignOut"
|
||||||
|
import { Button } from "components/elements"
|
||||||
|
|
||||||
const ProfileGrid = styled.div`
|
const ProfileGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
77
src/routes/Welcome.js
Normal file
77
src/routes/Welcome.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import React, { Component } from "react"
|
||||||
|
import { Helmet } from "react-helmet"
|
||||||
|
import { Link } from "gatsby"
|
||||||
|
import styled from "@emotion/styled"
|
||||||
|
import { withTheme } from "emotion-theming"
|
||||||
|
import { getDayOfYear } from "date-fns"
|
||||||
|
|
||||||
|
import { SIZES } from "styles/constants"
|
||||||
|
import { Button, P } from "components/elements"
|
||||||
|
import Footer from "components/Footer"
|
||||||
|
import { todayUrl } from "utils/date"
|
||||||
|
|
||||||
|
import Quotes from "data/quotes.json"
|
||||||
|
|
||||||
|
const WelcomeGrid = styled.div`
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 60px;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: ${props => props.theme.colors.primary};
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
`
|
||||||
|
|
||||||
|
const Quote = styled.blockquote`
|
||||||
|
margin-top: 30px;
|
||||||
|
font-family: Montserrat;
|
||||||
|
font-size: ${SIZES.medium};
|
||||||
|
color: ${props => props.theme.colors.primary};
|
||||||
|
`
|
||||||
|
const QuoteAuthor = styled(P)`
|
||||||
|
font-style: italic;
|
||||||
|
`
|
||||||
|
|
||||||
|
class Welcome extends Component {
|
||||||
|
render() {
|
||||||
|
const todaysQuote = Quotes[getDayOfYear(new Date()) % Quotes.length]
|
||||||
|
const { theme } = this.props
|
||||||
|
return (
|
||||||
|
<WelcomeGrid>
|
||||||
|
<Helmet>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
label="Connect with your soul through a simple, beautiful journaling experience from any device."
|
||||||
|
/>
|
||||||
|
</Helmet>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontFamily: "cursive",
|
||||||
|
fontSize: 100,
|
||||||
|
height: 60,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
"
|
||||||
|
</div>
|
||||||
|
<Quote>{todaysQuote.quote}</Quote>
|
||||||
|
<QuoteAuthor style={{ letterSpacing: 1.1, marginBottom: 30 }}>
|
||||||
|
- {todaysQuote.author}
|
||||||
|
</QuoteAuthor>
|
||||||
|
<div>
|
||||||
|
<P style={{ letterSpacing: 1.1, marginBottom: 30 }}>
|
||||||
|
This your space for wandering thoughts and ideas. Write about
|
||||||
|
whatever is on your mind.
|
||||||
|
</P>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link to={`/app${todayUrl()}`} style={{ textDecoration: "none" }}>
|
||||||
|
<Button colors={theme.colors}>Write about today</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
|
</WelcomeGrid>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withTheme(Welcome)
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import { Link } from "react-router-dom"
|
|
||||||
import styled from "@emotion/styled"
|
|
||||||
import { addYears, subYears, format, isThisYear, getMonth } from "date-fns"
|
import { addYears, subYears, format, isThisYear, getMonth } from "date-fns"
|
||||||
|
import styled from "@emotion/styled"
|
||||||
import { withTheme } from "emotion-theming"
|
import { withTheme } from "emotion-theming"
|
||||||
|
|
||||||
import { months } from "../../../utils/date"
|
import { AppLink as Link } from "components/elements"
|
||||||
import Seek from "../../Seek"
|
import Seek from "components/Seek"
|
||||||
|
import { months } from "utils/date"
|
||||||
|
|
||||||
const MonthCardGrid = styled.div`
|
const MonthCardGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -31,11 +31,7 @@ const MonthCard = styled.div`
|
|||||||
|
|
||||||
class Year extends Component {
|
class Year extends Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const { year } = this.props
|
||||||
match: {
|
|
||||||
params: { year },
|
|
||||||
},
|
|
||||||
} = this.props
|
|
||||||
const currentDate = new Date(year, 0, 1)
|
const currentDate = new Date(year, 0, 1)
|
||||||
|
|
||||||
// include all months unless it's this year
|
// include all months unless it's this year
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
|
// standardized role-based design tokens used throughout the whole app
|
||||||
|
// a name like lightGray doesn't make sense with themese when light
|
||||||
|
// and dark are possibile
|
||||||
const theme = {
|
const theme = {
|
||||||
LIGHT: {
|
LIGHT: {
|
||||||
name: "Light",
|
name: "LIGHT",
|
||||||
colors: {
|
colors: {
|
||||||
logo: "#344157",
|
logo: "#344157",
|
||||||
primary: "#2E3136",
|
primary: "#2E3136",
|
||||||
@@ -11,10 +14,11 @@ const theme = {
|
|||||||
bodyBackground: "#FFF",
|
bodyBackground: "#FFF",
|
||||||
inputBackground: "#FAFBFC",
|
inputBackground: "#FAFBFC",
|
||||||
hover: "hsla(233, 5%, 31%, 0.12)",
|
hover: "hsla(233, 5%, 31%, 0.12)",
|
||||||
|
button: "#f2f3f5",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
DARK: {
|
DARK: {
|
||||||
name: "Dark",
|
name: "DARK",
|
||||||
colors: {
|
colors: {
|
||||||
logo: "#EAEAEA",
|
logo: "#EAEAEA",
|
||||||
primary: "#F3F6F8",
|
primary: "#F3F6F8",
|
||||||
@@ -25,6 +29,7 @@ const theme = {
|
|||||||
bodyBackground: "#262B34",
|
bodyBackground: "#262B34",
|
||||||
inputBackground: "#272f3d",
|
inputBackground: "#272f3d",
|
||||||
hover: "hsla(233, 100%, 96%, 0.12)",
|
hover: "hsla(233, 100%, 96%, 0.12)",
|
||||||
|
button: "#464d5d",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user