├── .gitignore ├── client ├── styles │ ├── text.sass │ ├── stream_preview.sass │ ├── admin_preview.sass │ ├── root.sass │ ├── vars.sass │ ├── not_found.sass │ ├── banner.sass │ ├── iconsset.sass │ ├── animations.sass │ ├── branding.sass │ ├── skeletons.sass │ ├── job.sass │ ├── create_job.sass │ ├── promotions.sass │ ├── colours.sass │ ├── tasks.sass │ └── button.sass ├── src │ ├── wh │ │ ├── admin │ │ │ ├── tags │ │ │ │ └── db.cljs │ │ │ ├── events.cljs │ │ │ ├── articles │ │ │ │ ├── db.cljs │ │ │ │ └── subs.cljs │ │ │ ├── activities │ │ │ │ ├── events.cljs │ │ │ │ └── subs.cljs │ │ │ ├── queries.cljc │ │ │ └── create_offer │ │ │ │ └── db.cljs │ │ ├── logged_in │ │ │ ├── personalised_jobs │ │ │ │ └── db.cljs │ │ │ ├── notifications │ │ │ │ └── settings │ │ │ │ │ ├── db.cljs │ │ │ │ │ └── subs.cljs │ │ │ ├── apply │ │ │ │ └── common_events.cljs │ │ │ └── contribute │ │ │ │ ├── styles.sass │ │ │ │ └── styles.cljc │ │ ├── promotions │ │ │ ├── create_promotion │ │ │ │ └── db.cljs │ │ │ └── preview │ │ │ │ ├── subs.cljs │ │ │ │ ├── views.cljs │ │ │ │ └── events.cljs │ │ ├── components │ │ │ ├── conversation_link │ │ │ │ ├── styles.cljc │ │ │ │ ├── core.cljc │ │ │ │ └── styles.sass │ │ │ ├── error │ │ │ │ ├── db.cljs │ │ │ │ └── subs.cljs │ │ │ ├── forms │ │ │ │ ├── events.cljs │ │ │ │ └── db.cljs │ │ │ ├── rich_text_field │ │ │ │ └── loadable.cljs │ │ │ ├── banner.cljc │ │ │ ├── click_outside.cljs │ │ │ └── tabs │ │ │ │ └── views.cljs │ │ ├── common │ │ │ ├── core.cljs │ │ │ ├── attachments.cljs │ │ │ ├── fx │ │ │ │ ├── reload.cljs │ │ │ │ ├── focus.cljs │ │ │ │ ├── auth.cljs │ │ │ │ ├── confirm.cljs │ │ │ │ ├── tracking_pixels.cljs │ │ │ │ └── persistent_state.cljs │ │ │ ├── local_storage.cljs │ │ │ └── fx.cljs │ │ ├── user │ │ │ └── core.cljs │ │ ├── venia │ │ │ └── core.cljs │ │ ├── login │ │ │ ├── twitter_callback │ │ │ │ ├── subs.cljs │ │ │ │ ├── db.cljs │ │ │ │ └── views.cljs │ │ │ ├── github_callback │ │ │ │ ├── subs.cljs │ │ │ │ ├── db.cljs │ │ │ │ └── views.cljs │ │ │ ├── stackoverflow_callback │ │ │ │ ├── subs.cljs │ │ │ │ ├── db.cljs │ │ │ │ └── views.cljs │ │ │ ├── subs.cljs │ │ │ ├── shared.cljs │ │ │ └── core.cljs │ │ ├── company │ │ │ ├── dashboard │ │ │ │ └── db.cljs │ │ │ ├── create_job │ │ │ │ └── common_events.cljs │ │ │ ├── common.cljs │ │ │ ├── views.cljs │ │ │ └── candidate │ │ │ │ └── db.cljs │ │ ├── profile │ │ │ ├── section_admin │ │ │ │ └── db.cljc │ │ │ ├── core.cljs │ │ │ ├── update_private │ │ │ │ └── db.cljs │ │ │ └── update_public │ │ │ │ └── db.cljs │ │ ├── search │ │ │ └── core.cljs │ │ ├── landing_page │ │ │ └── core.cljs │ │ ├── pricing │ │ │ └── core.cljs │ │ ├── register │ │ │ └── core.cljs │ │ ├── jobs │ │ │ └── core.cljs │ │ ├── blogs │ │ │ └── core.cljs │ │ ├── messaging │ │ │ └── unread_status.cljs │ │ └── core.cljs │ └── workspaces │ │ ├── core_cards.cljs │ │ ├── login_cards.cljs │ │ ├── side_cards.cljs │ │ ├── stat_cards.cljs │ │ ├── profile_cards.cljs │ │ ├── landing_page_cards.cljs │ │ └── iconset_cards.cljs ├── env │ ├── dev │ │ └── wh │ │ │ ├── dev.cljs │ │ │ └── interceptors.cljs │ └── prod │ │ └── wh │ │ └── interceptors.cljs ├── vendor │ └── bulma │ │ ├── sass │ │ ├── grid │ │ │ ├── _all.sass │ │ │ └── tiles.sass │ │ ├── base │ │ │ ├── _all.sass │ │ │ └── minireset.sass │ │ ├── layout │ │ │ ├── _all.sass │ │ │ ├── footer.sass │ │ │ └── section.sass │ │ ├── utilities │ │ │ ├── animations.sass │ │ │ └── _all.sass │ │ ├── components │ │ │ ├── _all.sass │ │ │ └── media.sass │ │ └── elements │ │ │ ├── _all.sass │ │ │ ├── icon.sass │ │ │ ├── container.sass │ │ │ ├── box.sass │ │ │ ├── other.sass │ │ │ └── notification.sass │ │ └── bulma.sass ├── resources │ ├── public │ │ ├── cards │ │ │ ├── jcb.png │ │ │ ├── visa.png │ │ │ ├── discover.png │ │ │ ├── dinersclub.png │ │ │ ├── mastercard.png │ │ │ └── americanexpress.png │ │ ├── images │ │ │ ├── heap.png │ │ │ ├── avatar-1.png │ │ │ ├── avatar-2.png │ │ │ ├── avatar-3.png │ │ │ ├── avatar-4.png │ │ │ ├── avatar-5.png │ │ │ ├── profile │ │ │ │ ├── girl.png │ │ │ │ ├── document.png │ │ │ │ ├── document2.png │ │ │ │ ├── computer_guy.png │ │ │ │ ├── computer_guy2.png │ │ │ │ ├── people_group.png │ │ │ │ ├── social_process.png │ │ │ │ ├── member_since.svg │ │ │ │ ├── commits.svg │ │ │ │ ├── articles.svg │ │ │ │ ├── new_user.svg │ │ │ │ ├── top_user.svg │ │ │ │ └── repositories.svg │ │ │ ├── homepage │ │ │ │ ├── logos │ │ │ │ │ ├── habito.png │ │ │ │ │ ├── inchora.png │ │ │ │ │ ├── avantstay.png │ │ │ │ │ ├── troops.svg │ │ │ │ │ └── two-sigma.svg │ │ │ │ ├── triangle.svg │ │ │ │ └── triangle2.svg │ │ │ ├── share-facebook.svg │ │ │ ├── share-twitter.svg │ │ │ ├── hiw │ │ │ │ └── balls │ │ │ │ │ ├── grey.svg │ │ │ │ │ ├── blue.svg │ │ │ │ │ ├── orange.svg │ │ │ │ │ └── yellow.svg │ │ │ ├── share-linkedin.svg │ │ │ ├── antenna.svg │ │ │ └── employers │ │ │ │ ├── free.svg │ │ │ │ └── icons │ │ │ │ └── programming.svg │ │ ├── logos │ │ │ └── png │ │ │ │ ├── ai.png │ │ │ │ ├── www.png │ │ │ │ ├── java.png │ │ │ │ ├── golang.png │ │ │ │ ├── python.png │ │ │ │ ├── remote.png │ │ │ │ ├── blockchain.png │ │ │ │ ├── functional.png │ │ │ │ └── javascript.png │ │ ├── favicons │ │ │ ├── ai-32x32.png │ │ │ ├── www-32x32.png │ │ │ ├── java-32x32.png │ │ │ ├── golang-32x32.png │ │ │ ├── python-32x32.png │ │ │ ├── remote-32x32.png │ │ │ ├── blockchain-32x32.png │ │ │ ├── functional-32x32.png │ │ │ └── javascript-32x32.png │ │ ├── apple-touch-icon-precomposed.png │ │ ├── pswp │ │ │ └── default-skin │ │ │ │ ├── preloader.gif │ │ │ │ └── default-skin.png │ │ ├── fonts │ │ │ ├── montserrat-v15-latin-500.woff │ │ │ ├── montserrat-v15-latin-500.woff2 │ │ │ ├── montserrat-v15-latin-600.woff │ │ │ ├── montserrat-v15-latin-600.woff2 │ │ │ ├── montserrat-v15-latin-700.woff │ │ │ ├── montserrat-v15-latin-700.woff2 │ │ │ ├── montserrat-v15-latin-800.woff │ │ │ ├── montserrat-v15-latin-800.woff2 │ │ │ ├── montserrat-v15-latin-italic.woff │ │ │ ├── montserrat-v15-latin-italic.woff2 │ │ │ ├── montserrat-v15-latin-regular.woff │ │ │ ├── inconsolata-v17-latin-regular.woff │ │ │ ├── inconsolata-v17-latin-regular.woff2 │ │ │ └── montserrat-v15-latin-regular.woff2 │ │ └── symbols │ │ │ └── issues.svg │ └── publicjs.edn ├── legacy-styles │ ├── _auth_popup.sass │ ├── _metrics.sass │ ├── _recommendation_cards.sass │ ├── _login.sass │ ├── _mixins.sass │ ├── _sticky.sass │ ├── _links.sass │ ├── _number_circle.sass │ ├── _sitemap.sass │ ├── _dropdown.sass │ ├── _modifiers.sass │ ├── _policy.sass │ ├── _pagination.sass │ ├── _loaders.sass │ ├── _tracking.sass │ ├── _responsive.sass │ ├── _selector.sass │ ├── _verticals.sass │ ├── _pods.sass │ ├── _highlight_code.sass │ └── _cta_pod.sass └── src-js │ ├── jobs_filters.js │ ├── index.js │ ├── clipboard.js │ ├── local_storage.js │ ├── button_analytics.js │ ├── add_sourcing.js │ ├── photo.js │ ├── newsletter.js │ ├── tags_selector.js │ ├── navigation.js │ └── trending_content.js ├── common ├── src │ └── wh │ │ ├── styles │ │ ├── root.cljc │ │ ├── banner.cljc │ │ ├── iconsset.cljc │ │ ├── not_found.cljc │ │ ├── stat_card.cljc │ │ ├── buttons_page_navigation.cljc │ │ ├── tasks.cljc │ │ ├── tag_selector.cljc │ │ ├── job.cljc │ │ ├── branding.cljc │ │ ├── modal.cljc │ │ ├── stream_preview.cljc │ │ ├── create_job.cljc │ │ ├── skeletons.cljc │ │ ├── signin_buttons.cljc │ │ ├── side_card_mobile.cljc │ │ ├── card_actions.cljc │ │ ├── landing.cljc │ │ ├── search.cljc │ │ ├── attract_card.cljc │ │ └── form.cljc │ │ ├── components │ │ ├── navbar │ │ │ ├── db.cljc │ │ │ ├── events.cljs │ │ │ └── subs.cljc │ │ ├── video_player.cljc │ │ ├── activities │ │ │ ├── article_published.cljc │ │ │ ├── job_promoted.cljc │ │ │ ├── job_published.cljc │ │ │ ├── company_promoted.cljc │ │ │ ├── issue_promoted.cljc │ │ │ ├── issue_published.cljc │ │ │ ├── article_promoted.cljc │ │ │ └── company_published.cljc │ │ ├── selector.cljc │ │ ├── buttons_page_navigation_styles.cljc │ │ ├── stats │ │ │ ├── loadable.cljs │ │ │ └── views.cljc │ │ ├── loader.cljc │ │ ├── promote_button.cljc │ │ ├── info_icon.cljc │ │ ├── newsletter │ │ │ └── styles.cljc │ │ ├── not_found.cljc │ │ ├── skeletons │ │ │ └── components.cljc │ │ ├── branding.cljc │ │ ├── icons.cljc │ │ ├── buttons_page_navigation_styles.sass │ │ └── pods │ │ │ └── candidates.cljc │ │ ├── common │ │ ├── keycodes.cljc │ │ ├── tag.cljc │ │ ├── repo.cljc │ │ ├── specs │ │ │ ├── video.cljc │ │ │ └── offer.cljc │ │ ├── application.cljc │ │ ├── emoji.cljc │ │ ├── issue.cljc │ │ ├── cases.cljc │ │ └── blog.cljc │ │ ├── util_macros.cljc │ │ ├── re_frame │ │ ├── subs.cljc │ │ └── events.cljc │ │ ├── slug.cljc │ │ └── re_frame.cljc └── test │ └── wh │ ├── common │ └── url_test.clj │ ├── routes_test.clj │ └── util_test.clj ├── common-pages └── src │ └── wh │ ├── jobsboard │ ├── db.cljc │ └── events.cljc │ ├── sitemap │ └── subs.cljc │ ├── landing │ ├── views.cljc │ ├── events.cljc │ └── subs.cljc │ ├── landing_new │ ├── unread_messages │ │ ├── styles.cljc │ │ ├── view.cljc │ │ └── styles.sass │ └── tags.cljc │ ├── db.cljc │ ├── notification_settings │ ├── styles.cljc │ ├── styles.sass │ └── subs.cljc │ ├── pricing │ ├── subs.cljc │ └── events.cljc │ ├── blogs │ ├── blog │ │ ├── styles.cljc │ │ ├── db.cljc │ │ └── styles.sass │ └── liked │ │ └── subs.cljc │ ├── company │ ├── articles │ │ ├── db.cljc │ │ └── events.cljc │ └── jobs │ │ └── db.cljc │ ├── pages │ └── issue │ │ ├── db.cljc │ │ └── edit │ │ ├── db.cljc │ │ └── subs.cljc │ ├── login │ └── invalid_magic_link │ │ └── views.cljc │ ├── how_it_works │ └── subs.cljc │ └── issues │ └── manage │ └── db.cljc ├── postcss.config.js ├── CODEOWNERS ├── server └── src │ └── wh │ └── config.clj └── workspaces.html /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /target 3 | 4 | -------------------------------------------------------------------------------- /client/styles/text.sass: -------------------------------------------------------------------------------- 1 | $p-line-height: 1.6em 2 | -------------------------------------------------------------------------------- /client/src/wh/admin/tags/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.admin.tags.db) 2 | -------------------------------------------------------------------------------- /common/src/wh/styles/root.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.root) 2 | -------------------------------------------------------------------------------- /client/env/dev/wh/dev.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.dev 2 | (:require [wh.core])) 3 | -------------------------------------------------------------------------------- /common/src/wh/components/navbar/db.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.navbar.db) 2 | 3 | -------------------------------------------------------------------------------- /client/src/wh/logged_in/personalised_jobs/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.logged-in.personalised-jobs.db) 2 | -------------------------------------------------------------------------------- /client/src/wh/promotions/create_promotion/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.promotions.create-promotion.db) 2 | -------------------------------------------------------------------------------- /common/src/wh/common/keycodes.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.common.keycodes) 2 | 3 | (def up 38) 4 | (def down 40) 5 | -------------------------------------------------------------------------------- /common-pages/src/wh/jobsboard/db.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.jobsboard.db) 2 | 3 | (def view-type-param "view-type") 4 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/grid/_all.sass: -------------------------------------------------------------------------------- 1 | @charset "utf-8" 2 | 3 | @import "columns.sass" 4 | @import "tiles.sass" 5 | -------------------------------------------------------------------------------- /client/resources/public/cards/jcb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/cards/jcb.png -------------------------------------------------------------------------------- /client/resources/public/cards/visa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/cards/visa.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {}, 4 | 'postcss-import': {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /client/resources/public/images/heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/heap.png -------------------------------------------------------------------------------- /client/resources/public/logos/png/ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/logos/png/ai.png -------------------------------------------------------------------------------- /client/resources/public/logos/png/www.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/logos/png/www.png -------------------------------------------------------------------------------- /common/src/wh/styles/banner.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.banner) 2 | (def banner "banner__banner--2AH82") 3 | (def link "banner__link--3rYRX") -------------------------------------------------------------------------------- /client/resources/public/cards/discover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/cards/discover.png -------------------------------------------------------------------------------- /client/resources/public/images/avatar-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/avatar-1.png -------------------------------------------------------------------------------- /client/resources/public/images/avatar-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/avatar-2.png -------------------------------------------------------------------------------- /client/resources/public/images/avatar-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/avatar-3.png -------------------------------------------------------------------------------- /client/resources/public/images/avatar-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/avatar-4.png -------------------------------------------------------------------------------- /client/resources/public/images/avatar-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/avatar-5.png -------------------------------------------------------------------------------- /client/resources/public/logos/png/java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/logos/png/java.png -------------------------------------------------------------------------------- /client/src/wh/components/conversation_link/styles.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.conversation-link.styles) 2 | (def link "styles__link---n76u") -------------------------------------------------------------------------------- /client/resources/public/cards/dinersclub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/cards/dinersclub.png -------------------------------------------------------------------------------- /client/resources/public/cards/mastercard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/cards/mastercard.png -------------------------------------------------------------------------------- /client/resources/public/favicons/ai-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/favicons/ai-32x32.png -------------------------------------------------------------------------------- /client/resources/public/favicons/www-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/favicons/www-32x32.png -------------------------------------------------------------------------------- /client/resources/public/logos/png/golang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/logos/png/golang.png -------------------------------------------------------------------------------- /client/resources/public/logos/png/python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/logos/png/python.png -------------------------------------------------------------------------------- /client/resources/public/logos/png/remote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/logos/png/remote.png -------------------------------------------------------------------------------- /client/src/wh/common/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.common.core 2 | (:require 3 | [cljs.loader :as loader])) 4 | 5 | (loader/set-loaded! :common) 6 | -------------------------------------------------------------------------------- /client/src/wh/logged_in/notifications/settings/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.logged-in.notifications.settings.db) 2 | 3 | (def types #{:matching-job}) 4 | -------------------------------------------------------------------------------- /client/resources/public/favicons/java-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/favicons/java-32x32.png -------------------------------------------------------------------------------- /client/resources/public/images/profile/girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/profile/girl.png -------------------------------------------------------------------------------- /client/resources/public/logos/png/blockchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/logos/png/blockchain.png -------------------------------------------------------------------------------- /client/resources/public/logos/png/functional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/logos/png/functional.png -------------------------------------------------------------------------------- /client/resources/public/logos/png/javascript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/logos/png/javascript.png -------------------------------------------------------------------------------- /client/vendor/bulma/sass/base/_all.sass: -------------------------------------------------------------------------------- 1 | @charset "utf-8" 2 | 3 | @import "minireset.sass" 4 | @import "generic.sass" 5 | @import "helpers.sass" 6 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/layout/_all.sass: -------------------------------------------------------------------------------- 1 | @charset "utf-8" 2 | 3 | @import "hero.sass" 4 | @import "section.sass" 5 | @import "footer.sass" 6 | -------------------------------------------------------------------------------- /client/resources/public/cards/americanexpress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/cards/americanexpress.png -------------------------------------------------------------------------------- /client/resources/public/favicons/golang-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/favicons/golang-32x32.png -------------------------------------------------------------------------------- /client/resources/public/favicons/python-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/favicons/python-32x32.png -------------------------------------------------------------------------------- /client/resources/public/favicons/remote-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/favicons/remote-32x32.png -------------------------------------------------------------------------------- /client/resources/public/images/profile/document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/profile/document.png -------------------------------------------------------------------------------- /client/resources/public/favicons/blockchain-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/favicons/blockchain-32x32.png -------------------------------------------------------------------------------- /client/resources/public/favicons/functional-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/favicons/functional-32x32.png -------------------------------------------------------------------------------- /client/resources/public/favicons/javascript-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/favicons/javascript-32x32.png -------------------------------------------------------------------------------- /client/resources/public/images/profile/document2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/profile/document2.png -------------------------------------------------------------------------------- /client/env/prod/wh/interceptors.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.interceptors 2 | (:require 3 | [re-frame.core :refer [trim-v]])) 4 | 5 | (def default-interceptors [trim-v]) 6 | -------------------------------------------------------------------------------- /client/resources/public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /client/resources/public/images/homepage/logos/habito.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/homepage/logos/habito.png -------------------------------------------------------------------------------- /client/resources/public/images/profile/computer_guy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/profile/computer_guy.png -------------------------------------------------------------------------------- /client/resources/public/images/profile/computer_guy2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/profile/computer_guy2.png -------------------------------------------------------------------------------- /client/resources/public/images/profile/people_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/profile/people_group.png -------------------------------------------------------------------------------- /client/resources/public/pswp/default-skin/preloader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/pswp/default-skin/preloader.gif -------------------------------------------------------------------------------- /client/src/wh/admin/events.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.admin.events 2 | (:require 3 | [re-frame.core :refer [path reg-event-db reg-event-fx]] 4 | [wh.db :as db])) 5 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/utilities/animations.sass: -------------------------------------------------------------------------------- 1 | @keyframes spinAround 2 | from 3 | transform: rotate(0deg) 4 | to 5 | transform: rotate(359deg) 6 | -------------------------------------------------------------------------------- /client/resources/public/images/homepage/logos/inchora.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/homepage/logos/inchora.png -------------------------------------------------------------------------------- /client/resources/public/images/profile/social_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/profile/social_process.png -------------------------------------------------------------------------------- /client/resources/public/pswp/default-skin/default-skin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/pswp/default-skin/default-skin.png -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-500.woff -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-500.woff2 -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-600.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-600.woff -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-600.woff2 -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-700.woff -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-700.woff2 -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-800.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-800.woff -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-800.woff2 -------------------------------------------------------------------------------- /client/resources/public/images/homepage/logos/avantstay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/images/homepage/logos/avantstay.png -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-italic.woff -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-italic.woff2 -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-regular.woff -------------------------------------------------------------------------------- /client/resources/public/fonts/inconsolata-v17-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/inconsolata-v17-latin-regular.woff -------------------------------------------------------------------------------- /client/resources/public/fonts/inconsolata-v17-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/inconsolata-v17-latin-regular.woff2 -------------------------------------------------------------------------------- /client/resources/public/fonts/montserrat-v15-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WorksHub/client/HEAD/client/resources/public/fonts/montserrat-v15-latin-regular.woff2 -------------------------------------------------------------------------------- /common/src/wh/styles/iconsset.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.iconsset) 2 | (def page "iconsset__page--lEJEc") 3 | (def icon "iconsset__icon--1iWKc") 4 | (def icon__wrapper "iconsset__icon__wrapper--1sPM9") -------------------------------------------------------------------------------- /common-pages/src/wh/sitemap/subs.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.sitemap.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]])) 4 | 5 | (reg-sub 6 | :wh/sitemap 7 | (fn [db _] 8 | (:wh/sitemap db))) 9 | -------------------------------------------------------------------------------- /common/src/wh/common/tag.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.common.tag) 2 | 3 | (defn tech? [tag] 4 | (boolean (some-> tag 5 | :type 6 | keyword 7 | (= :tech)))) 8 | -------------------------------------------------------------------------------- /common/src/wh/styles/not_found.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.not-found) 2 | (def container "not_found__container--3Zu-g") 3 | (def numbers "not_found__numbers--2EMsN") 4 | (def description "not_found__description--2VjSw") -------------------------------------------------------------------------------- /client/legacy-styles/_auth_popup.sass: -------------------------------------------------------------------------------- 1 | .auth-popup__content, 2 | .auth-popup__additional-content 3 | display: none 4 | 5 | h2 6 | color: $red 7 | 8 | &.is-visible 9 | display: block 10 | 11 | 12 | -------------------------------------------------------------------------------- /client/src/wh/user/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.user.core 2 | (:require [cljs.loader :as loader] 3 | [wh.user.events] 4 | [wh.user.subs] 5 | [wh.user.views])) 6 | 7 | (loader/set-loaded! :user) 8 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # These owners will be the default owners for everything in the repo. 5 | * @lacogubik @acron0 6 | -------------------------------------------------------------------------------- /client/src/wh/common/attachments.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.common.attachments 2 | (:require [clojure.string :as str])) 3 | 4 | (defn downloadable? [filename] 5 | (some-> filename 6 | (str/ends-with? ".pdf") 7 | not)) 8 | 9 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/layout/footer.sass: -------------------------------------------------------------------------------- 1 | $footer-background-color: $white-bis !default 2 | $footer-padding: 3rem 1.5rem 6rem !default 3 | 4 | .footer 5 | background-color: $footer-background-color 6 | padding: $footer-padding 7 | -------------------------------------------------------------------------------- /common-pages/src/wh/landing/views.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.landing.views 2 | (:require [wh.components.www-homepage :as www] 3 | [wh.re-frame.subs :refer [ .card 9 | margin-bottom: 0 10 | 11 | & > .card:not(:last-child) 12 | margin-bottom: 10px 13 | -------------------------------------------------------------------------------- /common/src/wh/util_macros.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.util-macros 2 | #?(:cljs (:require-macros [wh.util-macros :refer [when-not-prod]]))) 3 | 4 | #?(:clj 5 | (defmacro when-not-prod 6 | [& body] 7 | (when (not= (System/getenv "ENVIRONMENT") "prod") 8 | `(do 9 | ~@body)))) 10 | -------------------------------------------------------------------------------- /client/legacy-styles/_login.sass: -------------------------------------------------------------------------------- 1 | .login-buttons 2 | margin-top: 15vh 3 | position: relative 4 | 5 | .button 6 | margin: 8px 0 7 | 8 | .sparkle 9 | position: absolute 10 | width: 351px 11 | height: 240px 12 | top: -40px 13 | left: -25px 14 | pointer-events: none 15 | -------------------------------------------------------------------------------- /client/vendor/bulma/bulma.sass: -------------------------------------------------------------------------------- 1 | @charset "utf-8" 2 | /*! bulma.io v0.7.4 | MIT License | github.com/jgthms/bulma */ 3 | @import "sass/utilities/_all" 4 | @import "sass/base/_all" 5 | @import "sass/elements/_all" 6 | @import "sass/components/_all" 7 | @import "sass/grid/_all" 8 | @import "sass/layout/_all" 9 | -------------------------------------------------------------------------------- /common-pages/src/wh/notification_settings/styles.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.notification-settings.styles) 2 | (def text "styles__text--329rk") 3 | (def submittable-radio "styles__submittable-radio--19KuT") 4 | (def wh-formx "styles__wh-formx--eTgvs") 5 | (def field "styles__field--210Ge") 6 | (def label "styles__label--yTsyl") -------------------------------------------------------------------------------- /client/resources/public/images/homepage/triangle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/resources/public/images/homepage/triangle2.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/src/wh/login/twitter_callback/subs.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.twitter-callback.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]] 4 | [wh.login.twitter-callback.db :as twitter-callback])) 5 | 6 | (reg-sub 7 | ::error 8 | (fn [db _] 9 | (get-in db [::twitter-callback/sub-db :error]))) 10 | -------------------------------------------------------------------------------- /client/src/wh/common/fx/auth.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.common.fx.auth 2 | (:require 3 | [re-frame.core :refer [reg-fx dispatch]])) 4 | 5 | (defn show-auth-popup-effect 6 | [{:keys [context redirect]}] 7 | (js/showAuthPopUp (name context) (pr-str redirect))) 8 | 9 | (reg-fx :show-auth-popup show-auth-popup-effect) 10 | -------------------------------------------------------------------------------- /server/src/wh/config.clj: -------------------------------------------------------------------------------- 1 | ;; This is placeholder code. Do not add config here. 2 | 3 | (ns wh.config 4 | (:refer-clojure :exclude [get get-in])) 5 | 6 | (def config {}) 7 | 8 | (defn get-in 9 | [ks] 10 | (clojure.core/get-in config ks)) 11 | 12 | (defn get 13 | [k] 14 | (clojure.core/get config k)) 15 | -------------------------------------------------------------------------------- /client/resources/public/images/share-facebook.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/src/wh/login/github_callback/subs.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.github-callback.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]] 4 | [wh.login.github-callback.db :as github-callback])) 5 | 6 | (reg-sub 7 | ::error 8 | (fn [db _] 9 | (get-in db [::github-callback/sub-db :error]))) 10 | -------------------------------------------------------------------------------- /client/legacy-styles/_mixins.sass: -------------------------------------------------------------------------------- 1 | =auto-center() 2 | position: absolute 3 | left: 50% 4 | top: 50% 5 | +desktop 6 | transform: translate(-50%, -50%) 7 | 8 | @mixin line-clamp($lines: 2) 9 | display: -webkit-box 10 | -webkit-line-clamp: $lines 11 | -webkit-box-orient: vertical 12 | overflow-y: hidden 13 | -------------------------------------------------------------------------------- /common/test/wh/common/url_test.clj: -------------------------------------------------------------------------------- 1 | (ns wh.common.url-test 2 | (:require [wh.common.url :as url] 3 | [wh.test-common :as tc])) 4 | 5 | (tc/def-spec-test url/concat-vector-values) 6 | (tc/def-spec-test url/parse-query-string) 7 | (tc/def-spec-test url/uri->query-params) 8 | (tc/def-spec-test url/serialize-query-params) 9 | -------------------------------------------------------------------------------- /common-pages/src/wh/pricing/subs.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.pricing.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]])) 4 | 5 | (reg-sub 6 | ::can-start-free-trial? 7 | (fn [db _] 8 | (let [company (get-in db [:wh.user.db/sub-db :wh.user.db/company])] 9 | (contains? (:permissions company) :can_start_free_trial)))) 10 | -------------------------------------------------------------------------------- /common/src/wh/styles/stat_card.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.stat-card) 2 | (def button "stat_card__button--2geJs") 3 | (def card "stat_card__card--347_n") 4 | (def text "stat_card__text--2dw3a") 5 | (def chart "stat_card__chart--31Jlv") 6 | (def chart--percentage "stat_card__chart--percentage--WmvX7") 7 | (def chart--icon "stat_card__chart--icon--1R_wt") -------------------------------------------------------------------------------- /client/src/wh/login/stackoverflow_callback/subs.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.stackoverflow-callback.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]] 4 | [wh.login.stackoverflow-callback.db :as stackoverflow-callback])) 5 | 6 | (reg-sub 7 | ::error 8 | (fn [db _] 9 | (get-in db [::stackoverflow-callback/sub-db :error]))) 10 | -------------------------------------------------------------------------------- /common/src/wh/styles/buttons_page_navigation.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.buttons-page-navigation) 2 | (def buttons "buttons_page_navigation__buttons--mZDht") 3 | (def button "buttons_page_navigation__button--RzGnQ") 4 | (def button--active "buttons_page_navigation__button--active--1WF_5") 5 | (def button__icon "buttons_page_navigation__button__icon--3wTQb") -------------------------------------------------------------------------------- /client/src/wh/promotions/preview/subs.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.promotions.preview.subs 2 | (:require [re-frame.core :refer [reg-sub]] 3 | [wh.re-frame.subs :refer [ 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /common-pages/src/wh/pricing/events.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.pricing.events 2 | #?(:cljs 3 | (:require 4 | [wh.pages.core :refer [on-page-load]]))) 5 | 6 | ;; TODO The only reason we need this is because the pricing page 7 | ;; still needs to load the app for some of its components. Fail. 8 | 9 | #?(:cljs 10 | (defmethod on-page-load :pricing [_] 11 | [[:wh.pages.core/unset-loader]])) 12 | -------------------------------------------------------------------------------- /common/test/wh/routes_test.clj: -------------------------------------------------------------------------------- 1 | (ns wh.routes-test 2 | (:require 3 | [bidi.bidi :as bidi] 4 | [wh.common.url :as url] 5 | [wh.routes :as r] 6 | [wh.test-common :as tc])) 7 | 8 | (tc/def-spec-test r/path 9 | r/prepare-path-params 10 | url/serialize-query-params 11 | bidi/path-for) 12 | (tc/def-spec-test r/prepare-path-params) 13 | -------------------------------------------------------------------------------- /client/legacy-styles/_number_circle.sass: -------------------------------------------------------------------------------- 1 | .number-circle 2 | min-width: 32px 3 | width: 32px 4 | height: 32px 5 | background-color: $red 6 | color: white 7 | border-radius: 32px 8 | text-align: center 9 | font-size: 18px 10 | font-weight: $font-medium 11 | padding-top: 1px 12 | 13 | .number-circle--inverted 14 | background-color: white 15 | color: $red 16 | border: 1px solid $red 17 | -------------------------------------------------------------------------------- /client/legacy-styles/_sitemap.sass: -------------------------------------------------------------------------------- 1 | .sitemap__link 2 | flex-basis: 33% 3 | a 4 | color: $red 5 | text-decoration: underline 6 | font-size: 14px 7 | line-height: 1.71 8 | 9 | 10 | .sitemap__container 11 | display: flex 12 | flex-wrap: wrap 13 | 14 | .sitemap__vertical 15 | color: $grey-darker 16 | font-weight: $font-semi-bold 17 | margin-top: 18px 18 | margin-bottom: 5px 19 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/components/_all.sass: -------------------------------------------------------------------------------- 1 | @charset "utf-8" 2 | 3 | @import "breadcrumb.sass" 4 | @import "card.sass" 5 | @import "dropdown.sass" 6 | @import "level.sass" 7 | @import "list.sass" 8 | @import "media.sass" 9 | @import "menu.sass" 10 | @import "message.sass" 11 | @import "modal.sass" 12 | @import "navbar.sass" 13 | @import "pagination.sass" 14 | @import "panel.sass" 15 | @import "tabs.sass" 16 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/elements/_all.sass: -------------------------------------------------------------------------------- 1 | @charset "utf-8" 2 | 3 | @import "box.sass" 4 | @import "button.sass" 5 | @import "container.sass" 6 | @import "content.sass" 7 | @import "form.sass" 8 | @import "icon.sass" 9 | @import "image.sass" 10 | @import "notification.sass" 11 | @import "progress.sass" 12 | @import "table.sass" 13 | @import "tag.sass" 14 | @import "title.sass" 15 | 16 | @import "other.sass" 17 | -------------------------------------------------------------------------------- /client/styles/root.sass: -------------------------------------------------------------------------------- 1 | @import vars 2 | @import mixins 3 | 4 | \:root 5 | --header-height: #{$header-height-mobile} 6 | --color-calendar-graph-day-bg: #ebedf0 7 | --color-calendar-graph-day-L1-bg: #9be9a8 8 | --color-calendar-graph-day-L2-bg: #40c463 9 | --color-calendar-graph-day-L3-bg: #30a14e 10 | --color-calendar-graph-day-L4-bg: #216e39 11 | +tablet 12 | --header-height: #{$header-height-desktop} -------------------------------------------------------------------------------- /client/vendor/bulma/sass/layout/section.sass: -------------------------------------------------------------------------------- 1 | $section-padding: 3rem 1.5rem !default 2 | $section-padding-medium: 9rem 1.5rem !default 3 | $section-padding-large: 18rem 1.5rem !default 4 | 5 | .section 6 | padding: $section-padding 7 | // Responsiveness 8 | +desktop 9 | // Sizes 10 | &.is-medium 11 | padding: $section-padding-medium 12 | &.is-large 13 | padding: $section-padding-large 14 | -------------------------------------------------------------------------------- /client/legacy-styles/_dropdown.sass: -------------------------------------------------------------------------------- 1 | $dropdown-width: 270px 2 | 3 | .dropdown-menu 4 | width: $dropdown-width 5 | padding-top: 0 6 | letter-spacing: 0.1em 7 | 8 | .dropdown__logo 9 | width: 40px 10 | height: 40px 11 | 12 | .dropdown-content 13 | border-radius: 0 0 2px 2px 14 | padding-top: 0 15 | box-shadow: none 16 | 17 | a.dropdown-item 18 | height: 50px 19 | align-items: center 20 | display: flex -------------------------------------------------------------------------------- /client/src-js/index.js: -------------------------------------------------------------------------------- 1 | import './auth.js' 2 | import './video.js' 3 | import './photo.js' 4 | import './code_highlight.js' 5 | import './button_analytics.js' 6 | import './newsletter.js' 7 | import './tags_selector.js' 8 | import './trending_content.js' 9 | import './navigation.js' 10 | import './feed_paging.js' 11 | import './clipboard.js' 12 | import './init.js' 13 | import './search_hints.js' 14 | import './jobs_filters' 15 | -------------------------------------------------------------------------------- /client/src/wh/login/github_callback/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.github-callback.db 2 | (:require [cljs.spec.alpha :as s])) 3 | 4 | (s/def ::error? (s/nilable map?)) 5 | (s/def ::callback-status #{:sent :fail :success}) 6 | (s/def ::sub-db (s/keys :opt-un [::error ::callback-status])) 7 | (def default-db {:error nil}) 8 | 9 | (defn already-connected? [error] 10 | (= "github-connected-to-another-account" 11 | (:message error))) -------------------------------------------------------------------------------- /client/src/wh/login/twitter_callback/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.twitter-callback.db 2 | (:require [cljs.spec.alpha :as s])) 3 | 4 | (s/def ::error (s/nilable map?)) 5 | (s/def ::callback-status #{:sent :fail :success}) 6 | (s/def ::sub-db (s/keys :opt-un [::error ::callback-status])) 7 | (def default-db {:error nil}) 8 | 9 | (defn already-connected? [error] 10 | (= "twitter-connected-to-another-account" 11 | (:message error))) -------------------------------------------------------------------------------- /client/src/wh/admin/articles/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.admin.articles.db 2 | (:require [wh.components.pagination :as pagination])) 3 | 4 | (def page-size 20) 5 | 6 | (defn page-number 7 | [db] 8 | (pagination/qps->page-number (:wh.db/query-params db))) 9 | 10 | (defn initialize-db 11 | [db] 12 | (merge {::articles nil 13 | ::pagination nil 14 | ::in-progress? false 15 | ::error? false} db)) 16 | -------------------------------------------------------------------------------- /common-pages/src/wh/landing/subs.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.landing.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]])) 4 | 5 | (reg-sub 6 | ::sub-db 7 | (fn [db _] 8 | (:wh.homepage.db/sub-db db))) 9 | 10 | (reg-sub 11 | ::jobs 12 | :<- [::sub-db] 13 | (fn [sub-db _] 14 | (:wh.homepage.db/jobs sub-db))) 15 | 16 | (reg-sub 17 | ::blogs 18 | :<- [::sub-db] 19 | (fn [sub-db _] 20 | (:wh.homepage.db/blogs sub-db))) 21 | -------------------------------------------------------------------------------- /common/src/wh/styles/tag_selector.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.tag-selector) 2 | (def card "tag_selector__card--2ODKJ") 3 | (def card--mobile "tag_selector__card--mobile--1YWDS") 4 | (def title "tag_selector__title--18wfY") 5 | (def status "tag_selector__status--1ZJzO") 6 | (def selected-counter "tag_selector__selected-counter--2j4Ie") 7 | (def reset-button "tag_selector__reset-button--1ef8G") 8 | (def reset-button__icon "tag_selector__reset-button__icon--2MZ55") -------------------------------------------------------------------------------- /client/src/wh/admin/activities/events.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.admin.activities.events 2 | (:require [wh.components.activities.queries :as queries] 3 | [wh.graphql-cache :refer [reg-query]] 4 | [wh.pages.core :refer [on-page-load]])) 5 | 6 | (reg-query :recent_activities queries/recent-activities-query) 7 | 8 | (defmethod on-page-load :feed-preview [_db] 9 | [[:graphql/query :recent_activities 10 | {:activities_tags []}]]) 11 | -------------------------------------------------------------------------------- /client/src/wh/components/forms/events.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.components.forms.events 2 | (:require [clojure.string :as str])) 3 | 4 | (defn multi-edit-fn 5 | "Helper for multi-edit events." 6 | [k & path] 7 | (fn [db [i value]] 8 | (let [old-values (k db) 9 | new-values (assoc-in old-values (into [i] path) value) 10 | new-values (vec (remove #(str/blank? (get-in % path)) new-values))] 11 | (assoc db k new-values)))) 12 | -------------------------------------------------------------------------------- /client/src/wh/login/stackoverflow_callback/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.stackoverflow-callback.db 2 | (:require [cljs.spec.alpha :as s])) 3 | 4 | (s/def ::error (s/nilable map?)) 5 | (s/def ::callback-status #{:sent :fail :success}) 6 | (s/def ::sub-db (s/keys :opt-un [::error ::callback-status])) 7 | (def default-db {:error nil}) 8 | 9 | (defn already-connected? [error] 10 | (= "stackoverflow-connected-to-another-account" 11 | (:message error))) -------------------------------------------------------------------------------- /common-pages/src/wh/landing_new/tags.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.landing-new.tags 2 | (:require [clojure.string :as str])) 3 | 4 | (defn- parse-tags [tags-param] 5 | (->> (str/split tags-param #",") 6 | (map 7 | (fn [tag] 8 | (str/split tag #":"))) 9 | (map (fn [[tag type]] 10 | {:slug tag :type type})))) 11 | 12 | 13 | (defn param->tags [tags-param] 14 | (or (some-> tags-param parse-tags) 15 | [])) 16 | -------------------------------------------------------------------------------- /client/src/wh/company/dashboard/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.company.dashboard.db 2 | (:require [cljs.spec.alpha :as s])) 3 | 4 | (s/def ::publishing-jobs (s/coll-of string? :kind set)) 5 | (s/def ::publish-celebrations (s/coll-of string? :kind set)) 6 | 7 | (defn initial-db 8 | [db] 9 | (merge 10 | {::error nil 11 | ::activity-items-count 15 12 | ::publishing-jobs #{} 13 | ::publish-celebrations #{}} 14 | db)) 15 | -------------------------------------------------------------------------------- /common/src/wh/styles/job.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.job) 2 | (def highlight__content "job__highlight__content--1O7Ml") 3 | (def highlight__subtitle "job__highlight__subtitle--3q5PA") 4 | (def highlight__icon "job__highlight__icon--1zZbQ") 5 | (def highlight__list__element "job__highlight__list__element--_psPk") 6 | (def remote-info "job__remote-info--2reJG") 7 | (def remote-info__icon "job__remote-info__icon--2hglS") 8 | (def timezones-list "job__timezones-list--1sJJ1") -------------------------------------------------------------------------------- /client/styles/vars.sass: -------------------------------------------------------------------------------- 1 | $global-min-width: 320px 2 | $global-max-width: 2000px 3 | $gap: 64px 4 | $tablet: 769px 5 | $desktop: 960px + (2 * $gap) 6 | $widescreen: 1152px + (2 * $gap) 7 | $header-height-desktop: 76px 8 | $header-height-mobile: 46px 9 | $font-family: Montserrat, serif 10 | $navbar-dropdown-starts-at: calc(100% - 4px) 11 | 12 | $navbar-z-index: 11 13 | $card-z-index: 1 14 | $modal-z-index: 101 15 | $card-element-z-index: $card-z-index + 1 16 | -------------------------------------------------------------------------------- /common-pages/src/wh/blogs/blog/styles.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.blogs.blog.styles) 2 | (def publisher "styles__publisher--1uJcc") 3 | (def publisher--devto "styles__publisher--devto--1fPmU") 4 | (def publisher--hashnode "styles__publisher--hashnode--2w-KF") 5 | (def publisher__name "styles__publisher__name--E8Dnr") 6 | (def publishers "styles__publishers--gvJKg") 7 | (def comment-section "styles__comment-section--WvJmU") 8 | (def comment-section-header "styles__comment-section-header--3dJuG") -------------------------------------------------------------------------------- /common/src/wh/styles/branding.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.branding) 2 | (def vertical-title "branding__vertical-title--1pSpw") 3 | (def vertical-title__line "branding__vertical-title__line--3myD3") 4 | (def vertical-title--multiline "branding__vertical-title--multiline--3GNyQ") 5 | (def vertical-title--navigation "branding__vertical-title--navigation--3D_M7") 6 | (def vertical-title--small "branding__vertical-title--small--7t970") 7 | (def vertical-title--medium "branding__vertical-title--medium--vZiqL") -------------------------------------------------------------------------------- /common-pages/src/wh/company/articles/db.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.company.articles.db 2 | (:require 3 | [wh.components.pagination :as pagination])) 4 | 5 | (def page-size 12) 6 | 7 | (defn company-slug 8 | [db] 9 | (get-in db [:wh.db/page-params :slug])) 10 | 11 | (defn page-number 12 | [db] 13 | (pagination/qps->page-number (:wh.db/query-params db))) 14 | 15 | (defn params 16 | [db] 17 | {:slug (company-slug db) 18 | :page_size page-size 19 | :page_number (page-number db)}) 20 | -------------------------------------------------------------------------------- /common/src/wh/styles/modal.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.modal) 2 | (def modal "modal__modal--D9-_D") 3 | (def modal__container "modal__modal__container--2e97x") 4 | (def overlay "modal__overlay--3h4hC") 5 | (def header "modal__header--2WdQK") 6 | (def footer "modal__footer--3Wgqu") 7 | (def body "modal__body--32sxr") 8 | (def close "modal__close--1S-z1") 9 | (def close__wrapper "modal__close__wrapper--3MTwN") 10 | (def button "modal__button--2tias") 11 | (def button--secondary "modal__button--secondary--1oBtQ") -------------------------------------------------------------------------------- /client/src/workspaces/core_cards.cljs: -------------------------------------------------------------------------------- 1 | (ns workspaces.core-cards 2 | (:require [nubank.workspaces.card-types.react :as ct.react] 3 | [nubank.workspaces.core :as ws] 4 | [reagent.core :as r] 5 | [wh.login.views :as views])) 6 | 7 | (defn element [name props & children] 8 | (apply js/React.createElement name (clj->js props) children)) 9 | 10 | (ws/defcard hello-card 11 | (ct.react/react-card 12 | (r/as-element [views/back-button]))) 13 | 14 | (defonce init (ws/mount)) 15 | -------------------------------------------------------------------------------- /client/src/wh/profile/section_admin/db.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.profile.section-admin.db) 2 | 3 | (def updating-user-status-key :updating-status) 4 | 5 | (defn updating-status [db] 6 | (get db updating-user-status-key)) 7 | 8 | (defn set-updating-status [db status] 9 | (assoc db updating-user-status-key (if (= "approved" status) 10 | :approving 11 | :rejecting))) 12 | 13 | (defn unset-updating-status [db] 14 | (assoc db updating-user-status-key nil)) -------------------------------------------------------------------------------- /common/src/wh/components/selector.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.selector 2 | (:require [wh.util :as util])) 3 | 4 | (defn selector 5 | [selected-tab tbs on-click] 6 | [:ul.selector 7 | {} 8 | (for [[id label :as t] tbs] 9 | ^{:key id} 10 | [:li 11 | (merge {:class (util/merge-classes "selector__option" 12 | (when (= id selected-tab) "selector__option--selected"))} 13 | #?(:cljs {:on-click #(when on-click (on-click id))})) 14 | label])]) 15 | -------------------------------------------------------------------------------- /common/src/wh/styles/stream_preview.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.stream-preview) 2 | (def object "stream_preview__object--1P7p1") 3 | (def activity "stream_preview__activity--1G6k7") 4 | (def header "stream_preview__header--2f0MA") 5 | (def show-hide "stream_preview__show-hide--3CUsN") 6 | (def date "stream_preview__date--1ukXf") 7 | (def activity--publish "stream_preview__activity--publish--Cn3JZ") 8 | (def activity--highlight "stream_preview__activity--highlight--3KvTl") 9 | (def activity--promote "stream_preview__activity--promote--1ouwv") -------------------------------------------------------------------------------- /client/src/wh/common/local_storage.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.common.local-storage) 2 | 3 | (defn set-item! 4 | "Set `key' in browser's localStorage to `val`." 5 | [key val] 6 | (.setItem (.-localStorage js/window) key val)) 7 | 8 | (defn get-item 9 | "Returns value of `key' from browser's localStorage." 10 | [key] 11 | (.getItem (.-localStorage js/window) key)) 12 | 13 | (defn remove-item! 14 | "Remove the browser's localStorage value for the given `key`" 15 | [key] 16 | (.removeItem (.-localStorage js/window) key)) 17 | 18 | -------------------------------------------------------------------------------- /common/src/wh/components/activities/job_promoted.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.activities.job-promoted 2 | (:require [wh.components.activities.components :as components] 3 | [wh.components.activities.job :as job])) 4 | 5 | (defn card [job actor description type opts] 6 | [components/card type 7 | [components/header 8 | [components/promoter actor] 9 | [components/entity-description :job type]] 10 | 11 | [components/description description] 12 | 13 | [job/base-card job (:job-company job) type opts]]) 14 | -------------------------------------------------------------------------------- /client/src/wh/common/fx.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.common.fx 2 | (:require 3 | [wh.common.fx.algolia] 4 | [wh.common.fx.analytics] 5 | [wh.common.fx.auth] 6 | [wh.common.fx.confirm] 7 | [wh.common.fx.debounce] 8 | [wh.common.fx.focus] 9 | [wh.common.fx.google-maps] 10 | [wh.common.fx.graphql] 11 | [wh.common.fx.http] 12 | [wh.common.fx.reload] 13 | ;; we don't load wh.common.fx.persistent-state since it's only needed in login module 14 | [wh.common.fx.scroll] 15 | [wh.common.fx.tracking-pixels])) 16 | -------------------------------------------------------------------------------- /client/src/wh/search/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.search.core 2 | (:require [cljs.loader :as loader] 3 | [re-frame.core :refer [dispatch-sync reg-event-db]] 4 | [wh.db :as db] 5 | [wh.search.views :as search-views])) 6 | 7 | (def page-mapping 8 | {:search search-views/search-page}) 9 | 10 | (reg-event-db 11 | ::initialize-page-mapping 12 | (fn [db _] 13 | (update db ::db/page-mapping merge page-mapping))) 14 | 15 | (dispatch-sync [::initialize-page-mapping]) 16 | 17 | (loader/set-loaded! :search) 18 | -------------------------------------------------------------------------------- /common/src/wh/components/activities/job_published.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.activities.job-published 2 | (:require [wh.components.activities.components :as components] 3 | [wh.components.activities.job :as job])) 4 | 5 | (defn card [job actor type opts] 6 | [components/card type 7 | [components/header 8 | [components/company-info actor :job type] 9 | [components/entity-description :job type]] 10 | 11 | [components/description {:type :cropped} (:tagline job)] 12 | 13 | [job/base-card job actor type opts]]) 14 | -------------------------------------------------------------------------------- /client/src/wh/company/create_job/common_events.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.company.create-job.common-events 2 | (:require [re-frame.core :refer [reg-event-fx]] 3 | [wh.db :as db])) 4 | 5 | (reg-event-fx 6 | :publish/try-publish 7 | db/default-interceptors 8 | (fn [{db :db} [{:keys [event event-type job-slug]}]] 9 | (if (db/logged-in? db) 10 | {:dispatch [event]} 11 | {:show-auth-popup {:context (some-> event-type name) 12 | :redirect [:job :params {:slug job-slug} :query-params {"publish" true}]}}))) 13 | -------------------------------------------------------------------------------- /client/src/wh/profile/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.profile.core 2 | (:require 3 | [cljs.loader :as loader] 4 | [re-frame.core :refer [dispatch dispatch-sync reg-event-db]] 5 | [wh.profile.views :as profile] 6 | [wh.profile.events] 7 | [wh.db :as db])) 8 | 9 | (def page-mapping 10 | {:user profile/page}) 11 | 12 | (reg-event-db 13 | ::initialize-page-mapping 14 | (fn [db _] 15 | (update db ::db/page-mapping merge page-mapping))) 16 | 17 | (dispatch-sync [::initialize-page-mapping]) 18 | 19 | (loader/set-loaded! :user) 20 | -------------------------------------------------------------------------------- /common/src/wh/components/buttons_page_navigation_styles.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.buttons-page-navigation-styles) 2 | (def buttons "buttons_page_navigation_styles__buttons--39jH9") 3 | (def button "buttons_page_navigation_styles__button--eHFcV") 4 | (def button--active "buttons_page_navigation_styles__button--active--2IWsO") 5 | (def button__icon "buttons_page_navigation_styles__button__icon--1x4yw") 6 | (def button--filters "buttons_page_navigation_styles__button--filters--p5aAK") 7 | (def filters-toggle "buttons_page_navigation_styles__filters-toggle--3BLVW") -------------------------------------------------------------------------------- /common/src/wh/components/stats/loadable.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.components.stats.loadable 2 | (:require [shadow.lazy :as lazy] 3 | [wh.re-frame :refer [atom]])) 4 | 5 | (def chart-lazy (lazy/loadable wh.components.stats.core/chart)) 6 | (def default (fn [] [:div])) 7 | 8 | (defn chart [_] 9 | (let [component (atom default) 10 | _promise (-> (lazy/load chart-lazy) 11 | (.then (fn [root-el] 12 | (reset! component root-el))))] 13 | (fn [props] 14 | [@component props]))) 15 | -------------------------------------------------------------------------------- /client/src-js/clipboard.js: -------------------------------------------------------------------------------- 1 | // https://techoverflow.net/2018/03/30/copying-strings-to-the-clipboard-using-pure-javascript/ 2 | export function copyStringToClipboard(str) { 3 | var el = document.createElement('textarea') 4 | el.value = str 5 | el.setAttribute('readonly', '') 6 | el.style = { position: 'absolute', left: '-9999px' } 7 | document.body.appendChild(el) 8 | el.select() 9 | document.execCommand('copy') 10 | document.body.removeChild(el) 11 | } 12 | 13 | window.copyStringToClipboard = copyStringToClipboard 14 | -------------------------------------------------------------------------------- /common/src/wh/components/activities/company_promoted.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.activities.company-promoted 2 | (:require [wh.components.activities.company :as company] 3 | [wh.components.activities.components :as components])) 4 | 5 | (defn card [company actor description type opts] 6 | [components/card type 7 | [components/header 8 | [components/promoter actor] 9 | [components/entity-description :company type]] 10 | 11 | [components/description description] 12 | 13 | [company/base-card company actor type opts]]) 14 | -------------------------------------------------------------------------------- /common/src/wh/components/activities/issue_promoted.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.activities.issue-promoted 2 | (:require [wh.components.activities.components :as components] 3 | [wh.components.activities.issue :as issue])) 4 | 5 | (defn card [issue actor description type opts] 6 | [components/card type 7 | [components/header 8 | [components/promoter actor] 9 | [components/entity-description :issue type]] 10 | 11 | [components/description description] 12 | 13 | [issue/base-card issue (:issue-company issue) type opts]]) 14 | -------------------------------------------------------------------------------- /client/env/dev/wh/interceptors.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.interceptors 2 | (:require 3 | [cljs.spec.alpha :as s] 4 | [re-frame.core :refer [after trim-v]])) 5 | 6 | (defn check-and-throw 7 | "Throws an exception if `db` doesn't match the Spec `a-spec`." 8 | [a-spec db] 9 | (when-not (s/valid? a-spec db) 10 | (js/console.error (clj->js (s/explain-data a-spec db))))) 11 | 12 | (def check-spec-interceptor (after (partial check-and-throw :wh.db/app-db))) 13 | 14 | (def default-interceptors [check-spec-interceptor trim-v]) 15 | -------------------------------------------------------------------------------- /client/src/wh/components/error/subs.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.components.error.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]] 4 | [wh.components.error.db :as error])) 5 | 6 | (reg-sub ::sub-db (fn [db _] (::error/sub-db db))) 7 | 8 | (reg-sub 9 | ::message 10 | :<- [::sub-db] 11 | (fn [db _] 12 | (::error/message db))) 13 | 14 | (reg-sub 15 | ::type 16 | :<- [::sub-db] 17 | (fn [db _] 18 | (name (::error/type db)))) 19 | 20 | (reg-sub 21 | ::retry-event 22 | :<- [::sub-db] 23 | (fn [db _] 24 | (::error/retry-event db))) -------------------------------------------------------------------------------- /common/src/wh/components/activities/issue_published.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.activities.issue-published 2 | (:require [wh.components.activities.components :as components] 3 | [wh.components.activities.issue :as issue])) 4 | 5 | (defn card [{:keys [body] :as issue} actor type opts] 6 | [components/card type 7 | [components/header 8 | [components/company-info actor :issue type] 9 | [components/entity-description :issue type]] 10 | [components/description {:type :cropped} body] 11 | [issue/base-card issue actor type opts]]) 12 | -------------------------------------------------------------------------------- /common/src/wh/common/specs/video.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.common.specs.video 2 | (:require 3 | [#?(:clj clojure.spec.alpha 4 | :cljs cljs.spec.alpha) :as s] 5 | [wh.common.specs.primitives :as p])) 6 | 7 | (s/def :wh.video/youtube-id ::p/non-empty-string) 8 | (s/def :wh.video/thumbnail ::p/non-empty-string) 9 | (s/def :wh.video/description ::p/non-empty-string) 10 | 11 | (s/def :wh/video (s/keys :req-un [:wh.video/youtube-id 12 | :wh.video/thumbnail] 13 | :opt-un [:wh.video/description])) 14 | -------------------------------------------------------------------------------- /common/src/wh/components/activities/article_promoted.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.activities.article-promoted 2 | (:require [wh.components.activities.article :as article] 3 | [wh.components.activities.components :as components] 4 | [wh.styles.activities :as styles])) 5 | 6 | (defn card [blog actor description type opts] 7 | [components/card type 8 | [components/promoter actor] 9 | 10 | [components/description {:class styles/description--article} description] 11 | 12 | [article/base-card blog (:author-info blog) type opts]]) 13 | -------------------------------------------------------------------------------- /client/src/wh/components/conversation_link/core.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.conversation-link.core 2 | (:require [wh.routes :as routes] 3 | [wh.components.conversation-link.styles :as styles] 4 | [wh.components.icons :refer [icon]])) 5 | 6 | (defn link 7 | [{:keys [conversations-enabled?] :as _ctx} 8 | {:keys [id] :as _conversation}] 9 | (when (and conversations-enabled? id) 10 | [:a {:href (routes/path :conversation :params {:id id}) 11 | :class styles/link} 12 | [icon "message-circle"] 13 | "Open conversation"])) 14 | -------------------------------------------------------------------------------- /common/src/wh/common/application.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.common.application) 2 | 3 | (def state-hired :hired) 4 | (def state-approved :approved) 5 | 6 | (defn state [a] (:state a)) 7 | 8 | (defn state? [s application] 9 | (boolean (some-> application 10 | state 11 | keyword 12 | (= s)))) 13 | 14 | (def approved? (partial state? state-approved)) 15 | (def hired? (partial state? state-hired)) 16 | 17 | (defn hubspot-deal-id [a] (get-in a [:hubspot :id])) 18 | (defn has-conversation? [a] (boolean (:conversation-id a))) 19 | 20 | -------------------------------------------------------------------------------- /common-pages/src/wh/landing_new/unread_messages/view.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.landing-new.unread-messages.view 2 | (:require [wh.components.activities.components :as activities] 3 | [wh.landing-new.unread-messages.styles :as styles] 4 | [wh.routes :as routes])) 5 | 6 | (defn unread-messages [] 7 | [:div {:class styles/card} 8 | [:div {:class styles/wrapper} 9 | [:div {:class styles/red-dot}] 10 | [:span "You have unread messages"]] 11 | [activities/button 12 | {:href (routes/path :conversations) :class styles/button} 13 | "Open conversations"]]) 14 | -------------------------------------------------------------------------------- /client/src/wh/components/conversation_link/styles.sass: -------------------------------------------------------------------------------- 1 | @import 'colours' 2 | 3 | .link 4 | height: 32px 5 | width: fit-content 6 | background: $white 7 | border-radius: 4px 8 | margin-top: 12px 9 | box-sizing: border-box 10 | color: $primary-red 11 | border: 1px solid $primary-red 12 | padding: 0 20px 13 | font-size: 13px 14 | font-weight: 600 15 | align-items: center 16 | display: flex 17 | justify-content: center 18 | 19 | &:hover 20 | color: $primary-red-hover 21 | border: 1px solid $primary-red-hover 22 | 23 | & > :global(.icon) 24 | margin-right: 6px 25 | -------------------------------------------------------------------------------- /client/src/wh/logged_in/apply/common_events.cljs: -------------------------------------------------------------------------------- 1 | ;; Contains apply-related events that need to be there for not-logged-in users. 2 | 3 | (ns wh.logged-in.apply.common-events 4 | (:require [re-frame.core :refer [reg-event-fx]] 5 | [wh.db :as db])) 6 | 7 | (reg-event-fx 8 | :apply/try-apply 9 | db/default-interceptors 10 | (fn [{db :db} [job event-type]] 11 | (let [apply-source (or (some-> event-type name) 12 | (get-in db [::db/query-params "apply_source"]))] 13 | {:load-and-dispatch [:logged-in [:apply/start-apply-for-job job apply-source]]}))) 14 | -------------------------------------------------------------------------------- /client/styles/not_found.sass: -------------------------------------------------------------------------------- 1 | @import colours 2 | @import mixins 3 | 4 | .container 5 | max-width: 800px 6 | margin: 0 auto 7 | padding: 20vh 0 0 0 8 | display: flex 9 | color: $primary-red 10 | flex-direction: column 11 | align-items: center 12 | 13 | .numbers 14 | font-size: 82px 15 | line-height: 82px 16 | font-weight: 600 17 | +tablet 18 | font-size: 168px 19 | line-height: 168px 20 | 21 | .description 22 | font-size: 22px 23 | line-height: 28px 24 | font-weight: 600 25 | text-align: center 26 | +tablet 27 | font-size: 36px 28 | line-height: 42px 29 | -------------------------------------------------------------------------------- /client/src/wh/company/common.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.company.common 2 | (:require 3 | [ajax.json :as ajax-json] 4 | [camel-snake-kebab.core :as c] 5 | [clojure.string :as str] 6 | [wh.common.data :as data] 7 | [wh.common.fx.google-maps :as google-maps])) 8 | 9 | (defn get-company-suggestions 10 | [n success] 11 | {:method :get 12 | :uri "https://autocomplete.clearbit.com/v1/companies/suggest" 13 | :params {:query n} 14 | :response-format (ajax-json/json-response-format {:keywords? true}) 15 | :timeout 10000 16 | :on-success [success]}) 17 | -------------------------------------------------------------------------------- /client/src/wh/landing_page/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.landing-page.core 2 | (:require 3 | [cljs.loader :as loader] 4 | [re-frame.core :refer [dispatch dispatch-sync reg-event-db]] 5 | [wh.db :as db] 6 | [wh.landing-new.events] ;; include this so events are registered 7 | [wh.landing-new.views :as landing])) 8 | 9 | (def page-mapping 10 | {:feed landing/page}) 11 | 12 | (reg-event-db 13 | ::initialize-page-mapping 14 | (fn [db _] 15 | (update db ::db/page-mapping merge page-mapping))) 16 | 17 | (dispatch-sync [::initialize-page-mapping]) 18 | 19 | (loader/set-loaded! :landing-page) 20 | -------------------------------------------------------------------------------- /client/src/wh/login/subs.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]] 4 | [wh.common.subs] 5 | [wh.login.db :as login])) 6 | 7 | (reg-sub ::email (fn [db] (login/email db))) 8 | (reg-sub ::password (fn [db] (login/password db))) 9 | (reg-sub ::submitting? (fn [db] (login/submitting? db))) 10 | (reg-sub ::error (fn [db] (login/error db))) 11 | (reg-sub ::email-sent? (fn [db] (login/email-sent? db))) 12 | (reg-sub ::error-message :<- [::error] (fn [status _] (login/status->error status))) 13 | (reg-sub ::show-password? :<- [:wh/env] (comp not boolean #{:prod} first vector)) -------------------------------------------------------------------------------- /common/src/wh/components/loader.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.loader 2 | (:require [wh.util :as util])) 3 | 4 | (defn loader 5 | ([] 6 | (loader nil)) 7 | ([class] 8 | [:svg 9 | (util/smc "loader" "loader-1" class) 10 | [:use {#?(:clj :xlink:href) #?(:cljs :xlink-href) "#loader-1"}]])) 11 | 12 | (defn loader-cover 13 | "Show a centered loader on top of child if pred is true" 14 | [pred child] 15 | [:div.load-wrap 16 | child 17 | (when pred 18 | [:div.loader-container 19 | (loader)])]) 20 | 21 | (defn loader-full-page [] 22 | [:div.loader-wrapper 23 | [loader]]) 24 | 25 | -------------------------------------------------------------------------------- /common/src/wh/styles/create_job.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.create-job) 2 | (def settings-card "create_job__settings-card--2i9xD") 3 | (def settings-card__title "create_job__settings-card__title--Q6S0c") 4 | (def checkbox "create_job__checkbox--3vGp6") 5 | (def remuneration__checkbox "create_job__remuneration__checkbox--sOnbW") 6 | (def remote-info "create_job__remote-info--3pzuC") 7 | (def remote-info__section "create_job__remote-info__section--ldoSA") 8 | (def timezone "create_job__timezone--S0QdD") 9 | (def timezone__item "create_job__timezone__item--26Wx_") 10 | (def timezone__close "create_job__timezone__close--Mx_ub") -------------------------------------------------------------------------------- /common/src/wh/styles/skeletons.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.skeletons) 2 | (def image-with-info "skeletons__image-with-info--3CGdG") 3 | (def image-with-info__logo "skeletons__image-with-info__logo--OidbC") 4 | (def image-with-info__info1 "skeletons__image-with-info__info1--1sHF5") 5 | (def image-with-info__info2 "skeletons__image-with-info__info2--3edJp") 6 | (def paragraph "skeletons__paragraph--3qvM6") 7 | (def paragraph__line "skeletons__paragraph__line--29cMN") 8 | (def paragraph__line--short "skeletons__paragraph__line--short--1M50l") 9 | (def button "skeletons__button--_-HJG") 10 | (def title "skeletons__title--VqswM") -------------------------------------------------------------------------------- /client/legacy-styles/_modifiers.sass: -------------------------------------------------------------------------------- 1 | .is-full-width 2 | width: 100% 3 | 4 | .is-full-width-mobile 5 | +mobile 6 | width: 100% 7 | 8 | .is-invisible 9 | visibility: hidden 10 | 11 | .is-danger, .is-error 12 | color: $dark-red 13 | 14 | .is-collapsed 15 | height: 0px !important 16 | 17 | .is-loading-spinner 18 | @include spinner 19 | 20 | .is-not-selectable 21 | -webkit-touch-callout: none 22 | -webkit-user-select: none 23 | -khtml-user-select: none 24 | -moz-user-select: none 25 | -ms-user-select: none 26 | user-select: none 27 | 28 | .is-underlined 29 | text-decoration: underline 30 | -------------------------------------------------------------------------------- /common/src/wh/styles/signin_buttons.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.signin-buttons) 2 | (def button "signin_buttons__button--1uldc") 3 | (def icon--email "signin_buttons__icon--email--3V0Pj") 4 | (def button--github "signin_buttons__button--github--1k7s9") 5 | (def button--twitter "signin_buttons__button--twitter--37eoC") 6 | (def icon--twitter "signin_buttons__icon--twitter--_mlZ7") 7 | (def button--stackoverflow "signin_buttons__button--stackoverflow--3SX4l") 8 | (def icon--stackoverflow "signin_buttons__icon--stackoverflow--4WQo1") 9 | (def button--auth "signin_buttons__button--auth--1R2vW") 10 | (def icon "signin_buttons__icon--32o81") -------------------------------------------------------------------------------- /client/src/wh/components/rich_text_field/loadable.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.components.rich-text-field.loadable 2 | (:require [shadow.lazy :as lazy] 3 | [wh.re-frame :refer [atom]])) 4 | 5 | (def rich-text-field-lazy (lazy/loadable wh.components.rich-text-field.core/rich-text-field)) 6 | (def default (fn [] [:div "Loading editor..."])) 7 | 8 | (defn rich-text-field [_] 9 | (let [component (atom default) 10 | _promise (-> (lazy/load rich-text-field-lazy) 11 | (.then (fn [root-el] 12 | (reset! component root-el))))] 13 | (fn [props] 14 | [@component props]))) -------------------------------------------------------------------------------- /common/src/wh/components/navbar/events.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.components.navbar.events 2 | (:require [re-frame.core :refer [reg-event-db reg-event-fx]] 3 | [wh.components.navbar.db :as db])) 4 | 5 | (reg-event-db 6 | ::set-search-value 7 | (fn [db [_ value]] 8 | (assoc db ::db/search-value value))) 9 | 10 | (reg-event-fx 11 | :wh.search/search-with-value 12 | (fn [{db :db} [_ value]] 13 | (when (seq value) 14 | {:db (-> db 15 | (assoc ::db/search-value value) 16 | (assoc-in [:wh.search/data] {})) 17 | :navigate [:search :params {:query value}]}))) 18 | -------------------------------------------------------------------------------- /client/src/wh/company/views.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.company.views 2 | (:require [goog.i18n.NumberFormat :as nf])) 3 | 4 | (def dollar-formatter (goog.i18n.NumberFormat. nf/Format.CURRENCY)) 5 | (defn int->dollars 6 | ([i] 7 | (int->dollars i {})) 8 | ([i {:keys [cents?] 9 | :or {cents? false}}] 10 | (if cents? 11 | (let [[dollars cents] (rest (re-find #"([\-0-9]+)([0-9]{2})" (str i)))] 12 | (str (int->dollars dollars) "." cents)) 13 | (let [d (.format dollar-formatter i)] 14 | (subs d 0 (- (count d) 3)))))) ;; remove decimals 15 | 16 | (defn double->dollars 17 | [i] 18 | (.format dollar-formatter i)) 19 | -------------------------------------------------------------------------------- /client/src/wh/login/shared.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.shared) 2 | 3 | (defn initialize-associated-jobs-and-blogs 4 | [{:keys [likes applied] :as user}] 5 | (-> user 6 | (assoc :liked-jobs (->> likes 7 | (filter #(= (:__typename %) "Job")) 8 | (map :id) 9 | set) 10 | :liked-blogs (->> likes 11 | (filter #(= (:__typename %) "Blog")) 12 | (map :id) 13 | set) 14 | :applied-jobs (set (map :jobId applied))) 15 | (dissoc :likes :applied))) -------------------------------------------------------------------------------- /client/src/wh/pricing/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.pricing.core 2 | (:require 3 | [cljs.loader :as loader] 4 | [re-frame.core :refer [dispatch dispatch-sync reg-event-db]] 5 | [wh.db :as db] 6 | [wh.landing.events] 7 | [wh.landing.views :as landing] 8 | [wh.pricing.views :as pricing])) ;; requires loading 9 | 10 | (def page-mapping 11 | {:pricing pricing/page 12 | :employers landing/page}) 13 | 14 | (reg-event-db 15 | ::initialize-page-mapping 16 | (fn [db _] 17 | (update db ::db/page-mapping merge page-mapping))) 18 | 19 | (dispatch-sync [::initialize-page-mapping]) 20 | 21 | (loader/set-loaded! :pricing) 22 | -------------------------------------------------------------------------------- /client/resources/publicjs.edn: -------------------------------------------------------------------------------- 1 | ;; Edit this file carefully; order is important 2 | ;; Init should always be the last thing in the list 3 | ["wh-client/client/src-js/util.js" 4 | "wh-client/client/src-js/public.js" 5 | "wh-client/client/src-js/analytics.js" 6 | "wh-client/client/src-js/auth.js" 7 | "wh-client/client/src-js/video.js" 8 | "wh-client/client/src-js/photo.js" 9 | "wh-client/client/src-js/promo_banner.js" 10 | "wh-client/client/src-js/code_highlight.js" 11 | "wh-client/client/src-js/button_analytics.js" 12 | "wh-client/client/src-js/tags.js" 13 | "wh-client/client/src-js/newsletter.js" 14 | "wh-client/client/src-js/init.js"] 15 | -------------------------------------------------------------------------------- /client/src/wh/admin/queries.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.admin.queries 2 | (#?(:clj :require :cljs :require-macros) 3 | [wh.graphql-macros :refer [defquery]])) 4 | 5 | (defquery set-approval-status-mutation 6 | {:venia/operation {:operation/type :mutation 7 | :operation/name "update_user_approval_status"} 8 | :venia/variables [{:variable/name "id" 9 | :variable/type :ID!} 10 | {:variable/name "status" 11 | :variable/type :String!}] 12 | :venia/queries [[:update_user_approval_status {:id :$id :status :$status}]]}) -------------------------------------------------------------------------------- /client/legacy-styles/_policy.sass: -------------------------------------------------------------------------------- 1 | .privacy 2 | @include margins 3 | position: relative 4 | background-color: white 5 | +desktop 6 | margin-top: 19px 7 | margin-bottom: 19px 8 | padding: 40px 9 | +mobile 10 | padding: 20px 11 | 12 | .heading 13 | font-weight: 600 14 | ol 15 | ol 16 | margin: 0 0 20px 10px 17 | ul 18 | list-style: disc 19 | li 20 | margin-left: 20px 21 | a 22 | font-weight: $font-semi-bold 23 | color: $red 24 | text-decoration: underline 25 | p 26 | line-height: 16px 27 | margin: 10px 0 28 | table > thead > tr > th:nth-child(1) 29 | width: 33% 30 | -------------------------------------------------------------------------------- /common-pages/src/wh/pages/issue/db.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.pages.issue.db 2 | (:require 3 | #?(:clj [clojure.spec.alpha :as s] 4 | :cljs [cljs.spec.alpha :as s]))) 5 | 6 | (def num-other-issues-to-show 2) 7 | (def num-related-jobs-to-show 2) 8 | 9 | (defn id 10 | [db] 11 | (get-in db [:wh.db/page-params :id])) 12 | 13 | (s/def ::show-cta-sticky? boolean?) 14 | 15 | (defn default-db 16 | [db] 17 | (merge db 18 | {::show-cta-sticky? false})) 19 | 20 | (defn repo->full-name [repo] 21 | (str (:owner repo) "/" (:name repo))) 22 | 23 | (defn page-title [{:keys [repo title]}] 24 | (str (repo->full-name repo) " Issue - " title)) 25 | -------------------------------------------------------------------------------- /client/styles/banner.sass: -------------------------------------------------------------------------------- 1 | @import vars 2 | @import colours 3 | @import mixins 4 | 5 | $banner-height: 48px 6 | $banner-height-mobile: 30px 7 | 8 | .banner 9 | display: none 10 | height: $banner-height 11 | background-color: $highlight-red 12 | text-align: center 13 | &:global(.is-open) 14 | display: flex 15 | align-items: center 16 | justify-content: center 17 | +mobile 18 | height: $banner-height-mobile 19 | 20 | .link 21 | color: $primary-red 22 | line-height: 16px 23 | font-weight: 600 24 | font-size: 16px 25 | +mobile 26 | font-size: 13px 27 | line-height: 13px 28 | &:hover 29 | color: $primary-red-hover -------------------------------------------------------------------------------- /common/src/wh/common/emoji.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.common.emoji 2 | (:require [clojure.string :as str])) 3 | 4 | (defn int->char [i] 5 | #?(:clj (str (doto (StringBuilder.) (.appendCodePoint ^int i))) 6 | :cljs (js/String.fromCodePoint i))) 7 | 8 | (defn char->int [c] 9 | #?(:clj (int c) 10 | :cljs (.charCodeAt c 0))) 11 | 12 | (defn country-code->emoji [country-code] 13 | (if (and country-code (<= 65 (char->int (first country-code)) 122)) 14 | (->> country-code 15 | str/upper-case 16 | (map (comp int->char (partial + 127397) char->int)) 17 | (str/join "")) 18 | country-code)) 19 | 20 | (def fire "\uD83D\uDD25") 21 | -------------------------------------------------------------------------------- /client/legacy-styles/_pagination.sass: -------------------------------------------------------------------------------- 1 | .pagination 2 | margin-top: 25px 3 | 4 | .pagination-link 5 | font-size: 11px 6 | margin-left: 6px 7 | margin-right: 6px 8 | width: 30px 9 | height: 30px 10 | border-radius: 2px 11 | border: solid 1px $white-two 12 | background-color: $white 13 | color: #c5c6c5 14 | font-weight: $font-semi-bold 15 | &:hover 16 | background-color: $disabled-gray 17 | border: solid 1px $white-two 18 | color: #c5c6c5 19 | transition: background-color $transition-time, color $transition-time 20 | &.is-current 21 | border: solid 1px $steel-gray 22 | background-color: $steel-gray 23 | color: $white -------------------------------------------------------------------------------- /common-pages/src/wh/blogs/liked/subs.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.blogs.liked.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]] 4 | [wh.blogs.learn.db :as learn] 5 | [wh.blogs.liked.events :as events] 6 | [wh.graphql-cache :as graphql])) 7 | 8 | (reg-sub 9 | ::liked-blogs 10 | (fn [db _] 11 | (let [params (learn/params db) 12 | data-path events/blogs-path 13 | data (graphql/result db events/query-name params) 14 | state (graphql/state db events/query-name params)] 15 | {:blogs (get-in data data-path) 16 | :loading? (or (= state :executing) 17 | (= state :initial))}))) 18 | -------------------------------------------------------------------------------- /common/src/wh/components/promote_button.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.promote-button 2 | (:require [wh.routes :as routes] 3 | [wh.styles.promotions :as styles] 4 | [wh.util :as util])) 5 | 6 | (defn promote-button [{:keys [id type class]}] 7 | [:a 8 | {:href (routes/path :create-promotion :params {:type type :id id}) 9 | :data-test (str "promote-" (name type)) 10 | :class (util/mc "button--promote" styles/button--promote class)} 11 | (str "Promote " 12 | (case type 13 | :article "Blog" 14 | :company "Company" 15 | :issue "Issue" 16 | :job "Job" 17 | ""))]) 18 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/elements/icon.sass: -------------------------------------------------------------------------------- 1 | $icon-dimensions: 1.5rem !default 2 | $icon-dimensions-small: 1rem !default 3 | $icon-dimensions-medium: 2rem !default 4 | $icon-dimensions-large: 3rem !default 5 | 6 | .icon 7 | align-items: center 8 | display: inline-flex 9 | justify-content: center 10 | height: $icon-dimensions 11 | width: $icon-dimensions 12 | // Sizes 13 | &.is-small 14 | height: $icon-dimensions-small 15 | width: $icon-dimensions-small 16 | &.is-medium 17 | height: $icon-dimensions-medium 18 | width: $icon-dimensions-medium 19 | &.is-large 20 | height: $icon-dimensions-large 21 | width: $icon-dimensions-large 22 | -------------------------------------------------------------------------------- /client/src/wh/admin/create_offer/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.admin.create-offer.db 2 | (:require [cljs.spec.alpha :as s] 3 | [wh.common.specs.offer :as offer] 4 | [wh.common.specs.primitives :as p] 5 | [wh.components.forms.db :as forms])) 6 | 7 | (def fields 8 | {::offer {:order 1 :initial nil, :validate keyword?} 9 | ::offer-fixed {:order 2 :initial nil, :validate :wh.offer/recurring-fee} 10 | ::offer-percentage {:order 3 :initial nil, :validate :wh.offer/placement-percentage}}) 11 | 12 | (defn initial-db [db] 13 | (merge (forms/initial-value fields) 14 | {::creating? false 15 | ::success? false})) 16 | -------------------------------------------------------------------------------- /client/src/wh/components/banner.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.banner 2 | (:require [wh.components.common :refer [link]] 3 | [wh.styles.banner :as styles] 4 | [wh.util :as util])) 5 | 6 | (def pages-with-banner #{:pricing :how-it-works :issues :homepage :homepage-not-logged-in}) 7 | 8 | (defn banner [{:keys [page logged-in?]}] 9 | (when (and (contains? pages-with-banner page) 10 | (not logged-in?)) 11 | ;; is-open class is used in our js files 12 | [:div 13 | {:class (util/mc styles/banner "is-open") 14 | :id "promo-banner"} 15 | [link "Hiring? Sign up and post your first job for FREE!" :register-company :class styles/link]])) 16 | -------------------------------------------------------------------------------- /common/src/wh/components/activities/company_published.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.activities.company-published 2 | (:require [wh.components.activities.components :as components] 3 | [wh.components.activities.company :as company])) 4 | 5 | (defn card [company actor type opts] 6 | [components/card type 7 | [components/header 8 | [components/company-info actor :company type] 9 | [components/entity-description :company type]] 10 | [components/description (if (= type :publish) 11 | "Recently published their public profile" 12 | "Recently had a lot of views")] 13 | [company/base-card company actor type opts]]) 14 | -------------------------------------------------------------------------------- /client/src-js/local_storage.js: -------------------------------------------------------------------------------- 1 | function setItem(key, value, ttlSeconds) { 2 | const now = new Date() 3 | const item = { 4 | value: value, 5 | expiry: now.getTime() + ttlSeconds * 1000, 6 | } 7 | localStorage.setItem(key, JSON.stringify(item)) 8 | } 9 | 10 | function getItem(key) { 11 | const itemStr = localStorage.getItem(key) 12 | if (!itemStr) { 13 | return null 14 | } 15 | const item = JSON.parse(itemStr) 16 | const now = new Date() 17 | if (now.getTime() > item.expiry) { 18 | localStorage.removeItem(key) 19 | return null 20 | } 21 | return item.value 22 | } 23 | 24 | export default { setItem, getItem } 25 | -------------------------------------------------------------------------------- /client/resources/public/images/share-twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /common/src/wh/components/info_icon.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.info-icon 2 | (:require #?(:cljs ["react-tooltip" :as ReactTooltip]) 3 | #?(:cljs [reagent.core :as reagent]) 4 | [wh.components.icons :refer [icon]])) 5 | 6 | #?(:cljs 7 | (def react-tooltip (reagent/adapt-react-class ReactTooltip))) 8 | 9 | (defn info-icon 10 | [id txt] 11 | #?(:cljs 12 | (let [tt-id (str "info-icon-"(name id))] 13 | [:div.info-icon.has-tooltip 14 | [:a {:data-tip true 15 | :data-for tt-id} 16 | [icon "info"]] 17 | [react-tooltip {:id tt-id :place "top" :type "light" :effect "solid" 18 | :class-name "tooltip"} 19 | txt]]))) 20 | -------------------------------------------------------------------------------- /common-pages/src/wh/blogs/blog/db.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.blogs.blog.db 2 | (:require [#?(:cljs cljs.spec.alpha :clj clojure.spec.alpha) :as s])) 3 | 4 | (defn id 5 | [db] 6 | (get-in db [:wh.db/page-params :id])) 7 | 8 | (s/def ::share-links-shown? boolean?) 9 | (s/def ::author-info-visible? boolean?) 10 | (s/def ::upvotes (s/map-of string? nat-int?)) 11 | 12 | (s/def ::sub-db (s/keys :req [::share-links-shown? ::author-info-visible? ::upvotes])) 13 | 14 | (def default-db 15 | {::share-links-shown? true 16 | ::author-info-visible? false 17 | ::upvotes {}}) 18 | 19 | (def page-size 4) 20 | 21 | (defn params [db] 22 | {:id (id db) 23 | :page_size page-size 24 | :vertical (:wh.db/vertical db)}) 25 | -------------------------------------------------------------------------------- /common-pages/src/wh/company/articles/events.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.company.articles.events 2 | (:require 3 | #?(:cljs [wh.pages.core :refer [on-page-load] :as pages]) 4 | [wh.company.articles.db :as articles] 5 | [wh.components.pagination :as pagination])) 6 | 7 | (defn company-query [db] 8 | [:company-card {:slug (articles/company-slug db)}]) 9 | 10 | (defn articles-query [db] 11 | [:company-articles-page (articles/params db)]) 12 | 13 | #?(:cljs 14 | (defmethod on-page-load :company-articles [db] 15 | (list (into [:graphql/query] (company-query db)) 16 | (into [:graphql/query] (conj (articles-query db) 17 | {:on-complete [:wh.events/scroll-to-top]}))))) 18 | -------------------------------------------------------------------------------- /common-pages/src/wh/landing_new/unread_messages/styles.sass: -------------------------------------------------------------------------------- 1 | @import colours 2 | @import 'mixins' 3 | 4 | .card 5 | background: white 6 | border-radius: 8px 7 | padding: 20px 8 | font-size: 16px 9 | line-height: 24px 10 | font-weight: 600 11 | display: flex 12 | flex-wrap: wrap 13 | align-items: center 14 | justify-content: center 15 | gap: 16px 16 | 17 | +tablet 18 | justify-content: space-between 19 | gap: 0 20 | 21 | .red-dot 22 | width: 10px 23 | min-width: 10px 24 | height: 10px 25 | min-height: 10px 26 | background: $primary-red 27 | border-radius: 50% 28 | 29 | .wrapper 30 | display: flex 31 | gap: 16px 32 | align-items: center 33 | 34 | .button 35 | margin-left: auto 36 | -------------------------------------------------------------------------------- /client/styles/iconsset.sass: -------------------------------------------------------------------------------- 1 | @import 'colours' 2 | 3 | .page 4 | background-color: $grey500 5 | width: 100% 6 | min-width: 1000px 7 | max-height: 100% 8 | overflow: scroll 9 | border-radius: 4px 10 | display: grid 11 | grid-template-columns: repeat(auto-fill, 100px) 12 | justify-content: center 13 | grid-gap: 16px 14 | padding: 32px 15 | 16 | .icon 17 | width: 36px 18 | height: 36px 19 | 20 | &__wrapper 21 | background: $background-white 22 | width: 100px 23 | height: 100px 24 | display: flex 25 | flex-direction: column 26 | align-items: center 27 | justify-content: space-between 28 | padding: 8px 29 | border-radius: 4px 30 | line-height: 12px 31 | text-align: center 32 | -------------------------------------------------------------------------------- /client/legacy-styles/_loaders.sass: -------------------------------------------------------------------------------- 1 | .loader-wrapper 2 | position: relative 3 | padding: 0 4 | margin: 0 5 | width: 100% 6 | z-index: $loader-z-index 7 | background: white 8 | display: flex 9 | flex-direction: column 10 | justify-content: center 11 | align-items: center 12 | +desktop 13 | height: calc(100vh - #{$navbar-height} - 10px) 14 | +mobile 15 | height: calc(100vh - #{$navbar-mobile-height} - 10px) 16 | &.loader-wrapper--fullscreen 17 | position: fixed 18 | height: 100vh 19 | top: 0 20 | left: 0 21 | 22 | .loader-1 23 | margin: auto 24 | background-position: left 25 | background-repeat: no-repeat 26 | height: 100px 27 | width: 100px 28 | animation: spinAround 2s linear infinite 29 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/elements/container.sass: -------------------------------------------------------------------------------- 1 | .container 2 | margin: 0 auto 3 | position: relative 4 | +desktop 5 | max-width: $desktop - (2 * $gap) 6 | width: $desktop - (2 * $gap) 7 | &.is-fluid 8 | margin-left: $gap 9 | margin-right: $gap 10 | max-width: none 11 | width: auto 12 | +until-widescreen 13 | &.is-widescreen 14 | max-width: $widescreen - (2 * $gap) 15 | width: auto 16 | +until-fullhd 17 | &.is-fullhd 18 | max-width: $fullhd - (2 * $gap) 19 | width: auto 20 | +widescreen 21 | max-width: $widescreen - (2 * $gap) 22 | width: $widescreen - (2 * $gap) 23 | +fullhd 24 | max-width: $fullhd - (2 * $gap) 25 | width: $fullhd - (2 * $gap) 26 | -------------------------------------------------------------------------------- /common-pages/src/wh/login/invalid_magic_link/views.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.login.invalid-magic-link.views 2 | (:require [wh.components.auth :as auth] 3 | [wh.routes :as routes] 4 | [wh.styles.register :as styles])) 5 | 6 | (defn page [] 7 | [auth/page 8 | [auth/card {:type :invalid-link} 9 | [auth/title "Invalid link"] 10 | [:div 11 | [auth/paragraph 12 | "Your login link is invalid"] 13 | [auth/paragraph 14 | [auth/link {:text "Try login again" 15 | :href (routes/path :login :params {:step :email})}]]] 16 | [:img {:src "/images/hiw/candidate/benefits/benefit2.svg" 17 | :class styles/invalid-link-image 18 | :width 220 19 | :height 165}]]]) 20 | -------------------------------------------------------------------------------- /common-pages/src/wh/pages/issue/edit/db.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.pages.issue.edit.db 2 | (:require 3 | #?(:clj [clojure.spec.alpha :as s] 4 | :cljs [cljs.spec.alpha :as s]))) 5 | 6 | (s/def ::displayed-dialog #{nil :edit :confirm}) 7 | (s/def ::updating? boolean?) 8 | (s/def ::pending-level (s/nilable keyword?)) ;; TODO use real spec once it's in CLJC 9 | (s/def ::pending-status #{nil :open :closed}) 10 | (s/def ::pending-compensation (s/nilable nat-int?)) 11 | 12 | (s/def ::on-success (s/nilable seq?)) 13 | 14 | (def default-db 15 | {::displayed-dialog nil 16 | ::pending-level nil 17 | ::pending-status nil 18 | ::pending-compensation nil 19 | ::on-success nil 20 | ::updating? false}) 21 | -------------------------------------------------------------------------------- /common/src/wh/common/issue.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.common.issue 2 | (:require 3 | #?(:clj [clj-time.coerce :as tc] 4 | :cljs [cljs-time.coerce :as tc]) 5 | #?(:clj [clj-time.format :as tf] 6 | :cljs [cljs-time.format :as tf]) 7 | [clojure.string :as str] 8 | [wh.common.cases :as cases] 9 | [wh.util :as util])) 10 | 11 | (defn gql-issue->issue 12 | [issue] 13 | (-> issue 14 | (cases/->kebab-case) 15 | (util/update* :level keyword) 16 | (util/update* :status keyword))) 17 | 18 | (defn format-compensation [{:keys [compensation] :as _issue}] 19 | (if (and compensation (:currency compensation) (pos? (:amount compensation))) 20 | (str (name (:currency compensation)) " " (:amount compensation)))) 21 | -------------------------------------------------------------------------------- /client/src/wh/components/click_outside.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.components.click-outside 2 | (:require [reagent.core :as r])) 3 | 4 | (defn click-outside [{:keys [element on-click-outside] :as opts} & children] 5 | (r/with-let [ref (r/atom nil) 6 | handler (fn [e] (when-not (.contains @ref (.-target e)) 7 | (and on-click-outside (on-click-outside)))) 8 | _ (.addEventListener js/document "click" handler) 9 | element (or element :div)] 10 | [element (-> opts 11 | (dissoc :element :on-click-outside) 12 | (assoc :ref #(reset! ref %))) 13 | children] 14 | 15 | (finally 16 | (.removeEventListener js/document "click" handler)))) 17 | -------------------------------------------------------------------------------- /common-pages/src/wh/jobsboard/events.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.jobsboard.events 2 | (:require [re-frame.core :refer [dispatch path reg-event-db reg-event-fx]] 3 | [wh.db :as db])) 4 | 5 | (reg-event-fx 6 | ::on-location-select 7 | db/default-interceptors 8 | (fn [_ [{:keys [attr value]}]] 9 | {:dispatch (cond 10 | (= attr "location.region") [:wh.search/toggle-region value] 11 | (= attr "location.city") [:wh.search/toggle-city value] 12 | (= attr "location.country-code") [:wh.search/toggle-country value])})) 13 | 14 | (reg-event-fx 15 | ::on-tag-select 16 | db/default-interceptors 17 | (fn [_ [{:keys [value]}]] 18 | {:dispatch [:wh.search/search-by-tag value true]})) 19 | -------------------------------------------------------------------------------- /common/test/wh/util_test.clj: -------------------------------------------------------------------------------- 1 | (ns wh.util-test 2 | (:require 3 | [clojure.test :refer :all] 4 | [clojure.test.check] 5 | [orchestra.spec.test :as st] 6 | [wh.test-common :as tc] 7 | [wh.util :as util])) 8 | 9 | (deftest remove-nils-test 10 | (st/instrument [`util/remove-nils]) 11 | (is (true? (tc/check `util/remove-nils)))) 12 | 13 | (deftest ->vec-test 14 | (st/instrument [`util/->vec]) 15 | (is (true? (tc/check `util/->vec)))) 16 | 17 | (deftest fix-order-unit-test 18 | (let [order (range 5)] 19 | (is (= (map :id (util/fix-order order :id (map #(hash-map :id %) (reverse order)))) order)))) 20 | 21 | (deftest fix-order-test 22 | (st/instrument [`util/fix-order]) 23 | (is (true? (tc/check `util/fix-order)))) 24 | -------------------------------------------------------------------------------- /common/src/wh/styles/side_card_mobile.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.side-card-mobile) 2 | (def card "side_card_mobile__card--ovTDb") 3 | (def card__content "side_card_mobile__card__content--35OeO") 4 | (def connected-entity "side_card_mobile__connected-entity--2DQg_") 5 | (def connected-entity__title "side_card_mobile__connected-entity__title--1KVjL") 6 | (def connected-entity__avatar "side_card_mobile__connected-entity__avatar--fxMO_") 7 | (def title "side_card_mobile__title--31wuZ") 8 | (def title--extended "side_card_mobile__title--extended--KvpUM") 9 | (def button "side_card_mobile__button--25HmC") 10 | (def horizontal-scrolling "side_card_mobile__horizontal-scrolling--14IS8") 11 | (def horizontal-scrolling-wrapper "side_card_mobile__horizontal-scrolling-wrapper--355Z0") -------------------------------------------------------------------------------- /workspaces.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 14 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /client/legacy-styles/_tracking.sass: -------------------------------------------------------------------------------- 1 | .tracking-popups 2 | display: none 3 | &.is-open 4 | display: block 5 | .tracking-popup 6 | +popup 7 | padding: 15px 15px 15px 25px 8 | bottom: 0 9 | border: 10px solid $light-blue-grey 10 | .button 11 | margin-top: 15px 12 | +desktop 13 | left: calc(100vw / 2 - 305px) 14 | width: 610px 15 | +mobile 16 | width: 100% 17 | line-height: 22px 18 | border: 0 19 | padding: 10px 17px 20 | 21 | .tracking-popup--collapsed 22 | display: none 23 | &.is-open 24 | display: flex 25 | justify-content: space-between 26 | align-items: center 27 | .button 28 | margin: 0 29 | width: 120px 30 | 31 | .tracking-popup--expanded 32 | display: none 33 | &.is-open 34 | display: block 35 | -------------------------------------------------------------------------------- /client/src/wh/register/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.register.core 2 | (:require 3 | [cljs.loader :as loader] 4 | [re-frame.core :refer [dispatch dispatch-sync reg-event-db]] 5 | [wh.db :as db] 6 | [wh.register.views :as register] 7 | [wh.register.events :as register-events])) 8 | 9 | (def page-mapping 10 | {:register {:page register/card-signup 11 | :can-access? (complement db/logged-in?)}}) 12 | 13 | (reg-event-db ::initialize-page-mapping 14 | (fn [db _] (update db ::db/page-mapping merge page-mapping))) 15 | 16 | (dispatch-sync [::initialize-page-mapping]) 17 | (dispatch-sync [::register-events/initialize-db]) 18 | (dispatch [:wh.pages.core/unset-loader]) 19 | 20 | (db/redefine-app-db-spec!) 21 | 22 | (loader/set-loaded! :register) 23 | -------------------------------------------------------------------------------- /client/resources/public/images/hiw/balls/grey.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /common/src/wh/common/specs/offer.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.common.specs.offer 2 | (:require 3 | [#?(:clj clojure.spec.alpha 4 | :cljs cljs.spec.alpha) :as s] 5 | [#?(:clj clojure.spec.gen.alpha 6 | :cljs cljs.spec.gen.alpha) :as gen] 7 | [wh.common.specs.primitives :as p])) 8 | 9 | (s/def :wh.offer/recurring-fee nat-int?) 10 | (s/def :wh.offer/placement-percentage ::p/percentage) 11 | (s/def :wh.offer/accepted-at inst?) 12 | (s/def :wh/offer (s/keys :req-un [:wh.offer/recurring-fee 13 | :wh.offer/placement-percentage] 14 | :opt-un [:wh.offer/accepted-at])) 15 | 16 | (s/def :wh/pending-offer (s/keys :req-un [:wh.offer/recurring-fee 17 | :wh.offer/placement-percentage])) 18 | -------------------------------------------------------------------------------- /client/resources/public/images/hiw/balls/blue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /client/resources/public/images/hiw/balls/orange.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /client/styles/animations.sass: -------------------------------------------------------------------------------- 1 | @keyframes shake 2 | 4%, 18% 3 | transform: translate3d(-1px, 0, 0) 4 | 4%, 16% 5 | transform: translate3d(2px, 0, 0) 6 | 6%, 10%, 14% 7 | transform: translate3d(-4px, 0, 0) 8 | 8%, 12% 9 | transform: translate3d(4px, 0, 0) 10 | 20% 11 | transform: translate3d(0, 0, 0) 12 | 13 | @keyframes bounceInLeft 14 | from, 15 | 60%, 16 | 75%, 17 | 90%, 18 | to 19 | animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1) 20 | 0% 21 | opacity: 0 22 | transform: translate3d(-3000px, 0, 0) 23 | 60% 24 | opacity: 1 25 | transform: translate3d(25px, 0, 0) 26 | 75% 27 | transform: translate3d(-10px, 0, 0) 28 | 90% 29 | transform: translate3d(5px, 0, 0) 30 | to 31 | transform: translate3d(0, 0, 0) -------------------------------------------------------------------------------- /client/legacy-styles/_responsive.sass: -------------------------------------------------------------------------------- 1 | // Taken from Bootstrap 2 | 3 | .embed-responsive 4 | position: relative 5 | display: block 6 | width: 100% 7 | padding: 0 8 | overflow: hidden 9 | 10 | &::before 11 | display: block 12 | content: "" 13 | 14 | .embed-responsive-item 15 | position: absolute 16 | top: 0 17 | bottom: 0 18 | left: 0 19 | width: 100% 20 | height: 100% 21 | border: 0 22 | 23 | .embed-responsive-21by9 24 | &::before 25 | padding-top: percentage(9 / 21) 26 | 27 | .embed-responsive-16by9 28 | &::before 29 | padding-top: percentage(9 / 16) 30 | 31 | .embed-responsive-4by3 32 | &::before 33 | padding-top: percentage(3 / 4) 34 | 35 | .embed-responsive-1by1 36 | &::before 37 | padding-top: percentage(1 / 1) 38 | -------------------------------------------------------------------------------- /common/src/wh/components/newsletter/styles.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.newsletter.styles) 2 | (def card "styles__card--24r-4") 3 | (def card__wrapper "styles__card__wrapper--12zMT") 4 | (def card__wrapper--blog-content "styles__card__wrapper--blog-content--11His") 5 | (def card__wrapper--blog-list "styles__card__wrapper--blog-list--3vUc6") 6 | (def card__wrapper--job-list "styles__card__wrapper--job-list--1xCWw") 7 | (def title "styles__title--3BznZ") 8 | (def text "styles__text--3nlQ5") 9 | (def input "styles__input--zwvqK") 10 | (def input__wrapper "styles__input__wrapper--DnYrm") 11 | (def button "styles__button--i7JjI") 12 | (def success "styles__success--l2l5T") 13 | (def success__text "styles__success__text--1bL2-") 14 | (def bounceInLeft "styles__bounceInLeft--uf8TJ") 15 | (def shake "styles__shake--1CmfU") -------------------------------------------------------------------------------- /client/src/workspaces/login_cards.cljs: -------------------------------------------------------------------------------- 1 | (ns workspaces.login-cards 2 | (:require [nubank.workspaces.card-types.react :as ct.react] 3 | [nubank.workspaces.core :as ws] 4 | [re-frame.core :as rf] 5 | [reagent.core :as r] 6 | [wh.login.views :as views])) 7 | 8 | (rf/reg-sub 9 | :wh.login.subs/magic-email 10 | (fn [db _] 11 | (or (:magic-email db) ""))) 12 | 13 | (rf/reg-sub 14 | :wh.login.subs/magic-status 15 | (fn [db _] 16 | :not-posted)) 17 | 18 | (rf/reg-event-db 19 | :wh.login.events/set-magic-email 20 | (fn [db [_ new-color-value]] 21 | (assoc (or db {}) :magic-email new-color-value))) 22 | 23 | 24 | (ws/defcard hello-card 25 | (ct.react/react-card 26 | (r/as-element [views/page]))) 27 | 28 | (defonce init (ws/mount)) 29 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/elements/box.sass: -------------------------------------------------------------------------------- 1 | $box-color: $text !default 2 | $box-background-color: $white !default 3 | $box-radius: $radius-large !default 4 | $box-shadow: 0 2px 3px rgba($black, 0.1), 0 0 0 1px rgba($black, 0.1) !default 5 | $box-padding: 1.25rem !default 6 | 7 | $box-link-hover-shadow: 0 2px 3px rgba($black, 0.1), 0 0 0 1px $link !default 8 | $box-link-active-shadow: inset 0 1px 2px rgba($black, 0.2), 0 0 0 1px $link !default 9 | 10 | .box 11 | @extend %block 12 | background-color: $box-background-color 13 | border-radius: $box-radius 14 | box-shadow: $box-shadow 15 | color: $box-color 16 | display: block 17 | padding: $box-padding 18 | 19 | a.box 20 | &:hover, 21 | &:focus 22 | box-shadow: $box-link-hover-shadow 23 | &:active 24 | box-shadow: $box-link-active-shadow 25 | -------------------------------------------------------------------------------- /common/src/wh/components/stats/views.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.stats.views 2 | (:require [wh.components.icons :refer [icon]] 3 | #?(:clj [wh.components.stats.core :as stats-core] 4 | :cljs [wh.components.stats.loadable :as stats-loadable]))) 5 | 6 | (defn stats-item [{:keys [icon-name caption x-axis y-axis values total change]}] 7 | [:div.stats__item {:class (str "stats__" icon-name)} 8 | [:div.stats__icon 9 | [icon icon-name]] 10 | [:div.stats__caption caption] 11 | [:div.stats__value-line 12 | [:span.stats__value total] 13 | [:span.stats__increase change]] 14 | (let [props {:x-axis x-axis 15 | :y-axis y-axis 16 | :values values}] 17 | #?(:clj [stats-core/chart props] 18 | :cljs [stats-loadable/chart props]))]) 19 | -------------------------------------------------------------------------------- /client/src/wh/logged_in/contribute/styles.sass: -------------------------------------------------------------------------------- 1 | @import "colours" 2 | @import "vars" 3 | @import "button" 4 | 5 | .cross-posting 6 | line-height: 1.8 7 | margin-top: 32px 8 | color: $grey500 9 | 10 | h2, h3 11 | color: $grey500 12 | font-weight: 600 13 | 14 | h2 15 | margin-bottom: 16px 16 | 17 | h3 18 | font-size: 16px 19 | margin-bottom: 4px 20 | 21 | &__publishers 22 | display: grid 23 | gap: 16px 24 | grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)) 25 | 26 | &__publisher 27 | height: 180px 28 | background-color: $white 29 | padding: 16px 30 | font-size: 13px 31 | display: flex 32 | flex-direction: column 33 | 34 | &__a 35 | text-decoration: underline 36 | 37 | &__button 38 | @include button 39 | margin-top: auto -------------------------------------------------------------------------------- /common/src/wh/common/cases.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.common.cases 2 | (:require [camel-snake-kebab.core :as c] 3 | [camel-snake-kebab.extras :as ce])) 4 | 5 | (defn ->kebab-case [m] 6 | (ce/transform-keys c/->kebab-case-keyword m)) 7 | 8 | (defn ->snake-case [m] 9 | (ce/transform-keys c/->snake_case_keyword m)) 10 | 11 | (defn ->camel-case [m] 12 | (ce/transform-keys c/->camelCaseKeyword m)) 13 | 14 | (defn ->camel-case-keys-str [m] 15 | (ce/transform-keys c/->camelCaseString m)) 16 | 17 | (def ->camel-case-str c/->camelCaseString) 18 | (def ->snake-case-str c/->snake_case_string) 19 | (def ->kebab-case-str c/->kebab-case-string) 20 | (def ->camel-case-keyword c/->camelCaseKeyword) 21 | (def ->snake-case-keyword c/->snake_case_keyword) 22 | (def ->kebab-case-keyword c/->kebab-case-keyword) 23 | -------------------------------------------------------------------------------- /client/src-js/button_analytics.js: -------------------------------------------------------------------------------- 1 | import { submitAnalyticsTrack } from './analytics' 2 | import { sendServerAnalytics } from './send_analytics' 3 | 4 | function sendAnalytics(id) { 5 | let eventName = 'Button Pressed' 6 | let properties = { id } 7 | 8 | sendServerAnalytics({ 9 | type: 'track', 10 | payload: { 'event-name': eventName, properties }, 11 | }) 12 | submitAnalyticsTrack(eventName, properties) 13 | } 14 | 15 | const isButton = elm => elm.tagName === 'BUTTON' 16 | const hasId = elm => elm.id !== '' 17 | const hasTrackClass = elm => elm.classList.contains('track-click') 18 | 19 | document.addEventListener('click', evt => { 20 | const elm = evt.target 21 | if (hasId(elm) && (isButton(elm) || hasTrackClass(elm))) { 22 | sendAnalytics(elm.id) 23 | } 24 | }) 25 | -------------------------------------------------------------------------------- /client/legacy-styles/_selector.sass: -------------------------------------------------------------------------------- 1 | $transition-time: 0.2s 2 | 3 | .selector 4 | display: flex 5 | margin-bottom: 24px 6 | +mobile 7 | width: 100% 8 | .selector__option 9 | text-align: center 10 | height: 30px 11 | +desktop 12 | min-width: 166px 13 | +mobile 14 | width: 100% 15 | color: $greyish 16 | font-weight: $font-semi-bold 17 | font-size: 11px 18 | line-height: 30px 19 | text-transform: uppercase 20 | border: 1px solid $greyish 21 | cursor: pointer 22 | background-color: white 23 | transition: background-color $transition-time, color $transition-time 24 | &:hover 25 | background-color: $pale-gray 26 | &:not(:first-child) 27 | border-left: unset 28 | .selector__option--selected 29 | background-color: $steel-gray 30 | color: white 31 | &:hover 32 | background-color: $steel-gray 33 | -------------------------------------------------------------------------------- /client/src-js/add_sourcing.js: -------------------------------------------------------------------------------- 1 | export function addSourcing(obj, atx) { 2 | var sourcing = {} 3 | 4 | if (atx.referrer != null && atx.referrer != '') { 5 | sourcing.referrer = atx.referrer 6 | } 7 | 8 | if (atx.utms && atx.utms.size > 0) { 9 | const utmsEntries = Array.from(atx.utms.entries()) 10 | 11 | sourcing.campaign = Object.assign( 12 | {}, 13 | ...utmsEntries.map(([k, v]) => ({ [k]: v })), 14 | ) 15 | 16 | // also add without the `utm_` part 17 | sourcing.campaign = Object.assign( 18 | sourcing.campaign, 19 | ...utmsEntries.map(([k, v]) => ({ [k.replace('utm_', '')]: v })), 20 | ) 21 | } 22 | 23 | if (Object.keys(sourcing).length > 0) { 24 | obj.sourcing = sourcing 25 | } 26 | 27 | return obj 28 | } 29 | -------------------------------------------------------------------------------- /client/src/wh/company/candidate/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.company.candidate.db 2 | (:require [cljs.spec.alpha :as s] 3 | [wh.logged-in.profile.db :as profile])) 4 | 5 | (s/def ::data 6 | (s/keys :opt-un [::profile/image-url 7 | ::profile/email 8 | ::profile/preferred-locations 9 | ::profile/name 10 | ::profile/other-urls 11 | ::profile/summary 12 | ::profile/skills 13 | ::profile/company-perks])) 14 | 15 | (s/def ::job-titles (s/map-of string? string?)) 16 | 17 | (s/def ::updating? boolean?) 18 | 19 | (s/def ::sub-db (s/keys :req [::data 20 | ::updating?] 21 | :opt [::job-titles])) 22 | 23 | (def default-db {::data {} 24 | ::updating? false}) 25 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/elements/other.sass: -------------------------------------------------------------------------------- 1 | .block 2 | @extend %block 3 | 4 | .delete 5 | @extend %delete 6 | 7 | .heading 8 | display: block 9 | font-size: 11px 10 | letter-spacing: 1px 11 | margin-bottom: 5px 12 | text-transform: uppercase 13 | 14 | .highlight 15 | @extend %block 16 | font-weight: $weight-normal 17 | max-width: 100% 18 | overflow: hidden 19 | padding: 0 20 | pre 21 | overflow: auto 22 | max-width: 100% 23 | 24 | .loader 25 | @extend %loader 26 | 27 | .number 28 | align-items: center 29 | background-color: $background 30 | border-radius: $radius-rounded 31 | display: inline-flex 32 | font-size: $size-medium 33 | height: 2em 34 | justify-content: center 35 | margin-right: 1.5rem 36 | min-width: 2.5em 37 | padding: 0.25rem 0.5rem 38 | text-align: center 39 | vertical-align: top 40 | -------------------------------------------------------------------------------- /client/resources/public/images/share-linkedin.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/grid/tiles.sass: -------------------------------------------------------------------------------- 1 | .tile 2 | align-items: stretch 3 | display: block 4 | flex-basis: 0 5 | flex-grow: 1 6 | flex-shrink: 1 7 | min-height: min-content 8 | // Modifiers 9 | &.is-ancestor 10 | margin-left: -0.75rem 11 | margin-right: -0.75rem 12 | margin-top: -0.75rem 13 | &:last-child 14 | margin-bottom: -0.75rem 15 | &:not(:last-child) 16 | margin-bottom: 0.75rem 17 | &.is-child 18 | margin: 0 !important 19 | &.is-parent 20 | padding: 0.75rem 21 | &.is-vertical 22 | flex-direction: column 23 | & > .tile.is-child:not(:last-child) 24 | margin-bottom: 1.5rem !important 25 | // Responsiveness 26 | +tablet 27 | &:not(.is-child) 28 | display: flex 29 | @for $i from 1 through 12 30 | &.is-#{$i} 31 | flex: none 32 | width: ($i / 12) * 100% 33 | -------------------------------------------------------------------------------- /client/src/wh/logged_in/contribute/styles.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.logged-in.contribute.styles) 2 | (def cross-posting "styles__cross-posting--2ut4Q") 3 | (def cross-posting__publishers "styles__cross-posting__publishers--1eFIA") 4 | (def cross-posting__publisher "styles__cross-posting__publisher--X7gx9") 5 | (def cross-posting__a "styles__cross-posting__a--3LjZJ") 6 | (def cross-posting__button "styles__cross-posting__button--223FF") 7 | (def cross-posting__button--inverted "styles__cross-posting__button--inverted--3BJUj") 8 | (def cross-posting__button--inverted-highlighted "styles__cross-posting__button--inverted-highlighted--2SHB5") 9 | (def cross-posting__button--short "styles__cross-posting__button--short--3bdTg") 10 | (def cross-posting__button--disabled "styles__cross-posting__button--disabled--9WjAQ") 11 | (def cross-posting__button--dark "styles__cross-posting__button--dark--2eZzo") -------------------------------------------------------------------------------- /client/src/wh/logged_in/notifications/settings/subs.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.logged-in.notifications.settings.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]] 4 | [wh.logged-in.notifications.settings.db :as sub-db])) 5 | 6 | (reg-sub 7 | ::sub-db 8 | (fn [db _] 9 | (::sub-db/sub-db db))) 10 | 11 | (reg-sub 12 | ::frequency 13 | :<- [::sub-db] 14 | (fn [sub-db [_ event-type]] 15 | (get-in sub-db [:frequencies event-type :frequency]))) 16 | 17 | (reg-sub 18 | ::saving? 19 | :<- [::sub-db] 20 | (fn [sub-db _] 21 | (:saving? sub-db))) 22 | 23 | (reg-sub 24 | ::save-enabled? 25 | :<- [::saving?] 26 | :<- [::frequency :matching-job] 27 | (fn [[saving? matching-job] _] 28 | (boolean (and matching-job (not saving?))))) 29 | 30 | (reg-sub 31 | ::save-status 32 | :<- [::sub-db] 33 | (fn [sub-db _] 34 | (:save-status sub-db))) 35 | -------------------------------------------------------------------------------- /client/resources/public/images/profile/member_since.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/resources/public/images/hiw/balls/yellow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /common/src/wh/components/not_found.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.not-found 2 | (:require [wh.routes :as routes] 3 | [wh.styles.not-found :as styles])) 4 | 5 | (defn not-found [] 6 | [:div.container 7 | [:h1 "404 - Page not Found"] 8 | [:div 9 | [:h2 "Play a game \uD83D\uDC7E instead?"] 10 | (let [msg "Seriously? No. Stop procrastinating and go find a job!"] 11 | [:a.button (merge {:href (routes/path :homepage)} 12 | #?(:clj {:onclick (str "alert('" msg "')")} 13 | :cljs {:on-click #(js/alert msg)})) 14 | "Play"])]]) 15 | 16 | (defn not-found-profile [] 17 | [:div {:class styles/container} 18 | [:div {:class styles/numbers} "404"] 19 | [:div {:class styles/description} "Profile page doesn't exist"]]) 20 | 21 | (defn not-found-page [] 22 | [:div.dashboard 23 | [:div.main.main--center-content 24 | [not-found]]]) 25 | -------------------------------------------------------------------------------- /client/src-js/photo.js: -------------------------------------------------------------------------------- 1 | /* global PhotoSwipeUI_Default, PhotoSwipe */ 2 | 3 | import { setClass } from './public' 4 | 5 | function openPhotoGallery(index, images) { 6 | var pswpElement = document.querySelectorAll('.pswp')[0] 7 | var options = { index: index, bgOpacity: 0.9, history: false } 8 | var items = [] 9 | for (var i = 0; i < images.length; i++) { 10 | items.push({ src: images[i].url, w: images[i].width, h: images[i].height }) 11 | } 12 | 13 | // mobile safari bug 14 | // we need to force z-index: 0 on the nav 15 | setClass('wh-navbar', 'navbar--reset-z-index', true) 16 | 17 | var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options) 18 | gallery.listen('close', function () { 19 | setClass('wh-navbar', 'navbar--reset-z-index', false) 20 | }) 21 | 22 | gallery.init() 23 | } 24 | 25 | window.openPhotoGallery = openPhotoGallery 26 | -------------------------------------------------------------------------------- /client/src/wh/admin/articles/subs.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.admin.articles.subs 2 | (:require [re-frame.core :refer [reg-sub]] 3 | [wh.admin.articles.db :as articles] 4 | [wh.components.pagination :as pagination])) 5 | 6 | (reg-sub 7 | ::sub-db 8 | (fn [db _] (::articles/sub-db db))) 9 | 10 | (reg-sub 11 | ::articles 12 | :<- [::sub-db] 13 | (fn [sub-db _] 14 | (::articles/articles sub-db))) 15 | 16 | (reg-sub 17 | ::error? 18 | :<- [::sub-db] 19 | (fn [sub-db _] 20 | (::articles/error? sub-db))) 21 | 22 | (reg-sub 23 | ::current-page-number 24 | (fn [db _] 25 | (articles/page-number db))) 26 | 27 | (reg-sub 28 | ::pagination 29 | :<- [::sub-db] 30 | :<- [::current-page-number] 31 | (fn [[sub-db current-page-number] _] 32 | (when-let [p (::articles/pagination sub-db)] 33 | (pagination/generate-pagination current-page-number (/ (:total p) articles/page-size))))) 34 | -------------------------------------------------------------------------------- /common/src/wh/styles/card_actions.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.card-actions) 2 | (def actions "card_actions__actions--6EeDA") 3 | (def actions__inner "card_actions__actions__inner--2Ko2V") 4 | (def actions__inner--open "card_actions__actions__inner--open--11RDL") 5 | (def actions__share "card_actions__actions__share--2WBdy") 6 | (def actions__share-button "card_actions__actions__share-button--32fgi") 7 | (def actions__share-button--center "card_actions__actions__share-button--center--nnRZt") 8 | (def actions__share-image "card_actions__actions__share-image--3_sM5") 9 | (def actions__container "card_actions__actions__container--2N3Ke") 10 | (def actions__action "card_actions__actions__action--2qv0g") 11 | (def actions__action--save "card_actions__actions__action--save--3NCQ_") 12 | (def actions__action--share "card_actions__actions__action--share--1XZpy") 13 | (def actions__action--saved-icon "card_actions__actions__action--saved-icon--2osN-") -------------------------------------------------------------------------------- /client/resources/public/images/homepage/logos/troops.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /common/src/wh/components/skeletons/components.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.skeletons.components 2 | (:require [wh.components.tag :as tag] 3 | [wh.styles.skeletons :as styles] 4 | [wh.util :as util])) 5 | 6 | (defn image-with-info [] 7 | [:div (util/smc styles/image-with-info) 8 | [:div (util/smc styles/image-with-info__logo)] 9 | [:div (util/smc styles/image-with-info__info1)] 10 | [:div (util/smc styles/image-with-info__info2)]]) 11 | 12 | (defn text [] 13 | [:div (util/smc styles/paragraph) 14 | [:div (util/smc styles/paragraph__line)] 15 | [:div (util/smc styles/paragraph__line)] 16 | [:div (util/smc styles/paragraph__line styles/paragraph__line--short)]]) 17 | 18 | (defn button [] 19 | [:div (util/smc styles/button)]) 20 | 21 | (defn title [] 22 | [:div (util/smc styles/title)]) 23 | 24 | (defn tags 25 | ([] 26 | (tags 5)) 27 | ([n] 28 | [tag/tag-list :li (repeat n nil)])) 29 | -------------------------------------------------------------------------------- /client/styles/branding.sass: -------------------------------------------------------------------------------- 1 | @import 'colours' 2 | @import 'mixins' 3 | 4 | .vertical-title 5 | display: flex 6 | flex-direction: column 7 | color: $grey500 8 | font-weight: 500 9 | letter-spacing: 0.08em 10 | line-height: 1 11 | text-transform: uppercase 12 | vertical-align: text-bottom 13 | +tablet 14 | flex-direction: row 15 | 16 | .vertical-title__line:first-child:not(:last-child) 17 | font-weight: 700 18 | letter-spacing: 0.1em 19 | 20 | .vertical-title--multiline 21 | align-items: center 22 | display: flex 23 | flex-direction: column 24 | .vertical-title__line:first-child:not(:last-child) 25 | margin-bottom: 3px 26 | 27 | .vertical-title--navigation 28 | display: flex 29 | flex-direction: column 30 | .vertical-title__line:first-child:not(:last-child) 31 | margin-bottom: 3px 32 | 33 | .vertical-title--small 34 | font-size: 12px 35 | 36 | .vertical-title--medium 37 | font-size: 16px 38 | -------------------------------------------------------------------------------- /common/src/wh/re_frame/subs.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.re-frame.subs 2 | (:require 3 | #?(:clj [taoensso.timbre :refer [error]]) 4 | [re-frame.core :as re-frame])) 5 | 6 | (defn (re-frame/subscribe c) 10 | (deref)) 11 | (catch #?(:clj Exception 12 | :cljs js/Error) e 13 | #?(:clj (do 14 | (error e "An error occurred whilst resolving the following subscription: " c) 15 | (throw e)) 16 | :cljs (throw e))))) 17 | 18 | ;; The next three forms are needed for reg-sub-raw to work in clj. 19 | 20 | #?(:clj (create-ns 'reagent.ratom)) 21 | 22 | #?(:clj 23 | (intern 'reagent.ratom 'make-reaction 24 | (fn make-reaction [f & [_args]] 25 | (reify clojure.lang.IDeref 26 | (deref [_] (f)))))) 27 | 28 | #?(:clj 29 | (defmacro reaction [& body] 30 | `(reagent.ratom/make-reaction 31 | (fn [] ~@body)))) 32 | -------------------------------------------------------------------------------- /client/styles/skeletons.sass: -------------------------------------------------------------------------------- 1 | @import 'colours' 2 | @import 'mixins' 3 | 4 | .image-with-info 5 | column-gap: 16px 6 | display: grid 7 | grid-template-columns: 40px 1fr 8 | grid-template-rows: 1fr 1fr 9 | height: 40px 10 | align-items: center 11 | row-gap: 4px 12 | &__logo 13 | grid-column: 1 14 | grid-row: 1/3 15 | @include skeleton(40px, 40px, $primary-red) 16 | &__info1 17 | grid-column: 2 18 | grid-row: 1 19 | @include skeleton(70%, 18px, $skeleton-grey-dark) 20 | &__info2 21 | grid-column: 2 22 | grid-row: 2 23 | @include skeleton(50%, 18px) 24 | 25 | .paragraph 26 | display: grid 27 | grid-gap: 4px 28 | &__line 29 | @include skeleton(95%, 18px) 30 | &__line--short 31 | width: 60% 32 | 33 | .button 34 | height: 40px 35 | border-radius: 4px 36 | width: 160px 37 | background-color: $primary-red 38 | 39 | .title 40 | @include skeleton(80%, 18px, $skeleton-grey-dark) 41 | -------------------------------------------------------------------------------- /common/src/wh/components/branding.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.branding 2 | (:require [clojure.string :as str] 3 | [wh.styles.branding :as branding-style] 4 | [wh.util :as util] 5 | [wh.verticals :as verticals])) 6 | 7 | (defn vertical-title 8 | [vertical {:keys [size type] 9 | :or {size :medium}}] 10 | [:div (util/smc branding-style/vertical-title 11 | [(= type :multiline) branding-style/vertical-title--multiline] 12 | [(= type :navigation) branding-style/vertical-title--navigation] 13 | (case size 14 | :small branding-style/vertical-title--small 15 | :medium branding-style/vertical-title--medium)) 16 | (map #(vector :span {:key % :class branding-style/vertical-title__line} %) 17 | (str/split (if (= "www" vertical) "Works Hub" 18 | (verticals/config vertical :platform-name)) #"\s"))]) 19 | -------------------------------------------------------------------------------- /client/src/wh/jobs/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.jobs.core 2 | (:require [cljs.loader :as loader] 3 | [re-frame.core :refer [dispatch dispatch-sync reg-event-db]] 4 | [wh.db :as db] 5 | [wh.job.views :as job] 6 | [wh.jobsboard.views :as jobsboard])) 7 | 8 | (def page-mapping 9 | {:job job/page 10 | :jobsboard jobsboard/jobsboard-page 11 | :jobsboard-search jobsboard/jobsboard-page 12 | :pre-set-search jobsboard/preset-search-page}) 13 | 14 | (reg-event-db 15 | ::initialize-page-mapping 16 | (fn [db _] 17 | (update db ::db/page-mapping merge page-mapping))) 18 | 19 | (dispatch-sync [::initialize-page-mapping]) 20 | (dispatch [:wh.pages.core/unset-loader]) 21 | 22 | ;; load extra symbols 23 | (let [symbol-filename "symbols/job.svg"] 24 | (when-not (.getElementById js/document (str "load-icons-" symbol-filename)) 25 | (js/loadSymbols symbol-filename))) 26 | 27 | (loader/set-loaded! :jobs) 28 | -------------------------------------------------------------------------------- /common-pages/src/wh/blogs/blog/styles.sass: -------------------------------------------------------------------------------- 1 | @import 'colours' 2 | 3 | .publisher 4 | display: block 5 | width: 300px 6 | height: 120px 7 | border-radius: 8px 8 | 9 | &--devto 10 | background-color: white 11 | display: flex 12 | align-items: center 13 | padding: 24px 14 | 15 | svg 16 | width: 70px 17 | height: 70px 18 | 19 | &--hashnode 20 | display: flex 21 | align-items: center 22 | justify-content: center 23 | background-color: white 24 | 25 | svg 26 | width: 210px 27 | height: 36px 28 | position: relative 29 | 30 | &__name 31 | font-size: 32px 32 | font-weight: 700 33 | color: black 34 | margin-left: 24px 35 | letter-spacing: 0 36 | 37 | 38 | .publishers 39 | display: flex 40 | gap: 16px 41 | flex-wrap: wrap 42 | 43 | .comment-section 44 | margin: 32px 0 64px 45 | 46 | .comment-section-header 47 | font-size: 20px 48 | font-weight: 600 49 | color: $grey500 -------------------------------------------------------------------------------- /common-pages/src/wh/company/jobs/db.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.company.jobs.db 2 | (:require [wh.components.pagination :as pagination])) 3 | 4 | (def page-size 12) 5 | 6 | (def default-sort [{:field "last-modified" 7 | :order :DESC}]) 8 | 9 | (defn company-slug [db] 10 | (get-in db [:wh.db/page-params :slug])) 11 | 12 | (defn page-number [db] 13 | (pagination/qps->page-number (:wh.db/query-params db))) 14 | 15 | (def default-unpublished? true) 16 | 17 | (defn show-unpublished? [admin? company? unpublished?] 18 | (and (or admin? company?) 19 | (if (nil? unpublished?) default-unpublished? unpublished?))) 20 | 21 | (defn published 22 | "Determines the value of the 'published' GraphQL query arg to pass. 23 | NB: It's `nil` for all (both published and unpublished) jobs OR 24 | `true` for published only. 25 | See `company-jobs` resolver and `fetch-jobs` for more details." 26 | [show-unpublished?] 27 | (when-not show-unpublished? true)) 28 | -------------------------------------------------------------------------------- /client/styles/job.sass: -------------------------------------------------------------------------------- 1 | @import mixins 2 | 3 | .highlight 4 | &__content 5 | font-size: 14px 6 | line-height: 20px 7 | margin-bottom: 8px 8 | &__subtitle 9 | font-weight: 600 10 | font-size: 12px 11 | line-height: 18px 12 | margin-bottom: 12px 13 | &__icon 14 | stroke: $grey-old 15 | &__list__element 16 | font-size: 14px 17 | line-height: 24px 18 | display: flex 19 | &::before 20 | content: '' 21 | background-color: $primary-red 22 | display: inline-block 23 | width: 6px 24 | height: 6px 25 | min-width: 6px 26 | min-height: 6px 27 | border-radius: 50% 28 | margin-right: 8px 29 | align-self: center 30 | 31 | .remote-info 32 | display: inline-block 33 | font-size: 14px 34 | line-height: 17px 35 | white-space: pre 36 | overflow: hidden 37 | text-overflow: ellipsis 38 | &__icon 39 | display: inline-block 40 | 41 | .timezones-list 42 | display: inline-flex 43 | -------------------------------------------------------------------------------- /common-pages/src/wh/how_it_works/subs.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.how-it-works.subs 2 | (:require 3 | #?(:clj [clojure.spec.alpha :as s] 4 | :cljs [cljs.spec.alpha :as s]) 5 | [re-frame.core :refer [reg-sub]] 6 | [wh.common.subs])) ;; required for inclusion 7 | 8 | (reg-sub 9 | ::selected-site 10 | (fn [db _] 11 | (let [vertical (:wh.db/vertical db) 12 | default-site (if (= "www" vertical) "company" "candidate")] 13 | (keyword (get-in db [:wh.db/query-params "site"] 14 | default-site))))) 15 | 16 | (reg-sub 17 | ::show-github-buttons? 18 | :<- [:user/company?] 19 | :<- [:user/company-connected-github?] 20 | (fn [[company? connected?] _] 21 | (and company? (not connected?)))) 22 | 23 | (reg-sub 24 | ::show-candidate-buttons? 25 | :<- [:user/candidate?] 26 | (fn [candidate? _] 27 | candidate?)) 28 | 29 | (reg-sub 30 | ::show-company-buttons? 31 | :<- [:user/company?] 32 | (fn [company? _] 33 | company?)) 34 | -------------------------------------------------------------------------------- /client/src/wh/blogs/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.blogs.core 2 | (:require 3 | [cljs.loader :as loader] 4 | [re-frame.core :refer [dispatch dispatch-sync reg-event-db]] 5 | [wh.blogs.blog.db :as blog-db] 6 | [wh.blogs.blog.views :as blog] 7 | [wh.blogs.blog.events] 8 | [wh.blogs.learn.views :as learn] 9 | [wh.blogs.learn.events] 10 | [wh.blogs.liked.views :as liked] 11 | [wh.blogs.liked.events] 12 | [wh.db :as db])) 13 | 14 | (def page-mapping 15 | {:blog blog/page 16 | :learn learn/page 17 | :learn-search learn/page 18 | :learn-by-tag learn/page 19 | :liked-blogs liked/page}) 20 | 21 | (reg-event-db 22 | ::initialize-page-mapping 23 | (fn [db _] 24 | (update db ::db/page-mapping merge page-mapping))) 25 | 26 | (swap! db/sub-dbs conj ::blog-db/sub-db) 27 | 28 | (dispatch-sync [::initialize-page-mapping]) 29 | ;; don't unset loader here; too early 30 | 31 | (db/redefine-app-db-spec!) 32 | 33 | (loader/set-loaded! :blogs) 34 | -------------------------------------------------------------------------------- /client/src-js/newsletter.js: -------------------------------------------------------------------------------- 1 | const listenNewsletterForm = () => { 2 | const selectors = { 3 | formNewsletter: '#newsletter-subscription-form', 4 | messageSuccess: '#newsletter-subscription-success', 5 | } 6 | 7 | const form = document.querySelector(selectors.formNewsletter) 8 | 9 | if (form) { 10 | const toggleVisibility = elm => elm.classList.toggle('is-hidden') 11 | const CREATE_PROSPECT_USER = window.location.origin + '/api/prospect' 12 | 13 | form.addEventListener('submit', e => { 14 | e.preventDefault() 15 | 16 | fetch(CREATE_PROSPECT_USER, { 17 | method: 'POST', 18 | body: new FormData(form), 19 | }).catch(console.error) 20 | 21 | const elementToDisplay = document.querySelector(selectors.messageSuccess) 22 | 23 | toggleVisibility(elementToDisplay) 24 | }) 25 | } 26 | } 27 | 28 | window.listenNewsletterForm = listenNewsletterForm 29 | -------------------------------------------------------------------------------- /client/legacy-styles/_verticals.sass: -------------------------------------------------------------------------------- 1 | .verticals-pod 2 | margin-top: 0 !important 3 | box-shadow: none 4 | hr 5 | background-color: $pale-gray 6 | margin-top: 10px 7 | 8 | .verticals-pod__verticals 9 | display: grid 10 | letter-spacing: 3px 11 | font-weight: $font-semi-bold 12 | .icon 13 | width: 28px 14 | height: 28px 15 | flex: 0 0 28px 16 | margin-right: 15px 17 | 18 | .verticals-pod__vertical--disabled 19 | opacity: 0.25 20 | 21 | .verticals-pod__verticals--off 22 | .verticals-pod__vertical-toggle 23 | opacity: 0.25 24 | +desktop 25 | &:hover 26 | opacity: 0.5 27 | 28 | .verticals-pod__verticals--on 29 | .verticals-pod__vertical-toggle 30 | +desktop 31 | &:hover 32 | opacity: 0.6 33 | 34 | .verticals-pod__vertical-toggle 35 | cursor: pointer 36 | display: flex 37 | align-items: center 38 | margin: 5px 0 5px 12px 39 | 40 | .verticals-pod__vertical-toggle-wrapper 41 | display: flex 42 | align-items: center 43 | -------------------------------------------------------------------------------- /client/src-js/tags_selector.js: -------------------------------------------------------------------------------- 1 | import { 2 | getCurrentSearchString, 3 | toggleParamValue, 4 | urlWithNewSearchString, 5 | removeParam, 6 | setParamValue, 7 | } from './search_string' 8 | 9 | function redirect(url) { 10 | window.location = url 11 | } 12 | 13 | function toggleTagAndRedirect(tagId) { 14 | const searchString = getCurrentSearchString(window) 15 | const newSearchStringWithoutActivityId = removeParam( 16 | removeParam(searchString, 'older-than'), 17 | 'newer-than', 18 | ) 19 | const newSearchString = toggleParamValue( 20 | newSearchStringWithoutActivityId, 21 | 'tags', 22 | tagId, 23 | ) 24 | const newSearchStringWithInteraction = setParamValue( 25 | newSearchString, 26 | 'interaction', 27 | 1, 28 | ) 29 | const newUrl = urlWithNewSearchString(window, newSearchStringWithInteraction) 30 | redirect(newUrl) 31 | } 32 | 33 | window.toggleTagAndRedirect = toggleTagAndRedirect 34 | -------------------------------------------------------------------------------- /client/src/workspaces/side_cards.cljs: -------------------------------------------------------------------------------- 1 | (ns workspaces.side-cards 2 | (:require [nubank.workspaces.card-types.react :as ct.react] 3 | [nubank.workspaces.core :as ws] 4 | [reagent.core :as r] 5 | [wh.components.side-card.side-card :as side-card])) 6 | 7 | (defn element [name props & children] 8 | (apply js/React.createElement name (clj->js props) children)) 9 | 10 | (ws/defcard osi-how-it-works-card 11 | (ct.react/react-card 12 | (r/as-element [:div {:style {:border "1px solid black" 13 | :max-width "280px"}} 14 | [side-card/osi-how-it-works]]))) 15 | 16 | (ws/defcard improve-your-recommendations-card 17 | (ct.react/react-card 18 | (r/as-element [:div {:style {:background "#eee" 19 | :max-width "350px" 20 | :padding "16px"}} 21 | [side-card/improve-your-recommendations true]]))) 22 | 23 | (defonce init (ws/mount)) 24 | -------------------------------------------------------------------------------- /client/src/wh/components/tabs/views.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.components.tabs.views 2 | (:require 3 | [reagent.core :as r] 4 | [wh.components.icons :refer [icon]])) 5 | 6 | (defn tabs 7 | [_selected-tab _tbs _on-click] 8 | (let [collapsed? (r/atom true)] 9 | (fn [selected-tab tbs on-click] 10 | [:ul.tabs 11 | {:class (when-not @collapsed? "tabs--expanded") 12 | :style (when-not @collapsed? {:height (str (* (count tbs) 40) "px")})} 13 | (for [[id label :as t] tbs] 14 | ^{:key id} 15 | [:li.tab 16 | {:class (when (= id selected-tab) "tab--selected") 17 | :on-click #(do 18 | (reset! collapsed? true) 19 | (when on-click (on-click id)))} 20 | label]) 21 | [:div.tab__roll-down 22 | {:on-click #(do (swap! collapsed? not) 23 | (.stopPropagation %)) 24 | :class (when-not @collapsed? "tab__roll-down--expanded")} 25 | [icon "roll-down"]]]))) 26 | -------------------------------------------------------------------------------- /common/src/wh/slug.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.slug 2 | (:require [clojure.string :as str])) 3 | 4 | (defn slug [s] 5 | "We currently have this function and wh.url/slugify (clojure only). 6 | We should have only one, consistent and cross-platform way of slugging, see story [ch2575]." 7 | (-> s 8 | (str/lower-case) 9 | (str/trim) 10 | (str/replace #"\," "-") 11 | (str/replace #"\s+" "-"))) 12 | 13 | (defn tag-label->slug [s] 14 | (-> s 15 | (str/lower-case) 16 | (str/trim) 17 | (str/replace #"#" "sharp") ;; C# 18 | (str/replace #"\+" "plus") ;; C++ 19 | (str/replace #"^\." "dot") ;; .NET 20 | (str/replace #"[^a-zA-Z0-9]+" "-"))) 21 | 22 | (defn slug->label 23 | "Changes URL-safe string into readable label. Useful when URL parameter 24 | is passed to DB query." 25 | [s] 26 | (-> s 27 | (str/lower-case) 28 | (str/trim) 29 | (str/replace #"sharp" "#") ;; C# 30 | (str/replace #"plus" "+") ;; C++ 31 | (str/replace #"dot" "."))) ;; .NET 32 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/elements/notification.sass: -------------------------------------------------------------------------------- 1 | $notification-background-color: $background !default 2 | $notification-radius: $radius !default 3 | $notification-padding: 1.25rem 2.5rem 1.25rem 1.5rem !default 4 | 5 | .notification 6 | @extend %block 7 | background-color: $notification-background-color 8 | border-radius: $notification-radius 9 | padding: $notification-padding 10 | position: relative 11 | a:not(.button):not(.dropdown-item) 12 | color: currentColor 13 | text-decoration: underline 14 | strong 15 | color: currentColor 16 | code, 17 | pre 18 | background: $white 19 | pre code 20 | background: transparent 21 | & > .delete 22 | position: absolute 23 | right: 0.5rem 24 | top: 0.5rem 25 | .title, 26 | .subtitle, 27 | .content 28 | color: currentColor 29 | // Colors 30 | @each $name, $pair in $colors 31 | $color: nth($pair, 1) 32 | $color-invert: nth($pair, 2) 33 | &.is-#{$name} 34 | background-color: $color 35 | color: $color-invert 36 | -------------------------------------------------------------------------------- /common/src/wh/components/navbar/subs.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.navbar.subs 2 | (:require [re-frame.core :refer [reg-sub]] 3 | [wh.common.search :as search] 4 | [wh.common.user :as user-common] 5 | [wh.components.navbar.db :as db] 6 | [wh.job.db :as job])) 7 | 8 | (reg-sub 9 | ::profile-image 10 | :<- [:user/sub-db] 11 | (fn [{:keys [wh.user.db/type wh.user.db/image-url wh.user.db/company] :as _user} _] 12 | (if (user-common/company-type? type) (get company :logo) image-url))) 13 | 14 | (reg-sub 15 | ::company-slug 16 | :<- [:user/sub-db] 17 | (fn [user _] 18 | (get-in user [:wh.user.db/company :slug]))) 19 | 20 | (reg-sub 21 | ::search-value 22 | (fn [db _] 23 | (or (::db/search-value db) 24 | (search/->search-term (:wh.db/page-params db) (:wh.db/query-params db))))) 25 | 26 | (reg-sub 27 | ::can-publish-jobs? 28 | (fn [db _] 29 | (job/can-publish-jobs? db))) 30 | 31 | (reg-sub 32 | ::can-create-jobs? 33 | (fn [db _] 34 | (job/can-create-jobs? db))) 35 | -------------------------------------------------------------------------------- /client/src/workspaces/stat_cards.cljs: -------------------------------------------------------------------------------- 1 | (ns workspaces.stat-cards 2 | (:require [nubank.workspaces.card-types.react :as ct.react] 3 | [nubank.workspaces.core :as ws] 4 | [reagent.core :as r] 5 | [wh.components.stat-card :as stat-card] 6 | [wh.verticals :as verticals])) 7 | 8 | (ws/defcard all-cards 9 | (let [vertical-idx (atom 0)] 10 | (ct.react/react-card 11 | vertical-idx 12 | (r/as-element 13 | [:a {:href "#" 14 | :on-click #(if (>= (inc @vertical-idx) (count verticals/all-verticals)) 15 | (reset! vertical-idx 0) 16 | (swap! vertical-idx inc))} 17 | [:div {:style {:display "grid" 18 | :grid-gap "10px" 19 | :width "100%"}} 20 | [stat-card/about-applications (nth (vec verticals/all-verticals) @vertical-idx)] 21 | [stat-card/about-salary-increase (nth (vec verticals/all-verticals) @vertical-idx)]]])))) 22 | 23 | (defonce init (ws/mount)) 24 | -------------------------------------------------------------------------------- /common/src/wh/components/icons.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.icons 2 | (:require [wh.common.url :as url] 3 | [wh.util :as util])) 4 | 5 | (defn icon [name & {:keys [tooltip] :as opts}] 6 | (let [svg [:svg (-> (dissoc opts :title :tooltip) 7 | (assoc :class (util/merge-classes (:class opts) "icon" (str "icon--" name)))) 8 | [:use {#?(:clj :xlink:href) #?(:cljs :xlink-href) (str "#" name)}]]] 9 | (if tooltip 10 | [:div.icon__container 11 | [:span.icon__tooltip tooltip] 12 | svg] 13 | svg))) 14 | 15 | (defn type->icon-name [type] 16 | (case type 17 | :twitter "twitter-circle" 18 | :linkedin "linkedin-circle" 19 | (name type))) 20 | 21 | (defn url-icons [other-urls class] 22 | (into 23 | [:div {:class class}] 24 | (for [{:keys [url type]} (url/detect-urls-type other-urls)] 25 | [:a 26 | {:href url 27 | :target "_blank" 28 | :rel "noopener" 29 | :class "url-icon"} 30 | [icon (type->icon-name type) :class (str class "__icon")]]))) 31 | -------------------------------------------------------------------------------- /client/resources/public/images/profile/commits.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/styles/create_job.sass: -------------------------------------------------------------------------------- 1 | @import mixins 2 | @import colours 3 | 4 | .settings-card 5 | padding: 20px 16px 6 | background: $white 7 | border-radius: 8px 8 | margin-bottom: 16px 9 | &__title 10 | color: $grey300 11 | 12 | .checkbox 13 | margin: 16px 0 14 | display: block 15 | 16 | .remuneration 17 | &__checkbox 18 | user-select: none 19 | display: block 20 | margin: 16px 0 21 | 22 | .remote-info 23 | margin: 16px 0 48px 0 24 | &__section 25 | font-size: 14px 26 | 27 | .timezone 28 | display: grid 29 | grid-template-columns: 1fr 200px 200px 20px 30 | align-items: center 31 | margin: 0 -16px 32 | padding-right: 16px 33 | margin-bottom: 16px 34 | +mobile 35 | grid-template-rows: 44px 44px 36 | grid-template-columns: 1fr 1fr 20px 37 | grid-row-gap: 8px 38 | &__item 39 | +mobile 40 | grid-row: 2 41 | &:first-child 42 | grid-row: 1 43 | grid-column: 1/3 44 | margin: 0 16px 45 | position: relative 46 | &__close 47 | cursor: pointer 48 | +mobile 49 | grid-row: 1 50 | -------------------------------------------------------------------------------- /common/src/wh/re_frame/events.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.re-frame.events 2 | (:require [re-frame.core :as re-frame])) 3 | 4 | #?(:clj 5 | (defn dispatch 6 | "no-op" 7 | [_]) 8 | :cljs 9 | (def dispatch re-frame/dispatch)) 10 | 11 | #?(:clj 12 | (defn dispatch-sync 13 | "no-op" 14 | [_]) 15 | :cljs 16 | (def dispatch-sync re-frame/dispatch-sync)) 17 | 18 | #?(:clj 19 | (defn reg-event-db 20 | "no-op" 21 | [& _]) 22 | :cljs 23 | (def reg-event-db re-frame/reg-event-db)) 24 | 25 | #?(:clj 26 | (defn reg-event-fx 27 | "no-op" 28 | [& _]) 29 | :cljs 30 | (def reg-event-fx re-frame/reg-event-fx)) 31 | 32 | #?(:clj 33 | (defn reg-cofx 34 | "no-op" 35 | [& _]) 36 | :cljs 37 | (def reg-cofx re-frame/reg-cofx)) 38 | 39 | #?(:clj 40 | (defn inject-cofx 41 | "no-op" 42 | [_]) 43 | :cljs 44 | (def inject-cofx re-frame/inject-cofx)) 45 | 46 | #?(:clj 47 | (defn client-only-handler [_] 48 | (fn [_ _])) 49 | :cljs 50 | (defn client-only-handler [handler] 51 | handler)) 52 | -------------------------------------------------------------------------------- /client/resources/public/images/antenna.svg: -------------------------------------------------------------------------------- 1 | star 30x30-- -------------------------------------------------------------------------------- /common/src/wh/styles/landing.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.landing) 2 | (def page "landing__page--2REJ9") 3 | (def page__main "landing__page__main--2aEJv") 4 | (def side-column "landing__side-column--1krwu") 5 | (def side-column--left "landing__side-column--left--1Ucjl") 6 | (def tablet-only "landing__tablet-only--18Cc3") 7 | (def main-column "landing__main-column--3d3VB") 8 | (def card "landing__card--1Kley") 9 | (def card--tag-picker "landing__card--tag-picker--2fgJO") 10 | (def card--blog-published "landing__card--blog-published--1t1Ub") 11 | (def card--job-published "landing__card--job-published--3kvVB") 12 | (def card--matching-issues "landing__card--matching-issues--3l9_0") 13 | (def card--company-stats "landing__card--company-stats--2p-JS") 14 | (def card--issue-started "landing__card--issue-started--OHecJ") 15 | (def card--matching-jobs "landing__card--matching-jobs--1xlgC") 16 | (def loader "landing__loader--3T80b") 17 | (def prev-next-buttons "landing__prev-next-buttons--NZ9Q3") 18 | (def prev-next-button__text "landing__prev-next-button__text---fDJ8") 19 | (def separator "landing__separator--3E_kH") -------------------------------------------------------------------------------- /client/legacy-styles/_pods.sass: -------------------------------------------------------------------------------- 1 | .pod 2 | position: relative 3 | background-color: white 4 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.3) 5 | padding: 18px 6 | color: $steel-gray 7 | width: 100% 8 | min-width: 250px 9 | margin-bottom: 18px 10 | p 11 | font-size: 14px 12 | line-height: 21px 13 | flex: 1 14 | font-family: $family-secondary 15 | a:not(.cta-pod__auth-button) 16 | font-weight: 600 17 | color: $red 18 | text-decoration: underline 19 | &:hover 20 | color: $red 21 | h1, h2 22 | line-height: 16px 23 | letter-spacing: 0.3px 24 | margin: 0 25 | h1 26 | margin-top: 8px 27 | font-size: 18px 28 | font-weight: 600 29 | color: $steel-gray 30 | h2 31 | &:not(:first-child) 32 | margin-top: 6px 33 | font-size: 14px 34 | i 35 | margin-left: 1px 36 | font-weight: initial 37 | font-style: normal 38 | font-size: 12px 39 | h3 40 | line-height: 18px 41 | font-weight: $font-semi-bold 42 | &:not(:first-child) 43 | margin-top: 18px 44 | 45 | .pod--no-shadow 46 | box-shadow: unset 47 | -------------------------------------------------------------------------------- /client/resources/public/images/employers/free.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/components/media.sass: -------------------------------------------------------------------------------- 1 | .media 2 | align-items: flex-start 3 | display: flex 4 | text-align: left 5 | .content:not(:last-child) 6 | margin-bottom: 0.75rem 7 | .media 8 | border-top: 1px solid rgba($border, 0.5) 9 | display: flex 10 | padding-top: 0.75rem 11 | .content:not(:last-child), 12 | .control:not(:last-child) 13 | margin-bottom: 0.5rem 14 | .media 15 | padding-top: 0.5rem 16 | & + .media 17 | margin-top: 0.5rem 18 | & + .media 19 | border-top: 1px solid rgba($border, 0.5) 20 | margin-top: 1rem 21 | padding-top: 1rem 22 | // Sizes 23 | &.is-large 24 | & + .media 25 | margin-top: 1.5rem 26 | padding-top: 1.5rem 27 | 28 | .media-left, 29 | .media-right 30 | flex-basis: auto 31 | flex-grow: 0 32 | flex-shrink: 0 33 | 34 | .media-left 35 | margin-right: 1rem 36 | 37 | .media-right 38 | margin-left: 1rem 39 | 40 | .media-content 41 | flex-basis: auto 42 | flex-grow: 1 43 | flex-shrink: 1 44 | text-align: left 45 | 46 | +mobile 47 | .media-content 48 | overflow-x: auto 49 | -------------------------------------------------------------------------------- /common/src/wh/re_frame.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.re-frame 2 | (:require #?(:cljs [reagent.core :as r]) 3 | [re-frame.db :as r-db] 4 | [re-frame.interop]) 5 | (:refer-clojure :exclude [atom])) 6 | 7 | (defn set-app-db! 8 | [app-db] 9 | (reset! r-db/app-db app-db)) 10 | 11 | (def atom 12 | #?(:cljs r/atom 13 | :clj clojure.core/atom)) 14 | 15 | (def props 16 | #?(:cljs r/props 17 | :clj identity)) 18 | 19 | (def dom-node 20 | #?(:cljs r/dom-node 21 | :clj identity)) 22 | 23 | #?(:clj 24 | (defn next-tick 25 | [f] (f)) 26 | :cljs 27 | (def next-tick r/next-tick)) 28 | 29 | #?(:clj 30 | (defn create-class 31 | [m] (:reagent-render m)) 32 | :cljs 33 | (def create-class r/create-class)) 34 | 35 | #?(:clj 36 | (defn with-app-db-per-thread 37 | "creates re-frame app-db per thread, 38 | by default re-frame uses one atom for all threads" 39 | [{:keys [app-db] :as req} fn] 40 | (binding [re-frame.db/app-db (re-frame.interop/ratom app-db) 41 | re-frame.subs/query->reaction (atom {})] 42 | (fn req)))) 43 | -------------------------------------------------------------------------------- /client/src/wh/login/twitter_callback/views.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.twitter-callback.views 2 | (:require 3 | [wh.components.conversation.views :refer [error-message button]] 4 | [wh.components.icons :refer [icon]] 5 | [wh.login.twitter-callback.subs :as subs] 6 | [wh.login.twitter-callback.db :as twitter-callback] 7 | [wh.login.views :as login-views] 8 | [wh.subs :refer [errors 5 | [form] 6 | (let [salary? (not (nil? (get-in form [:salary :min]))) 7 | currency-missing? (nil? (get-in form [:salary :currency])) 8 | time-period-missing? (nil? (get-in form [:salary :time-period])) 9 | salary-incorrect? (and salary? (or currency-missing? time-period-missing?))] 10 | (cond-> {} 11 | (str/blank? (:email form)) 12 | (assoc :email "Please fill in your email") 13 | salary-incorrect? 14 | (assoc :salary "Please fill in currency and time period")))) 15 | 16 | (defn other-visa-status-present? [visa-statuses] 17 | (contains? visa-statuses "Other")) 18 | 19 | (defn initialize-preferred-locations 20 | "we want preferred locations list to be a vector, 21 | without initialization it will become a map because 22 | (= (assoc nil 0 1) {0 1}) but with initialization (= (assoc [] 0 1) [1])" 23 | [preferred-locations] 24 | (if (nil? preferred-locations) 25 | [] 26 | preferred-locations)) 27 | -------------------------------------------------------------------------------- /client/styles/promotions.sass: -------------------------------------------------------------------------------- 1 | @import 'colours' 2 | @import 'button' 3 | @import 'admin_preview' 4 | 5 | .create-promotion 6 | max-width: 674px 7 | &__description 8 | width: 100% 9 | margin-bottom: 24px 10 | &__select-channel 11 | display: flex 12 | align-items: baseline 13 | margin-bottom: 24px 14 | &__title 15 | margin-left: 14px 16 | font-weight: 600 17 | font-size: 18px 18 | line-height: 22px 19 | &--active, &:hover 20 | text-decoration: underline 21 | color: $primary-red 22 | &__send 23 | margin-top: 24px 24 | &__status 25 | color: $primary-red 26 | text-align: center 27 | flex: 1 28 | margin-bottom: 24px 29 | &__button 30 | width: 300px 31 | 32 | .button--promote 33 | &, 34 | // overriding job page buttons styles 35 | \:global(.job__admin-buttons) & 36 | @include button 37 | display: flex 38 | font-size: 11px 39 | text-transform: uppercase 40 | +tablet 41 | font-size: 11px 42 | 43 | .preview 44 | &__promotion 45 | @extend .object 46 | border-top: 2px solid $aquamarine 47 | -------------------------------------------------------------------------------- /common/src/wh/common/blog.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.common.blog 2 | (:require [wh.common.text :as text] 3 | [wh.common.time :as time])) 4 | 5 | (defn translate-blog [blog] 6 | (try 7 | (-> blog 8 | (assoc 9 | :display-date (time/human-time (time/str->time (:creation-date blog) :date-time)))) 10 | (catch #?(:cljs js/Error :clj Exception) _ 11 | (assoc blog :display-date "???")))) 12 | 13 | (defn format-reading-time [blog] 14 | (let [reading-time (max 1 (:reading-time blog))] 15 | (str reading-time " " (text/pluralize reading-time "min")))) 16 | 17 | (defn created-by-company? [blog] 18 | (boolean (:company-id blog))) 19 | 20 | (defn created-by-user? [blog] 21 | (boolean (:author-id blog))) 22 | 23 | ;; 24 | 25 | (defn can-edit? [{:keys [admin? published? creator-id user-id]}] 26 | (or admin? 27 | (and (and creator-id (= creator-id user-id)) 28 | (false? published?)))) 29 | 30 | ;; 31 | 32 | (defn show-unpublished? [{:keys [admin? published? creator-id user-id]}] 33 | (and (false? published?) 34 | (or admin? 35 | (and creator-id (= creator-id user-id))))) 36 | -------------------------------------------------------------------------------- /client/src/workspaces/profile_cards.cljs: -------------------------------------------------------------------------------- 1 | (ns workspaces.profile-cards 2 | (:require [nubank.workspaces.card-types.react :as ct.react] 3 | [nubank.workspaces.core :as ws] 4 | [reagent.core :as r] 5 | [wh.logged-in.profile.components :as components])) 6 | 7 | (ws/defcard stats-grid 8 | (ct.react/react-card 9 | (r/as-element 10 | [:div 11 | {:style {:width "100vw"}} 12 | [components/stats-grid 13 | [components/stat-container 14 | {:title "Title" 15 | :text "Text" 16 | :image "Image" 17 | :key :foo}] 18 | [components/stat-container 19 | {:title "Title" 20 | :text "Text" 21 | :image "Image" 22 | :key :bar}] 23 | [components/stat-container 24 | {:title "Title" 25 | :text [:a {:href "#"} "Link"] 26 | :image "Image" 27 | :key :baz}] 28 | [components/stat-container 29 | {:title "Title" 30 | :text [:a {:href "#"} "Link"] 31 | :image "Image" 32 | :key :qux}]]]))) 33 | 34 | (defonce init (ws/mount)) 35 | -------------------------------------------------------------------------------- /client/src-js/navigation.js: -------------------------------------------------------------------------------- 1 | const mobileMenuId = 'navigation' 2 | const openMenuIconId = 'toggle-button-menu-icon' 3 | const closeMenuIconId = 'toggle-button-close-icon' 4 | 5 | const displayMenu = elmId => { 6 | const elm = document.getElementById(elmId) 7 | elm.style.display = 'flex' 8 | elm.scrollTop = 0 9 | } 10 | const displayIcon = elmId => 11 | (document.getElementById(elmId).style.display = 'inline-flex') 12 | const hide = elmId => (document.getElementById(elmId).style.display = 'none') 13 | const isMenuDisplayed = elmId => 14 | Boolean(document.getElementById(elmId).style.display) && 15 | document.getElementById(elmId).style.display !== 'none' 16 | 17 | function hideMenu() { 18 | hide(mobileMenuId) 19 | hide(closeMenuIconId) 20 | displayIcon(openMenuIconId) 21 | } 22 | 23 | function toggleMenuDisplay() { 24 | if (isMenuDisplayed(mobileMenuId)) { 25 | hideMenu() 26 | } else { 27 | displayMenu(mobileMenuId) 28 | hide(openMenuIconId) 29 | displayIcon(closeMenuIconId) 30 | } 31 | } 32 | 33 | window.toggleMenuDisplay = toggleMenuDisplay 34 | window.hideMenu = hideMenu 35 | -------------------------------------------------------------------------------- /client/resources/public/images/employers/icons/programming.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/vendor/bulma/sass/base/minireset.sass: -------------------------------------------------------------------------------- 1 | /*! minireset.css v0.0.4 | MIT License | github.com/jgthms/minireset.css */ 2 | // Blocks 3 | html, 4 | body, 5 | p, 6 | ol, 7 | ul, 8 | li, 9 | dl, 10 | dt, 11 | dd, 12 | blockquote, 13 | figure, 14 | fieldset, 15 | legend, 16 | textarea, 17 | pre, 18 | iframe, 19 | hr, 20 | h1, 21 | h2, 22 | h3, 23 | h4, 24 | h5, 25 | h6 26 | margin: 0 27 | padding: 0 28 | 29 | // Headings 30 | h1, 31 | h2, 32 | h3, 33 | h4, 34 | h5, 35 | h6 36 | font-size: 100% 37 | font-weight: normal 38 | 39 | // List 40 | ul 41 | list-style: none 42 | 43 | // Form 44 | button, 45 | input, 46 | select, 47 | textarea 48 | margin: 0 49 | 50 | // Box sizing 51 | html 52 | box-sizing: border-box 53 | 54 | * 55 | &, 56 | &::before, 57 | &::after 58 | box-sizing: inherit 59 | 60 | // Media 61 | img, 62 | embed, 63 | iframe, 64 | object, 65 | video 66 | height: auto 67 | max-width: 100% 68 | 69 | audio 70 | max-width: 100% 71 | 72 | // Iframe 73 | iframe 74 | border: 0 75 | 76 | // Table 77 | table 78 | border-collapse: collapse 79 | border-spacing: 0 80 | 81 | td, 82 | th 83 | padding: 0 84 | text-align: left 85 | -------------------------------------------------------------------------------- /client/src/wh/login/github_callback/views.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.github-callback.views 2 | (:require 3 | [wh.components.conversation.views :refer [error-message button]] 4 | [wh.components.icons :refer [icon]] 5 | [wh.login.github-callback.db :as github-callback] 6 | [wh.login.github-callback.subs :as subs] 7 | [wh.login.views :as login-views] 8 | [wh.subs :refer [> (mapv (partial validate-field fields db) (keys fields)) 28 | (remove nil?))) 29 | 30 | (defn invalid-fields 31 | [fields db] 32 | (->> fields 33 | (keys) 34 | (keep #(when-not (field-valid? fields db %) %)) 35 | (not-empty))) 36 | -------------------------------------------------------------------------------- /client/src/wh/login/core.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.core 2 | (:require [cljs.loader :as loader] 3 | [re-frame.core :refer [dispatch dispatch-sync reg-event-db]] 4 | [wh.db :as db] 5 | [wh.login.events :as login-events] 6 | [wh.login.github-callback.events] 7 | [wh.login.github-callback.views :as github-callback] 8 | [wh.login.stackoverflow-callback.events] 9 | [wh.login.stackoverflow-callback.views :as stackoverflow-callback] 10 | [wh.login.twitter-callback.events] 11 | [wh.login.twitter-callback.views :as twitter-callback] 12 | [wh.login.views :as login])) 13 | 14 | (def page-mapping 15 | {:github-callback github-callback/page 16 | :stackoverflow-callback stackoverflow-callback/page 17 | :twitter-callback twitter-callback/page 18 | :login login/page}) 19 | 20 | (reg-event-db 21 | ::initialize-page-mapping 22 | (fn [db _] 23 | (update db ::db/page-mapping merge page-mapping))) 24 | 25 | (dispatch-sync [::login-events/initialize-db]) 26 | (dispatch-sync [::initialize-page-mapping]) 27 | 28 | (loader/set-loaded! :login) 29 | -------------------------------------------------------------------------------- /client/src/wh/messaging/unread_status.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.messaging.unread-status 2 | (:require 3 | [re-frame.core :refer [path reg-event-db reg-event-fx reg-sub]] 4 | [wh.db :as db] 5 | [wh.user.db :as user-db]) 6 | (:require-macros 7 | [wh.graphql-macros :refer [defquery]])) 8 | 9 | ;; event handlers 10 | 11 | (defquery unread-status 12 | {:venia/operation {:operation/type :query 13 | :operation/name "unread_status"} 14 | :venia/queries [[:me [[:conversationsUnreadStatus [:total]]]]]}) 15 | 16 | (reg-event-fx 17 | ::fetch-unread-status 18 | db/default-interceptors 19 | (fn [_ _] 20 | {:graphql {:query unread-status 21 | :on-success [::fetch-unread-status-success]}})) 22 | 23 | (reg-event-db 24 | ::fetch-unread-status-success 25 | db/default-interceptors 26 | (fn [db [resp]] 27 | (assoc-in db [::user-db/sub-db ::user-db/conversations-unread-status] 28 | (get-in resp [:data :me :conversationsUnreadStatus])))) 29 | 30 | ;; subs 31 | 32 | (reg-sub 33 | ::unread-conversations-count 34 | (fn [db _] 35 | (get-in db [::user-db/sub-db ::user-db/conversations-unread-status :total] 0))) 36 | -------------------------------------------------------------------------------- /client/resources/public/images/homepage/logos/two-sigma.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/src/wh/promotions/preview/views.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.promotions.preview.views 2 | (:require [reagent.core :as r] 3 | [wh.promotions.preview.events] 4 | [wh.promotions.preview.subs :as subs] 5 | [wh.re-frame.subs :refer [ 2 | -------------------------------------------------------------------------------- /client/src/wh/login/stackoverflow_callback/views.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.login.stackoverflow-callback.views 2 | (:require 3 | [wh.components.conversation.views :refer [error-message button]] 4 | [wh.components.icons :refer [icon]] 5 | [wh.login.stackoverflow-callback.subs :as subs] 6 | [wh.login.stackoverflow-callback.db :as stackoverflow-callback] 7 | [wh.login.views :as login-views] 8 | [wh.subs :refer [ 2 | -------------------------------------------------------------------------------- /client/src/wh/common/fx/persistent_state.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.common.fx.persistent-state 2 | (:require 3 | [alandipert.storage-atom :as storage] 4 | [cognitect.transit :as transit] 5 | [re-frame.core :refer [reg-cofx reg-fx]]) 6 | (:import 7 | [goog.date UtcDateTime])) 8 | 9 | ;; Enable cljs-time values to be serialized 10 | ;; Adapted from https://github.com/andrewmcveigh/cljs-time/issues/15#issuecomment-173706115 11 | 12 | (def transit-readers 13 | {"m" (transit/read-handler (fn [s] (UtcDateTime.fromTimestamp s)))}) 14 | 15 | (def transit-writers 16 | {UtcDateTime (transit/write-handler 17 | (constantly "m") 18 | (fn [v] (.getTime v)) 19 | (fn [v] (str (.getTime v))))}) 20 | 21 | (swap! storage/transit-read-handlers merge transit-readers) 22 | (swap! storage/transit-write-handlers merge transit-writers) 23 | 24 | (def persistent-state 25 | (storage/local-storage (atom {}) :persistent-state)) 26 | 27 | (reg-fx 28 | :persist-state 29 | (fn [value] 30 | (reset! persistent-state value))) 31 | 32 | (reg-cofx 33 | :persistent-state 34 | (fn [coeffects _] 35 | (assoc coeffects :persistent-state @persistent-state))) 36 | -------------------------------------------------------------------------------- /client/src/wh/promotions/preview/events.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.promotions.preview.events 2 | (:require [wh.blogs.blog.events] 3 | [wh.graphql-cache :refer [reg-query]] 4 | [wh.graphql.company] 5 | [wh.graphql.issues] 6 | [wh.graphql.jobs] 7 | [wh.pages.core :refer [on-page-load]]) 8 | (:require-macros [wh.graphql-macros :refer [defquery]])) 9 | 10 | 11 | (defquery recent-promotions-query 12 | {:venia/operation {:operation/type :query 13 | :operation/name "recent_promotions"} 14 | :venia/queries [[:query_promotions [[:promotions 15 | [:id 16 | :object_type 17 | :object_id 18 | :channel 19 | :start_date 20 | :description]]]]]}) 21 | 22 | (reg-query :recent-promotions recent-promotions-query) 23 | 24 | (defn recent-promotions [_] 25 | [:recent-promotions {}]) 26 | 27 | (defmethod on-page-load :promotions-preview [db] 28 | [(into [:graphql/query] (recent-promotions db))]) 29 | -------------------------------------------------------------------------------- /client/resources/public/images/profile/top_user.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/resources/public/images/profile/repositories.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /common/src/wh/styles/search.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.search) 2 | (def search-page "search__search-page--1Y4bc") 3 | (def results-title "search__results-title--22vNM") 4 | (def tabs "search__tabs--1QrDX") 5 | (def tab "search__tab--2lxDF") 6 | (def tab--active "search__tab--active--5JgwK") 7 | (def results-section "search__results-section--37k_t") 8 | (def results-section__header "search__results-section__header--1t5fX") 9 | (def results-section__header__title "search__results-section__header__title--l9J6B") 10 | (def results-section__header__title__hits "search__results-section__header__title__hits--iznwY") 11 | (def results-section__header__button "search__results-section__header__button--1Vfkw") 12 | (def results-section__content "search__results-section__content--3Wc2S") 13 | (def result-card--skeleton "search__result-card--skeleton--2RGxZ") 14 | (def result-card "search__result-card--37isB") 15 | (def result-card__content "search__result-card__content--36-sL") 16 | (def result-card__img "search__result-card__img--2KRb0") 17 | (def result-card__title "search__result-card__title--2JEeT") 18 | (def result-card__sub-title "search__result-card__sub-title--2hhgR") 19 | (def result-card__description "search__result-card__description--3_TlN") -------------------------------------------------------------------------------- /common-pages/src/wh/notification_settings/subs.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.notification-settings.subs 2 | (:require [re-frame.core :refer [reg-sub]])) 3 | 4 | (reg-sub 5 | ::sub-db 6 | (fn [db _] 7 | (:wh.notification-settings/sub-db db))) 8 | 9 | (reg-sub 10 | ::frequency-options 11 | :<- [::sub-db] 12 | (fn [_sub-db _] 13 | [{:id "disabled" :label "Never"} 14 | {:id "daily" :label "Daily"} 15 | {:id "weekly" :label "Weekly"} 16 | {:id "monthly" :label "Monthly"}])) 17 | 18 | (reg-sub 19 | ::current-value 20 | :<- [::sub-db] 21 | (fn [sub-db _] 22 | (:wh.notification-settings/current-value sub-db))) 23 | 24 | (reg-sub 25 | ::frequency 26 | :<- [::current-value] 27 | (fn [current-value [_ event-type]] 28 | (get-in current-value [event-type :frequency]))) 29 | 30 | (reg-sub 31 | ::user-token 32 | :<- [::sub-db] 33 | (fn [sub-db _] 34 | (:wh.notification-settings/user-token sub-db))) 35 | 36 | (reg-sub 37 | ::updated? 38 | :<- [:wh/query-params] 39 | (fn [query-params _] 40 | (boolean (get query-params "updated")))) 41 | 42 | (reg-sub 43 | ::wrong-arguments? 44 | :<- [:wh/query-params] 45 | (fn [query-params _] 46 | (boolean (get query-params "wrong-arguments")))) 47 | -------------------------------------------------------------------------------- /client/styles/colours.sass: -------------------------------------------------------------------------------- 1 | $primary-red: #ef8374 2 | $primary-red-hover: #cb6052 3 | $highlight-red: #fceae8 4 | $error-red: #c4000f 5 | 6 | $orange: #ffae71 7 | 8 | $white: #fff 9 | 10 | $grey100: #F4F5F8 11 | $grey200: #E8E8E8 12 | $grey250: #cdcdcd 13 | $grey300: #728088 14 | $grey400: #a9b7be 15 | $grey500: #454E54 16 | 17 | $grey-old: #adadad 18 | 19 | $iceberg: #d4f4f2 20 | $iceberg-dark: #1aaea8 21 | $iceberg-light: #DAF3F2 22 | $iceberg-pale: #effffe 23 | 24 | $green100: #80b5bc 25 | 26 | $text-white: $white 27 | $text-black: $grey500 28 | $text-gray: $grey300 29 | 30 | $background-white: $white 31 | $background-overlay: rgba(37, 65, 84, 0.6) 32 | 33 | $border-gray: #eaeaea 34 | $border-red: $primary-red 35 | $twitter-blue: #1da1f2 36 | 37 | $card-shadow-color: rgba(0, 0, 0, .08) 38 | 39 | $skeleton-grey: #ddd 40 | $skeleton-grey-dark: #b7b7b7 41 | 42 | $github-black: #24292e 43 | $twitter-blue: #1da1f2 44 | $stackoverflow-orange: #ef8236 45 | 46 | $aquamarine: #5197B4 47 | $aquamarine-light: #e7f0f2 48 | 49 | $blue: #1976D2 50 | $blue-light: #90CAF9 51 | 52 | // forms 53 | $color-border: $grey400 54 | $color-border-focus: $grey500 55 | $color-form-text: $grey500 56 | 57 | // publisher 58 | $devto: #000 59 | $hashnode: #2962FF 60 | -------------------------------------------------------------------------------- /common/src/wh/styles/attract_card.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.attract-card) 2 | (def attract-card "attract_card__attract-card--3GQdd") 3 | (def intro "attract_card__intro--2ezbQ") 4 | (def intro__branding "attract_card__intro__branding--CMhp_") 5 | (def intro__icon "attract_card__intro__icon--2s5N_") 6 | (def intro__description "attract_card__intro__description--2Snok") 7 | (def intro__vertical-title "attract_card__intro__vertical-title--1kAhP") 8 | (def button "attract_card__button--2rB7-") 9 | (def contribute "attract_card__contribute--2EaEV") 10 | (def contribute--side-column "attract_card__contribute--side-column--2Ge-_") 11 | (def contribute__info "attract_card__contribute__info--b6U5T") 12 | (def contribute__heading "attract_card__contribute__heading--BwTiw") 13 | (def contribute__copy "attract_card__contribute__copy--1uIju") 14 | (def contribute__illustration "attract_card__contribute__illustration--1pjkK") 15 | (def signin "attract_card__signin--1SReL") 16 | (def signin--side-column "attract_card__signin--side-column--1wgMh") 17 | (def signin__buttons "attract_card__signin__buttons--2G9OD") 18 | (def signin__copy "attract_card__signin__copy--2UFCN") 19 | (def signin__heading "attract_card__signin__heading--3ygBE") 20 | (def cards "attract_card__cards--KoupM") -------------------------------------------------------------------------------- /common-pages/src/wh/pages/issue/edit/subs.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.pages.issue.edit.subs 2 | (:require 3 | [re-frame.core :refer [reg-sub]] 4 | [wh.pages.issue.edit.db :as issue-edit])) 5 | 6 | (reg-sub 7 | ::sub-db 8 | (fn [db _] (::issue-edit/sub-db db))) 9 | 10 | (reg-sub 11 | ::current-issue 12 | :<- [::sub-db] 13 | (fn [db _] 14 | (::issue-edit/current-issue db))) 15 | 16 | (reg-sub 17 | ::updating? 18 | :<- [::sub-db] 19 | (fn [db _] 20 | (::issue-edit/updating? db))) 21 | 22 | (reg-sub 23 | ::pending-level 24 | :<- [::sub-db] 25 | :<- [::current-issue] 26 | (fn [[db current-issue] _] 27 | (or (::issue-edit/pending-level db) 28 | (keyword (:level current-issue))))) 29 | 30 | (reg-sub 31 | ::pending-status 32 | :<- [::sub-db] 33 | :<- [::current-issue] 34 | (fn [[db current-issue] _] 35 | (or (::issue-edit/pending-status db) 36 | (keyword (:status current-issue))))) 37 | 38 | (reg-sub 39 | ::pending-compensation 40 | :<- [::sub-db] 41 | :<- [::current-issue] 42 | (fn [[db] _] 43 | (or (::issue-edit/pending-compensation db) 0))) 44 | 45 | (reg-sub 46 | :edit-issue/displayed-dialog 47 | :<- [::sub-db] 48 | (fn [db _] 49 | (::issue-edit/displayed-dialog db))) 50 | 51 | -------------------------------------------------------------------------------- /client/legacy-styles/_highlight_code.sass: -------------------------------------------------------------------------------- 1 | // https://github.com/highlightjs/highlight.js/blob/master/src/styles/atelier-cave-light.css 2 | 3 | .hljs-comment, 4 | .hljs-quote 5 | color: #655f6d 6 | 7 | .hljs-variable, 8 | .hljs-template-variable, 9 | .hljs-attribute, 10 | .hljs-tag, 11 | .hljs-name, 12 | .hljs-regexp, 13 | .hljs-link, 14 | .hljs-name, 15 | .hljs-name, 16 | .hljs-selector-id, 17 | .hljs-selector-class 18 | color: #be4678 19 | 20 | .hljs-number, 21 | .hljs-meta, 22 | .hljs-built_in, 23 | .hljs-builtin-name, 24 | .hljs-literal, 25 | .hljs-type, 26 | .hljs-params 27 | color: #aa573c 28 | 29 | .hljs-string, 30 | .hljs-symbol, 31 | .hljs-bullet 32 | color: #2a9292 33 | 34 | .hljs-title, 35 | .hljs-section 36 | color: #576ddb 37 | 38 | .hljs-keyword, 39 | .hljs-selector-tag 40 | color: #955ae7 41 | 42 | .hljs-deletion, 43 | .hljs-addition 44 | color: #19171c 45 | display: inline-block 46 | width: 100% 47 | 48 | .hljs-deletion 49 | background-color: #be4678 50 | 51 | .hljs-addition 52 | background-color: #2a9292 53 | 54 | .hljs 55 | display: block 56 | overflow-x: auto 57 | background: $code-background 58 | color: #585260 59 | 60 | .hljs-emphasis 61 | font-style: italic 62 | 63 | .hljs-strong 64 | font-weight: bold 65 | -------------------------------------------------------------------------------- /common/src/wh/styles/form.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.styles.form) 2 | (def input "form__input--38yKu") 3 | (def input--textarea "form__input--textarea--A1gVE") 4 | (def input--select "form__input--select--27t3d") 5 | (def input-wrapper--select "form__input-wrapper--select--nTSfw") 6 | (def suggestions__wrapper "form__suggestions__wrapper--2tJ_S") 7 | (def suggestions__search-icon "form__suggestions__search-icon--2EBwy") 8 | (def suggestions__loading "form__suggestions__loading--3wdi7") 9 | (def suggestions__delete-icon "form__suggestions__delete-icon--8zbHH") 10 | (def suggestions__input "form__suggestions__input--378J_") 11 | (def suggestions__suggestions "form__suggestions__suggestions--N_eYx") 12 | (def suggestions__suggestion "form__suggestions__suggestion--2ohwX") 13 | (def label__text "form__label__text--2sTct") 14 | (def avatar "form__avatar--1BUFX") 15 | (def avatar__wrapper "form__avatar__wrapper--1Zb03") 16 | (def avatar__controls-wrapper "form__avatar__controls-wrapper--1x45Y") 17 | (def avatar__controls-wrapper--disabled "form__avatar__controls-wrapper--disabled--3ZxOr") 18 | (def avatar__edit "form__avatar__edit--1ukqS") 19 | (def avatar__edit-icon "form__avatar__edit-icon--1-jVC") 20 | (def avatar__message "form__avatar__message--2z9Sk") 21 | (def error "form__error--3xs2U") -------------------------------------------------------------------------------- /client/src/wh/profile/update_public/db.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.profile.update-public.db 2 | (:require [cljs.spec.alpha :as s] 3 | [clojure.string :as str] 4 | [wh.common.specs.primitives :as specs])) 5 | 6 | (s/def ::id string?) 7 | (s/def ::name string?) 8 | (s/def ::summary string?) 9 | (s/def ::image-url string?) 10 | (s/def ::other-urls (s/keys :req-un [::specs/url])) 11 | (s/def ::editing-profile? boolean?) 12 | (s/def ::submit-attempted? boolean?) 13 | (s/def ::initial-values (s/keys :opt-un [::id ::name ::summary ::image-url ::other-urls])) 14 | (s/def ::sub-db (s/keys :opt-un [::id ::name ::summary ::image-url ::other-urls 15 | ::initial-values ::editing-profile? ::submit-attempted?])) 16 | 17 | (defn form->errors 18 | [form] 19 | (cond-> {} 20 | (str/blank? (:name form)) 21 | (assoc :name "Please fill in your name") 22 | 23 | (->> (:other-urls form) 24 | (map :url) 25 | (remove empty?) 26 | (every? #(s/valid? ::specs/url %)) 27 | not) 28 | (assoc :other-urls "One of the website links is invalid") 29 | 30 | (> (count (:summary form)) 1000) 31 | (assoc :summary "Summary should be less than 1000 symbols"))) -------------------------------------------------------------------------------- /client/src/wh/admin/activities/subs.cljs: -------------------------------------------------------------------------------- 1 | (ns wh.admin.activities.subs 2 | (:require [re-frame.core :refer [reg-sub]] 3 | [wh.re-frame.subs :refer [ activity 9 | (merge 10 | (cond 11 | feed-job {:object feed-job 12 | :object-type "job"} 13 | feed-blog {:object feed-blog 14 | :object-type "article"} 15 | feed-issue {:object feed-issue 16 | :object-type "issue"} 17 | feed-company {:object feed-company 18 | :object-type "company"} 19 | :else {})) 20 | (update-in [:actor :actor-data] util/remove-nils) 21 | (dissoc :feed-job :feed-blog :feed-issue :feed-company))) 22 | 23 | (reg-sub 24 | ::activities 25 | (fn [_ _] 26 | (let [activities (get-in (= (inc @vertical-idx) (count verticals/all-verticals)) 17 | (reset! vertical-idx 0) 18 | (swap! vertical-idx inc))} 19 | [attract/intro (nth (vec verticals/all-verticals) @vertical-idx)]])))) 20 | 21 | (ws/defcard attract-contribute-card 22 | {::wsm/card-width 4::wsm/card-height 8} 23 | (ct.react/react-card 24 | (r/as-element 25 | [attract/contribute false]))) 26 | 27 | (ws/defcard attract-signin-card 28 | {::wsm/card-width 4::wsm/card-height 8} 29 | (ct.react/react-card 30 | (r/as-element 31 | [attract/signin]))) 32 | 33 | (defonce init (ws/mount)) 34 | -------------------------------------------------------------------------------- /client/src-js/trending_content.js: -------------------------------------------------------------------------------- 1 | const sectionId = { 2 | blogs: 'trending-content-blogs', 3 | issues: 'trending-content-issues', 4 | jobs: 'trending-content-jobs', 5 | } 6 | 7 | const displaySection = elmId => (document.getElementById(elmId).style = 'display: grid') 8 | const hideSection = elmId => (document.getElementById(elmId).style = '') 9 | const isSectionDisplayed = elmId => Boolean(document.getElementById(elmId).style.display) 10 | const areAllSectionsHidden = () => 11 | ![sectionId.blogs, sectionId.issues, sectionId.jobs].some(isSectionDisplayed) 12 | const getDisplayedSection = () => 13 | [sectionId.blogs, sectionId.issues, sectionId.jobs].filter(isSectionDisplayed)[0] 14 | 15 | function toggleDisplay(type) { 16 | const sectId = { 17 | blogs: sectionId.blogs, 18 | issues: sectionId.issues, 19 | jobs: sectionId.jobs, 20 | }[type] 21 | 22 | if (areAllSectionsHidden()) { 23 | displaySection(sectId) 24 | } else if (!areAllSectionsHidden() && !isSectionDisplayed(sectId)) { 25 | hideSection(getDisplayedSection()) 26 | displaySection(sectId) 27 | } else if (!areAllSectionsHidden() && isSectionDisplayed(sectId)) { 28 | hideSection(sectId) 29 | } 30 | } 31 | 32 | window.toggleDisplay = toggleDisplay 33 | -------------------------------------------------------------------------------- /client/src/wh/core.cljs: -------------------------------------------------------------------------------- 1 | (ns ^:dev/always wh.core 2 | (:require [cljs.loader :as loader] 3 | [re-frame.core :as re-frame] 4 | [reagent.core :as reagent] 5 | [wh.events] 6 | [wh.pages.core :as pages] 7 | [wh.subs] 8 | [wh.views :as views])) 9 | 10 | (def debug? 11 | ^boolean goog.DEBUG) 12 | 13 | (defn dev-setup [] 14 | (when debug? 15 | (enable-console-print!) 16 | (js/console.log "dev mode"))) 17 | 18 | (defn ^:dev/after-load mount-root [] 19 | (re-frame/clear-subscription-cache!) 20 | (reagent/render [views/main-panel] 21 | (.getElementById js/document "app"))) 22 | 23 | ;;TODO CH4832 figure out why init is called two times on production 24 | ;;for some reason init function is called twice, 25 | ;;we put an atom in order to mitigate this issue" 26 | (defonce init-called? (atom false)) 27 | 28 | ;; NB: This fn is called by `shadow-cljs` (see config). 29 | (defn ^:export init [] 30 | (when (= @init-called? false) 31 | (js/console.log "initializing...") 32 | (pages/hook-browser-navigation!) 33 | (mount-root) 34 | (reset! init-called? true))) 35 | 36 | (dev-setup) 37 | (re-frame/dispatch-sync [:init]) 38 | 39 | (loader/set-loaded! :wh) 40 | (js/console.log "js app loaded") 41 | -------------------------------------------------------------------------------- /client/legacy-styles/_cta_pod.sass: -------------------------------------------------------------------------------- 1 | .cta-pod 2 | display: flex 3 | flex-direction: column 4 | 5 | .cta-pod__title 6 | font-size: 18px 7 | color: $red 8 | font-weight: 700 9 | margin-bottom: 4px 10 | 11 | .cta-pod__subtitle 12 | font-size: 14px 13 | color: $grey-darker 14 | line-height: 18px 15 | font-weight: 600 16 | margin-bottom: 16px 17 | 18 | .cta-pod__img 19 | width: 100px 20 | margin: 0 auto 16px 21 | 22 | .cta-pod__img--company 23 | width: 55% 24 | 25 | .cta-pod__description 26 | font-family: inherit 27 | font-size: 14px 28 | line-height: 20px 29 | margin-bottom: 16px 30 | 31 | .cta-pod__button 32 | font-size: 1rem 33 | padding: 1em 34 | height: auto 35 | text-decoration: none 36 | color: $white 37 | 38 | &:not(:last-of-type) 39 | margin-bottom: 8px 40 | 41 | .cta-pod__content 42 | display: flex 43 | flex-direction: column 44 | 45 | .cta-pod__form 46 | margin-top: -16px 47 | 48 | & input 49 | max-height: 36px 50 | 51 | .field--errored + .cta-pod__button 52 | margin-top: 18px 53 | 54 | .field__error:not(.is-invisible) 55 | margin-top: 12px 56 | 57 | .cta-pod__auth-button 58 | width: 100% 59 | 60 | &:not(:last-of-type) 61 | margin-bottom: 8px 62 | -------------------------------------------------------------------------------- /client/styles/tasks.sass: -------------------------------------------------------------------------------- 1 | @import colours 2 | @import mixins 3 | @import vars 4 | 5 | $tasks-width: 380px 6 | $tasks-width-mobile: 320px 7 | $icon-size: 20px 8 | 9 | .title 10 | font-size: 14px 11 | line-height: 18px 12 | font-weight: 600 13 | letter-spacing: 0.02em 14 | color: $text-black 15 | 16 | .subtitle 17 | font-size: 14px 18 | line-height: 18px 19 | color: $grey500 20 | 21 | .task 22 | background-color: $white 23 | display: grid 24 | padding: 12px 12px 12px 48px 25 | grid-gap: 6px 26 | border-radius: 4px 27 | position: relative 28 | 29 | &__icon 30 | position: absolute 31 | top: calc(50% - 10px) 32 | left: 12px 33 | width: $icon-size 34 | height: $icon-size 35 | fill: $grey500 36 | color: $grey500 37 | 38 | .header 39 | font-size: 16px 40 | line-height: 46px 41 | font-weight: 700 42 | color: $white 43 | padding-left: 6px 44 | 45 | .tasks 46 | display: grid 47 | grid-gap: 6px 48 | 49 | &__wrapper 50 | background-color: $green100 51 | border-radius: 8px 52 | padding: 0 8px 8px 53 | 54 | .content 55 | left: 0 56 | position: absolute 57 | width: $tasks-width-mobile 58 | top: $navbar-dropdown-starts-at 59 | transform: translateX(-50vw) 60 | +tablet 61 | transform: translateX(-45%) 62 | width: $tasks-width 63 | -------------------------------------------------------------------------------- /client/styles/button.sass: -------------------------------------------------------------------------------- 1 | @import 'colours' 2 | @import 'text' 3 | @import 'vars' 4 | @import 'mixins' 5 | 6 | @mixin button 7 | border-radius: 4px 8 | height: 40px 9 | align-items: center 10 | display: flex 11 | justify-content: center 12 | background: $primary-red 13 | border: 1px solid $border-red 14 | box-sizing: border-box 15 | color: $text-white 16 | padding: 0 20px 17 | 18 | font-family: $font-family 19 | font-size: 12px 20 | white-space: nowrap 21 | font-weight: 600 22 | letter-spacing: 0.02em 23 | line-height: 135% 24 | text-transform: capitalize 25 | 26 | +tablet 27 | font-size: 13px 28 | padding: 0 40px 29 | 30 | &:hover 31 | background: $highlight-red 32 | color: $primary-red 33 | cursor: pointer 34 | &--inverted, 35 | &--inverted-highlighted 36 | background: transparent 37 | border: none 38 | color: $primary-red 39 | padding: 0 20px 40 | &--inverted-highlighted 41 | border: 1px solid $border-red 42 | &--short 43 | padding: 0 40px 44 | 45 | &--disabled, 46 | &:disabled 47 | opacity: 0.3 48 | cursor: not-allowed 49 | 50 | &--dark 51 | border: 1px solid transparent 52 | color: $text-white 53 | background: $grey500 54 | 55 | &:hover 56 | background: $grey300 57 | color: $text-white 58 | -------------------------------------------------------------------------------- /common-pages/src/wh/issues/manage/db.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.issues.manage.db 2 | (:require 3 | #?(:clj [clojure.spec.alpha :as s] 4 | :cljs [cljs.spec.alpha :as s]))) 5 | 6 | (s/def ::loading? boolean?) 7 | (s/def ::repo-tuple (s/keys :req-un [:wh.repo/owner 8 | :wh.repo/name])) 9 | 10 | (s/def ::repo-syncs (s/map-of ::repo-tuple (s/keys :req-un [:wh.repo.sync/id 11 | :wh.repo.sync/total-issue-count 12 | :wh.repo.sync/time-started] 13 | :opt-un [:wh.repo.sync/running-issue-count 14 | :wh.repo.sync/time-updated]))) 15 | 16 | #?(:cljs (s/def ::sub-db 17 | (s/keys :req [::issues 18 | ::loading? 19 | ::repo-syncs] 20 | :opt [::company]))) 21 | 22 | (defn default-db 23 | [db] 24 | (merge {::loading? false 25 | ::syncing-repos? false 26 | ::pending #{} 27 | ::orgs [] 28 | ::fetched-repos #{} 29 | ::syncing-issues false 30 | ::issues {} 31 | ::repo-syncs {}} 32 | db)) 33 | -------------------------------------------------------------------------------- /client/src/workspaces/iconset_cards.cljs: -------------------------------------------------------------------------------- 1 | (ns workspaces.iconset-cards 2 | (:require [nubank.workspaces.card-types.react :as ct.react] 3 | [nubank.workspaces.core :as ws] 4 | [nubank.workspaces.model :as wsm] 5 | [reagent.core :as r] 6 | [wh.components.icons :as icons] 7 | [wh.styles.iconsset :as style])) 8 | 9 | (defn get-icons [] 10 | (->> (array-seq (js/document.querySelectorAll ".svg-container")) 11 | (map (fn [elm] (. elm -innerHTML))) 12 | (apply str) 13 | (re-seq #"symbol id=\"(.+?)\"\s") 14 | (map second))) 15 | 16 | (defn all-icons [] 17 | (let [icon-names (r/atom [])] 18 | (r/create-class 19 | {:component-did-mount (fn [] (reset! icon-names (get-icons))) 20 | :reagent-render (fn [] 21 | [:div {:class style/page} 22 | (for [icon-name @icon-names] 23 | [:div {:class style/icon__wrapper} 24 | [icons/icon icon-name :class style/icon] 25 | [:span icon-name]])])}))) 26 | 27 | (ws/defcard all-icons 28 | {::wsm/card-width 12 29 | ::wsm/card-height 20} 30 | (ct.react/react-card 31 | (r/as-element [all-icons]))) 32 | 33 | (defonce init (ws/mount)) 34 | -------------------------------------------------------------------------------- /common/src/wh/components/pods/candidates.cljc: -------------------------------------------------------------------------------- 1 | (ns wh.components.pods.candidates 2 | (:require 3 | [wh.components.button-auth :as button-auth] 4 | [wh.components.common :refer [link]] 5 | [wh.components.icons :refer [icon]] 6 | [wh.re-frame.subs :refer [