From ac06e47130645606b7bdc527af56df4348281cb9 Mon Sep 17 00:00:00 2001 From: "R. Tyler Croy" Date: Sat, 23 Nov 2019 12:39:35 -0800 Subject: [PATCH] Dynamically incorporate Lever jobs on the home page and on blog pages for teams I think this should be fairly straightforward to style up and make pretty. Fixes #3 --- _data/teams.yml | 13 ++ _includes/js.html | 1 + _layouts/home.html | 57 ++++---- _layouts/post.html | 13 ++ ...7-calculating-customer-lifetime-revenue.md | 2 +- _posts/2019-03-04-experiments-with-seq2seq.md | 2 +- assets/js/jobs.js | 123 ++++++++++++++++++ 7 files changed, 176 insertions(+), 35 deletions(-) create mode 100644 _data/teams.yml create mode 100644 assets/js/jobs.js diff --git a/_data/teams.yml b/_data/teams.yml new file mode 100644 index 0000000..73ff96e --- /dev/null +++ b/_data/teams.yml @@ -0,0 +1,13 @@ +# +# This data file has some metadata about the teams and is a critical part of +# plumbing jobs into team's blog posts +--- +ios: + # the category in Lever + lever: 'iOS' + +android: + lever: 'Android' + +datascience: + lever: 'Data Science - San Francisco' diff --git a/_includes/js.html b/_includes/js.html index 2d4eee5..5653661 100644 --- a/_includes/js.html +++ b/_includes/js.html @@ -1 +1,2 @@ + diff --git a/_layouts/home.html b/_layouts/home.html index 30cf2d0..9bb1168 100644 --- a/_layouts/home.html +++ b/_layouts/home.html @@ -25,41 +25,32 @@ layout: default
-
diff --git a/_layouts/post.html b/_layouts/post.html index 1e97edc..2bc49e2 100644 --- a/_layouts/post.html +++ b/_layouts/post.html @@ -18,9 +18,22 @@ layout: default

+ +
{{ content }}
+ +{%- if page.team and site.data.teams[page.team] -%} + +{%- endif -%} diff --git a/_posts/2019-02-07-calculating-customer-lifetime-revenue.md b/_posts/2019-02-07-calculating-customer-lifetime-revenue.md index 7306a56..5989c3a 100644 --- a/_posts/2019-02-07-calculating-customer-lifetime-revenue.md +++ b/_posts/2019-02-07-calculating-customer-lifetime-revenue.md @@ -4,7 +4,7 @@ title: Calculating Customer Lifetime Revenue author: bclearly tags: - ltv -team: data-science +team: datascience --- Why LTR? (Lifetime Revenue) diff --git a/_posts/2019-03-04-experiments-with-seq2seq.md b/_posts/2019-03-04-experiments-with-seq2seq.md index 613910a..a9816c0 100644 --- a/_posts/2019-03-04-experiments-with-seq2seq.md +++ b/_posts/2019-03-04-experiments-with-seq2seq.md @@ -5,7 +5,7 @@ author: siweiz tags: - machinelearning - deeplearning -team: data-science +team: datascience --- How much data do you need to train a seq2seq model? Let’s say that you want to translate sentences from one language to another. You probably need a bigger dataset to translate longer sentences than if you wanted to translate shorter ones. How does the need for data grow as the sentence length increases? diff --git a/assets/js/jobs.js b/assets/js/jobs.js new file mode 100644 index 0000000..0051c33 --- /dev/null +++ b/assets/js/jobs.js @@ -0,0 +1,123 @@ +/* + * This JavaScript file was hand-crafted by a developer who doesn't normally + * write JavaScript and should not be considered indicative of how Scribd's + * proper web engineers write JavaScript. + * + * With that disclaimer out of the way... + * + * This file handles the fetching of jobs from Lever such that they can be + * dynamically inserted into different parts of the tech blog + */ + +/* + * This API will return an list of departments which must then be filtered + * through to find the .postings under each + */ +const API_URL = 'https://api.lever.co/v0/postings/scribd?group=department&mode=json' + + +/* + * Everybody loves globals, this will make sure we don't hit the API more than + * we need to. + */ +window.jobsCache = {}; +window.jobsFetched = false; + + +/** + * Fetch the jobs from the Lever API and cache them into a page-wide global + * + * This will always return a Promise, even when the cache is hit + */ +function fetchJobs() { + if (window.jobsFetched) { + // Whoa there cowboy, only hit their API once per page + return Promise.resolve(window.jobsCache); + } + + return fetch(API_URL) + .then(async (response) => { + const departments = await response.json(); + /* + * Since this is the tech blog, we're only pulling a couple of + * departments + */ + departments + .filter(d => ['Engineering', 'Data Science', 'Design'].includes(d.title)) + .forEach((department) => { + department.postings.forEach((posting) => { + const team = posting.categories.team; + if (!window.jobsCache[team]) { + window.jobsCache[team] = []; + } + window.jobsCache[team].push(posting); + }); + }); + window.jobsFetched = true; + return window.jobsCache; + }) + .catch((err) => { + console.error(`Failed to fetch the jobs from Lever, ruh roh ${err}`); + }); +} + + +/** + * Render the available jobs into the given element + * + * team is an optional parameter and will filter the results to just that team. + * Send null to receive all engineering jobs + * + * Use the randomLimit parameter to receive a random slice of the jobs limited + * to the number passed through + */ +function renderJobs(elem, team, randomLimit) { + if (!elem) { + console.error("Cannot renderJobs() to an empty element"); + return; + } + + fetchJobs().then((jobs) => { + let toRender = (team ? jobs[team] : Object.values(jobs).flat()); + + /* + * Sometimes we won't have any jobs for a team + */ + if (!toRender) { + return; + } + + if (randomLimit) { + shuffleArray(toRender); + toRender = toRender.slice(0, randomLimit); + } + + toRender.forEach((job) => { + const li = document.createElement('li'); + li.className = 'card theme-midnight'; + li.innerHTML = ` +
+
+ ${job.text} +
+

${job.categories.location}

+
+`; + elem.appendChild(li); + }); + + + }); +} + + +/* + * Nice shuffle method courtesy of https://stackoverflow.com/a/12646864 + */ +function shuffleArray(array) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } +} +