├── .gitignore ├── frontend ├── src │ ├── img │ │ ├── business.jpg │ │ └── 45.svg │ ├── app.js │ ├── templates.js │ ├── utils.js │ ├── scss │ │ └── app.scss │ └── JobSearch.js ├── package.json ├── .cache │ ├── 14 │ │ └── 4a9a7180a17ec674ebdbc158ad5ce6.json │ ├── 94 │ │ └── b4209ada9b3069fbf5fb0c811b446c.json │ ├── c3 │ │ └── 395c7d7428ec73498eb7e0798ccd7a.json │ ├── 0e │ │ └── 9ed2ee4108341553c6c33d91d5cce7.json │ ├── 9b │ │ └── 3966e0131e408256dff65fff8c9b07.json │ └── d3 │ │ └── d633b5f1caf367b2188ffb60a62787.json ├── index.html └── dist │ ├── index.html │ ├── app.a6a4d504.js.map │ └── app.a6a4d504.js └── api ├── config.js ├── package.json ├── server.js └── package-lock.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .cache 4 | dist 5 | -------------------------------------------------------------------------------- /frontend/src/img/business.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebubb/job-search-app/HEAD/frontend/src/img/business.jpg -------------------------------------------------------------------------------- /frontend/src/app.js: -------------------------------------------------------------------------------- 1 | import { JobSearch } from './JobSearch'; 2 | 3 | const jobSearch = new JobSearch('#search-form', '.result-container', '.loading-element'); 4 | jobSearch.setCountryCode(); 5 | jobSearch.configureFormListener(); 6 | -------------------------------------------------------------------------------- /api/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | APP_ID: process.env.APP_ID, 3 | API_KEY: process.env.API_KEY, 4 | BASE_URL: 'https://api.adzuna.com/v1/api/jobs', 5 | BASE_PARAMS: 'search/1?&results_per_page=20&content-type=application/json', 6 | }; 7 | -------------------------------------------------------------------------------- /api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "job-search", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.19.0", 14 | "chalk": "^2.4.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/templates.js: -------------------------------------------------------------------------------- 1 | export const jobTemplate = (job, currency) => ` 2 |
3 |
4 |

${job.title} up to ${currency}${job.salary_max}

5 |
${job.location.display_name}
6 |

${job.description}

7 | View Job 8 |
9 |
10 | `; -------------------------------------------------------------------------------- /frontend/src/utils.js: -------------------------------------------------------------------------------- 1 | export const extractFormData = form => Array 2 | .from(form.elements) 3 | .reduce((acc, { id, value }) => ({ [id]: value, ...acc }), {}); 4 | 5 | export const getCurrencySymbol = country => { 6 | const currencies = { 7 | gb: '£', 8 | us: '$', 9 | au: '$', 10 | ca: '$', 11 | }; 12 | return currencies[country]; 13 | } -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "node ./node_modules/parcel/bin/cli index.html", 8 | "build": "node ./node_modules/parcel/bin/cli build index.html" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "parcel": "^1.12.3" 15 | }, 16 | "devDependencies": { 17 | "sass": "^1.22.12" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /frontend/src/scss/app.scss: -------------------------------------------------------------------------------- 1 | header { 2 | padding: 50px; 3 | background-image: url(../img/business.jpg); 4 | background-repeat: no-repeat; 5 | height: 400px; 6 | 7 | h2 { 8 | font-size: 1.2rem; 9 | } 10 | 11 | form { 12 | margin-top: 50px; 13 | max-width: 400px; 14 | } 15 | } 16 | 17 | .card { 18 | margin: 25px 0; 19 | } 20 | 21 | .loading-element { 22 | width: 100px; 23 | height: 100px; 24 | margin: 0 auto; 25 | display: none; 26 | &.loading { 27 | display: block; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /frontend/src/img/45.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/.cache/c3/395c7d7428ec73498eb7e0798ccd7a.json: -------------------------------------------------------------------------------- 1 | {"id":"index.html","dependencies":[{"name":"./src/app.js","dynamic":true,"resolved":"/home/bubb/dev/job-search/frontend/src/app.js","parent":"/home/bubb/dev/job-search/frontend/index.html"}],"generated":{"html":"\n\n\n \n \n \n Job Search\n\n\n
\n \n \n \n
\n
\n \n\n"},"sourceMaps":null,"error":null,"hash":"8beeb98c67be1d565a9a0c3bcefb8bed","cacheData":{}} -------------------------------------------------------------------------------- /frontend/.cache/94/b4209ada9b3069fbf5fb0c811b446c.json: -------------------------------------------------------------------------------- 1 | {"id":"src/app.js","dependencies":[{"name":"/home/bubb/dev/job-search/frontend/package.json","includedInParent":true,"mtime":1568645081763},{"name":"./JobSearch","loc":{"line":1,"column":26},"parent":"/home/bubb/dev/job-search/frontend/src/app.js","resolved":"/home/bubb/dev/job-search/frontend/src/JobSearch.js"}],"generated":{"js":"\"use strict\";\n\nvar _JobSearch = require(\"./JobSearch\");\n\nnew _JobSearch.JobSearch();"},"sourceMaps":{"js":{"mappings":[{"generated":{"line":3,"column":0},"source":"src/app.js","original":{"line":1,"column":0}},{"generated":{"line":5,"column":0},"source":"src/app.js","original":{"line":3,"column":0}},{"name":"JobSearch","generated":{"line":5,"column":4},"source":"src/app.js","original":{"line":3,"column":4}},{"generated":{"line":5,"column":24},"source":"src/app.js","original":{"line":3,"column":0}}],"sources":{"src/app.js":"import { JobSearch } from './JobSearch';\n\nnew JobSearch();"},"lineCount":null}},"error":null,"hash":"4cc5b2f780be11202df45020dae8adea","cacheData":{"env":{}}} -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Job Search 10 | 11 | 12 |
13 |
14 |

Job Search App

15 |

Find your perfect job today!

16 |
17 | 18 | 19 | 20 |
21 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /frontend/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Job Search 10 | 11 | 12 |
13 |
14 |

Job Search App

15 |

Find your perfect job today!

16 |
17 | 18 | 19 | 20 |
21 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /api/server.js: -------------------------------------------------------------------------------- 1 | const createServer = require('http').createServer; 2 | const url = require('url'); 3 | const axios = require('axios'); 4 | const chalk = require('chalk'); 5 | const config = require('./config'); 6 | 7 | const headers = { 8 | 'Content-Type': 'application/json', 9 | 'Access-Control-Allow-Origin': '*', 10 | 'Access-Control-Allow-Methods': 'GET', 11 | }; 12 | 13 | const server = createServer((req, res) => { 14 | const requestURL = url.parse(req.url); 15 | const decodedParams = decodeParams(new URLSearchParams(requestURL.search)); 16 | const { search, location, country = 'gb' } = decodedParams; 17 | 18 | const targetURL = `${config.BASE_URL}/${country.toLowerCase()}/${config.BASE_PARAMS}&app_id=${config.APP_ID}&app_key=${config.API_KEY}&what=${search}&where=${location}`; 19 | if (req.method === 'GET') { 20 | console.log(chalk.green(`Proxy GET request to : ${targetURL}`)); 21 | axios.get(targetURL) 22 | .then(response => { 23 | res.writeHead(200, headers); 24 | res.end(JSON.stringify(response.data)); 25 | }) 26 | .catch(response => { 27 | console.log(chalk.red(response)); 28 | res.writeHead(500, headers); 29 | res.end(JSON.stringify(response)); 30 | }); 31 | } 32 | }); 33 | 34 | 35 | server.listen(3000, () => { 36 | console.log(chalk.green('Server listening')); 37 | } ); 38 | 39 | 40 | const decodeParams = searchParams => Array 41 | .from(searchParams.keys()) 42 | .reduce((acc, key) => ({ ...acc, [key]: searchParams.get(key) }), {}); -------------------------------------------------------------------------------- /frontend/src/JobSearch.js: -------------------------------------------------------------------------------- 1 | import { jobTemplate } from './templates'; 2 | import { extractFormData, getCurrencySymbol } from './utils'; 3 | 4 | 5 | export class JobSearch { 6 | 7 | constructor(searchFormSelector, resultsContainerSelector, loadingElementSelector) { 8 | this.searchForm = document.querySelector(searchFormSelector); 9 | this.resultsContainer = document.querySelector(resultsContainerSelector); 10 | this.loadingElement = document.querySelector(loadingElementSelector); 11 | } 12 | 13 | setCountryCode() { 14 | this.countryCode = 'gb'; 15 | this.setCurrencySymbol(); 16 | 17 | fetch('http://ip-api.com/json') 18 | .then(results => results.json()) 19 | .then(results => { 20 | this.countryCode = results.countryCode.toLowerCase(); 21 | this.setCurrencySymbol(); 22 | }); 23 | } 24 | 25 | setCurrencySymbol() { 26 | this.currencySymbol = getCurrencySymbol(this.countryCode); 27 | } 28 | 29 | configureFormListener() { 30 | this.searchForm.addEventListener('submit', (event) => { 31 | event.preventDefault(); 32 | this.startLoading(); 33 | this.resultsContainer.innerHTML = ''; 34 | const { search, location } = extractFormData(this.searchForm); 35 | fetch(`http://localhost:3000/?search=${search}&location=${location}&country=${this.countryCode}`) 36 | .then(response => response.json()) 37 | .then(({ results }) => { 38 | this.stopLoading(); 39 | return results 40 | .map(job => jobTemplate(job, this.currencySymbol)) 41 | .join(''); 42 | }) 43 | .then(jobs => this.resultsContainer.innerHTML = jobs) 44 | .catch(() => this.stopLoading()); 45 | }); 46 | } 47 | 48 | startLoading() { 49 | this.loadingElement.classList.add('loading'); 50 | } 51 | 52 | stopLoading() { 53 | this.loadingElement.classList.remove('loading'); 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /frontend/.cache/0e/9ed2ee4108341553c6c33d91d5cce7.json: -------------------------------------------------------------------------------- 1 | {"id":"src/templates.js","dependencies":[{"name":"/home/bubb/dev/job-search/frontend/package.json","includedInParent":true,"mtime":1568645081763}],"generated":{"js":"\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.jobTemplate = void 0;\n\nvar jobTemplate = function jobTemplate(job) {\n return \"\\n

\".concat(job.title, \"

\\n\");\n};\n\nexports.jobTemplate = jobTemplate;"},"sourceMaps":{"js":{"mappings":[{"generated":{"line":8,"column":0},"source":"src/templates.js","original":{"line":1,"column":7}},{"name":"jobTemplate","generated":{"line":8,"column":4},"source":"src/templates.js","original":{"line":1,"column":13}},{"generated":{"line":8,"column":15},"source":"src/templates.js","original":{"line":1,"column":24}},{"generated":{"line":8,"column":18},"source":"src/templates.js","original":{"line":1,"column":27}},{"name":"jobTemplate","generated":{"line":8,"column":27},"source":"src/templates.js","original":{"line":1,"column":13}},{"generated":{"line":8,"column":38},"source":"src/templates.js","original":{"line":1,"column":27}},{"name":"job","generated":{"line":8,"column":39},"source":"src/templates.js","original":{"line":1,"column":27}},{"generated":{"line":8,"column":42},"source":"src/templates.js","original":{"line":1,"column":30}},{"generated":{"line":9,"column":0},"source":"src/templates.js","original":{"line":1,"column":30}},{"name":"job","generated":{"line":9,"column":27},"source":"src/templates.js","original":{"line":2,"column":8}},{"generated":{"line":9,"column":30},"source":"src/templates.js","original":{"line":2,"column":11}},{"name":"title","generated":{"line":9,"column":31},"source":"src/templates.js","original":{"line":2,"column":12}},{"generated":{"line":9,"column":36},"source":"src/templates.js","original":{"line":1,"column":30}},{"generated":{"line":10,"column":0},"source":"src/templates.js","original":{"line":1,"column":30}},{"generated":{"line":10,"column":1},"source":"src/templates.js","original":{"line":1,"column":7}}],"sources":{"src/templates.js":"export const jobTemplate = job => `\n

${job.title}

\n`;"},"lineCount":null}},"error":null,"hash":"cace8e648554db110569dfb16af140b3","cacheData":{"env":{}}} -------------------------------------------------------------------------------- /api/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "job-search", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ansi-styles": { 8 | "version": "3.2.1", 9 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 10 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 11 | "requires": { 12 | "color-convert": "^1.9.0" 13 | } 14 | }, 15 | "axios": { 16 | "version": "0.19.0", 17 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", 18 | "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", 19 | "requires": { 20 | "follow-redirects": "1.5.10", 21 | "is-buffer": "^2.0.2" 22 | } 23 | }, 24 | "chalk": { 25 | "version": "2.4.2", 26 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 27 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 28 | "requires": { 29 | "ansi-styles": "^3.2.1", 30 | "escape-string-regexp": "^1.0.5", 31 | "supports-color": "^5.3.0" 32 | } 33 | }, 34 | "color-convert": { 35 | "version": "1.9.3", 36 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 37 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 38 | "requires": { 39 | "color-name": "1.1.3" 40 | } 41 | }, 42 | "color-name": { 43 | "version": "1.1.3", 44 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 45 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 46 | }, 47 | "debug": { 48 | "version": "3.1.0", 49 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 50 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 51 | "requires": { 52 | "ms": "2.0.0" 53 | } 54 | }, 55 | "escape-string-regexp": { 56 | "version": "1.0.5", 57 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 58 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 59 | }, 60 | "follow-redirects": { 61 | "version": "1.5.10", 62 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", 63 | "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", 64 | "requires": { 65 | "debug": "=3.1.0" 66 | } 67 | }, 68 | "has-flag": { 69 | "version": "3.0.0", 70 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 71 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 72 | }, 73 | "is-buffer": { 74 | "version": "2.0.3", 75 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", 76 | "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==" 77 | }, 78 | "ms": { 79 | "version": "2.0.0", 80 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 81 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 82 | }, 83 | "supports-color": { 84 | "version": "5.5.0", 85 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 86 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 87 | "requires": { 88 | "has-flag": "^3.0.0" 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /frontend/dist/app.a6a4d504.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["src/templates.js","src/utils.js","src/JobSearch.js","src/app.js"],"names":["jobTemplate","job","currency","title","salary_max","location","display_name","description","redirect_url","extractFormData","form","Array","from","elements","reduce","acc","id","value","getCurrencySymbol","country","currencies","gb","us","au","ca","JobSearch","searchFormSelector","resultsContainerSelector","loadingElementSelector","searchForm","document","querySelector","resultsContainer","loadingElement","countryCode","setCurrencySymbol","fetch","then","results","json","toLowerCase","currencySymbol","addEventListener","event","preventDefault","startLoading","innerHTML","search","response","stopLoading","map","join","jobs","catch","classList","add","remove","jobSearch","setCountryCode","configureFormListener"],"mappings":"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","file":"app.a6a4d504.js","sourceRoot":"..","sourcesContent":["export const jobTemplate = (job, currency) => `\n
\n
\n

${job.title} up to ${currency}${job.salary_max}

\n
${job.location.display_name}
\n

${job.description}

\n View Job\n
\n
\n`;","export const extractFormData = form => Array\n .from(form.elements)\n .reduce((acc, { id, value }) => ({ [id]: value, ...acc }), {});\n\nexport const getCurrencySymbol = country => {\n const currencies = {\n gb: '£',\n us: '$',\n au: '$',\n ca: '$',\n };\n return currencies[country];\n}","import { jobTemplate } from './templates';\nimport { extractFormData, getCurrencySymbol } from './utils';\n\n\nexport class JobSearch {\n\n constructor(searchFormSelector, resultsContainerSelector, loadingElementSelector) {\n this.searchForm = document.querySelector(searchFormSelector);\n this.resultsContainer = document.querySelector(resultsContainerSelector);\n this.loadingElement = document.querySelector(loadingElementSelector);\n }\n\n setCountryCode() {\n this.countryCode = 'gb';\n this.setCurrencySymbol();\n\n fetch('http://ip-api.com/json')\n .then(results => results.json())\n .then(results => {\n this.countryCode = results.countryCode.toLowerCase();\n this.setCurrencySymbol();\n });\n }\n\n setCurrencySymbol() {\n this.currencySymbol = getCurrencySymbol(this.countryCode);\n }\n\n configureFormListener() {\n this.searchForm.addEventListener('submit', (event) => {\n event.preventDefault();\n this.startLoading();\n this.resultsContainer.innerHTML = '';\n const { search, location } = extractFormData(this.searchForm);\n fetch(`http://localhost:3000/?search=${search}&location=${location}&country=${this.countryCode}`)\n .then(response => response.json())\n .then(({ results }) => {\n this.stopLoading();\n return results\n .map(job => jobTemplate(job, this.currencySymbol))\n .join('');\n })\n .then(jobs => this.resultsContainer.innerHTML = jobs)\n .catch(() => this.stopLoading());\n });\n }\n\n startLoading() {\n this.loadingElement.classList.add('loading');\n }\n\n stopLoading() {\n this.loadingElement.classList.remove('loading');\n }\n}\n\n","import { JobSearch } from './JobSearch';\n\nconst jobSearch = new JobSearch('#search-form', '.result-container', '.loading-element');\njobSearch.setCountryCode();\njobSearch.configureFormListener();\n"]} -------------------------------------------------------------------------------- /frontend/.cache/9b/3966e0131e408256dff65fff8c9b07.json: -------------------------------------------------------------------------------- 1 | {"id":"src/utils.js","dependencies":[{"name":"/home/bubb/dev/job-search/frontend/package.json","includedInParent":true,"mtime":1568645081763}],"generated":{"js":"\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.extractFormData = void 0;\n\nfunction ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }\n\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nvar extractFormData = function extractFormData(form) {\n return Array.from(form.elements).reduce(function (acc, _ref) {\n var id = _ref.id,\n value = _ref.value;\n return _objectSpread(_defineProperty({}, id, value), acc);\n }, {});\n};\n\nexports.extractFormData = extractFormData;"},"sourceMaps":{"js":{"mappings":[{"generated":{"line":14,"column":0},"source":"src/utils.js","original":{"line":1,"column":7}},{"name":"extractFormData","generated":{"line":14,"column":4},"source":"src/utils.js","original":{"line":1,"column":13}},{"generated":{"line":14,"column":19},"source":"src/utils.js","original":{"line":1,"column":28}},{"generated":{"line":14,"column":22},"source":"src/utils.js","original":{"line":1,"column":31}},{"name":"extractFormData","generated":{"line":14,"column":31},"source":"src/utils.js","original":{"line":1,"column":13}},{"generated":{"line":14,"column":46},"source":"src/utils.js","original":{"line":1,"column":31}},{"name":"form","generated":{"line":14,"column":47},"source":"src/utils.js","original":{"line":1,"column":31}},{"generated":{"line":14,"column":51},"source":"src/utils.js","original":{"line":1,"column":35}},{"generated":{"line":15,"column":0},"source":"src/utils.js","original":{"line":1,"column":35}},{"name":"Array","generated":{"line":15,"column":9},"source":"src/utils.js","original":{"line":1,"column":39}},{"generated":{"line":15,"column":14},"source":"src/utils.js","original":{"line":1,"column":44}},{"name":"from","generated":{"line":15,"column":15},"source":"src/utils.js","original":{"line":2,"column":1}},{"generated":{"line":15,"column":19},"source":"src/utils.js","original":{"line":1,"column":39}},{"name":"form","generated":{"line":15,"column":20},"source":"src/utils.js","original":{"line":2,"column":6}},{"generated":{"line":15,"column":24},"source":"src/utils.js","original":{"line":2,"column":10}},{"name":"elements","generated":{"line":15,"column":25},"source":"src/utils.js","original":{"line":2,"column":11}},{"generated":{"line":15,"column":33},"source":"src/utils.js","original":{"line":1,"column":39}},{"name":"reduce","generated":{"line":15,"column":35},"source":"src/utils.js","original":{"line":3,"column":1}},{"generated":{"line":15,"column":41},"source":"src/utils.js","original":{"line":1,"column":39}},{"generated":{"line":15,"column":42},"source":"src/utils.js","original":{"line":3,"column":8}},{"name":"acc","generated":{"line":15,"column":52},"source":"src/utils.js","original":{"line":3,"column":9}},{"generated":{"line":15,"column":55},"source":"src/utils.js","original":{"line":3,"column":8}},{"generated":{"line":16,"column":0},"source":"src/utils.js","original":{"line":3,"column":8}},{"name":"id","generated":{"line":16,"column":8},"source":"src/utils.js","original":{"line":3,"column":16}},{"generated":{"line":16,"column":10},"source":"src/utils.js","original":{"line":3,"column":8}},{"name":"id","generated":{"line":16,"column":18},"source":"src/utils.js","original":{"line":3,"column":16}},{"generated":{"line":16,"column":20},"source":"src/utils.js","original":{"line":3,"column":8}},{"generated":{"line":17,"column":0},"source":"src/utils.js","original":{"line":3,"column":8}},{"name":"value","generated":{"line":17,"column":8},"source":"src/utils.js","original":{"line":3,"column":20}},{"generated":{"line":17,"column":13},"source":"src/utils.js","original":{"line":3,"column":8}},{"name":"value","generated":{"line":17,"column":21},"source":"src/utils.js","original":{"line":3,"column":20}},{"generated":{"line":17,"column":26},"source":"src/utils.js","original":{"line":3,"column":8}},{"generated":{"line":18,"column":0},"source":"src/utils.js","original":{"line":3,"column":8}},{"name":"id","generated":{"line":18,"column":45},"source":"src/utils.js","original":{"line":3,"column":36}},{"generated":{"line":18,"column":47},"source":"src/utils.js","original":{"line":3,"column":8}},{"name":"value","generated":{"line":18,"column":49},"source":"src/utils.js","original":{"line":3,"column":41}},{"generated":{"line":18,"column":54},"source":"src/utils.js","original":{"line":3,"column":8}},{"name":"acc","generated":{"line":18,"column":57},"source":"src/utils.js","original":{"line":3,"column":51}},{"generated":{"line":18,"column":60},"source":"src/utils.js","original":{"line":3,"column":8}},{"generated":{"line":19,"column":0},"source":"src/utils.js","original":{"line":3,"column":8}},{"generated":{"line":19,"column":3},"source":"src/utils.js","original":{"line":1,"column":39}},{"generated":{"line":19,"column":5},"source":"src/utils.js","original":{"line":3,"column":59}},{"generated":{"line":19,"column":7},"source":"src/utils.js","original":{"line":1,"column":39}},{"generated":{"line":19,"column":8},"source":"src/utils.js","original":{"line":1,"column":35}},{"generated":{"line":20,"column":0},"source":"src/utils.js","original":{"line":1,"column":35}},{"generated":{"line":20,"column":1},"source":"src/utils.js","original":{"line":1,"column":7}}],"sources":{"src/utils.js":"export const extractFormData = form => Array\n.from(form.elements)\n.reduce((acc, { id, value }) => ({ [id]: value, ...acc }), {});"},"lineCount":null}},"error":null,"hash":"c639f8a9c00cefaf896ddc60010b9936","cacheData":{"env":{}}} -------------------------------------------------------------------------------- /frontend/.cache/d3/d633b5f1caf367b2188ffb60a62787.json: -------------------------------------------------------------------------------- 1 | {"id":"src/JobSearch.js","dependencies":[{"name":"/home/bubb/dev/job-search/frontend/package.json","includedInParent":true,"mtime":1568645081763},{"name":"./templates","loc":{"line":1,"column":28},"parent":"/home/bubb/dev/job-search/frontend/src/JobSearch.js","resolved":"/home/bubb/dev/job-search/frontend/src/templates.js"},{"name":"./utils","loc":{"line":2,"column":32},"parent":"/home/bubb/dev/job-search/frontend/src/JobSearch.js","resolved":"/home/bubb/dev/job-search/frontend/src/utils.js"}],"generated":{"js":"\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.JobSearch = void 0;\n\nvar _templates = require(\"./templates\");\n\nvar _utils = require(\"./utils\");\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nvar JobSearch =\n/*#__PURE__*/\nfunction () {\n function JobSearch() {\n _classCallCheck(this, JobSearch);\n\n this.searchForm = document.querySelector('#search-form');\n this.resultContainer = document.querySelector('.result-container');\n this.configureFormListener();\n }\n\n _createClass(JobSearch, [{\n key: \"configureFormListener\",\n value: function configureFormListener() {\n var _this = this;\n\n this.searchForm.addEventListener('submit', function (event) {\n event.preventDefault();\n\n var _extractFormData = (0, _utils.extractFormData)(_this.searchForm),\n search = _extractFormData.search,\n location = _extractFormData.location;\n\n fetch(\"http://localhost:3000/?search=\".concat(search, \"&location=\").concat(location)).then(function (response) {\n return response.json();\n }).then(function (_ref) {\n var results = _ref.results;\n return results.map(_templates.jobTemplate).join('');\n }).then(function (jobs) {\n return _this.resultContainer.innerHTML = jobs;\n });\n });\n }\n }]);\n\n return JobSearch;\n}();\n\nexports.JobSearch = JobSearch;"},"sourceMaps":{"js":{"mappings":[{"generated":{"line":8,"column":0},"source":"src/JobSearch.js","original":{"line":1,"column":0}},{"generated":{"line":10,"column":0},"source":"src/JobSearch.js","original":{"line":2,"column":0}},{"name":"JobSearch","generated":{"line":18,"column":4},"source":"src/JobSearch.js","original":{"line":5,"column":13}},{"generated":{"line":21,"column":0},"source":"src/JobSearch.js","original":{"line":7,"column":2}},{"generated":{"line":21,"column":23},"source":"src/JobSearch.js","original":{"line":7,"column":16}},{"generated":{"line":22,"column":0},"source":"src/JobSearch.js","original":{"line":7,"column":16}},{"generated":{"line":24,"column":0},"source":"src/JobSearch.js","original":{"line":8,"column":4}},{"name":"searchForm","generated":{"line":24,"column":9},"source":"src/JobSearch.js","original":{"line":8,"column":9}},{"generated":{"line":24,"column":19},"source":"src/JobSearch.js","original":{"line":8,"column":4}},{"name":"document","generated":{"line":24,"column":22},"source":"src/JobSearch.js","original":{"line":8,"column":22}},{"generated":{"line":24,"column":30},"source":"src/JobSearch.js","original":{"line":8,"column":30}},{"name":"querySelector","generated":{"line":24,"column":31},"source":"src/JobSearch.js","original":{"line":8,"column":31}},{"generated":{"line":24,"column":44},"source":"src/JobSearch.js","original":{"line":8,"column":22}},{"generated":{"line":24,"column":45},"source":"src/JobSearch.js","original":{"line":8,"column":45}},{"generated":{"line":24,"column":59},"source":"src/JobSearch.js","original":{"line":8,"column":22}},{"generated":{"line":24,"column":60},"source":"src/JobSearch.js","original":{"line":8,"column":4}},{"generated":{"line":25,"column":0},"source":"src/JobSearch.js","original":{"line":9,"column":4}},{"name":"resultContainer","generated":{"line":25,"column":9},"source":"src/JobSearch.js","original":{"line":9,"column":9}},{"generated":{"line":25,"column":24},"source":"src/JobSearch.js","original":{"line":9,"column":4}},{"name":"document","generated":{"line":25,"column":27},"source":"src/JobSearch.js","original":{"line":9,"column":27}},{"generated":{"line":25,"column":35},"source":"src/JobSearch.js","original":{"line":9,"column":35}},{"name":"querySelector","generated":{"line":25,"column":36},"source":"src/JobSearch.js","original":{"line":9,"column":36}},{"generated":{"line":25,"column":49},"source":"src/JobSearch.js","original":{"line":9,"column":27}},{"generated":{"line":25,"column":50},"source":"src/JobSearch.js","original":{"line":9,"column":50}},{"generated":{"line":25,"column":69},"source":"src/JobSearch.js","original":{"line":9,"column":27}},{"generated":{"line":25,"column":70},"source":"src/JobSearch.js","original":{"line":9,"column":4}},{"generated":{"line":26,"column":0},"source":"src/JobSearch.js","original":{"line":10,"column":4}},{"name":"configureFormListener","generated":{"line":26,"column":9},"source":"src/JobSearch.js","original":{"line":10,"column":9}},{"generated":{"line":26,"column":30},"source":"src/JobSearch.js","original":{"line":10,"column":4}},{"generated":{"line":27,"column":0},"source":"src/JobSearch.js","original":{"line":11,"column":3}},{"generated":{"line":31,"column":44},"source":"src/JobSearch.js","original":{"line":13,"column":24}},{"generated":{"line":32,"column":0},"source":"src/JobSearch.js","original":{"line":13,"column":24}},{"generated":{"line":34,"column":0},"source":"src/JobSearch.js","original":{"line":14,"column":2}},{"name":"searchForm","generated":{"line":34,"column":11},"source":"src/JobSearch.js","original":{"line":14,"column":7}},{"generated":{"line":34,"column":21},"source":"src/JobSearch.js","original":{"line":14,"column":2}},{"name":"addEventListener","generated":{"line":34,"column":22},"source":"src/JobSearch.js","original":{"line":14,"column":18}},{"generated":{"line":34,"column":38},"source":"src/JobSearch.js","original":{"line":14,"column":2}},{"generated":{"line":34,"column":39},"source":"src/JobSearch.js","original":{"line":14,"column":35}},{"generated":{"line":34,"column":47},"source":"src/JobSearch.js","original":{"line":14,"column":2}},{"generated":{"line":34,"column":49},"source":"src/JobSearch.js","original":{"line":14,"column":45}},{"name":"event","generated":{"line":34,"column":59},"source":"src/JobSearch.js","original":{"line":14,"column":46}},{"generated":{"line":34,"column":64},"source":"src/JobSearch.js","original":{"line":14,"column":45}},{"generated":{"line":34,"column":66},"source":"src/JobSearch.js","original":{"line":14,"column":56}},{"name":"event","generated":{"line":35,"column":0},"source":"src/JobSearch.js","original":{"line":15,"column":4}},{"name":"event","generated":{"line":35,"column":8},"source":"src/JobSearch.js","original":{"line":15,"column":4}},{"generated":{"line":35,"column":13},"source":"src/JobSearch.js","original":{"line":15,"column":9}},{"name":"preventDefault","generated":{"line":35,"column":14},"source":"src/JobSearch.js","original":{"line":15,"column":10}},{"generated":{"line":35,"column":28},"source":"src/JobSearch.js","original":{"line":15,"column":4}},{"generated":{"line":37,"column":0},"source":"src/JobSearch.js","original":{"line":14,"column":56}},{"generated":{"line":37,"column":31},"source":"src/JobSearch.js","original":{"line":16,"column":33}},{"generated":{"line":37,"column":59},"source":"src/JobSearch.js","original":{"line":16,"column":49}},{"generated":{"line":37,"column":64},"source":"src/JobSearch.js","original":{"line":16,"column":53}},{"name":"searchForm","generated":{"line":37,"column":65},"source":"src/JobSearch.js","original":{"line":16,"column":54}},{"generated":{"line":37,"column":75},"source":"src/JobSearch.js","original":{"line":16,"column":33}},{"generated":{"line":37,"column":76},"source":"src/JobSearch.js","original":{"line":14,"column":56}},{"generated":{"line":38,"column":0},"source":"src/JobSearch.js","original":{"line":14,"column":56}},{"name":"search","generated":{"line":38,"column":12},"source":"src/JobSearch.js","original":{"line":16,"column":12}},{"generated":{"line":38,"column":18},"source":"src/JobSearch.js","original":{"line":14,"column":56}},{"name":"search","generated":{"line":38,"column":38},"source":"src/JobSearch.js","original":{"line":16,"column":12}},{"generated":{"line":38,"column":44},"source":"src/JobSearch.js","original":{"line":14,"column":56}},{"generated":{"line":39,"column":0},"source":"src/JobSearch.js","original":{"line":14,"column":56}},{"name":"location","generated":{"line":39,"column":12},"source":"src/JobSearch.js","original":{"line":16,"column":20}},{"generated":{"line":39,"column":20},"source":"src/JobSearch.js","original":{"line":14,"column":56}},{"name":"location","generated":{"line":39,"column":40},"source":"src/JobSearch.js","original":{"line":16,"column":20}},{"generated":{"line":39,"column":48},"source":"src/JobSearch.js","original":{"line":14,"column":56}},{"name":"fetch","generated":{"line":41,"column":0},"source":"src/JobSearch.js","original":{"line":17,"column":4}},{"name":"fetch","generated":{"line":41,"column":8},"source":"src/JobSearch.js","original":{"line":17,"column":4}},{"generated":{"line":41,"column":13},"source":"src/JobSearch.js","original":{"line":17,"column":9}},{"name":"search","generated":{"line":41,"column":54},"source":"src/JobSearch.js","original":{"line":17,"column":43}},{"generated":{"line":41,"column":60},"source":"src/JobSearch.js","original":{"line":17,"column":9}},{"name":"location","generated":{"line":41,"column":83},"source":"src/JobSearch.js","original":{"line":17,"column":62}},{"generated":{"line":41,"column":91},"source":"src/JobSearch.js","original":{"line":17,"column":9}},{"generated":{"line":41,"column":93},"source":"src/JobSearch.js","original":{"line":17,"column":4}},{"name":"then","generated":{"line":41,"column":94},"source":"src/JobSearch.js","original":{"line":18,"column":5}},{"generated":{"line":41,"column":98},"source":"src/JobSearch.js","original":{"line":17,"column":4}},{"generated":{"line":41,"column":99},"source":"src/JobSearch.js","original":{"line":18,"column":10}},{"name":"response","generated":{"line":41,"column":109},"source":"src/JobSearch.js","original":{"line":18,"column":10}},{"generated":{"line":41,"column":117},"source":"src/JobSearch.js","original":{"line":18,"column":18}},{"generated":{"line":42,"column":0},"source":"src/JobSearch.js","original":{"line":18,"column":18}},{"name":"response","generated":{"line":42,"column":17},"source":"src/JobSearch.js","original":{"line":18,"column":22}},{"generated":{"line":42,"column":25},"source":"src/JobSearch.js","original":{"line":18,"column":30}},{"name":"json","generated":{"line":42,"column":26},"source":"src/JobSearch.js","original":{"line":18,"column":31}},{"generated":{"line":42,"column":30},"source":"src/JobSearch.js","original":{"line":18,"column":22}},{"generated":{"line":42,"column":32},"source":"src/JobSearch.js","original":{"line":18,"column":18}},{"generated":{"line":43,"column":0},"source":"src/JobSearch.js","original":{"line":18,"column":18}},{"generated":{"line":43,"column":9},"source":"src/JobSearch.js","original":{"line":17,"column":4}},{"name":"then","generated":{"line":43,"column":11},"source":"src/JobSearch.js","original":{"line":19,"column":5}},{"generated":{"line":43,"column":15},"source":"src/JobSearch.js","original":{"line":17,"column":4}},{"generated":{"line":43,"column":16},"source":"src/JobSearch.js","original":{"line":19,"column":10}},{"generated":{"line":44,"column":0},"source":"src/JobSearch.js","original":{"line":19,"column":10}},{"name":"results","generated":{"line":44,"column":14},"source":"src/JobSearch.js","original":{"line":19,"column":13}},{"generated":{"line":44,"column":21},"source":"src/JobSearch.js","original":{"line":19,"column":10}},{"name":"results","generated":{"line":44,"column":29},"source":"src/JobSearch.js","original":{"line":19,"column":13}},{"generated":{"line":44,"column":36},"source":"src/JobSearch.js","original":{"line":19,"column":10}},{"generated":{"line":45,"column":0},"source":"src/JobSearch.js","original":{"line":19,"column":10}},{"name":"results","generated":{"line":45,"column":17},"source":"src/JobSearch.js","original":{"line":19,"column":27}},{"generated":{"line":45,"column":24},"source":"src/JobSearch.js","original":{"line":19,"column":34}},{"name":"map","generated":{"line":45,"column":25},"source":"src/JobSearch.js","original":{"line":19,"column":35}},{"generated":{"line":45,"column":28},"source":"src/JobSearch.js","original":{"line":19,"column":27}},{"name":"jobTemplate","generated":{"line":45,"column":29},"source":"src/JobSearch.js","original":{"line":19,"column":39}},{"generated":{"line":45,"column":51},"source":"src/JobSearch.js","original":{"line":19,"column":27}},{"name":"join","generated":{"line":45,"column":53},"source":"src/JobSearch.js","original":{"line":19,"column":52}},{"generated":{"line":45,"column":57},"source":"src/JobSearch.js","original":{"line":19,"column":27}},{"generated":{"line":45,"column":58},"source":"src/JobSearch.js","original":{"line":19,"column":57}},{"generated":{"line":45,"column":60},"source":"src/JobSearch.js","original":{"line":19,"column":27}},{"generated":{"line":45,"column":61},"source":"src/JobSearch.js","original":{"line":19,"column":10}},{"generated":{"line":46,"column":0},"source":"src/JobSearch.js","original":{"line":19,"column":10}},{"generated":{"line":46,"column":9},"source":"src/JobSearch.js","original":{"line":17,"column":4}},{"name":"then","generated":{"line":46,"column":11},"source":"src/JobSearch.js","original":{"line":20,"column":5}},{"generated":{"line":46,"column":15},"source":"src/JobSearch.js","original":{"line":17,"column":4}},{"generated":{"line":46,"column":16},"source":"src/JobSearch.js","original":{"line":20,"column":10}},{"name":"jobs","generated":{"line":46,"column":26},"source":"src/JobSearch.js","original":{"line":20,"column":10}},{"generated":{"line":46,"column":30},"source":"src/JobSearch.js","original":{"line":20,"column":14}},{"generated":{"line":47,"column":0},"source":"src/JobSearch.js","original":{"line":20,"column":14}},{"generated":{"line":47,"column":17},"source":"src/JobSearch.js","original":{"line":20,"column":18}},{"generated":{"line":47,"column":22},"source":"src/JobSearch.js","original":{"line":20,"column":22}},{"name":"resultContainer","generated":{"line":47,"column":23},"source":"src/JobSearch.js","original":{"line":20,"column":23}},{"generated":{"line":47,"column":38},"source":"src/JobSearch.js","original":{"line":20,"column":18}},{"name":"innerHTML","generated":{"line":47,"column":39},"source":"src/JobSearch.js","original":{"line":20,"column":39}},{"generated":{"line":47,"column":48},"source":"src/JobSearch.js","original":{"line":20,"column":18}},{"name":"jobs","generated":{"line":47,"column":51},"source":"src/JobSearch.js","original":{"line":20,"column":51}},{"generated":{"line":47,"column":55},"source":"src/JobSearch.js","original":{"line":20,"column":14}},{"generated":{"line":48,"column":0},"source":"src/JobSearch.js","original":{"line":20,"column":14}},{"generated":{"line":48,"column":9},"source":"src/JobSearch.js","original":{"line":17,"column":4}},{"generated":{"line":49,"column":0},"source":"src/JobSearch.js","original":{"line":21,"column":3}},{"generated":{"line":49,"column":7},"source":"src/JobSearch.js","original":{"line":14,"column":2}},{"generated":{"line":50,"column":0},"source":"src/JobSearch.js","original":{"line":22,"column":1}}],"sources":{"src/JobSearch.js":"import { jobTemplate } from './templates';\nimport { extractFormData } from './utils';\n\n\nexport class JobSearch {\n \n constructor() {\n this.searchForm = document.querySelector('#search-form');\n this.resultContainer = document.querySelector('.result-container');\n this.configureFormListener();\n }\n\nconfigureFormListener() {\n this.searchForm.addEventListener('submit', (event) => {\n event.preventDefault();\n const { search, location } = extractFormData(this.searchForm);\n fetch(`http://localhost:3000/?search=${search}&location=${location}`)\n .then(response => response.json())\n .then(({ results }) => results.map(jobTemplate).join(''))\n .then(jobs => this.resultContainer.innerHTML = jobs);\n });\n}\n}\n\n"},"lineCount":null}},"error":null,"hash":"b27e51f6c91611e81a87b94db262b55a","cacheData":{"env":{}}} -------------------------------------------------------------------------------- /frontend/dist/app.a6a4d504.js: -------------------------------------------------------------------------------- 1 | // modules are defined as an array 2 | // [ module function, map of requires ] 3 | // 4 | // map of requires is short require name -> numeric require 5 | // 6 | // anything defined in a previous bundle is accessed via the 7 | // orig method which is the require for previous bundles 8 | parcelRequire = (function (modules, cache, entry, globalName) { 9 | // Save the require from previous bundle to this closure if any 10 | var previousRequire = typeof parcelRequire === 'function' && parcelRequire; 11 | var nodeRequire = typeof require === 'function' && require; 12 | 13 | function newRequire(name, jumped) { 14 | if (!cache[name]) { 15 | if (!modules[name]) { 16 | // if we cannot find the module within our internal map or 17 | // cache jump to the current global require ie. the last bundle 18 | // that was added to the page. 19 | var currentRequire = typeof parcelRequire === 'function' && parcelRequire; 20 | if (!jumped && currentRequire) { 21 | return currentRequire(name, true); 22 | } 23 | 24 | // If there are other bundles on this page the require from the 25 | // previous one is saved to 'previousRequire'. Repeat this as 26 | // many times as there are bundles until the module is found or 27 | // we exhaust the require chain. 28 | if (previousRequire) { 29 | return previousRequire(name, true); 30 | } 31 | 32 | // Try the node require function if it exists. 33 | if (nodeRequire && typeof name === 'string') { 34 | return nodeRequire(name); 35 | } 36 | 37 | var err = new Error('Cannot find module \'' + name + '\''); 38 | err.code = 'MODULE_NOT_FOUND'; 39 | throw err; 40 | } 41 | 42 | localRequire.resolve = resolve; 43 | localRequire.cache = {}; 44 | 45 | var module = cache[name] = new newRequire.Module(name); 46 | 47 | modules[name][0].call(module.exports, localRequire, module, module.exports, this); 48 | } 49 | 50 | return cache[name].exports; 51 | 52 | function localRequire(x){ 53 | return newRequire(localRequire.resolve(x)); 54 | } 55 | 56 | function resolve(x){ 57 | return modules[name][1][x] || x; 58 | } 59 | } 60 | 61 | function Module(moduleName) { 62 | this.id = moduleName; 63 | this.bundle = newRequire; 64 | this.exports = {}; 65 | } 66 | 67 | newRequire.isParcelRequire = true; 68 | newRequire.Module = Module; 69 | newRequire.modules = modules; 70 | newRequire.cache = cache; 71 | newRequire.parent = previousRequire; 72 | newRequire.register = function (id, exports) { 73 | modules[id] = [function (require, module) { 74 | module.exports = exports; 75 | }, {}]; 76 | }; 77 | 78 | var error; 79 | for (var i = 0; i < entry.length; i++) { 80 | try { 81 | newRequire(entry[i]); 82 | } catch (e) { 83 | // Save first error but execute all entries 84 | if (!error) { 85 | error = e; 86 | } 87 | } 88 | } 89 | 90 | if (entry.length) { 91 | // Expose entry point to Node, AMD or browser globals 92 | // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js 93 | var mainExports = newRequire(entry[entry.length - 1]); 94 | 95 | // CommonJS 96 | if (typeof exports === "object" && typeof module !== "undefined") { 97 | module.exports = mainExports; 98 | 99 | // RequireJS 100 | } else if (typeof define === "function" && define.amd) { 101 | define(function () { 102 | return mainExports; 103 | }); 104 | 105 | //