- implement "Import from JSON Resume" feature

This commit is contained in:
Amruth Pillai
2020-07-16 11:58:31 +05:30
parent 8e9bd99e91
commit f41018c60b
6 changed files with 108 additions and 14 deletions

View File

@ -1,4 +1,5 @@
import arrayMove from 'array-move'; import arrayMove from 'array-move';
import { v4 as uuidv4 } from 'uuid';
import { import {
clone, clone,
findIndex, findIndex,
@ -123,6 +124,86 @@ const ResumeProvider = ({ children }) => {
debouncedUpdateResume(newState); debouncedUpdateResume(newState);
return newState; return newState;
case 'on_import_jsonresume':
temp = clone(state);
newState = initialState;
newState.id = temp.id;
newState.user = temp.user;
newState.name = temp.name;
newState.preview = temp.preview;
newState.createdAt = temp.createdAt;
newState.updatedAt = temp.updatedAt;
newState.profile = {
address: {
city: payload.basics.location.city,
line1: payload.basics.location.address,
line2: payload.basics.location.region,
pincode: payload.basics.location.postalCode,
},
email: payload.basics.email,
firstName: payload.basics.name,
phone: payload.basics.phone,
photograph: payload.basics.picture,
subtitle: payload.basics.label,
website: payload.basics.website,
};
newState.social.items = payload.basics.profiles.map((x) => ({
id: uuidv4(),
network: x.network,
username: x.username,
url: x.url,
}));
newState.objective.body = payload.basics.summary;
newState.work.items = payload.work.map((x) => ({
id: uuidv4(),
company: x.company,
endDate: x.endDate,
position: x.position,
startDate: x.startDate,
summary: x.summary,
website: x.website,
}));
newState.education.items =
payload.education &&
payload.education.map((x) => ({
id: uuidv4(),
degree: x.studyType,
endDate: x.endDate,
field: x.area,
gpa: x.gpa,
institution: x.institution,
startDate: x.startDate,
summary: x.courses.join('\n'),
}));
newState.awards.items = payload.awards.map((x) => ({
id: uuidv4(),
awarder: x.awarder,
date: x.date,
summary: x.summary,
title: x.title,
}));
newState.skills.items = payload.skills.map((x) => ({
id: uuidv4(),
level: 'Fundamental Awareness',
name: x.name,
}));
newState.hobbies.items = payload.interests.map((x) => ({
id: uuidv4(),
name: x.name,
}));
newState.languages.items = payload.languages.map((x) => ({
id: uuidv4(),
name: x.language,
fluency: x.fluency,
}));
newState.references.items = payload.references.map((x) => ({
id: uuidv4(),
name: x.name,
summary: x.reference,
}));
debouncedUpdateResume(newState);
return newState;
case 'set_data': case 'set_data':
newState = payload; newState = payload;
debouncedUpdateResume(newState); debouncedUpdateResume(newState);

View File

@ -185,7 +185,6 @@
"lastName": "Pillai", "lastName": "Pillai",
"phone": "+91 98453 36113", "phone": "+91 98453 36113",
"photograph": "https://i.imgur.com/2dmLSCT.jpg", "photograph": "https://i.imgur.com/2dmLSCT.jpg",
"profile": "",
"subtitle": "Full Stack Web Developer", "subtitle": "Full Stack Web Developer",
"website": "amruthpillai.com" "website": "amruthpillai.com"
}, },

View File

@ -11,7 +11,6 @@
"city": "", "city": "",
"pincode": "" "pincode": ""
}, },
"profile": "",
"website": "", "website": "",
"email": "" "email": ""
}, },

View File

@ -1,6 +1,6 @@
{ {
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"additionalProperties": false, "$id": "http://json-schema.org/draft-04/schema#",
"definitions": { "definitions": {
"iso8601": { "iso8601": {
"type": "string", "type": "string",
@ -9,11 +9,6 @@
} }
}, },
"properties": { "properties": {
"$schema": {
"type": "string",
"description": "link to the version of the schema that can validate the resume",
"format": "uri"
},
"basics": { "basics": {
"type": "object", "type": "object",
"additionalProperties": true, "additionalProperties": true,

View File

@ -1,6 +1,6 @@
{ {
"$schema": "http://json-schema.org/draft-07/schema", "$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/example.json", "$id": "http://json-schema.org/draft-07/schema",
"type": "object", "type": "object",
"title": "The root schema", "title": "The root schema",
"description": "The root schema comprises the entire JSON document.", "description": "The root schema comprises the entire JSON document.",

View File

@ -7,6 +7,7 @@ import Button from '../../components/shared/Button';
import ModalContext from '../../contexts/ModalContext'; import ModalContext from '../../contexts/ModalContext';
import { useDispatch } from '../../contexts/ResumeContext'; import { useDispatch } from '../../contexts/ResumeContext';
import reactiveResumeSchema from '../../data/schema/reactiveResume.json'; import reactiveResumeSchema from '../../data/schema/reactiveResume.json';
import jsonResumeSchema from '../../data/schema/jsonResume.json';
import BaseModal from '../BaseModal'; import BaseModal from '../BaseModal';
const ImportModal = () => { const ImportModal = () => {
@ -39,6 +40,21 @@ const ImportModal = () => {
fr.readAsText(event.target.files[0]); fr.readAsText(event.target.files[0]);
}; };
const importJsonResume = (event) => {
const fr = new FileReader();
fr.addEventListener('load', () => {
const payload = JSON.parse(fr.result);
const valid = ajv.validate(jsonResumeSchema, payload);
if (!valid) {
ajv.errors.forEach((x) => toast.error(`Invalid Data: ${x.message}`));
return;
}
dispatch({ type: 'on_import_jsonresume', payload });
setOpen(false);
});
fr.readAsText(event.target.files[0]);
};
return ( return (
<BaseModal <BaseModal
hideActions hideActions
@ -74,11 +90,15 @@ const ImportModal = () => {
<p className="leading-loose">{t('modals.import.jsonResume.text')}</p> <p className="leading-loose">{t('modals.import.jsonResume.text')}</p>
<Tooltip title="Coming Soon" placement="right" arrow> <Button className="mt-5" onClick={() => fileInputRef.current.click()}>
<div className="mt-5 inline-block"> {t('modals.import.button')}
<Button className="opacity-50">{t('modals.import.button')}</Button> </Button>
</div> <input
</Tooltip> ref={fileInputRef}
type="file"
className="hidden"
onChange={importJsonResume}
/>
</div> </div>
<hr className="my-8" /> <hr className="my-8" />