Small World is overloaded
+sorry, Small World is a little more popular than we anticipated!
+if you refresh, the website should be back up in a few seconds
+diff --git a/.gitignore b/.gitignore index c1b3d413..21469fcb 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,8 @@ dev/.DS_Store figwheel_server.log .rebel_readline_history resources/public/js -bin/set-env-variables.sh \ No newline at end of file +bin/set-env-variables.sh + +# IntelliJ files +.idea/* +*.iml diff --git a/Procfile b/Procfile index 2a92b316..a4de12ce 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: java $JVM_OPTS -jar target/smallworld.jar -m smallworld.web \ No newline at end of file +web: java -Xmx300M -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -jar target/smallworld.jar -m smallworld.web \ No newline at end of file diff --git a/README.md b/README.md index 59ed3da2..6c4b929a 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,16 @@ https://smallworld.kiwi - [update code running in the repl](#update-code-running-in-the-repl) - [deploy to Heroku](#deploy-to-heroku) - [initial designs](#initial-designs) -- [emails & scheduled jobs](#emails--scheduled-jobs) +- [emails](#emails) - [sql cheatsheet](#sql-cheatsheet) +- [misc commands cheatsheet](#misc-commands-cheatsheet) ## run, build, & deploy ### local setup 1. `lein install` 2. install postgres: https://postgresapp.com (database) -3. create local postgres db called `smallworld-local` +3. run `bin/setup` to create a local postgres db called `smallworld-local` ### local development 1. run `bin/start-dev.sh` - sets the environment variables @@ -84,11 +85,9 @@ bin/make-and-deploy.sh | - | - | - | | | | | -## emails & scheduled jobs +## emails - the server sends emails via SendGrid. view/edit the templates here: https://mc.sendgrid.com/dynamic-templates -- jobs are scheduled through the Heroku Scheduler: -https://dashboard.heroku.com/apps/small-world-friends/scheduler ## sql cheatsheet @@ -114,8 +113,7 @@ https://dashboard.heroku.com/apps/small-world-friends/scheduler - make a user go through welcome flow again: ```sql - update settings - set welcome_flow_complete = false + update settings set welcome_flow_complete = false where screen_name = 'devon_dos'; ``` @@ -142,3 +140,18 @@ https://dashboard.heroku.com/apps/small-world-friends/scheduler ALTER TABLE "settings" ADD COLUMN locations jsonb; ``` +## misc commands cheatsheet + +- run command line inside of Heroku: + ``` + heroku ps:exec --app=small-world-friends + ``` +- view environment variables for process with pid 4: + ``` + cat /proc/4/environ | tr '\0' '\n' + ``` +- run prod jar locally: + ```sh + lein uberjar # builds the jar + java -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -jar target/smallworld.jar -m smallworld.web + ``` \ No newline at end of file diff --git a/bin/open-local-db.sh b/bin/open-local-db.sh new file mode 100755 index 00000000..3f7d955b --- /dev/null +++ b/bin/open-local-db.sh @@ -0,0 +1 @@ +/Applications/Postgres.app/Contents/Versions/14/bin/psql -p5432 "devonzuegel" \ No newline at end of file diff --git a/bin/open-prod-db.sh b/bin/open-prod-db.sh new file mode 100755 index 00000000..0e568051 --- /dev/null +++ b/bin/open-prod-db.sh @@ -0,0 +1 @@ +heroku pg:psql postgresql-fluffy-56995 --app small-world-friends \ No newline at end of file diff --git a/bin/set-env-variables TEMPLATE.sh b/bin/set-env-variables TEMPLATE.sh index 5b38f167..2f1a1fbd 100644 --- a/bin/set-env-variables TEMPLATE.sh +++ b/bin/set-env-variables TEMPLATE.sh @@ -6,4 +6,5 @@ export BING_MAPS_API_KEY=get from Bing Developer export COOKIE_STORE_SECRET_KEY=generate a 16-char random string export DATABASE_URL=set up in Heroku export LEIN_JVM_OPTS="-XX:TieredStopAtLevel=1" # suppresses OpenJDK 64-Bit Server VM warning: https://stackoverflow.com/a/67695691/2639250 +export JAVA_OPTS="-Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8" # match the max heap/stack size set by Heroku export SENDGRID_API_KEY=get from https://sendgrid.com \ No newline at end of file diff --git a/bin/setup b/bin/setup new file mode 100755 index 00000000..1ad368f2 --- /dev/null +++ b/bin/setup @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +psql -U postgres -c "CREATE DATABASE \"smallworld-local\"" diff --git a/dev/dev/repl.clj b/dev/dev/repl.clj index 1169968c..2972907d 100644 --- a/dev/dev/repl.clj +++ b/dev/dev/repl.clj @@ -9,13 +9,14 @@ #_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]} (defn restart-server [] - (use 'smallworld.web :reload) (backend/stop!) - (backend/start! PORT)) + (use 'smallworld.web :reload) + (println "\nrestarting server......\n") + (backend/-main)) (defn initialize-repl [] (println (str "\n\n🌎 starting the small world server (backend): http://localhost:" PORT " 🌍\n")) - (backend/start! 3001) + (backend/-main) (println "\n\n🎨 starting the Figwheel server (frontend hot-reloading) 🎨\n") (repl-api/start-figwheel!) diff --git a/latest.dump b/latest.dump new file mode 100644 index 00000000..84a5bc5d Binary files /dev/null and b/latest.dump differ diff --git a/project.clj b/project.clj index 6fa8a303..58ddbec7 100644 --- a/project.clj +++ b/project.clj @@ -14,6 +14,7 @@ [twttr "3.2.3"] [cheshire "5.10.1"] [oauth-clj "0.1.16"] + [metosin/reitit "0.5.18"] [cljsjs/mapbox "0.46.0-0"] [ring/ring-jetty-adapter "1.9.5"] [ring/ring-ssl "0.3.0"] @@ -44,12 +45,10 @@ :source-paths ["src"] :figwheel true :compiler {:main "smallworld.frontend" - ;; :preloads [devtools.preload] :asset-path "js/out" :output-to "resources/public/js/main.js" :output-dir "resources/public/js/out" :optimizations :none - ;; :recompile-dependents true :source-map true}}]}} :uberjar {:env {:production true} :source-paths ["src"] diff --git a/resources/public/css/styles.css b/resources/public/css/styles.css index 6106b43f..8d3fb426 100644 --- a/resources/public/css/styles.css +++ b/resources/public/css/styles.css @@ -80,7 +80,7 @@ select { bottom: 0px; left: 0px; opacity: 0.26; - height: 46px; + height: 42px; } .nav .globe-loader { position: relative; @@ -202,6 +202,10 @@ select { font-size: 0.85em; opacity: 0.6; vertical-align: middle; + gap: 14px; +} +.friends-list .loading .loader { + margin: -6px; } /******************************************************************************/ @@ -209,7 +213,7 @@ select { /******************************************************************************/ .home-page { margin: auto; - padding: 24px 16px 12px 16px; + padding: 16px 16px 4px 16px; max-width: calc(758px + 20px); /* leave space for 2 columns + padding */ /* the following is so the map is centered, even when it overflows*/ @@ -329,11 +333,11 @@ tr:nth-child(even) { .category { border: 1px solid #d9d3cc22; border-radius: 10px; - margin-bottom: 12px; + margin-bottom: 16px; width: 100%; } -.category { - margin-top: 18px; +#track-new-location-field + .category { + margin-top: 16px !important; } .category .current-user-location { transform: translateY(calc(-50% - 6px)); @@ -349,11 +353,11 @@ tr:nth-child(even) { } .no-locations-info { color: #d9d3cccc; - padding: 24px; - border: 2px solid #ffffff22; + padding: 20px; + border: 1px solid #ffffff22; border-radius: 8px; line-height: 1.7; - margin-top: 16px; + margin-bottom: 16px; } .no-locations-info p, ul { @@ -362,9 +366,21 @@ ul { .friends-list { padding: 9px 6px; } +.friends-list svg.info { + fill: white; + opacity: 0.45; + margin-bottom: -3px; + margin-left: 8px; + cursor: pointer; + transition: all 50ms ease-out; + transform: scale(1.1); +} +.friends-list svg.info:hover { + opacity: 1; + transition: all 50ms ease-out; +} .friends-list .verb-gerund { - border-bottom: dashed 2px #ffffff55; - cursor: help; + border-bottom: solid 2px #ffffff33; } // @media screen and (max-width: 720px) { // .friends-list { @@ -388,7 +404,6 @@ ul { .friends-list.header { font-size: 0.85em; display: flex; - min-height: 59px; flex-direction: row; background-color: #ffffff0d; border-radius: 8px 8px 0 0; @@ -401,15 +416,10 @@ ul { font-weight: 600; } .friends-list .mapbox-container { - min-width: 80px; + width: 50px; + height: 50px; border-radius: 80px; } - -@media (max-width: 768px) /* mobile */ { - .friends-list .mapbox-container { - min-width: 60px; - } -} .friends-list .mapbox-container .mapboxgl-map { height: 100% !important; width: 100% !important; @@ -426,7 +436,8 @@ ul { display: flex; flex-wrap: wrap; gap: 12px; - margin-top: 12px; + margin-top: 8px; + transition: margin-top 100ms ease-out; } @media screen and (min-width: 720px) { .friends-list .friends { @@ -497,6 +508,32 @@ ul { opacity: 0.7; cursor: default; } +.friend-bubbles { + display: flex; + flex-wrap: wrap; + gap: 1px; + margin: 8px auto 6px 2px; + cursor: pointer; + transition: margin-top 200ms ease-out; +} +.friend-bubbles .friend { + width: auto; + display: inline; + margin: 1px; + opacity: 0.8; +} +.friend-bubbles .friend:hover { + opacity: 1; + transition: opacity 100ms ease-out; +} +.friend-bubbles .friend .twitter-pic { + border-width: 1px; +} +.friend-bubbles .friend .twitter-pic, +.friend-bubbles .friend .twitter-pic img { + height: 20px; + width: 20px; +} /******************************************************************************/ /**** friend: current-user ********************************************************************/ /******************************************************************************/ @@ -510,10 +547,9 @@ ul { margin: auto; } .twitter-data-explanation > .twitter-data { - background: #ffffff11; display: flex; padding: 8px 16px; - border-radius: 8px; + margin-top: 16px; column-gap: 12px; } .twitter-data-explanation > .twitter-data .right-side { @@ -531,8 +567,10 @@ ul { } .twitter-data-explanation > .twitter-data img { height: 50px; + width: 50px; border-radius: 100%; border: 2px solid #d9d3cc44; + background-color: #d9d3cc22; } .twitter-data-explanation { text-align: left; @@ -588,7 +626,6 @@ ul { align-items: center; } } - .current-user .friend { margin-bottom: 24px; } @@ -765,7 +802,8 @@ ul { .welcome-flow .you-signed-in-as, .welcome-flow .location-field, .welcome-flow .heads-up, -.welcome-flow .email-options { +.welcome-flow .email-options, +.welcome-flow .email-address { max-width: 340px; margin: auto; padding: 16px 12px; @@ -775,7 +813,6 @@ ul { .welcome-flow #track-new-location-field { width: fit-content; margin: auto; - margin-top: 12px; padding: 8px 14px; border-radius: 24px; fill: #d9d3cc; @@ -796,6 +833,9 @@ ul { margin-right: 2px; margin-bottom: -6px; } +.welcome-flow #track-new-location-field { + margin-top: 12px; +} .welcome-flow svg.cancel-icon, .home-page .delete-location-btn svg.cancel-icon { float: right; @@ -814,7 +854,7 @@ ul { } .welcome-flow svg.cancel-icon { margin-right: -18px; - margin-top: -28px; + margin-top: -20px; } .home-page .friends-list.header .right-side { margin-left: 12px; @@ -836,15 +876,16 @@ ul { margin-top: -14px; } .welcome-flow .location-field { - padding: 24px 12px; + padding: 16px 12px; padding-bottom: 6px; margin-top: 14px; } .welcome-flow .location-field label .small-info-text { padding: 0 10px; } +.welcome-flow .location-field, .welcome-flow .email-options, -.welcome-flow .location-field { +.welcome-flow .email-address { border: 1px solid #ffffff33; } .welcome-flow input { @@ -852,7 +893,9 @@ ul { } .welcome-flow .location-field:focus-within, .welcome-flow .email-options:focus-within, -.welcome-flow .email-options:focus /* the radio btns field is different */ { +.welcome-flow .email-options:focus /* the radio btns field is different */ +.welcome-flow .email-address:focus, +.welcome-flow .email-address:focus-within { border: 1px solid #ffffff55; } .welcome-flow .you-signed-in-as .friend { @@ -869,7 +912,11 @@ ul { position: absolute; opacity: 0.5; } -.welcome-flow input[type='text'] { +.welcome-flow .field { + font-size: 0.95em; +} +.welcome-flow input[type='text'], +.welcome-flow input[type='email'] { width: 254px; padding: 4px 32px 4px 5px; background: #ffffff11; @@ -901,6 +948,12 @@ ul { } .welcome-flow .email-options { margin-top: 14px; + padding-top: 6px; + padding-bottom: 0; +} +.welcome-flow .email-address { + margin-top: 14px; + padding-bottom: 12px; } .welcome-flow .email-options .radio-btns { text-align: left; @@ -956,21 +1009,22 @@ input[type='radio']:checked::before { } input[type='radio']:focus { - outline: 0.1em solidwhite; + outline: 0.1em solid white; outline-offset: max(2px, 0.15em); } :not(.error) .error-msg { display: none; } +.welcome-flow input::placeholder { + color: #d9d3cc55; +} .error .error-msg { display: block; - background: #ffdfe1; - border-radius: 4px; - color: #c2000d; + color: #ffa88d; + font-weight: 900; font-size: 0.8em; font-weight: 500; - margin: 2px auto 0; - padding: 4px; + margin: 0 auto; text-align: center; text-align: center; width: 289px; @@ -1047,19 +1101,18 @@ input[type='radio']:focus { box-shadow: 0px 0px 18px #ffffff22; border-radius: 24px; position: relative; /* required so that position:absolute works for the .expand-me btn */ + margin: 0 0 16px 0; } @media (max-width: 768px) /* mobile */ { #mapbox-container { width: calc(100vw - 32px); height: calc(60vh - 40px - 41px); /* 41px accounts for the margin */ - margin: 16px 0 20px 0; } } @media (min-width: 768px) /* desktop */ { #mapbox-container { - width: calc(100vw - 60px); - height: calc(60vh - 60px - 41px); /* 41px accounts for the margin */ - margin: 16px 0 20px 0; + width: calc(100vw - 40px); + height: calc(70vh - 60px - 41px); /* 41px accounts for the margin */ } } #mapbox-container.expanded { @@ -1076,17 +1129,35 @@ input[type='radio']:focus { z-index: 1; border-radius: 0; } +// #mapbox-container.loading { +// height: 20vh; +// transition: height 900ms ease-in-out; +// } +#mapbox-container .controls { + right: 0; + margin-top: 6px; + margin-right: 6px; + background: rgba(255, 255, 255, 0.9); + width: fit-content; + height: fit-content; + z-index: 1; + border-radius: 24px; + position: absolute; + display: flex; + justify-content: space-between; + gap: 12px; + padding: 0 11px 4px 13px; +} #mapbox-container .zoom-in, #mapbox-container .zoom-out, #mapbox-container .expand-me { - position: absolute; /* #mapbox-container needs position:relative */ pointer-events: auto; fill: #013917; cursor: pointer; filter: drop-shadow(0 0 2px rgb(255 255 255 / 0.5)); z-index: 300; margin-top: 12px; - margin-left: 12px; + transform: scale(1.3); } #mapbox-container .zoom-in:hover, #mapbox-container .zoom-out:hover, @@ -1094,11 +1165,8 @@ input[type='radio']:focus { fill: black; filter: drop-shadow(0 0 2px rgb(255 255 255 / 0.8)); } -#mapbox-container svg.zoom-in { - margin-left: 48px; -} -#mapbox-container svg.zoom-out { - margin-left: 80px; +#mapbox-container .expand-me { + margin-right: 4px; } #mapbox-container .mapboxgl-map { background: #9dc7d9; @@ -1408,3 +1476,180 @@ ul li { .info-footer a:hover { cursor: pointer; } + +/**************************************************************** + ** tooltips **************************************************** + ****************************************************************/ + +/* Base styles for the element that has a tooltip */ +[data-tooltip], +.tooltip { + position: relative; + cursor: pointer; +} +/* Base styles for the entire tooltip tooltip */ +[data-tooltip]:before, +[data-tooltip]:after, +.tooltip:before, +.tooltip:after { + position: absolute; + visibility: hidden; + -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=0)'; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); + opacity: 0; + -webkit-transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out, -webkit-transform 0.2s cubic-bezier(0.71, 1.7, 0.77, 1.24); + -moz-transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out, -moz-transform 0.2s cubic-bezier(0.71, 1.7, 0.77, 1.24); + transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out, transform 0.2s cubic-bezier(0.71, 1.7, 0.77, 1.24); + -webkit-transform: translate3d(0, 0, 0); + -moz-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + pointer-events: none; +} +/* Show the entire tooltip on hover and focus tooltip */ +[data-tooltip]:hover:before, +[data-tooltip]:hover:after, +[data-tooltip]:focus:before, +[data-tooltip]:focus:after, +.tooltip:hover:before, +.tooltip:hover:after, +.tooltip:focus:before, +.tooltip:focus:after { + visibility: visible; + -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)'; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + opacity: 1; +} +/* Base styles for the tooltip's directional arrow tooltip */ +.tooltip:before, +[data-tooltip]:before { + z-index: 1001; + border: 6px solid transparent; + background: transparent; + content: ''; +} +/* Base styles for the tooltip's content area tooltip */ +.tooltip:after, +[data-tooltip]:after { + z-index: 1000; + padding: 8px; + width: 224px; + background-color: #022610; + color: #fff; + content: attr(data-tooltip); + font-size: 14px; + line-height: 1.2; +} +/* Directions tooltip */ +/* Top (default) */ +[data-tooltip]:before, +[data-tooltip]:after, +.tooltip:before, +.tooltip:after, +.tooltip-top:before, +.tooltip-top:after { + bottom: 100%; + left: 50%; +} +[data-tooltip]:before, +.tooltip:before, +.tooltip-top:before { + margin-left: -6px; + margin-bottom: -12px; + border-top-color: #022610; +} +/* Horizontally align top/bottom tooltips tooltip */ +[data-tooltip]:after, +.tooltip:after, +.tooltip-top:after { + margin-left: -80px; +} +[data-tooltip]:hover:before, +[data-tooltip]:hover:after, +[data-tooltip]:focus:before, +[data-tooltip]:focus:after, +.tooltip:hover:before, +.tooltip:hover:after, +.tooltip:focus:before, +.tooltip:focus:after, +.tooltip-top:hover:before, +.tooltip-top:hover:after, +.tooltip-top:focus:before, +.tooltip-top:focus:after { + -webkit-transform: translateY(-12px); + -moz-transform: translateY(-12px); + transform: translateY(-12px); +} +/* Left tooltip */ +.tooltip-left:before, +.tooltip-left:after { + right: 100%; + bottom: 50%; + left: auto; +} +.tooltip-left:before { + margin-left: 0; + margin-right: -12px; + margin-bottom: 0; + border-top-color: transparent; + border-left-color: #022610; +} +.tooltip-left:hover:before, +.tooltip-left:hover:after, +.tooltip-left:focus:before, +.tooltip-left:focus:after { + -webkit-transform: translateX(-12px); + -moz-transform: translateX(-12px); + transform: translateX(-12px); +} +/* Bottom tooltip */ +.tooltip-bottom:before, +.tooltip-bottom:after { + top: 100%; + bottom: auto; + left: 50%; +} +.tooltip-bottom:before { + margin-top: -12px; + margin-bottom: 0; + border-top-color: transparent; + border-bottom-color: #022610; +} +.tooltip-bottom:hover:before, +.tooltip-bottom:hover:after, +.tooltip-bottom:focus:before, +.tooltip-bottom:focus:after { + -webkit-transform: translateY(12px); + -moz-transform: translateY(12px); + transform: translateY(12px); +} +/* Right tooltip */ +.tooltip-right:before, +.tooltip-right:after { + bottom: 50%; + left: 100%; +} +.tooltip-right:before { + margin-bottom: 0; + margin-left: -12px; + border-top-color: transparent; + border-right-color: #022610; +} +.tooltip-right:hover:before, +.tooltip-right:hover:after, +.tooltip-right:focus:before, +.tooltip-right:focus:after { + -webkit-transform: translateX(12px); + -moz-transform: translateX(12px); + transform: translateX(12px); +} +/* Move directional arrows down a bit for left/right tooltips tooltip */ +.tooltip-left:before, +.tooltip-right:before { + top: 3px; +} +/* Vertically center tooltip content for left/right tooltips tooltip */ +.tooltip-left:after, +.tooltip-right:after { + margin-left: 0; + margin-bottom: -16px; +} diff --git a/resources/public/heroku-errors/application-error.html b/resources/public/heroku-errors/application-error.html new file mode 100644 index 00000000..be8da205 --- /dev/null +++ b/resources/public/heroku-errors/application-error.html @@ -0,0 +1,36 @@ + + +
sorry, Small World is a little more popular than we anticipated!
+if you refresh, the website should be back up in a few seconds
+