|
1 | | -export default function decorate(block) { |
2 | | - const jobList = document.createElement('div'); |
3 | | - jobList.classList.add('job-list', 'grid-container'); |
| 1 | +import { dataStore } from "../../scripts/helpers/index.js"; |
4 | 2 |
|
5 | | - const [headingRow, ...jobRows] = [...block.children]; |
| 3 | +const DEFAULT_CONTENT = { |
| 4 | + noJobs: "There are no jobs currently available." |
| 5 | +}; |
6 | 6 |
|
7 | | - const heading = headingRow.children?.[0]?.children?.[0]; |
8 | | - if (heading) { |
9 | | - heading.classList.add('job-list__heading', 'util-heading-s', 'grid-item', 'grid-item--33'); |
10 | | - heading.textContent = headingRow.textContent; |
11 | | - jobList.append(heading); |
12 | | - } |
| 7 | +const HEADING_LEVEL = "h3"; |
13 | 8 |
|
14 | | - const jobListings = document.createElement('div'); |
15 | | - jobListings.className = 'job-list__listings grid-item grid-item--66'; |
| 9 | +/** |
| 10 | + * Display a list of jobs, under heading(s) for each discipline. |
| 11 | + * |
| 12 | + * Jobs are dynamically listed using query-index data pulled from the careers directory. |
| 13 | + * The list of disciplines is entered in the content to allow for manual ordering. |
| 14 | + * |
| 15 | + * @param {Element} block |
| 16 | + */ |
| 17 | +export default function decorate(block) { |
| 18 | + /** |
| 19 | + * Discipline headings from each row of content. |
| 20 | + * @type {string[]} |
| 21 | + */ |
| 22 | + const headings = [...block.children].map((el) => el.textContent.trim()).filter(Boolean); |
16 | 23 |
|
17 | | - jobRows.forEach(row => { |
18 | | - const [title, subheading, detail, jobId] = row.children; |
| 24 | + // Create container. |
| 25 | + const blockContainer = document.createElement('div'); |
| 26 | + blockContainer.classList.add('job-list-block'); |
| 27 | + blockContainer.textContent = ""; |
19 | 28 |
|
20 | | - const jobListing = document.createElement('a'); |
21 | | - jobListing.className = 'job-listing'; |
| 29 | + // Replace wrapper div parent with new block. |
| 30 | + block?.parentElement?.classList?.length === 0 ? block.parentElement.replaceWith(blockContainer) : block.replaceWith(blockContainer); |
22 | 31 |
|
23 | | - const contentWrapper = document.createElement('span'); |
24 | | - contentWrapper.className = 'job-listing__content'; |
| 32 | + // Fetch the dynamic job data async, create markup, and append to the container. |
| 33 | + (async () => { |
| 34 | + // Get jobs data from endpoint. |
| 35 | + const jobsData = await dataStore.getData(dataStore.commonEndpoints.careers); |
25 | 36 |
|
26 | | - if (title) { |
27 | | - const titleEl = document.createElement('span'); |
28 | | - titleEl.className = 'job-listing__title'; |
29 | | - titleEl.textContent = title.textContent; |
30 | | - contentWrapper.append(titleEl); |
31 | | - } |
| 37 | + // Filter only the ones with disciplines that are displayed. |
| 38 | + const allJobsForDisplay = jobsData?.data?.length |
| 39 | + ? jobsData.data.filter(job => job?.jobDiscipline && headings.includes(job.jobDiscipline)) |
| 40 | + : []; |
32 | 41 |
|
33 | | - if (subheading) { |
34 | | - const subheadingEl = document.createElement('span'); |
35 | | - subheadingEl.className = 'job-listing__subheading'; |
36 | | - subheadingEl.textContent = subheading.textContent; |
37 | | - contentWrapper.append(subheadingEl); |
| 42 | + // If no jobs, display null state message. |
| 43 | + if (!allJobsForDisplay.length) { |
| 44 | + blockContainer.classList.remove('grid-container'); |
| 45 | + const message = document.createElement('p'); |
| 46 | + message.textContent = DEFAULT_CONTENT.noJobs; |
| 47 | + blockContainer.append(message); |
| 48 | + return; |
38 | 49 | } |
39 | 50 |
|
40 | | - if (detail) { |
41 | | - const detailEl = document.createElement('span'); |
42 | | - detailEl.className = 'job-listing__detail'; |
43 | | - detailEl.textContent = detail.textContent; |
44 | | - contentWrapper.append(detailEl); |
45 | | - } |
| 51 | + // Newly created elements that will be appended to blockContainer when finished. |
| 52 | + const allJobMarkup = document.createDocumentFragment(); |
46 | 53 |
|
47 | | - jobListing.append(contentWrapper); |
| 54 | + // Loop through each discipline. |
| 55 | + headings.forEach(heading => { |
| 56 | + /** |
| 57 | + * Jobs with this discipline in metadata |
| 58 | + * @type {object[]} |
| 59 | + */ |
| 60 | + const jobs = jobsData?.data?.filter(job => job?.jobDiscipline == heading) ?? []; |
| 61 | + if (!jobs.length) { return; } |
48 | 62 |
|
49 | | - if (jobId) { |
50 | | - jobListing.href = `https://adobe.design/jobs/job-posts/${jobId.textContent.trim()}`; |
51 | | - } |
| 63 | + // Container with heading and job list. |
| 64 | + const jobGrouping = document.createElement('div'); |
| 65 | + jobGrouping.classList.add('job-list','grid-container'); |
52 | 66 |
|
53 | | - jobListings.append(jobListing); |
54 | | - }); |
| 67 | + // Heading element. |
| 68 | + const headingElement = document.createElement(HEADING_LEVEL); |
| 69 | + headingElement.classList.add('job-list__heading', 'util-heading-s', 'grid-item', 'grid-item--33'); |
| 70 | + headingElement.textContent = heading; |
55 | 71 |
|
56 | | - jobList.append(jobListings); |
57 | | - block.textContent = ''; |
| 72 | + // Job list under this heading. |
| 73 | + const jobsListingsWrap = document.createElement('ul'); |
| 74 | + jobsListingsWrap.classList.add('job-list__listings', 'grid-item', 'grid-item--66'); |
58 | 75 |
|
59 | | - // Replace wrapper div parent with new block. |
60 | | - block?.parentElement?.classList?.length === 0 ? block.parentElement.replaceWith(jobList) : block.replaceWith(jobList);; |
| 76 | + // Display each job (using "job-listing" component styles). |
| 77 | + jobs.forEach(row => { |
| 78 | + const {jobTitle, department, location, path} = row; |
| 79 | + |
| 80 | + const jobListItem = document.createElement('li'); |
| 81 | + const jobItem = document.createElement('a'); |
| 82 | + jobItem.classList.add('job-listing'); |
| 83 | + jobListItem.append(jobItem); |
| 84 | + |
| 85 | + // Link to job page. |
| 86 | + if (path) { |
| 87 | + jobItem.href = path.trim(); |
| 88 | + } |
| 89 | + |
| 90 | + const contentWrapper = document.createElement('span'); |
| 91 | + contentWrapper.classList.add('job-listing__content'); |
| 92 | + jobItem.append(contentWrapper); |
| 93 | + |
| 94 | + if (jobTitle) { |
| 95 | + const titleEl = document.createElement('span'); |
| 96 | + titleEl.classList.add('job-listing__title'); |
| 97 | + titleEl.textContent = jobTitle.trim(); |
| 98 | + contentWrapper.append(titleEl); |
| 99 | + } |
| 100 | + |
| 101 | + if (department) { |
| 102 | + const subheadingEl = document.createElement('span'); |
| 103 | + subheadingEl.classList.add('job-listing__subheading'); |
| 104 | + subheadingEl.textContent = department.trim(); |
| 105 | + contentWrapper.append(subheadingEl); |
| 106 | + } |
| 107 | + |
| 108 | + if (location) { |
| 109 | + const detailEl = document.createElement('span'); |
| 110 | + detailEl.classList.add('job-listing__detail'); |
| 111 | + detailEl.textContent = location.trim(); |
| 112 | + contentWrapper.append(detailEl); |
| 113 | + } |
| 114 | + |
| 115 | + // Append job. |
| 116 | + jobsListingsWrap.append(jobListItem); |
| 117 | + }); |
| 118 | + |
| 119 | + // Append grouping with heading and its jobs. |
| 120 | + jobGrouping.append(headingElement, jobsListingsWrap); |
| 121 | + allJobMarkup.append(jobGrouping); |
| 122 | + }); |
| 123 | + |
| 124 | + // Append all new elements to the main block container. |
| 125 | + blockContainer.append(allJobMarkup); |
| 126 | + })(); |
61 | 127 | } |
0 commit comments