diff --git a/LICENSE b/LICENSE index a992253..c4cb858 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 blopa +Copyright (c) 2021 blopa Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.MD b/README.MD index 07d0f37..6b005bc 100644 --- a/README.MD +++ b/README.MD @@ -26,7 +26,11 @@ Older versions: [V1](https://github.com/blopa/Resume-Builder/blob/main/README_V1 - Cover Letter Editor ## JSON Resume Schema -This project uses the [jsonresume/resume-schema](https://github.com/jsonresume/resume-schema) v1.0.0, but due a need to extend some of it's features, we also added 2 new fields: `__translation__` to translate template keys, and `coverLetter` so you can add your own Cover Letter template. +This project uses the [jsonresume/resume-schema](https://github.com/jsonresume/resume-schema) v1.0.0, but due a need to extend some of it's features, we also added 4 new fields: +- `__translation__` to translate template keys. +- `coverLetter` to add your own Cover Letter template. +- `work[].keywords` to add keywords to your work experience. +- `enableSourceDataDownload` to allow the JSON data to be downloaded from the resume itself. ## Online viewer Create a GitHub repo [like this one](https://github.com/blopa/resume.json) with the name `resume.json` and a file called `resume.json` in a branch called `main` and following the JSON schema from [github.com/jsonresume/resume-schema](https://github.com/jsonresume/resume-schema/tree/v1.0.0) v1.0.0. @@ -146,6 +150,10 @@ The following `JSON` is a result of [this Google Spreadsheet](https://docs.googl "Build an algorithm for artist to detect if their music was violating copy right infringement laws", "Successfully won Techcrunch Disrupt", "Optimized an algorithm that holds the current world record for Weisman Scores" + ], + "keywords": [ + "Javascript", + "React" ] } ], @@ -267,11 +275,6 @@ The following `JSON` is a result of [this Google Spreadsheet](https://docs.googl "type": "application" } ], - "meta": { - "canonical": "https://raw.githubusercontent.com/jsonresume/resume-schema/master/resume.json", - "version": "v1.0.0", - "lastModified": "2017-12-24T15:53:00" - }, "__translation__": { "awards": "Prizes", "volunteers": "Volunteers", @@ -284,7 +287,8 @@ The following `JSON` is a result of [this Google Spreadsheet](https://docs.googl "summary": "Summary", "experience": "Experience", "at": "at" - } + }, + "enableSourceDataDownload": true } ``` @@ -299,6 +303,13 @@ The following `JSON` is a result of [this Google Spreadsheet](https://docs.googl ![ScreenShot](https://raw.githubusercontent.com/blopa/Resume-Builder/main/screenshots/v4/screenshot_3.png) ## Release Notes +- **v4.0.2:** + - Filter out resume templates that are not ready yet. + - Add download link to download the JSON data. + - Fix resume viewer. + - Add missing fields on "work" and "projects". + - Small layout fixes in the "Default" template. + - Arrays from the spreadsheet are now parsed using `';'` instead of `','`. - **v4.0.1:** - Add visual cue to the cover letter variables. - **v4.0.0:** @@ -307,6 +318,8 @@ The following `JSON` is a result of [this Google Spreadsheet](https://docs.googl - Update JSON Schema to v1.0.0. - Update Gatsby to v3. +[Complete Release Notes here](https://github.com/blopa/Resume-Builder/blob/main/release-notes.md) + ## Thanks to - SEO resume photo by [Markus Winkler](https://unsplash.com/@markuswinkler?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/resume?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText). @@ -320,6 +333,12 @@ A: I can try. Open an issue, and I'll see what I can do. A: Thank you! You can help by codding more features, creating pull requests, or donating via [https://bunq.me/BuyMeASoda](https://bunq.me/BuyMeASoda) ## TODO +- Fix all TODOs in the code +- Add proptypes to the components +- Add documentation on how to create new templates +- Add form to manually add resume data +- Add support for Redux Tools extension +- Use https://github.com/MrRio/jsPDF - Load a JSON resume from any URL - Actually create a second template - Add unit tests diff --git a/README_V1.MD b/README_V1.MD index d963ed6..0344ee8 100644 --- a/README_V1.MD +++ b/README_V1.MD @@ -282,6 +282,8 @@ The following ``JSON`` is a result of [this Google Spreadsheet](https://docs.goo - **v0.0.1:** - First working version +[Complete Release Notes here](https://github.com/blopa/Resume-Builder/blob/main/release-notes.md) + ## F.A.Q. **Q: Can you implement function?** diff --git a/README_V2.MD b/README_V2.MD index 729c185..327cf0b 100644 --- a/README_V2.MD +++ b/README_V2.MD @@ -164,7 +164,7 @@ The following ``JSON`` is a result of [this Google Spreadsheet](https://docs.goo ![ScreenShot](https://raw.githubusercontent.com/blopa/Resume-Builder/main/screenshots/v2/screenshot_3.png) ## Release Notes -- **v2.0.3:** (not tagged yet) +- **v2.0.3:** (not tagged) - ~~Fix CORS problem when loading a spreadsheet from URL.~~ (still trying to figure this one out) - Update packages. - Add new ESlint rules. @@ -176,6 +176,8 @@ The following ``JSON`` is a result of [this Google Spreadsheet](https://docs.goo - **v2.0.0:** - Everything rebuild from scratch. +[Complete Release Notes here](https://github.com/blopa/Resume-Builder/blob/main/release-notes.md) + ## F.A.Q. **Q: Can you implement function?** diff --git a/README_V3.MD b/README_V3.MD index db2b954..9c00257 100644 --- a/README_V3.MD +++ b/README_V3.MD @@ -13,7 +13,7 @@ ## About -[Resume Builder](https://blopa.github.io/Legacy-Resume-Builder/v3) is a free open-source project that allows anyone to easily maintain and build any kind of resume using Google Spreadsheets. This was develop as a personal project to help a friend who was struggling spending up to an hour to make a custom resumes. **[TRY IT NOW](https://blopa.github.io/Legacy-Resume-Builder/v3).** +[Resume Builder](https://blopa.github.io/Legacy-Resume-Builder/v3/en) is a free open-source project that allows anyone to easily maintain and build any kind of resume using Google Spreadsheets. This was develop as a personal project to help a friend who was struggling spending up to an hour to make a custom resumes. **[TRY IT NOW](https://blopa.github.io/Legacy-Resume-Builder/v3/en).** For the latest version, access [https://resume-builder.js.org](https://resume-builder.js.org). @@ -227,6 +227,8 @@ The following ``JSON`` is a result of [this Google Spreadsheet](https://docs.goo - **v3.0.0:** - Rebuild using Gatsby. +[Complete Release Notes here](https://github.com/blopa/Resume-Builder/blob/main/release-notes.md) + ## Thanks to - SEO resume photo by [Markus Winkler](https://unsplash.com/@markuswinkler?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/resume?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText). diff --git a/gatsby-node.js b/gatsby-node.js index e561b0e..dd6ad3a 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -3,6 +3,7 @@ const { promises: fs } = require('fs'); const packageJson = require('./package.json'); const TEMPLATES_PATH = path.resolve(__dirname, 'src/components/ResumeTemplates'); +const disabledTemplates = ['Compact', 'VanHack']; const ignoredPages = ['/Home/']; const { convertToKebabCase, @@ -44,24 +45,26 @@ exports.onCreatePage = async ({ page, actions }) => { if (page.context.intl.originalPath === '/ResumeViewer/') { const templates = await fs.readdir(TEMPLATES_PATH); - templates.forEach((template) => { - if ( - page.internalComponentName === 'ComponentResumeViewer' + + templates.filter((template) => !disabledTemplates.includes(template)) + .forEach((template) => { + if ( + page.internalComponentName === 'ComponentResumeViewer' && language !== 'en' - ) { - return; - } + ) { + return; + } - pagePath = `/view/${template}`.toLocaleLowerCase(); - matchPath = `${pagePath}/*`; - myCreatePage( - createPage, - page, - pagePath, - matchPath, - language - ); - }); + pagePath = `/view/${template}`.toLocaleLowerCase(); + matchPath = `${pagePath}/*`; + myCreatePage( + createPage, + page, + pagePath, + matchPath, + language + ); + }); return; } @@ -80,10 +83,18 @@ exports.onCreateWebpackConfig = async ({ actions, }) => { const templates = await fs.readdir(TEMPLATES_PATH); + + // TODO this fixes the 'React Refresh Babel' error where NODE_ENV is 'local' for some reason + if (process.env.NODE_ENV !== 'production') { + process.env.NODE_ENV = 'development'; + } + actions.setWebpackConfig({ plugins: [ plugins.define({ - TEMPLATES_LIST: JSON.stringify(templates), + TEMPLATES_LIST: JSON.stringify( + templates.filter((template) => !disabledTemplates.includes(template)) + ), VERSION: JSON.stringify(packageJson.version), }), ], diff --git a/package-lock.json b/package-lock.json index 298d888..5fdf154 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "resume-builder", - "version": "4.0.1", + "version": "4.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1121,9 +1121,9 @@ } }, "@babel/standalone": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.14.0.tgz", - "integrity": "sha512-PPkwh7AQyP+QBHUavMBNSnAVsW4xFe76CQn3d8kWorwwu9l5R7QDjA9v4GkF6jHhL5fen6so20eqY1KDaJjMEQ==" + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.14.1.tgz", + "integrity": "sha512-HFkwJyIv91mP38447ERwnVgw9yhx2/evs+r0+1hdAXf1Q1fBypPwtY8YOqsPniqoYCEVbBIqYELt0tNrOAg/Iw==" }, "@babel/template": { "version": "7.12.13", @@ -1183,9 +1183,9 @@ } }, "@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz", + "integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==", "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -2718,24 +2718,82 @@ "integrity": "sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==" }, "@typescript-eslint/eslint-plugin": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.0.tgz", - "integrity": "sha512-U8SP9VOs275iDXaL08Ln1Fa/wLXfj5aTr/1c0t0j6CdbOnxh+TruXu1p4I0NAvdPBQgoPjHsgKn28mOi0FzfoA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.1.tgz", + "integrity": "sha512-kVTAghWDDhsvQ602tHBc6WmQkdaYbkcTwZu+7l24jtJiYvm9l+/y/b2BZANEezxPDiX5MK2ZecE+9BFi/YJryw==", "requires": { - "@typescript-eslint/experimental-utils": "4.22.0", - "@typescript-eslint/scope-manager": "4.22.0", + "@typescript-eslint/experimental-utils": "4.22.1", + "@typescript-eslint/scope-manager": "4.22.1", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", "regexpp": "^3.0.0", "semver": "^7.3.2", "tsutils": "^3.17.1" + }, + "dependencies": { + "@typescript-eslint/experimental-utils": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.1.tgz", + "integrity": "sha512-svYlHecSMCQGDO2qN1v477ax/IDQwWhc7PRBiwAdAMJE7GXk5stF4Z9R/8wbRkuX/5e9dHqbIWxjeOjckK3wLQ==", + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.22.1", + "@typescript-eslint/types": "4.22.1", + "@typescript-eslint/typescript-estree": "4.22.1", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.1.tgz", + "integrity": "sha512-d5bAiPBiessSmNi8Amq/RuLslvcumxLmyhf1/Xa9IuaoFJ0YtshlJKxhlbY7l2JdEk3wS0EnmnfeJWSvADOe0g==", + "requires": { + "@typescript-eslint/types": "4.22.1", + "@typescript-eslint/visitor-keys": "4.22.1" + } + }, + "@typescript-eslint/types": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.1.tgz", + "integrity": "sha512-2HTkbkdAeI3OOcWbqA8hWf/7z9c6gkmnWNGz0dKSLYLWywUlkOAQ2XcjhlKLj5xBFDf8FgAOF5aQbnLRvgNbCw==" + }, + "@typescript-eslint/typescript-estree": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.1.tgz", + "integrity": "sha512-p3We0pAPacT+onSGM+sPR+M9CblVqdA9F1JEdIqRVlxK5Qth4ochXQgIyb9daBomyQKAXbygxp1aXQRV0GC79A==", + "requires": { + "@typescript-eslint/types": "4.22.1", + "@typescript-eslint/visitor-keys": "4.22.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.1.tgz", + "integrity": "sha512-WPkOrIRm+WCLZxXQHCi+WG8T2MMTUFR70rWjdWYddLT7cEfb2P4a3O/J2U1FBVsSFTocXLCoXWY6MZGejeStvQ==", + "requires": { + "@typescript-eslint/types": "4.22.1", + "eslint-visitor-keys": "^2.0.0" + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + } } }, "@typescript-eslint/experimental-utils": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.0.tgz", "integrity": "sha512-xJXHHl6TuAxB5AWiVrGhvbGL8/hbiCQ8FiWwObO3r0fnvBdrbWEDy1hlvGQOAWc6qsCWuWMKdVWlLAEMpxnddg==", + "dev": true, "requires": { "@types/json-schema": "^7.0.3", "@typescript-eslint/scope-manager": "4.22.0", @@ -2746,20 +2804,65 @@ } }, "@typescript-eslint/parser": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.0.tgz", - "integrity": "sha512-z/bGdBJJZJN76nvAY9DkJANYgK3nlRstRRi74WHm3jjgf2I8AglrSY+6l7ogxOmn55YJ6oKZCLLy+6PW70z15Q==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.1.tgz", + "integrity": "sha512-l+sUJFInWhuMxA6rtirzjooh8cM/AATAe3amvIkqKFeMzkn85V+eLzb1RyuXkHak4dLfYzOmF6DXPyflJvjQnw==", "requires": { - "@typescript-eslint/scope-manager": "4.22.0", - "@typescript-eslint/types": "4.22.0", - "@typescript-eslint/typescript-estree": "4.22.0", + "@typescript-eslint/scope-manager": "4.22.1", + "@typescript-eslint/types": "4.22.1", + "@typescript-eslint/typescript-estree": "4.22.1", "debug": "^4.1.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.1.tgz", + "integrity": "sha512-d5bAiPBiessSmNi8Amq/RuLslvcumxLmyhf1/Xa9IuaoFJ0YtshlJKxhlbY7l2JdEk3wS0EnmnfeJWSvADOe0g==", + "requires": { + "@typescript-eslint/types": "4.22.1", + "@typescript-eslint/visitor-keys": "4.22.1" + } + }, + "@typescript-eslint/types": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.1.tgz", + "integrity": "sha512-2HTkbkdAeI3OOcWbqA8hWf/7z9c6gkmnWNGz0dKSLYLWywUlkOAQ2XcjhlKLj5xBFDf8FgAOF5aQbnLRvgNbCw==" + }, + "@typescript-eslint/typescript-estree": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.1.tgz", + "integrity": "sha512-p3We0pAPacT+onSGM+sPR+M9CblVqdA9F1JEdIqRVlxK5Qth4ochXQgIyb9daBomyQKAXbygxp1aXQRV0GC79A==", + "requires": { + "@typescript-eslint/types": "4.22.1", + "@typescript-eslint/visitor-keys": "4.22.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.1.tgz", + "integrity": "sha512-WPkOrIRm+WCLZxXQHCi+WG8T2MMTUFR70rWjdWYddLT7cEfb2P4a3O/J2U1FBVsSFTocXLCoXWY6MZGejeStvQ==", + "requires": { + "@typescript-eslint/types": "4.22.1", + "eslint-visitor-keys": "^2.0.0" + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + } } }, "@typescript-eslint/scope-manager": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.0.tgz", "integrity": "sha512-OcCO7LTdk6ukawUM40wo61WdeoA7NM/zaoq1/2cs13M7GyiF+T4rxuA4xM+6LeHWjWbss7hkGXjFDRcKD4O04Q==", + "dev": true, "requires": { "@typescript-eslint/types": "4.22.0", "@typescript-eslint/visitor-keys": "4.22.0" @@ -2768,12 +2871,14 @@ "@typescript-eslint/types": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.0.tgz", - "integrity": "sha512-sW/BiXmmyMqDPO2kpOhSy2Py5w6KvRRsKZnV0c4+0nr4GIcedJwXAq+RHNK4lLVEZAJYFltnnk1tJSlbeS9lYA==" + "integrity": "sha512-sW/BiXmmyMqDPO2kpOhSy2Py5w6KvRRsKZnV0c4+0nr4GIcedJwXAq+RHNK4lLVEZAJYFltnnk1tJSlbeS9lYA==", + "dev": true }, "@typescript-eslint/typescript-estree": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.0.tgz", "integrity": "sha512-TkIFeu5JEeSs5ze/4NID+PIcVjgoU3cUQUIZnH3Sb1cEn1lBo7StSV5bwPuJQuoxKXlzAObjYTilOEKRuhR5yg==", + "dev": true, "requires": { "@typescript-eslint/types": "4.22.0", "@typescript-eslint/visitor-keys": "4.22.0", @@ -2788,6 +2893,7 @@ "version": "4.22.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.0.tgz", "integrity": "sha512-nnMu4F+s4o0sll6cBSsTeVsT4cwxB7zECK3dFxzEjPBii9xLpq4yqqsy/FU5zMfan6G60DKZSCXAa3sHJZrcYw==", + "dev": true, "requires": { "@typescript-eslint/types": "4.22.0", "eslint-visitor-keys": "^2.0.0" @@ -2796,7 +2902,8 @@ "eslint-visitor-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==" + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true } } }, @@ -5380,29 +5487,29 @@ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "contentful-management": { - "version": "7.17.4", - "resolved": "https://registry.npmjs.org/contentful-management/-/contentful-management-7.17.4.tgz", - "integrity": "sha512-kmxUr1n0ql93MSgcO2OaD2Wj189ZpjFjiog/QW3sQhglwCE1rIKHcu2tVFr6H2W9RinlAqqQCrPsnp68R9h3hQ==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/contentful-management/-/contentful-management-7.18.2.tgz", + "integrity": "sha512-d8P6BsOvjhgXavWTksfPB/C7etHQ5EP+R59d1wQ3xr8qHv4bVYOYF+eRnrgRHJQ9Cae8lk7N5JmZLwG/gEQuag==", "requires": { "@types/json-patch": "0.0.30", "axios": "^0.21.0", - "contentful-sdk-core": "^6.7.0", + "contentful-sdk-core": "^6.8.0", "fast-copy": "^2.1.0", "lodash.isplainobject": "^4.0.6", - "type-fest": "0.20.2" + "type-fest": "1.0.2" }, "dependencies": { "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.0.2.tgz", + "integrity": "sha512-a720oz3Kjbp3ll0zkeN9qjRhO7I34MKMhPGQiQJAmaZQZQ1lo+NWThK322f7sXV+kTg9B1Ybt16KgBXWgteT8w==" } } }, "contentful-sdk-core": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/contentful-sdk-core/-/contentful-sdk-core-6.7.0.tgz", - "integrity": "sha512-+b8UXVE249Z6WzMLXvsu3CIvN/s5xXRZ9o+zY7zDdPkIYBMW15xcs9N2ATI6ncmc+s1uj4XZij/2skflletHiw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/contentful-sdk-core/-/contentful-sdk-core-6.8.0.tgz", + "integrity": "sha512-X45uNrcbQ2qY2p4G/Wx2EFUdnLnoDXjw29i+d0JVTUXqCG58p3q4GHuAPzTX+uafJL4h0ZY2xPOn4nvJ83eRBQ==", "requires": { "fast-copy": "^2.1.0", "qs": "^6.9.4" @@ -5477,9 +5584,9 @@ } }, "core-js": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.11.1.tgz", - "integrity": "sha512-k93Isqg7e4txZWMGNYwevZL9MiogLk8pd1PtwrmFmi8IBq4GXqUaVW/a33Llt6amSI36uSjd0GWwc9pTT9ALlQ==" + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.12.0.tgz", + "integrity": "sha512-SaMnchL//WwU2Ot1hhkPflE8gzo7uq1FGvUJ8GKmi3TOU7rGTHIU+eir1WGf6qOtTyxdfdcp10yPdGZ59sQ3hw==" }, "core-js-compat": { "version": "3.11.1", @@ -5600,6 +5707,58 @@ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, + "cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "cross-fetch": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", @@ -5719,9 +5878,9 @@ } }, "postcss": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz", - "integrity": "sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ==", + "version": "8.2.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.14.tgz", + "integrity": "sha512-+jD0ZijcvyCqPQo/m/CW0UcARpdFylq04of+Q7RKX6f/Tu+dvpUI/9Sp81+i6/vJThnOBX09Quw0ZLOVwpzX3w==", "requires": { "colorette": "^1.2.2", "nanoid": "^3.1.22", @@ -6121,9 +6280,9 @@ "integrity": "sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ==" }, "date-fns": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.21.1.tgz", - "integrity": "sha512-m1WR0xGiC6j6jNFAyW4Nvh4WxAi4JF4w9jRJwSI8nBmNcyZXPcP9VUQG+6gHQXAmqaGEKDKhOqAtENDC941UkA==" + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.21.3.tgz", + "integrity": "sha512-HeYdzCaFflc1i4tGbj7JKMjM4cKGYoyxwcIIkHzNgCkX8xXDNJDZXgDDVchIWpN4eQc3lH37WarduXFZJOtxfw==" }, "debug": { "version": "4.3.1", @@ -6818,9 +6977,9 @@ } }, "dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" }, "download": { "version": "6.2.5", @@ -7053,9 +7212,9 @@ } }, "engine.io-client": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.1.3.tgz", - "integrity": "sha512-C3JYYyvna0FvSKOWGWpo0/EQ6MayO8uEKam1oedLZRpxLego9Fk6K3UH/Phieu1xPHauM7YqAygJ+6SraVc0Qg==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.1.4.tgz", + "integrity": "sha512-843fqAdKeUMFqKi1sSjnR11tJ4wi8sIefu6+JC1OzkkJBmjtc/gM/rZ53tJfu5Iae/3gApm5veoS+v+gtT0+Fg==", "requires": { "base64-arraybuffer": "0.1.4", "component-emitter": "~1.3.0", @@ -7065,7 +7224,7 @@ "parseqs": "0.0.6", "parseuri": "0.0.6", "ws": "~7.4.2", - "xmlhttprequest-ssl": "~1.5.4", + "xmlhttprequest-ssl": "~1.6.2", "yeast": "0.1.2" } }, @@ -7258,12 +7417,12 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz", - "integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.26.0.tgz", + "integrity": "sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==", "requires": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", + "@eslint/eslintrc": "^0.4.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -7350,9 +7509,9 @@ } }, "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" }, "globals": { "version": "13.8.0", @@ -7863,16 +8022,15 @@ "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==" }, "eslint-plugin-unicorn": { - "version": "31.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-31.0.0.tgz", - "integrity": "sha512-HR3gI4ANtV8A+0FLAaxjBD/G5J3PWBo+7OswyGeK5nylGqtKLJVbnPksIkBgmVg+SFpxu5MnjaxQQI+9KjyVAg==", + "version": "32.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-32.0.0.tgz", + "integrity": "sha512-VYE/XvZvdcY0RvOKGxsrVVWo8DaI/tGVYuhKzSd6Uuy69Ydc8zX+roZ/H9PgyykM4nuj8JDoOHSwVk9a4OYbCQ==", "dev": true, "requires": { "ci-info": "^3.1.1", "clean-regexp": "^1.0.0", "eslint-template-visitor": "^2.3.2", "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", "import-modules": "^2.1.0", "is-builtin-module": "^3.1.0", "lodash": "^4.17.21", @@ -7890,12 +8048,6 @@ "integrity": "sha512-kdRWLBIJwdsYJWYJFtAFFYxybguqeF91qpZaggjG5Nf8QKdizFG2hjqvaTXbxFIcYbSaD74KpAXv6BSm17DHEQ==", "dev": true }, - "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true - }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -7976,9 +8128,9 @@ }, "dependencies": { "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true } } @@ -9102,9 +9254,9 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "gatsby": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/gatsby/-/gatsby-3.4.0.tgz", - "integrity": "sha512-gqfJn1gvcNgVfhn1L0EWgW3To2tHZM9hdoxUweZVOtA9HdXeOONEV5xob2aDOl+fl3CLUmvSPSsb9PnqQEikuw==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/gatsby/-/gatsby-3.4.2.tgz", + "integrity": "sha512-iMIzCNOktXCPJ9Z7LPOyFkGvyfUxk3Jbt4j3B94AJVQje2E7KltOH1eJqg9GiJ0kzYO60jOyDw4abnr6gNSugQ==", "requires": { "@babel/code-frame": "^7.10.4", "@babel/core": "^7.12.3", @@ -9174,16 +9326,16 @@ "find-cache-dir": "^3.3.1", "fs-exists-cached": "1.0.0", "fs-extra": "^8.1.0", - "gatsby-cli": "^3.4.0", + "gatsby-cli": "^3.4.1", "gatsby-core-utils": "^2.4.0", "gatsby-graphiql-explorer": "^1.4.0", "gatsby-legacy-polyfills": "^1.4.0", "gatsby-link": "^3.4.0", - "gatsby-plugin-page-creator": "^3.4.0", + "gatsby-plugin-page-creator": "^3.4.1", "gatsby-plugin-typescript": "^3.4.0", "gatsby-plugin-utils": "^1.4.0", "gatsby-react-router-scroll": "^4.4.0", - "gatsby-telemetry": "^2.4.0", + "gatsby-telemetry": "^2.4.1", "glob": "^7.1.6", "got": "8.3.2", "graphql": "^15.4.0", @@ -9205,7 +9357,7 @@ "memoizee": "^0.4.15", "micromatch": "^4.0.2", "mime": "^2.4.6", - "mini-css-extract-plugin": "1.3.9", + "mini-css-extract-plugin": "1.5.1", "mitt": "^1.2.0", "mkdirp": "^0.5.1", "moment": "^2.27.0", @@ -9336,9 +9488,9 @@ } }, "gatsby-cli": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/gatsby-cli/-/gatsby-cli-3.4.0.tgz", - "integrity": "sha512-mqf8SbaY0ZEQBUedkchnGwLlBR64HQSXJ/KA1kciDwWyHpOlipXByYpXNpakolA9VDKBfHYTu1tofPxcfM+0fA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/gatsby-cli/-/gatsby-cli-3.4.1.tgz", + "integrity": "sha512-w93IcAL/Zl1x9oD6pw/iJ0DkAC1V78NhL9K0QvIjwa5Rx/EOhZ0cx3+bX9/l1v1aDX8YSUk09Ac4QhAizeGBUA==", "requires": { "@babel/code-frame": "^7.10.4", "@types/common-tags": "^1.8.0", @@ -9354,8 +9506,8 @@ "fs-exists-cached": "^1.0.0", "fs-extra": "^8.1.0", "gatsby-core-utils": "^2.4.0", - "gatsby-recipes": "^0.15.0", - "gatsby-telemetry": "^2.4.0", + "gatsby-recipes": "^0.15.1", + "gatsby-telemetry": "^2.4.1", "hosted-git-info": "^3.0.6", "is-valid-path": "^0.1.1", "joi": "^17.4.0", @@ -9730,9 +9882,9 @@ } }, "gatsby-plugin-page-creator": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/gatsby-plugin-page-creator/-/gatsby-plugin-page-creator-3.4.0.tgz", - "integrity": "sha512-H+UaS/XFalUUIIvaLXWKLeBdqLwp3gkGOYNoNfcmIsd82PHQWvcaVmCNmzaA+ji6ByOA043rNB2tOcAz84s+jw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/gatsby-plugin-page-creator/-/gatsby-plugin-page-creator-3.4.1.tgz", + "integrity": "sha512-/nDtxG2Bq5SMpvg0MONHJ5m+r2fPzXtiap+XXvLO7tsc08E7YdckrpJZ5OQ5NlEjcN3iPPHmYpLoUd9wSgttXA==", "requires": { "@babel/traverse": "^7.12.5", "@sindresorhus/slugify": "^1.1.2", @@ -9740,7 +9892,7 @@ "fs-exists-cached": "^1.0.0", "gatsby-core-utils": "^2.4.0", "gatsby-page-utils": "^1.4.0", - "gatsby-telemetry": "^2.4.0", + "gatsby-telemetry": "^2.4.1", "globby": "^11.0.3", "lodash": "^4.17.21" } @@ -9763,9 +9915,9 @@ } }, "gatsby-plugin-sharp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/gatsby-plugin-sharp/-/gatsby-plugin-sharp-3.4.0.tgz", - "integrity": "sha512-qIdW+5p0wv+Tr8lv87tRh39H8WZFyaR2yyXVrDDde7HUWUbfUbbR7+WzXzHC9X5VEWnZDC4g/66CLpKzOnV2tQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/gatsby-plugin-sharp/-/gatsby-plugin-sharp-3.4.2.tgz", + "integrity": "sha512-0fr6Oemfj4DeRinisH6I1BVsMV6WujXNtS94FV+ayar6Cr8kdzl8rgwEiW7egXbHsG1xKnYnzQ0zQACT9S47AA==", "requires": { "@babel/runtime": "^7.12.5", "async": "^3.2.0", @@ -9773,7 +9925,7 @@ "filenamify": "^4.2.0", "fs-extra": "^9.1.0", "gatsby-core-utils": "^2.4.0", - "gatsby-telemetry": "^2.4.0", + "gatsby-telemetry": "^2.4.1", "got": "^10.7.0", "imagemin": "^7.0.1", "imagemin-mozjpeg": "^9.0.0", @@ -9905,9 +10057,9 @@ "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" }, "p-cancelable": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.0.tgz", - "integrity": "sha512-HAZyB3ZodPo+BDpb4/Iu7Jv4P6cSazBz9ZM0ChhEXp70scx834aWCEjQRwgt41UzzejUAPdbqqONfRWTPYrPAQ==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" }, "responselike": { "version": "2.0.0", @@ -9989,9 +10141,9 @@ } }, "gatsby-recipes": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/gatsby-recipes/-/gatsby-recipes-0.15.0.tgz", - "integrity": "sha512-obucDJnWXbOKoxCfNdI9IZ2tXZzfvp8HkRJ6T2xNX8Wwk9F/UuwoQAvWZXdfHR9+rO8ynRBLMPMRcszKa9x+iw==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/gatsby-recipes/-/gatsby-recipes-0.15.1.tgz", + "integrity": "sha512-GyQbITic2Id1rkG7UaQ1ALqAy/rP1ACS90jOM8iU4KTTYMfClNRoRcpOFuPGGBhNJ71Oigbk9fXDCYEHy8IZdw==", "requires": { "@babel/core": "^7.12.3", "@babel/generator": "^7.12.5", @@ -10017,7 +10169,7 @@ "express-graphql": "^0.9.0", "fs-extra": "^8.1.0", "gatsby-core-utils": "^2.4.0", - "gatsby-telemetry": "^2.4.0", + "gatsby-telemetry": "^2.4.1", "glob": "^7.1.6", "graphql": "^15.4.0", "graphql-compose": "~7.25.0", @@ -10054,9 +10206,9 @@ }, "dependencies": { "@graphql-tools/utils": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.8.1.tgz", - "integrity": "sha512-LDbOweemjxPYgJuHXK5XZJgObsBkiD92ul98lcuZxgA49IzQazHho5Y1Hs3MluD93YtZpxsQg/f7gNPnAyR6yw==", + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.9.1.tgz", + "integrity": "sha512-k4bQWsOnSJSW7suBnVUJf3Sc8uXuvIYLHXujbEoSrwOEHjC+707GvXbQ7rg+8l7v8NMgpyARyuKFlqz3cfoxBQ==", "requires": { "@ardatan/aggregate-error": "0.0.6", "camel-case": "4.1.2", @@ -10137,9 +10289,9 @@ } }, "gatsby-telemetry": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/gatsby-telemetry/-/gatsby-telemetry-2.4.0.tgz", - "integrity": "sha512-OF4Qj1bn+BeBn0DQ9wwbOxaFFz6IPyYIoZW7nxdb65wwotBlWNBkL2LhwpEpvQ6U4tydxVNGYEZSJ7TSVS/+Gg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/gatsby-telemetry/-/gatsby-telemetry-2.4.1.tgz", + "integrity": "sha512-VLlZvFCdpCCT0mxnSK1UE/uD7NY/7Sj5vwvv09WRDlIGw6qaUJFWLIav99WXocbIN0FvYKKGIbmIUlmBnhxzVA==", "requires": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -13598,9 +13750,9 @@ }, "dependencies": { "acorn": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.2.tgz", - "integrity": "sha512-VrMS8kxT0e7J1EX0p6rI/E0FbfOVcvBpbIqHThFv+f8YrZIlMfVotYcXKVPmTvPW8sW5miJzfUFrrvthUZg8VQ==" + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.4.tgz", + "integrity": "sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg==" } } }, @@ -13683,9 +13835,9 @@ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" }, "mini-css-extract-plugin": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.9.tgz", - "integrity": "sha512-Ac4s+xhVbqlyhXS5J/Vh/QXUz3ycXlCqoCPpg0vdfhsIBH9eg/It/9L1r1XhSCH737M1lqcWnMuWL13zcygn5A==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.5.1.tgz", + "integrity": "sha512-wEpr0XooH6rw/Mlf+9KTJoMBLT3HujzdTrmohPjAzF47N4Q6yAeczQLpRD/WxvAtXvskcXbily7TAdCfi2M4Dg==", "requires": { "loader-utils": "^2.0.0", "schema-utils": "^3.0.0", @@ -18096,9 +18248,9 @@ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" }, "selfsigned": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", - "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz", + "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==", "requires": { "node-forge": "^0.10.0" } @@ -18510,9 +18662,9 @@ } }, "slugify": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.5.0.tgz", - "integrity": "sha512-Q2UPZ2udzquy1ElHfOLILMBMqBEXkiD3wE75qtBvV+FsDdZZjUqPZ44vqLTejAVq+wLLHacOMcENnP8+ZbzmIA==" + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.5.2.tgz", + "integrity": "sha512-Grpsq9/NLsae2qF2GJcoTcnDxIKp1Yt59mC+Lq+SE5xovVAckY8xG4A8jUPdY7IXhHg84u0cU/oij1XX4FXxpA==" }, "smart-buffer": { "version": "4.1.0", @@ -18657,9 +18809,9 @@ }, "dependencies": { "@types/node": { - "version": "14.14.43", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.43.tgz", - "integrity": "sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ==" + "version": "14.14.44", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.44.tgz", + "integrity": "sha512-+gaugz6Oce6ZInfI/tK4Pq5wIIkJMEJUu92RB3Eu93mtj4wjjjz9EB5mLp5s1pSsLXdC/CPut/xF20ZzAQJbTA==" } } }, @@ -19542,13 +19694,12 @@ } }, "table": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.6.0.tgz", - "integrity": "sha512-iZMtp5tUvcnAdtHpZTWLPF0M7AgiQsURR2DwmxnJwSy8I3+cY+ozzVvYha3BOLG2TB+L0CqjIz+91htuj6yCXg==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.0.tgz", + "integrity": "sha512-SAM+5p6V99gYiiy2gT5ArdzgM1dLDed0nkrWmG6Fry/bUS/m9x83BwpJUOf1Qj/x2qJd+thL6IkIx7qPGRxqBw==", "requires": { "ajv": "^8.0.1", "lodash.clonedeep": "^4.5.0", - "lodash.flatten": "^4.4.0", "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", "string-width": "^4.2.0", @@ -20550,6 +20701,11 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, + "use-detect-print": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/use-detect-print/-/use-detect-print-0.0.2.tgz", + "integrity": "sha512-J0fu46/PNDuuP0qyXkabwi9nJtPPZmOOr6p6KLyEGHOA1fWqREMliS4Bcj7znp9zVrDdq67vpzX55PGJamK+2Q==" + }, "utif": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", @@ -20740,9 +20896,9 @@ }, "dependencies": { "acorn": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.2.tgz", - "integrity": "sha512-VrMS8kxT0e7J1EX0p6rI/E0FbfOVcvBpbIqHThFv+f8YrZIlMfVotYcXKVPmTvPW8sW5miJzfUFrrvthUZg8VQ==" + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.2.4.tgz", + "integrity": "sha512-Ibt84YwBDDA890eDiDCEqcbwvHlBvzzDkU2cGBBDDI1QWT12jTiXIOn2CIw5KK4i6N5Z2HUxwYjzriDyqaqqZg==" }, "schema-utils": { "version": "3.0.0", @@ -21796,14 +21952,14 @@ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.2.tgz", + "integrity": "sha512-tYOaldF/0BLfKuoA39QMwD4j2m8lq4DIncqj1yuNELX4vz9+z/ieG/vwmctjJce+boFHXstqhWnHSxc4W8f4qg==" }, "xss": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.8.tgz", - "integrity": "sha512-3MgPdaXV8rfQ/pNn16Eio6VXYPTkqwa0vc7GkiymmY/DqR1SE/7VPAAVZz1GJsJFrllMYO3RHfEaiUGjab6TNw==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.9.tgz", + "integrity": "sha512-2t7FahYnGJys6DpHLhajusId7R0Pm2yTmuL0GV9+mV0ZlaLSnb2toBmppATfg5sWIhZQGlsTLoecSzya+l4EAQ==", "requires": { "commander": "^2.20.3", "cssfilter": "0.0.10" diff --git a/package.json b/package.json index c7bae61..110bdcf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "resume-builder", - "version": "4.0.1", + "version": "4.0.2", "description": "Resume Builder", "main": "index.js", "author": "Pablo Pirata", @@ -11,8 +11,8 @@ "scripts": { "inspect": "node --inspect-brk --no-lazy node_modules/gatsby/dist/bin/gatsby develop", "clean": "gatsby clean", - "build": "NODE_ENV=production && gatsby build --prefix-paths", - "develop": "NODE_ENV=development && gatsby develop", + "build": "cross-env NODE_ENV=production && gatsby build --prefix-paths", + "develop": "cross-env NODE_ENV=development && gatsby develop", "format": "prettier --write \"**/*.{js,jsx,json,md}\"", "start": "npm run develop", "serve": "gatsby serve", @@ -30,7 +30,7 @@ "@material-ui/lab": "^4.0.0-alpha.58", "@material-ui/styles": "^4.11.4", "classnames": "^2.3.1", - "gatsby": "^3.4.0", + "gatsby": "^3.4.2", "gatsby-background-image": "^1.5.3", "gatsby-image": "^3.4.0", "gatsby-plugin-disqus": "^1.2.2", @@ -43,7 +43,7 @@ "gatsby-plugin-offline": "^4.4.0", "gatsby-plugin-react-helmet": "^4.4.0", "gatsby-plugin-robots-txt": "^1.5.6", - "gatsby-plugin-sharp": "^3.4.0", + "gatsby-plugin-sharp": "^3.4.2", "gatsby-plugin-sitemap": "^4.0.0", "gatsby-plugin-typography": "^3.4.0", "gatsby-source-filesystem": "^3.4.0", @@ -60,12 +60,14 @@ "typeface-roboto": "1.1.13", "typography": "^0.16.19", "typography-theme-wordpress-2016": "^0.16.19", + "use-detect-print": "0.0.2", "uuid": "^8.3.2", "xlsx": "^0.16.9" }, "devDependencies": { "babel-preset-gatsby": "^1.4.0", - "eslint": "^7.25.0", + "cross-env": "^7.0.3", + "eslint": "^7.26.0", "eslint-config-airbnb": "^18.2.1", "eslint-config-gatsby-standard": "^3.0.2", "eslint-import-resolver-webpack": "^0.13.0", @@ -79,7 +81,7 @@ "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-react": "^7.23.2", "eslint-plugin-react-hooks": "^4.2.0", - "eslint-plugin-unicorn": "^31.0.0", + "eslint-plugin-unicorn": "^32.0.0", "eslint-plugin-unused-imports": "^1.1.1", "gatsby-plugin-eslint": "^3.0.0", "npm-check-updates": "^11.5.10", diff --git a/resume.json b/resume.json index 9b6a378..5d4d6ce 100644 --- a/resume.json +++ b/resume.json @@ -43,6 +43,10 @@ "Build an algorithm for artist to detect if their music was violating copy right infringement laws", "Successfully won Techcrunch Disrupt", "Optimized an algorithm that holds the current world record for Weisman Scores" + ], + "keywords": [ + "Javascript", + "React" ] } ], @@ -181,5 +185,6 @@ "summary": "Summary", "experience": "Experience", "at": "at" - } + }, + "enableSourceDataDownload": true } diff --git a/src/components/DownloadJsonLink.jsx b/src/components/DownloadJsonLink.jsx new file mode 100644 index 0000000..be1c6d0 --- /dev/null +++ b/src/components/DownloadJsonLink.jsx @@ -0,0 +1,57 @@ +/* eslint-disable react/jsx-props-no-spreading, no-shadow */ +import React, { useMemo } from 'react'; +import { Link } from '@material-ui/core'; +import PropTypes from 'prop-types'; +import { makeStyles } from '@material-ui/core/styles'; +import classNames from 'classnames'; + +// Utils +import { isClient } from '../utils/utils'; + +const useStyles = makeStyles((theme) => ({ + linkWrapper: {}, +})); + +const DownloadJsonLink = ({ + className = null, + children, + json = {}, + name = 'object.json', +}) => { + const classes = useStyles(); + const href = useMemo( + () => { + if (isClient()) { + const base64Data = btoa(unescape(encodeURIComponent(JSON.stringify(json)))); + return `data:application/json;base64,${base64Data}`; + } + + return '#'; + }, + [json] + ); + + return ( + + {children} + + ); +}; + +DownloadJsonLink.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + name: PropTypes.string, + // eslint-disable-next-line react/forbid-prop-types + json: PropTypes.object, +}; + +export default DownloadJsonLink; diff --git a/src/components/ResumeDrawerItems/Items/CoverLetter.jsx b/src/components/ResumeDrawerItems/Items/CoverLetter.jsx index 0653ec8..60a6c22 100644 --- a/src/components/ResumeDrawerItems/Items/CoverLetter.jsx +++ b/src/components/ResumeDrawerItems/Items/CoverLetter.jsx @@ -3,6 +3,7 @@ import { makeStyles } from '@material-ui/styles'; // Components import ItemInput from './List/ItemInput'; +import VariableInput from './List/VariableInput'; // Styles import style from '../resumeDrawerStyles'; @@ -12,7 +13,6 @@ import setResumeCoverLetter from '../../../store/actions/setResumeCoverLetter'; // Hooks import { useDispatch } from '../../../store/StoreProvider'; -import VariableInput from './List/VariableInput'; const useStyles = makeStyles((theme) => ({ ...style, diff --git a/src/components/ResumeDrawerItems/Items/Download.jsx b/src/components/ResumeDrawerItems/Items/Download.jsx new file mode 100644 index 0000000..46a88ec --- /dev/null +++ b/src/components/ResumeDrawerItems/Items/Download.jsx @@ -0,0 +1,38 @@ +import React, { useCallback, memo } from 'react'; +import { makeStyles } from '@material-ui/styles'; + +// Components +import ItemInput from './List/ItemInput'; + +// Styles +import style from '../resumeDrawerStyles'; + +// Actions +import setEnableSourceDataDownload from '../../../store/actions/setEnableSourceDataDownload'; + +// Hooks +import { useDispatch } from '../../../store/StoreProvider'; + +const useStyles = makeStyles((theme) => ({ + ...style, +})); + +function Download({ enableSourceDataDownload }) { + const classes = useStyles(); + const dispatch = useDispatch(); + const toggleCoverLetter = useCallback(() => { + dispatch(setEnableSourceDataDownload(!enableSourceDataDownload)); + }, [enableSourceDataDownload, dispatch]); + + return ( +
+ +
+ ); +} + +export default memo(Download); diff --git a/src/components/ResumeDrawerItems/Items/Work.jsx b/src/components/ResumeDrawerItems/Items/Work.jsx index 78e5104..2ea456b 100644 --- a/src/components/ResumeDrawerItems/Items/Work.jsx +++ b/src/components/ResumeDrawerItems/Items/Work.jsx @@ -106,6 +106,40 @@ function Work({ work: workData }) { }, }; } + + return wrk; + }); + setResumeWorkState(newWork); + }, [setResumeWorkState, workData]); + + const toggleWorkKeywords = useCallback((oldWork, keyword) => () => { + const newWork = { ...workData }; + newWork.value = + newWork?.value.map((wrk) => { + if (JSON.stringify(wrk?.value) === JSON.stringify(oldWork?.value)) { + return { + ...wrk, + value: { + ...wrk?.value, + keywords: { + ...wrk?.value.keywords, + value: [ + ...wrk?.value.keywords?.value.map((kword) => { + if (JSON.stringify(kword?.value) === JSON.stringify(keyword?.value)) { + return { + ...kword, + enabled: !kword?.enabled, + }; + } + + return kword; + }), + ], + }, + }, + }; + } + return wrk; }); setResumeWorkState(newWork); @@ -131,6 +165,7 @@ function Work({ work: workData }) { endDate, summary, highlights, + keywords, } = work?.value || {}; return ( @@ -249,6 +284,31 @@ function Work({ work: workData }) { ))} )} + {keywords && ( + + )} + {keywords?.enabled && ( + + )} )} diff --git a/src/components/ResumeDrawerItems/ResumeDrawerItems.jsx b/src/components/ResumeDrawerItems/ResumeDrawerItems.jsx index aa210e9..1db29ab 100644 --- a/src/components/ResumeDrawerItems/ResumeDrawerItems.jsx +++ b/src/components/ResumeDrawerItems/ResumeDrawerItems.jsx @@ -21,6 +21,7 @@ import Volunteer from './Items/Volunteer'; import Work from './Items/Work'; import CoverLetter from './Items/CoverLetter'; import Certificates from './Items/Certificates'; +import Download from './Items/Download'; // Utils import { isObjectNotEmpty } from '../../utils/utils'; @@ -47,8 +48,10 @@ const ResumeDrawerItems = ({ interests, references, projects, - coverLetter, certificates, + // custom attributes + coverLetter, + enableSourceDataDownload = false, }, onClose, jsonResume, @@ -62,7 +65,10 @@ const ResumeDrawerItems = ({ }; const handleDownloadJson = useCallback(() => { - downloadJson(jsonResume); + downloadJson({ + ...jsonResume, + coverLetter: jsonResume.coverLetter.text, + }); }, [jsonResume]); return ( @@ -104,6 +110,9 @@ const ResumeDrawerItems = ({ coverLetter={coverLetter} /> )} + {isObjectNotEmpty(basics) && ( ({ })); const Compact = ({ - resume: { + togglableJsonResume: { basics, work, skills, diff --git a/src/components/ResumeTemplates/Compact/Sections/Awards.jsx b/src/components/ResumeTemplates/Compact/Sections/Awards.jsx index b3a8c58..a67cd76 100644 --- a/src/components/ResumeTemplates/Compact/Sections/Awards.jsx +++ b/src/components/ResumeTemplates/Compact/Sections/Awards.jsx @@ -1,7 +1,7 @@ -import React, { useContext } from 'react'; +import React from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; import { Typography } from '@material-ui/core'; import classNames from 'classnames'; @@ -18,6 +18,7 @@ const useStyles = makeStyles((theme) => ({ marginBottom: '-25px', }, }, + resumeAwards: {}, })); const Awards = ({ @@ -25,7 +26,7 @@ const Awards = ({ className = null, }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); return awards.length > 0 && (
({ resumeBasicsWrapper: { @@ -78,7 +78,7 @@ const Basics = ({ }, }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); return (
diff --git a/src/components/ResumeTemplates/Compact/Sections/Education.jsx b/src/components/ResumeTemplates/Compact/Sections/Education.jsx index f5f164f..36de215 100644 --- a/src/components/ResumeTemplates/Compact/Sections/Education.jsx +++ b/src/components/ResumeTemplates/Compact/Sections/Education.jsx @@ -1,7 +1,7 @@ -import React, { useContext } from 'react'; +import React from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; import { Typography } from '@material-ui/core'; import classNames from 'classnames'; @@ -10,6 +10,7 @@ const useStyles = makeStyles((theme) => ({ textTransform: 'uppercase', fontWeight: 'bold', }, + resumeEducation: {}, })); const Education = ({ @@ -17,7 +18,7 @@ const Education = ({ className = null, }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); return educations.length > 0 && (
({ @@ -9,13 +9,14 @@ const useStyles = makeStyles((theme) => ({ textTransform: 'uppercase', fontWeight: 'bold', }, + resumePublications: {}, })); const Publications = ({ publications, }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); return publications.length > 0 && (
diff --git a/src/components/ResumeTemplates/Compact/Sections/Skills.jsx b/src/components/ResumeTemplates/Compact/Sections/Skills.jsx index dfd6b68..6d45df3 100644 --- a/src/components/ResumeTemplates/Compact/Sections/Skills.jsx +++ b/src/components/ResumeTemplates/Compact/Sections/Skills.jsx @@ -1,7 +1,7 @@ -import React, { useContext } from 'react'; +import React from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; import { Typography } from '@material-ui/core'; const useStyles = makeStyles((theme) => ({ @@ -9,11 +9,12 @@ const useStyles = makeStyles((theme) => ({ textTransform: 'uppercase', fontWeight: 'bold', }, + resumeSkills: {}, })); const Skills = ({ skills }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); return skills.length > 0 && (
diff --git a/src/components/ResumeTemplates/Compact/intl/en.json b/src/components/ResumeTemplates/Compact/intl/en.json index a0af232..a23abf1 100644 --- a/src/components/ResumeTemplates/Compact/intl/en.json +++ b/src/components/ResumeTemplates/Compact/intl/en.json @@ -4,13 +4,13 @@ "skills": "Skills", "references": "References", "publications": "Publications", + "certificates": "Certificates", + "projects": "Projects", "languages": "Languages", "interests": "Interests", "education": "Education", - "about": "About", - "contact": "Contact", - "projects": "Projects", - "months": "Months", - "achievements": "achievements", - "experience": "Experience" + "summary": "Summary", + "experience": "Experience", + "at": "@", + "download_data": "Download the JSON data source for this resume here." } diff --git a/src/components/ResumeTemplates/Compact/intl/es.json b/src/components/ResumeTemplates/Compact/intl/es.json index 544c733..8e86c13 100644 --- a/src/components/ResumeTemplates/Compact/intl/es.json +++ b/src/components/ResumeTemplates/Compact/intl/es.json @@ -4,13 +4,13 @@ "skills": "Habilidades", "references": "Referencias", "publications": "Publicaciones", + "certificates": "Certificados", + "projects": "Proyectos", "languages": "Idiomas", "interests": "Intereses", "education": "Educación", - "about": "Acerca", - "contact": "Contacto", - "projects": "Proyectos", - "months": "Meses", - "achievements": "logros", - "experience": "Experiencia" + "summary": "Resumen", + "experience": "Experiencia", + "at": "@", + "download_data": "Descargue los datos JSON para esta hoja de vida haciendo clic aquí" } diff --git a/src/components/ResumeTemplates/Compact/intl/pt-br.json b/src/components/ResumeTemplates/Compact/intl/pt-br.json index 1c3199f..8c38fb1 100644 --- a/src/components/ResumeTemplates/Compact/intl/pt-br.json +++ b/src/components/ResumeTemplates/Compact/intl/pt-br.json @@ -4,13 +4,13 @@ "skills": "Habilidades", "references": "Referências", "publications": "Publicações", + "certificates": "Certificados", + "projects": "Projetos", "languages": "Línguas", "interests": "Interesses", "education": "Educação", - "about": "Sobre", - "contact": "Contato", - "projects": "Projetos", - "months": "Meses", - "achievements": "Conquistas", - "experience": "Experiência" + "summary": "Sumário", + "experience": "Experiência", + "at": "@", + "download_data": "Baixe os dados JSON desse currículo clicando aqui." } diff --git a/src/components/ResumeTemplates/Default/Index.jsx b/src/components/ResumeTemplates/Default/Index.jsx index 1916c5e..8d82359 100644 --- a/src/components/ResumeTemplates/Default/Index.jsx +++ b/src/components/ResumeTemplates/Default/Index.jsx @@ -19,6 +19,7 @@ import Work from './Sections/Work'; import Projects from './Sections/Projects'; import CoverLetter from './Sections/CoverLetter'; import Certificates from './Sections/Certificates'; +import Download from './Sections/Download'; // Utils import { isObjectNotEmpty } from '../../../utils/utils'; @@ -47,7 +48,10 @@ const useStyles = makeStyles((theme) => ({ const Default = ({ customTranslations = {}, - resume: { + isPrinting = false, + isOnlineViewer = false, + jsonResume, + togglableJsonResume: { basics, work, skills, @@ -59,8 +63,10 @@ const Default = ({ interests, references, projects, - coverLetter, certificates, + // custom attributes + coverLetter, + enableSourceDataDownload = false, }, }) => { const intl = useIntl(); @@ -99,6 +105,9 @@ const Default = ({ coverLetter={coverLetter?.value} /> )} + {enableSourceDataDownload && ( + + )} {basics?.enabled && ( ({ margin: '0', padding: '0', listStyle: 'none', - '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, }, contentWrapper: { marginLeft: '4px', @@ -35,7 +40,7 @@ const useStyles = makeStyles((theme) => ({ const Awards = ({ awards }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); diff --git a/src/components/ResumeTemplates/Default/Sections/Basics.jsx b/src/components/ResumeTemplates/Default/Sections/Basics.jsx index ed1c081..8d37c92 100644 --- a/src/components/ResumeTemplates/Default/Sections/Basics.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Basics.jsx @@ -1,7 +1,7 @@ -import React, { Fragment, useContext } from 'react'; +import React, { Fragment } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; const useStyles = makeStyles((theme) => ({ resumeSummary: { @@ -83,7 +83,7 @@ const Basics = ({ }, }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); return ( diff --git a/src/components/ResumeTemplates/Default/Sections/Certificates.jsx b/src/components/ResumeTemplates/Default/Sections/Certificates.jsx index 6065f5a..950e19b 100644 --- a/src/components/ResumeTemplates/Default/Sections/Certificates.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Certificates.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -16,7 +16,12 @@ const useStyles = makeStyles((theme) => ({ margin: '0', padding: '0', listStyle: 'none', - '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, }, contentWrapper: { marginLeft: '4px', @@ -35,7 +40,7 @@ const useStyles = makeStyles((theme) => ({ const Certificates = ({ certificates }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); diff --git a/src/components/ResumeTemplates/Default/Sections/CoverLetter.jsx b/src/components/ResumeTemplates/Default/Sections/CoverLetter.jsx index 51e12d9..a504b31 100644 --- a/src/components/ResumeTemplates/Default/Sections/CoverLetter.jsx +++ b/src/components/ResumeTemplates/Default/Sections/CoverLetter.jsx @@ -1,6 +1,6 @@ -import React, { Fragment, useContext, useMemo } from 'react'; +import React, { Fragment, useMemo } from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; import Mustache from 'mustache'; import { renderToString } from 'react-dom/server'; @@ -42,7 +42,7 @@ const useStyles = makeStyles((theme) => ({ const CoverLetter = ({ coverLetter }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const variables = useMemo(() => { const newVariables = {}; Object.entries(coverLetter.variables) diff --git a/src/components/ResumeTemplates/Default/Sections/Download.jsx b/src/components/ResumeTemplates/Default/Sections/Download.jsx new file mode 100644 index 0000000..2cdfaf9 --- /dev/null +++ b/src/components/ResumeTemplates/Default/Sections/Download.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Components +import DownloadJsonLink from '../../../DownloadJsonLink'; + +const useStyles = makeStyles((theme) => ({ + resumeDownload: {}, +})); + +const Download = ({ jsonResume }) => { + const classes = useStyles(); + const intl = useIntl(); + + return ( +
+ {intl.formatMessage({ + id: 'download_data', + }, + { + // eslint-disable-next-line react/display-name + a: (msg) => ( + + {msg} + + ), + })} +
+ ); +}; + +export default Download; diff --git a/src/components/ResumeTemplates/Default/Sections/Education.jsx b/src/components/ResumeTemplates/Default/Sections/Education.jsx index df8981d..d20dcdf 100644 --- a/src/components/ResumeTemplates/Default/Sections/Education.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Education.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -21,7 +21,12 @@ const useStyles = makeStyles((theme) => ({ margin: '0', padding: '0', listStyle: 'none', - '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, }, coursesDetails: { display: 'flex', @@ -50,7 +55,7 @@ const useStyles = makeStyles((theme) => ({ const Education = ({ education: educations }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); diff --git a/src/components/ResumeTemplates/Default/Sections/Interests.jsx b/src/components/ResumeTemplates/Default/Sections/Interests.jsx index 24a9aad..bcfef07 100644 --- a/src/components/ResumeTemplates/Default/Sections/Interests.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Interests.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -51,7 +51,7 @@ const useStyles = makeStyles((theme) => ({ const Interests = ({ interests }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); diff --git a/src/components/ResumeTemplates/Default/Sections/Languages.jsx b/src/components/ResumeTemplates/Default/Sections/Languages.jsx index 64368e5..0144af8 100644 --- a/src/components/ResumeTemplates/Default/Sections/Languages.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Languages.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -13,7 +13,12 @@ const useStyles = makeStyles((theme) => ({ }, languages: { margin: '0', - '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, }, contentWrapper: { marginLeft: '4px', @@ -28,7 +33,7 @@ const useStyles = makeStyles((theme) => ({ const Languages = ({ languages }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); diff --git a/src/components/ResumeTemplates/Default/Sections/Projects.jsx b/src/components/ResumeTemplates/Default/Sections/Projects.jsx index 5a4d30e..5080438 100644 --- a/src/components/ResumeTemplates/Default/Sections/Projects.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Projects.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -18,13 +18,32 @@ const useStyles = makeStyles((theme) => ({ '& li': { margin: '0 0 10px 0', '&:last-child': { - margin: '0', + margin: '3px 0 0', }, }, }, project: { fontWeight: 'bold', }, + highlights: { + '& li': { + marginBottom: '1px', + fontStyle: 'italic', + }, + }, + keywords: { + flexWrap: 'wrap', + listStyle: 'none', + paddingLeft: 0, + display: 'inline-flex', + '& li': { + fontStyle: 'italic', + margin: '3px 3px 0 0', + backgroundColor: theme.palette.type === 'dark' ? '#28407b' : '#dae4f4', + borderRadius: '3px', + padding: '1px 3px', + }, + }, contentWrapper: { marginLeft: '4px', }, @@ -42,7 +61,7 @@ const useStyles = makeStyles((theme) => ({ const Projects = ({ projects }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); @@ -103,6 +122,26 @@ const Projects = ({ projects }) => { {entity && entity?.enabled &&

{entity?.value}

} {(url && url?.enabled && url?.value) && {url.value}} {description && description?.enabled &&

{description?.value}

} + {highlights?.enabled && ( +
    + {highlights?.value.map((highlight) => + highlight?.enabled && ( +
  • + {highlight?.value} +
  • + ))} +
+ )} + {keywords?.enabled && ( +
    + {keywords?.value.map((keyword) => + keyword?.enabled && ( +
  • + {keyword?.value} +
  • + ))} +
+ )} ); } diff --git a/src/components/ResumeTemplates/Default/Sections/Publications.jsx b/src/components/ResumeTemplates/Default/Sections/Publications.jsx index 60b6254..cff4df3 100644 --- a/src/components/ResumeTemplates/Default/Sections/Publications.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Publications.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -15,7 +15,12 @@ const useStyles = makeStyles((theme) => ({ margin: '0', padding: '0', listStyle: 'none', - '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, }, publication: { fontWeight: 'bold', @@ -37,7 +42,7 @@ const useStyles = makeStyles((theme) => ({ const Publications = ({ publications }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); diff --git a/src/components/ResumeTemplates/Default/Sections/References.jsx b/src/components/ResumeTemplates/Default/Sections/References.jsx index ca97da3..09a6725 100644 --- a/src/components/ResumeTemplates/Default/Sections/References.jsx +++ b/src/components/ResumeTemplates/Default/Sections/References.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -15,7 +15,22 @@ const useStyles = makeStyles((theme) => ({ margin: '0', padding: '0', listStyle: 'none', - '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, + }, + reference: { + fontStyle: 'italic', + textIndent: '15px', + '&:before': { + content: '"❝"', + fontSize: '25px', + margin: '-8px 0 0 -35px', + position: 'absolute', + }, }, contentWrapper: { marginLeft: '4px', @@ -30,7 +45,7 @@ const useStyles = makeStyles((theme) => ({ const References = ({ references }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); @@ -72,7 +87,11 @@ const References = ({ references }) => { {name?.value}

)} - {reference?.enabled &&

{reference?.value}

} + {reference?.enabled && ( +

+ {reference?.value} +

+ )} ); } diff --git a/src/components/ResumeTemplates/Default/Sections/Skills.jsx b/src/components/ResumeTemplates/Default/Sections/Skills.jsx index cf0841f..06b9edd 100644 --- a/src/components/ResumeTemplates/Default/Sections/Skills.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Skills.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -49,7 +49,7 @@ const useStyles = makeStyles((theme) => ({ const Skills = ({ skills }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); diff --git a/src/components/ResumeTemplates/Default/Sections/Volunteer.jsx b/src/components/ResumeTemplates/Default/Sections/Volunteer.jsx index d5c32cf..9752d36 100644 --- a/src/components/ResumeTemplates/Default/Sections/Volunteer.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Volunteer.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -48,7 +48,7 @@ const useStyles = makeStyles((theme) => ({ const Volunteer = ({ volunteer: volunteers }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); diff --git a/src/components/ResumeTemplates/Default/Sections/Work.jsx b/src/components/ResumeTemplates/Default/Sections/Work.jsx index 9c7febf..6d92b4e 100644 --- a/src/components/ResumeTemplates/Default/Sections/Work.jsx +++ b/src/components/ResumeTemplates/Default/Sections/Work.jsx @@ -1,7 +1,7 @@ -import React, { useContext, useRef } from 'react'; +import React, { useRef } from 'react'; import { v4 as uuid } from 'uuid'; import { makeStyles } from '@material-ui/core/styles'; -import { IntlContext } from 'gatsby-plugin-intl'; +import { useIntl } from 'gatsby-plugin-intl'; // Hooks import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; @@ -35,6 +35,7 @@ const useStyles = makeStyles((theme) => ({ }, summary: { whiteSpace: 'break-spaces', + marginBottom: '5px !important', }, description: { whiteSpace: 'break-spaces', @@ -45,6 +46,19 @@ const useStyles = makeStyles((theme) => ({ fontStyle: 'italic', }, }, + keywords: { + flexWrap: 'wrap', + listStyle: 'none', + paddingLeft: 0, + display: 'inline-flex', + '& li': { + fontStyle: 'italic', + margin: '3px 3px 0 0', + backgroundColor: theme.palette.type === 'dark' ? '#28407b' : '#dae4f4', + borderRadius: '3px', + padding: '1px 3px', + }, + }, contentWrapper: { marginLeft: '4px', }, @@ -61,7 +75,7 @@ const useStyles = makeStyles((theme) => ({ const Work = ({ work: works }) => { const classes = useStyles(); - const intl = useContext(IntlContext); + const intl = useIntl(); const firstItem = useRef(null); const sectionTitle = useRef(null); const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); @@ -89,6 +103,7 @@ const Work = ({ work: works }) => { endDate, summary, highlights, + keywords, } = work?.value || {}; let refProps = {}; @@ -152,6 +167,16 @@ const Work = ({ work: works }) => { ))} )} + {keywords?.enabled && ( +
    + {keywords?.value.map((keyword) => + keyword?.enabled && ( +
  • + {keyword?.value} +
  • + ))} +
+ )} ); } diff --git a/src/components/ResumeTemplates/Default/intl/en.json b/src/components/ResumeTemplates/Default/intl/en.json index 68bf44f..a23abf1 100644 --- a/src/components/ResumeTemplates/Default/intl/en.json +++ b/src/components/ResumeTemplates/Default/intl/en.json @@ -11,5 +11,6 @@ "education": "Education", "summary": "Summary", "experience": "Experience", - "at": "@" + "at": "@", + "download_data": "Download the JSON data source for this resume here." } diff --git a/src/components/ResumeTemplates/Default/intl/es.json b/src/components/ResumeTemplates/Default/intl/es.json index 1c465ca..8e86c13 100644 --- a/src/components/ResumeTemplates/Default/intl/es.json +++ b/src/components/ResumeTemplates/Default/intl/es.json @@ -11,5 +11,6 @@ "education": "Educación", "summary": "Resumen", "experience": "Experiencia", - "at": "@" + "at": "@", + "download_data": "Descargue los datos JSON para esta hoja de vida haciendo clic aquí" } diff --git a/src/components/ResumeTemplates/Default/intl/pt-br.json b/src/components/ResumeTemplates/Default/intl/pt-br.json index 8e9ad73..8c38fb1 100644 --- a/src/components/ResumeTemplates/Default/intl/pt-br.json +++ b/src/components/ResumeTemplates/Default/intl/pt-br.json @@ -11,5 +11,6 @@ "education": "Educação", "summary": "Sumário", "experience": "Experiência", - "at": "@" + "at": "@", + "download_data": "Baixe os dados JSON desse currículo clicando aqui." } diff --git a/src/components/ResumeTemplates/VanHack/Index.jsx b/src/components/ResumeTemplates/VanHack/Index.jsx new file mode 100644 index 0000000..0fad657 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Index.jsx @@ -0,0 +1,167 @@ +import React, { useMemo } from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import { createIntl, createIntlCache, RawIntlProvider, useIntl } from 'gatsby-plugin-intl'; + +// local template translations +import templateIntls from './intl'; + +// Components +import Basics from './Sections/Basics'; +import Awards from './Sections/Awards'; +import Education from './Sections/Education'; +import Interests from './Sections/Interests'; +import Languages from './Sections/Languages'; +import Publications from './Sections/Publications'; +import References from './Sections/References'; +import Skills from './Sections/Skills'; +import Volunteer from './Sections/Volunteer'; +import Work from './Sections/Work'; +import Projects from './Sections/Projects'; +import CoverLetter from './Sections/CoverLetter'; +import Certificates from './Sections/Certificates'; + +// Utils +import { isObjectNotEmpty } from '../../../utils/utils'; + +const useStyles = makeStyles((theme) => ({ + resumeDefaultTemplate: { + padding: '40px', + '& h3': { margin: '0' }, + color: theme.palette.text.primary, + '& a': { + color: '#8da4f7', + }, + '& a:visited': { + color: '#48578a', + }, + '& p': { + margin: 0, + marginBlockStart: 0, + marginBlockEnd: 0, + }, + '@media print': { + padding: 0, + }, + }, +})); + +const VanHack = ({ + customTranslations = {}, + togglableJsonResume: { + basics, + work, + skills, + education, + awards, + volunteer, + publications, + languages, + interests, + references, + projects, + coverLetter, + certificates, + }, +}) => { + const intl = useIntl(); + const classes = useStyles(); + const templateIntl = useMemo(() => { + let newIntl = templateIntls.find( + (tempIntl) => tempIntl.locale === intl.locale + ); + + if (!newIntl) { + newIntl = templateIntls.find( + (tempIntl) => tempIntl.locale === intl.defaultLocale + ); + } + + if (isObjectNotEmpty(customTranslations)) { + return createIntl({ + locale: newIntl.locale, + messages: { + ...newIntl.messages, + ...customTranslations, + }, + }, createIntlCache()); + } + + return newIntl; + }, [customTranslations, intl.defaultLocale, intl.locale]); + + return ( + +
+ {(coverLetter?.enabled && coverLetter?.value) && ( + + )} + {basics?.enabled && ( + + )} + {(skills?.enabled && skills?.value.length) && ( + + )} + {(work?.enabled && work?.value.length) && ( + + )} + {(education?.enabled && education?.value.length) && ( + + )} + {(awards?.enabled && awards?.value.length) && ( + + )} + {(certificates?.enabled && certificates?.value.length) && ( + + )} + {(volunteer?.enabled && volunteer?.value.length) && ( + + )} + {(publications?.enabled && publications?.value.length) && ( + + )} + {(projects?.enabled && projects?.value.length) && ( + + )} + {(languages?.enabled && languages?.value.length) && ( + + )} + {(interests?.enabled && interests?.value.length) && ( + + )} + {(references?.enabled && references?.value.length) && ( + + )} +
+
+ ); +}; + +export default VanHack; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Awards.jsx b/src/components/ResumeTemplates/VanHack/Sections/Awards.jsx new file mode 100644 index 0000000..96ce2fb --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Awards.jsx @@ -0,0 +1,99 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeAwards: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + award: { fontWeight: 'bold' }, + awards: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + }, + contentWrapper: { + marginLeft: '4px', + }, + awardWrapper: { + pageBreakInside: 'avoid', + }, + positionDate: { + fontStyle: 'italic', + fontSize: '0.8rem', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Awards = ({ awards }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return awards.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'awards' })} +

+
+
    + {awards.map((award) => { + if (award?.enabled) { + const { + title, + date, + awarder, + summary, + } = award?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • +

    + {title?.enabled && title?.value} + {(date?.enabled && date?.value) && ( + + {` (${date?.value})`} + + )} +

    +

    {awarder?.enabled && awarder?.value}

    +

    {summary?.enabled && summary?.value}

    +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Awards; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Basics.jsx b/src/components/ResumeTemplates/VanHack/Sections/Basics.jsx new file mode 100644 index 0000000..8d37c92 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Basics.jsx @@ -0,0 +1,164 @@ +import React, { Fragment } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +const useStyles = makeStyles((theme) => ({ + resumeSummary: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + resumeBasics: { + pageBreakInside: 'avoid', + padding: '10px 0', + borderBottom: '1px solid #ddd', + '& h2': { textTransform: 'uppercase', margin: '0' }, + }, + address: { + margin: '0', + padding: '0', + display: 'flex', + listStyle: 'none', + '& li': { + margin: '0 5px 0 0', + '&:after': { content: '","' }, + '&:last-child': { '&:after': { content: '""' } }, + }, + }, + 'contact-info': { + margin: '0', + padding: '0', + display: 'flex', + listStyle: 'none', + '& li': { + margin: '0 5px 0 0', + '&:after': { content: '" |"' }, + '&:last-child': { '&:after': { content: '""' } }, + }, + }, + 'social-media': { + margin: '0', + padding: '0', + display: 'flex', + listStyle: 'none', + '& li': { + margin: '0 5px 0 0', + '&:after': { content: '" |"' }, + '&:last-child': { '&:after': { content: '""' } }, + }, + }, + url: {}, + detailsWrapper: { + marginLeft: '4px', + }, + summaryWrapper: { + marginLeft: '4px', + }, + image: { + width: '100px', + float: 'right', + }, +})); + +const Basics = ({ + basics: { + name, + label, + image, + email, + phone, + url, + summary, + location: { + enabled: locationEnabled, + value: { + address, + postalCode, + city, + countryCode, + region, + }, + }, + profiles, + }, +}) => { + const classes = useStyles(); + const intl = useIntl(); + + return ( + +
+ {(image?.enabled && image.value) && ( + avatar + )} + {name?.enabled &&

{name?.value}

} + {label?.enabled &&

{label?.value}

} +
+ {locationEnabled && ( +
    + {address?.enabled &&
  • {address?.value}
  • } + {city?.enabled &&
  • {city?.value}
  • } + {region?.enabled &&
  • {region?.value}
  • } + {postalCode?.enabled &&
  • {postalCode?.value}
  • } + {countryCode?.enabled &&
  • {countryCode?.value}
  • } +
+ )} +
    + {url?.enabled && ( +
  • + + {url?.value} + +
  • + )} + {phone?.enabled &&
  • {phone?.value}
  • } + {email?.enabled &&
  • {email?.value}
  • } +
+ {profiles?.enabled && ( +
    + {profiles?.value.map((profile) => { + if (profile?.enabled) { + const { url: profileUrl, network, username } = profile?.value || {}; + + return profileUrl?.enabled && network?.enabled && username?.enabled && ( +
  • + + {network?.value} + +
  • + ); + } + + return null; + })} +
+ )} +
+
+ {summary?.enabled && ( +
+

+ {intl.formatMessage({ id: 'summary' })} +

+
+

{summary?.value}

+
+
+ )} +
+ ); +}; + +export default Basics; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Certificates.jsx b/src/components/ResumeTemplates/VanHack/Sections/Certificates.jsx new file mode 100644 index 0000000..54c3f22 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Certificates.jsx @@ -0,0 +1,99 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeCertificates: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + award: { fontWeight: 'bold' }, + certificates: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + }, + contentWrapper: { + marginLeft: '4px', + }, + awardWrapper: { + pageBreakInside: 'avoid', + }, + positionDate: { + fontStyle: 'italic', + fontSize: '0.8rem', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Certificates = ({ certificates }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return certificates.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'certificates' })} +

+
+
    + {certificates.map((award) => { + if (award?.enabled) { + const { + name, + date, + url, + issuer, + } = award?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • +

    + {name?.enabled && name?.value} + {(date?.enabled && date?.value) && ( + + {` (${date?.value})`} + + )} +

    + {(url && url?.enabled && url?.value) && {url.value}} +

    {issuer?.enabled && issuer?.value}

    +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Certificates; diff --git a/src/components/ResumeTemplates/VanHack/Sections/CoverLetter.jsx b/src/components/ResumeTemplates/VanHack/Sections/CoverLetter.jsx new file mode 100644 index 0000000..a504b31 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/CoverLetter.jsx @@ -0,0 +1,81 @@ +import React, { Fragment, useMemo } from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; +import Mustache from 'mustache'; +import { renderToString } from 'react-dom/server'; + +const useStyles = makeStyles((theme) => ({ + contentWrapper: { + whiteSpace: 'break-spaces', + marginBottom: '40px', + '@media print': { + clear: 'both', + pageBreakAfter: 'always', + breakAfter: 'page', + minHeight: '29.7cm', + marginBottom: 0, + }, + }, + variable: { + backgroundColor: theme.palette.type === 'dark' ? '#303030' : '#cccccc', + padding: '0 2px', + '@media print': { + backgroundColor: 'unset', + padding: 0, + }, + }, + pageBreakWarning: { + height: '35px', + padding: 0, + marginLeft: '-42px', + width: '112%', + textAlign: 'center', + fontStyle: 'italic', + color: theme.palette.type === 'dark' ? '#6b6b6b' : '#b1afaf', + backgroundColor: theme.palette.type === 'dark' ? '#303030' : '#fafafa', + paddingTop: '5px', + '@media print': { + display: 'none', + }, + }, +})); + +const CoverLetter = ({ coverLetter }) => { + const classes = useStyles(); + const intl = useIntl(); + const variables = useMemo(() => { + const newVariables = {}; + Object.entries(coverLetter.variables) + .forEach((entry) => { + const [key, value] = entry; + newVariables[key] = renderToString( + + {value} + + ); + }); + + return newVariables; + }, [classes.variable, coverLetter.variables]); + + const text = useMemo( + () => coverLetter.text.replaceAll('{{', '{{{').replaceAll('}}', '}}}'), + [coverLetter.text] + ); + + return ( + +
+
+ {intl.formatMessage({ id: 'this_is_a_page_break' })} +
+ + ); +}; + +export default CoverLetter; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Education.jsx b/src/components/ResumeTemplates/VanHack/Sections/Education.jsx new file mode 100644 index 0000000..f29a1b3 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Education.jsx @@ -0,0 +1,149 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeEducation: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + type: { fontWeight: 'bold' }, + institution: {}, + positionDate: { + fontStyle: 'italic', + fontSize: '0.8rem', + }, + courses: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + }, + coursesDetails: { + display: 'flex', + '& ul': { + margin: '0 0 0 5px', + padding: '0', + display: 'flex', + listStyle: 'none', + '& li': { + margin: '0 5px 0 0', + '&:after': { content: '","' }, + '&:last-child': { '&:after': { content: '""' } }, + }, + }, + }, + contentWrapper: { + marginLeft: '4px', + }, + educationWrapper: { + pageBreakInside: 'avoid', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Education = ({ education: educations }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return educations.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'education' })} +

+
+
    + {educations.map((education) => { + if (education?.enabled) { + const { + institution, + url, + area, + studyType, + startDate, + endDate, + score, + courses, + } = education?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • +

    + {area?.enabled && area?.value} + {( + (area?.enabled && studyType?.enabled) + && (area?.value && studyType?.value) + ) && ', '} + {studyType?.enabled && studyType?.value} + {(startDate?.enabled || endDate?.enabled) && ( + + {' ('} + {startDate?.enabled && startDate?.value} + {(startDate?.enabled && endDate?.enabled) && ' - '} + {endDate?.enabled && endDate?.value} + {')'} + + )} +

    +

    + { + (url?.enabled && institution?.enabled) + && (url?.value && institution?.value) ? + ( + + {institution?.value} + + ) + : institution?.value} + {score && score?.enabled && `, score: ${score?.value}`} +

    + {courses && courses?.enabled && ( +
    +

    Courses:

    +
      + {courses?.value.map((course) => course?.enabled && ( +
    • + {course?.value} +
    • + ))} +
    +
    + )} +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Education; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Interests.jsx b/src/components/ResumeTemplates/VanHack/Sections/Interests.jsx new file mode 100644 index 0000000..bcfef07 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Interests.jsx @@ -0,0 +1,118 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeInterests: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + interests: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, + }, + interest: { + fontWeight: 'bold', + }, + keywords: { + flexWrap: 'wrap', + listStyle: 'none', + paddingLeft: 0, + display: 'inline-flex', + '& li': { + fontStyle: 'italic', + margin: '3px 3px 0 0', + backgroundColor: theme.palette.type === 'dark' ? '#28407b' : '#dae4f4', + borderRadius: '3px', + padding: '1px 3px', + }, + }, + contentWrapper: { + marginLeft: '4px', + }, + interestWrapper: { + pageBreakInside: 'avoid', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Interests = ({ interests }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return interests.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'interests' })} +

+
+
    + {interests.map((interest) => { + if (interest?.enabled) { + const { + name, + keywords, + } = interest?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • + {name?.enabled && ( +

    + {name?.value} +

    + )} + {keywords?.enabled && ( +
      + {keywords?.value.map((keyword) => + keyword?.enabled && ( +
    • + {keyword?.value} +
    • + ))} +
    + )} +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Interests; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Languages.jsx b/src/components/ResumeTemplates/VanHack/Sections/Languages.jsx new file mode 100644 index 0000000..b1a2172 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Languages.jsx @@ -0,0 +1,84 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeLanguages: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + languages: { + margin: '0', + '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + }, + contentWrapper: { + marginLeft: '4px', + }, + languageWrapper: { + pageBreakInside: 'avoid', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Languages = ({ languages }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return languages.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'languages' })} +

+
+
    + {languages.map((lang) => { + if (lang?.enabled) { + const { + language, + fluency, + } = lang?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • +

    + {language?.enabled && language?.value}{', '} + {fluency?.enabled && fluency?.value} +

    +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Languages; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Projects.jsx b/src/components/ResumeTemplates/VanHack/Sections/Projects.jsx new file mode 100644 index 0000000..1eda811 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Projects.jsx @@ -0,0 +1,118 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeProjects: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + projects: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '0', + }, + }, + }, + project: { + fontWeight: 'bold', + }, + contentWrapper: { + marginLeft: '4px', + }, + projectWrapper: { + pageBreakInside: 'avoid', + }, + positionDate: { + fontStyle: 'italic', + fontSize: '0.8rem', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Projects = ({ projects }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return projects.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'projects' })} +

+
+
    + {projects.map((project) => { + if (project?.enabled) { + const { + name, + description, + highlights, + keywords, + startDate, + endDate, + url, + roles, + entity, + type, + } = project?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • +

    + {name?.enabled && name?.value} + {(startDate?.enabled || endDate?.enabled) && ( + + {' ('} + {startDate?.enabled && startDate?.value} + {(startDate?.enabled && endDate?.enabled) && ' - '} + {endDate?.enabled && endDate?.value} + {')'} + + )} +

    + {type && type?.enabled &&

    {type?.value}

    } + {entity && entity?.enabled &&

    {entity?.value}

    } + {(url && url?.enabled && url?.value) && {url.value}} + {description && description?.enabled &&

    {description?.value}

    } +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Projects; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Publications.jsx b/src/components/ResumeTemplates/VanHack/Sections/Publications.jsx new file mode 100644 index 0000000..04f22dd --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Publications.jsx @@ -0,0 +1,107 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumePublications: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + publications: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + }, + publication: { + fontWeight: 'bold', + }, + contentWrapper: { + marginLeft: '4px', + }, + publicationWrapper: { + pageBreakInside: 'avoid', + }, + positionDate: { + fontStyle: 'italic', + fontSize: '0.8rem', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Publications = ({ publications }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return publications.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'publications' })} +

+
+
    + {publications.map((publication) => { + if (publication?.enabled) { + const { + name, + publisher, + releaseDate, + url, + summary, + } = publication?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • +

    + {name?.enabled && name?.value} + {( + (publisher?.enabled && name?.enabled) + && (publisher?.value && name?.value) + ) && ` ${intl.formatMessage({ id: 'at' })} `} + {publisher?.enabled && publisher?.value} + {(releaseDate?.enabled && releaseDate?.value) && ( + + {` (${releaseDate?.value})`} + + )} +

    + {(url && url?.enabled && url?.value) && {url.value}} + {summary && summary?.enabled &&

    {summary?.value}

    } +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Publications; diff --git a/src/components/ResumeTemplates/VanHack/Sections/References.jsx b/src/components/ResumeTemplates/VanHack/Sections/References.jsx new file mode 100644 index 0000000..cdce0c1 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/References.jsx @@ -0,0 +1,88 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeReferences: { + padding: '10px 0', + }, + name: { fontWeight: 'bold' }, + references: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { margin: '0 0 10px 0', '&:last-child': { margin: '0' } }, + }, + contentWrapper: { + marginLeft: '4px', + }, + referenceWrapper: { + pageBreakInside: 'avoid', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const References = ({ references }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return references.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'references' })} +

+
+
    + {references.map((ref) => { + if (ref?.enabled) { + const { + name, + reference, + } = ref?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • + {name?.enabled && ( +

    + {name?.value} +

    + )} + {reference?.enabled &&

    {reference?.value}

    } +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default References; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Skills.jsx b/src/components/ResumeTemplates/VanHack/Sections/Skills.jsx new file mode 100644 index 0000000..06b9edd --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Skills.jsx @@ -0,0 +1,118 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeSkills: { + pageBreakInside: 'avoid', + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + skills: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, + }, + skillTitle: { + fontWeight: 'bold', + }, + keywords: { + flexWrap: 'wrap', + listStyle: 'none', + paddingLeft: 0, + display: 'inline-flex', + '& li': { + fontStyle: 'italic', + margin: '3px 3px 0 0', + backgroundColor: theme.palette.type === 'dark' ? '#28407b' : '#dae4f4', + borderRadius: '3px', + padding: '1px 3px', + }, + }, + contentWrapper: { + marginLeft: '4px', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Skills = ({ skills }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return skills.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'skills' })} +

+
+
    + {skills.map((skill) => { + if (skill?.enabled) { + const { + name, + level, + keywords, + } = skill?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • + {(name?.enabled || level?.enabled) && ( +

    + {name?.enabled && name?.value} + {(name?.enabled && level?.enabled) && ', '} + {level?.enabled && level?.value} +

    + )} + {keywords?.enabled && ( +
      + {keywords?.value.map((keyword) => + keyword?.enabled && ( +
    • + {keyword?.value} +
    • + ))} +
    + )} +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Skills; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Volunteer.jsx b/src/components/ResumeTemplates/VanHack/Sections/Volunteer.jsx new file mode 100644 index 0000000..9752d36 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Volunteer.jsx @@ -0,0 +1,138 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeVolunteer: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + volunteers: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, + }, + position: { fontWeight: 'bold' }, + positionDate: { + fontStyle: 'italic', + fontSize: '0.8rem', + }, + url: {}, + summary: {}, + highlights: { + '& li': { + marginBottom: '1px', + fontStyle: 'italic', + }, + }, + contentWrapper: { + marginLeft: '4px', + }, + volunteerWrapper: { + pageBreakInside: 'avoid', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Volunteer = ({ volunteer: volunteers }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return volunteers.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'volunteers' })} +

+
+
    + {volunteers.map((volunteer) => { + if (volunteer?.enabled) { + const { + organization, + position, + url, + startDate, + endDate, + summary, + highlights, + } = volunteer?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • +

    + {position?.enabled && position?.value} + {( + (position?.enabled && organization?.enabled) + && (position?.value && organization?.value) + ) && ` ${intl.formatMessage({ id: 'at' })} `} + {organization?.enabled && organization?.value} + {(startDate?.enabled || endDate?.enabled) && ( + + {' ('} + {startDate?.enabled && startDate?.value} + {(startDate?.enabled && endDate?.enabled) && ' - '} + {endDate?.enabled && endDate?.value} + {')'} + + )} +

    +

    + {(url && url?.enabled && url?.value) && {url.value}} +

    +

    + {summary?.enabled && summary?.value} +

    + {highlights?.enabled && ( +
      + {highlights?.value.map((highlight) => + highlight?.enabled && ( +
    • + {highlight?.value} +
    • + ))} +
    + )} +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Volunteer; diff --git a/src/components/ResumeTemplates/VanHack/Sections/Work.jsx b/src/components/ResumeTemplates/VanHack/Sections/Work.jsx new file mode 100644 index 0000000..28823d1 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/Sections/Work.jsx @@ -0,0 +1,167 @@ +import React, { useRef } from 'react'; +import { v4 as uuid } from 'uuid'; +import { makeStyles } from '@material-ui/core/styles'; +import { useIntl } from 'gatsby-plugin-intl'; + +// Hooks +import useAntiPageBreakTitle from '../../../hooks/useAntiPageBreakTitle'; + +const useStyles = makeStyles((theme) => ({ + resumeWork: { + padding: '10px 0', + borderBottom: '1px solid #ddd', + }, + works: { + margin: '0', + padding: '0', + listStyle: 'none', + '& li': { + margin: '0 0 10px 0', + '&:last-child': { + margin: '3px 0 0', + }, + }, + }, + position: { + fontWeight: 'bold', + }, + positionDate: { + fontStyle: 'italic', + fontSize: '0.8rem', + }, + urlAndLocation: { + fontStyle: 'italic', + color: theme.palette.type === 'dark' ? '#b7bfc1' : '#6a5e5e', + }, + summary: { + whiteSpace: 'break-spaces', + }, + description: { + whiteSpace: 'break-spaces', + }, + highlights: { + '& li': { + marginBottom: '1px', + fontStyle: 'italic', + }, + }, + contentWrapper: { + marginLeft: '4px', + }, + workWrapper: { + pageBreakInside: 'avoid', + }, + workHeader: { + marginBottom: '5px', + }, + title: { + pageBreakInside: 'avoid', + }, +})); + +const Work = ({ work: works }) => { + const classes = useStyles(); + const intl = useIntl(); + const firstItem = useRef(null); + const sectionTitle = useRef(null); + const titleStyle = useAntiPageBreakTitle(sectionTitle, firstItem); + + return works.length > 0 && ( +
+

+ {intl.formatMessage({ id: 'experience' })} +

+
+
    + {works.map((work) => { + if (work?.enabled) { + const { + name, + location, + description, + position, + url, + startDate, + endDate, + summary, + highlights, + } = work?.value || {}; + + let refProps = {}; + if (!firstItem.current) { + refProps = { + ref: firstItem, + }; + } + + return ( +
  • +
    +

    + {position?.enabled && position?.value} + {( + (position?.enabled && name?.enabled) + && (position?.value && name?.value) + ) && ` ${intl.formatMessage({ id: 'at' })} `} + {name?.enabled && name?.value} + {(startDate?.enabled || endDate?.enabled) && ( + + {' ('} + {startDate?.enabled && startDate?.value} + {(startDate?.enabled && endDate?.enabled) && ' - '} + {endDate?.enabled && endDate?.value} + {')'} + + )} +

    +

    + {location?.enabled && location?.value} + {( + (location?.enabled && url?.enabled) + && (location?.value && url?.value) + ) && ', '} + {url?.enabled && ( + + {url?.value} + + )} +

    +
    +

    + {summary?.enabled && summary?.value} +

    +

    + {description?.enabled && description?.value} +

    + {highlights?.enabled && ( +
      + {highlights?.value.map((highlight) => + highlight?.enabled && ( +
    • + {highlight?.value} +
    • + ))} +
    + )} +
  • + ); + } + + return null; + })} +
+
+
+ ); +}; + +export default Work; diff --git a/src/components/ResumeTemplates/VanHack/intl/en.json b/src/components/ResumeTemplates/VanHack/intl/en.json new file mode 100644 index 0000000..a23abf1 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/intl/en.json @@ -0,0 +1,16 @@ +{ + "awards": "Awards", + "volunteers": "Volunteers", + "skills": "Skills", + "references": "References", + "publications": "Publications", + "certificates": "Certificates", + "projects": "Projects", + "languages": "Languages", + "interests": "Interests", + "education": "Education", + "summary": "Summary", + "experience": "Experience", + "at": "@", + "download_data": "Download the JSON data source for this resume here." +} diff --git a/src/components/ResumeTemplates/VanHack/intl/es.json b/src/components/ResumeTemplates/VanHack/intl/es.json new file mode 100644 index 0000000..8e86c13 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/intl/es.json @@ -0,0 +1,16 @@ +{ + "awards": "Premios", + "volunteers": "Voluntarios", + "skills": "Habilidades", + "references": "Referencias", + "publications": "Publicaciones", + "certificates": "Certificados", + "projects": "Proyectos", + "languages": "Idiomas", + "interests": "Intereses", + "education": "Educación", + "summary": "Resumen", + "experience": "Experiencia", + "at": "@", + "download_data": "Descargue los datos JSON para esta hoja de vida haciendo clic aquí" +} diff --git a/src/components/ResumeTemplates/VanHack/intl/index.js b/src/components/ResumeTemplates/VanHack/intl/index.js new file mode 100644 index 0000000..6b2c67e --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/intl/index.js @@ -0,0 +1,39 @@ +import { createIntl, createIntlCache } from 'gatsby-plugin-intl'; + +// local translations +import localEn from './en.json'; +import localPtBr from './pt-br.json'; +import localEs from './es.json'; + +// global translations +import globalEn from '../../../../intl/en.json'; +import globalPtBr from '../../../../intl/pt-br.json'; +import globalEs from '../../../../intl/es.json'; + +const translations = [ + { + locale: 'en', + messages: { + ...globalEn, + ...localEn, + }, + }, + { + locale: 'pt-br', + messages: { + ...globalPtBr, + ...localPtBr, + }, + }, + { + locale: 'es', + messages: { + ...globalEs, + ...localEs, + }, + }, +]; + +export default translations.map( + (translation) => createIntl(translation, createIntlCache()) +); diff --git a/src/components/ResumeTemplates/VanHack/intl/pt-br.json b/src/components/ResumeTemplates/VanHack/intl/pt-br.json new file mode 100644 index 0000000..8c38fb1 --- /dev/null +++ b/src/components/ResumeTemplates/VanHack/intl/pt-br.json @@ -0,0 +1,16 @@ +{ + "awards": "Prêmios", + "volunteers": "Voluntários", + "skills": "Habilidades", + "references": "Referências", + "publications": "Publicações", + "certificates": "Certificados", + "projects": "Projetos", + "languages": "Línguas", + "interests": "Interesses", + "education": "Educação", + "summary": "Sumário", + "experience": "Experiência", + "at": "@", + "download_data": "Baixe os dados JSON desse currículo clicando aqui." +} diff --git a/src/intl/release-notes.md b/src/intl/release-notes.md new file mode 100644 index 0000000..2611e86 --- /dev/null +++ b/src/intl/release-notes.md @@ -0,0 +1,58 @@ +## Release Notes +- **v4.0.2:** + - Filter out resume templates that are not ready yet + - Add download link to download the JSON data +- **v4.0.1:** + - Add visual cue to the cover letter variables. +- **v4.0.0:** + - Fix page break between title and items using a dirty hack (but hey it works). + - Add cover letter editor. + - Update JSON Schema to v1.0.0. + - Update Gatsby to v3. +- **v3.1.1:** + - Fix Resume Viewer page for SSR +- **v3.1.0:** + - Update spreadsheet and JSON schema + - Fix template selector not using the global state + - Add option to set language in the Resume Viewer page + - Other small improvements (lintering) in the code + - Improve JSON object generation + - Improve Default resume template + - Add custom translations +- **v3.0.6:** + - Update dependency packages versions +- **v3.0.5:** + - Add Spanish translation (thanks [simonhoyos](https://github.com/simonhoyos)) +- **v3.0.4:** + - Fix React suspense on the resume viewer page. +- **v3.0.3:** + - Add online resume viewer. Example: [https://https://blopa.github.io/Legacy-Resume-Builder/v3/view/default/blopa](https://https://blopa.github.io/Legacy-Resume-Builder/v3/view/default/blopa). +- **v3.0.2:** + - Fix template selector + - Fix interests toggler +- **v3.0.1:** + - Make schema compatible with [linkedin-to-jsonresume](https://github.com/joshuatz/linkedin-to-jsonresume) + - Make toggler menu more efficient (thanks [milenagd](https://github.com/milenagd)) +- **v3.0.0:** + - Rebuild using Gatsby. +- **v2.0.3:** (not tagged) + - ~~Fix CORS problem when loading a spreadsheet from URL.~~ (still trying to figure this one out) + - Update packages. + - Add new ESlint rules. +- **v2.0.2:** + - Fix printing issue when sidebar is open. + - Add Google Analytics option. +- **v2.0.1:** + - Add option to parse spreadsheet from Google Spreadsheet URL. +- **v2.0.0:** + - Everything rebuild from scratch. +- **v0.0.4:** + - New resume display style +- **v0.0.3:** + - Cleaning code to fit ESLint standards + - Get JSON object from URL to parse a Resume + - Replace CSS for SASS +- **v0.0.2:** + - Tiny changes on template layout +- **v0.0.1:** + - First working version diff --git a/src/pages/Build.jsx b/src/pages/Build.jsx index 4d516b8..09e8b85 100644 --- a/src/pages/Build.jsx +++ b/src/pages/Build.jsx @@ -4,6 +4,7 @@ import { makeStyles } from '@material-ui/core/styles'; import { Drawer } from '@material-ui/core'; import { navigate, useIntl } from 'gatsby-plugin-intl'; import { v4 as uuid } from 'uuid'; +import useDetectPrint from 'use-detect-print'; // Components import SEO from '../components/SEO'; @@ -48,6 +49,7 @@ const BuildPage = () => { const togglableJsonResume = useSelector(selectTogglableJsonResume); const resumeTemplateName = useSelector(selectResumeTemplate); const hasData = isObjectNotEmpty(togglableJsonResume) && isObjectNotEmpty(jsonResume); + const isPrinting = useDetectPrint(); useEffect(() => { if (!hasData) { @@ -61,15 +63,16 @@ const BuildPage = () => { setResumeTemplate([