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
+
+{%- 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 = `
+