diff --git a/README.md b/README.md index ccd3e969..a832f746 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,11 @@ For those of you familiar with the Crowdin Platform, you could do that too and j ##### Languages Currently Supported - English -- Kannada (ಕನ್ನಡ) -- Spanish (Español) (by [@jrgonzalezrios](https://github.com/jrgonzalezrios)) -- Portuguese (Brazilian) (by [Felipe CG](https://github.com/felcg)) - Finnish (Suomalainen) (by Ari Pikkarainen) +- French (Français) (by [MeisterLLD](https://github.com/MeisterLLD)) +- Kannada (ಕನ್ನಡ) +- Portuguese (Brazilian) (by [Felipe CG](https://github.com/felcg)) +- Spanish (Español) (by [@jrgonzalezrios](https://github.com/jrgonzalezrios)) ### Building from Source diff --git a/gatsby-config.js b/gatsby-config.js index dcf8873f..37b34d19 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -5,7 +5,7 @@ module.exports = { title: 'Reactive Resume', siteUrl: 'https://rxresu.me', description: 'A free and open source resume builder.', - version: '2.0.1', + version: '2.0.2', }, plugins: [ 'gatsby-plugin-react-helmet', diff --git a/package-lock.json b/package-lock.json index 0fc6529f..5cc2a0b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6704,9 +6704,9 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.4.0.tgz", - "integrity": "sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.5.0.tgz", + "integrity": "sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -6717,9 +6717,9 @@ "doctrine": "^3.0.0", "enquirer": "^2.3.5", "eslint-scope": "^5.1.0", - "eslint-utils": "^2.0.0", - "eslint-visitor-keys": "^1.2.0", - "espree": "^7.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.2.0", "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", @@ -6733,7 +6733,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.14", + "lodash": "^4.17.19", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -6809,14 +6809,14 @@ } }, "espree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz", - "integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz", + "integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==", "dev": true, "requires": { - "acorn": "^7.2.0", + "acorn": "^7.3.1", "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.2.0" + "eslint-visitor-keys": "^1.3.0" } }, "glob-parent": { diff --git a/package.json b/package.json index 2c2653b8..a8e9ad5e 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ }, "devDependencies": { "autoprefixer": "^9.8.5", - "eslint": "^7.4.0", + "eslint": "^7.5.0", "eslint-config-airbnb": "^18.2.0", "eslint-config-prettier": "^6.11.0", "eslint-loader": "^4.0.2", diff --git a/src/components/builder/center/Artboard.js b/src/components/builder/center/Artboard.js index 7a5f4c70..6651fcb5 100644 --- a/src/components/builder/center/Artboard.js +++ b/src/components/builder/center/Artboard.js @@ -1,4 +1,4 @@ -import React, { memo } from 'react'; +import React, { memo, useEffect, useState } from 'react'; import { Helmet } from 'react-helmet'; import { useTranslation } from 'react-i18next'; import { useSelector } from '../../../contexts/ResumeContext'; @@ -13,9 +13,14 @@ import styles from './Artboard.module.css'; const Artboard = () => { const state = useSelector(); const { t } = useTranslation(); + const [width, setWidth] = useState(0); const { id, name, metadata } = state; const { template } = metadata; + useEffect(() => { + setWidth(typeof window !== `undefined` && window && window.innerWidth); + }, [typeof window !== `undefined` && window && window.innerWidth]); + return ( <> @@ -25,7 +30,12 @@ const Artboard = () => { -
+
{template === 'onyx' && } {template === 'pikachu' && } {template === 'gengar' && } diff --git a/src/components/builder/center/Artboard.module.css b/src/components/builder/center/Artboard.module.css index 045ab997..5ad63bf9 100644 --- a/src/components/builder/center/Artboard.module.css +++ b/src/components/builder/center/Artboard.module.css @@ -1,22 +1,9 @@ @media screen { .container { - width: 210mm; - height: 297mm; - zoom: 0.5; + width: 794px; + min-height: 1122px; overflow: scroll; box-shadow: var(--shadow); @apply my-16 bg-white rounded; } } - -@media screen and (min-width: 1366px) { - .container { - zoom: 0.65; - } -} - -@media screen and (min-width: 1440px) { - .container { - zoom: 0.8; - } -} \ No newline at end of file diff --git a/src/components/builder/left/LeftSidebar.module.css b/src/components/builder/left/LeftSidebar.module.css index 65c96f6d..cc4dbcbe 100644 --- a/src/components/builder/left/LeftSidebar.module.css +++ b/src/components/builder/left/LeftSidebar.module.css @@ -1,6 +1,5 @@ .container { z-index: 10; - box-shadow: var(--left-shadow); @apply w-full h-screen overflow-scroll p-8; @apply grid gap-8; } \ No newline at end of file diff --git a/src/components/builder/right/RightSidebar.module.css b/src/components/builder/right/RightSidebar.module.css index de68bb23..7f0ccf8c 100644 --- a/src/components/builder/right/RightSidebar.module.css +++ b/src/components/builder/right/RightSidebar.module.css @@ -1,6 +1,5 @@ .container { z-index: 10; - box-shadow: var(--right-shadow); @apply w-full h-screen overflow-scroll p-8; @apply grid gap-8; } diff --git a/src/components/dashboard/ResumePreview.js b/src/components/dashboard/ResumePreview.js index e651e140..bb47bb23 100644 --- a/src/components/dashboard/ResumePreview.js +++ b/src/components/dashboard/ResumePreview.js @@ -1,16 +1,16 @@ import { Menu, MenuItem } from '@material-ui/core'; import { navigate } from 'gatsby'; -import moment from 'moment'; +import moment from 'moment/min/moment-with-locales'; import React, { useContext, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { MdMoreHoriz, MdOpenInNew } from 'react-icons/md'; import { toast } from 'react-toastify'; -import { useTranslation } from 'react-i18next'; import DatabaseContext from '../../contexts/DatabaseContext'; import ModalContext from '../../contexts/ModalContext'; import styles from './ResumePreview.module.css'; const ResumePreview = ({ resume }) => { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const [anchorEl, setAnchorEl] = useState(null); const { emitter, events } = useContext(ModalContext); const { duplicateResume, deleteResume } = useContext(DatabaseContext); @@ -84,7 +84,9 @@ const ResumePreview = ({ resume }) => { {resume.updatedAt && ( {t('dashboard.lastUpdated', { - timestamp: moment(resume.updatedAt).fromNow(), + timestamp: moment(resume.updatedAt) + .locale(i18n.language.substr(0, 2)) + .fromNow(), })} )} diff --git a/src/i18n/index.js b/src/i18n/index.js index 0a24620c..721dbded 100644 --- a/src/i18n/index.js +++ b/src/i18n/index.js @@ -8,20 +8,24 @@ const languages = [ name: 'English (US)', }, { - code: 'kn', - name: 'Kannada (ಕನ್ನಡ)', + code: 'fi', + name: 'Finnish (Suomalainen)', }, { - code: 'es', - name: 'Spanish (Español)', + code: 'fr', + name: 'French (Français)', + }, + { + code: 'kn', + name: 'Kannada (ಕನ್ನಡ)', }, { code: 'ptBr', name: 'Portuguese (Brazilian)', }, { - code: 'fi', - name: 'Finnish (Suomalainen)', + code: 'es', + name: 'Spanish (Español)', }, ]; diff --git a/src/i18n/locales/index.js b/src/i18n/locales/index.js index 9e669fcd..65e3588d 100644 --- a/src/i18n/locales/index.js +++ b/src/i18n/locales/index.js @@ -1,13 +1,15 @@ import en from './en.json'; -import kn from './kn.json'; import es from './es.json'; -import ptBr from './pt-br.json'; import fi from './fi.json'; +import fr from './fr.json'; +import kn from './kn.json'; +import ptBr from './pt-br.json'; export default { en: { translation: en }, - kn: { translation: kn }, es: { translation: es }, - ptBr: { translation: ptBr }, fi: { translation: fi }, + fr: { translation: fr }, + kn: { translation: kn }, + ptBr: { translation: ptBr }, }; diff --git a/src/pages/app/builder.module.css b/src/pages/app/builder.module.css index c53f47c0..c475f80e 100644 --- a/src/pages/app/builder.module.css +++ b/src/pages/app/builder.module.css @@ -1,33 +1,19 @@ .container { - @apply w-screen h-screen grid grid-cols-10; + @apply relative h-screen w-screen overflow-hidden flex items-start justify-center; } .left { - @apply col-span-3; + width: calc(100vw / 4); + box-shadow: var(--left-shadow); + @apply bg-primary-50 absolute top-0 bottom-0 left-0 z-10; } .center { - @apply col-span-4 h-screen overflow-scroll bg-primary-100 grid justify-center items-center; + @apply relative z-0 h-screen overflow-scroll; } .right { - @apply col-span-3; + width: calc(100vw / 4); + box-shadow: var(--right-shadow); + @apply bg-primary-50 absolute top-0 bottom-0 right-0 z-10; } - -@media screen and (min-width: 1440px) { - .container { - @apply grid-cols-11; - } - - .left { - @apply col-span-3; - } - - .center { - @apply col-span-5; - } - - .right { - @apply col-span-3; - } -} \ No newline at end of file diff --git a/src/templates/blocks/Awards/AwardsA.js b/src/templates/blocks/Awards/AwardsA.js index 4ea2c96e..2e54824f 100644 --- a/src/templates/blocks/Awards/AwardsA.js +++ b/src/templates/blocks/Awards/AwardsA.js @@ -1,27 +1,34 @@ -import moment from 'moment'; +import moment from 'moment/min/moment-with-locales'; import React, { memo, useContext } from 'react'; +import { useTranslation } from 'react-i18next'; import ReactMarkdown from 'react-markdown'; import PageContext from '../../../contexts/PageContext'; import { safetyCheck } from '../../../utils'; -const AwardItem = (x) => ( -
-
-
-
{x.title}
- {x.awarder} +const AwardItem = (x) => { + const { i18n } = useTranslation(); + + return ( +
+
+
+
{x.title}
+ {x.awarder} +
+ {x.date && ( +
+ {moment(x.date) + .locale(i18n.language.substr(0, 2)) + .format('MMMM YYYY')} +
+ )}
- {x.date && ( -
- {moment(x.date).format('MMMM YYYY')} -
+ {x.summary && ( + )}
- {x.summary && ( - - )} -
-); + ); +}; const AwardsA = () => { const { data, heading: Heading } = useContext(PageContext); diff --git a/src/templates/blocks/Certifications/CertificationsA.js b/src/templates/blocks/Certifications/CertificationsA.js index 08d9d2f2..52bcd2d9 100644 --- a/src/templates/blocks/Certifications/CertificationsA.js +++ b/src/templates/blocks/Certifications/CertificationsA.js @@ -1,27 +1,34 @@ -import moment from 'moment'; +import moment from 'moment/min/moment-with-locales'; import React, { memo, useContext } from 'react'; +import { useTranslation } from 'react-i18next'; import ReactMarkdown from 'react-markdown'; import PageContext from '../../../contexts/PageContext'; import { safetyCheck } from '../../../utils'; -const CertificationItem = (x) => ( -
-
-
-
{x.title}
- {x.issuer} +const CertificationItem = (x) => { + const { i18n } = useTranslation(); + + return ( +
+
+
+
{x.title}
+ {x.issuer} +
+ {x.date && ( +
+ {moment(x.date) + .locale(i18n.language.substr(0, 2)) + .format('MMMM YYYY')} +
+ )}
- {x.date && ( -
- {moment(x.date).format('MMMM YYYY')} -
+ {x.summary && ( + )}
- {x.summary && ( - - )} -
-); + ); +}; const CertificationsA = () => { const { data, heading: Heading } = useContext(PageContext); diff --git a/src/templates/blocks/Projects/ProjectsA.js b/src/templates/blocks/Projects/ProjectsA.js index f8a196a2..b92ff558 100644 --- a/src/templates/blocks/Projects/ProjectsA.js +++ b/src/templates/blocks/Projects/ProjectsA.js @@ -1,31 +1,38 @@ -import moment from 'moment'; +import moment from 'moment/min/moment-with-locales'; import React, { memo, useContext } from 'react'; +import { useTranslation } from 'react-i18next'; import ReactMarkdown from 'react-markdown'; import PageContext from '../../../contexts/PageContext'; import { safetyCheck } from '../../../utils'; -const ProjectItem = (x) => ( -
-
-
-
{x.title}
- {x.link && ( - - {x.link} - +const ProjectItem = (x) => { + const { i18n } = useTranslation(); + + return ( +
+
+
+
{x.title}
+ {x.link && ( + + {x.link} + + )} +
+ {x.date && ( +
+ {moment(x.date) + .locale(i18n.language.substr(0, 2)) + .format('MMMM YYYY')} +
)}
- {x.date && ( -
- {moment(x.date).format('MMMM YYYY')} -
+ {x.summary && ( + )}
- {x.summary && ( - - )} -
-); + ); +}; const ProjectsA = () => { const { data, heading: Heading } = useContext(PageContext); diff --git a/src/utils/index.js b/src/utils/index.js index 82e6d2e3..963a657c 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,5 +1,5 @@ import { get, isEmpty } from 'lodash'; -import moment from 'moment'; +import moment from 'moment/min/moment-with-locales'; import { useTranslation } from 'react-i18next'; export const getModalText = (isEditMode, type) => { @@ -22,10 +22,19 @@ export const isFileImage = (file) => { return file && acceptedImageTypes.includes(file.type); }; -export const formatDateRange = ({ startDate, endDate }) => - `${moment(startDate).format('MMMM Y')} — ${ - moment(endDate).isValid() ? moment(endDate).format('MMMM Y') : 'Present' - }`; +export const formatDateRange = ({ startDate, endDate }) => { + const { i18n } = useTranslation(); + + const start = `${moment(startDate) + .locale(i18n.language.substr(0, 2)) + .format('MMMM Y')}`; + + const end = moment(endDate).isValid() + ? `${moment(endDate).locale(i18n.language.substr(0, 2)).format('MMMM Y')}` + : 'Present'; + + return `${start} - ${end}`; +}; export const getFieldProps = (formik, schema, name) => ({ touched: get(formik, `touched.${name}`, false),