From a8c5d2985809df9d7b8397b8430dff3995633845 Mon Sep 17 00:00:00 2001
From: Amruth Pillai
Date: Fri, 10 Jul 2020 13:40:48 +0530
Subject: [PATCH] - implement actions section
---
.eslintrc | 1 +
package-lock.json | 166 +++++++++---------
package.json | 2 +-
src/components/builder/lists/List.js | 10 +-
.../builder/right/sections/Actions.js | 55 ++++--
.../builder/right/sections/Colors.js | 4 +-
.../builder/right/sections/Fonts.js | 4 +-
.../builder/right/sections/Templates.js | 4 +-
src/components/landing/Hero.js | 13 +-
src/components/shared/Button.js | 13 +-
src/components/shared/Button.module.css | 12 ++
src/components/shared/Input.js | 1 -
src/constants/ModalEvents.js | 1 +
src/contexts/DatabaseContext.js | 30 +---
src/contexts/ResumeContext.js | 5 +
src/data/{colors.js => colorOptions.js} | 4 +-
src/data/{fonts.js => fontOptions.js} | 4 +-
src/data/{templates.js => templateOptions.js} | 4 +-
src/modals/AuthModal.js | 18 +-
src/modals/BaseModal.js | 19 +-
src/modals/DataModal.js | 4 +-
src/modals/ModalRegistrar.js | 2 +
src/modals/sections/ImportModal.js | 95 ++++++++++
23 files changed, 304 insertions(+), 167 deletions(-)
rename src/data/{colors.js => colorOptions.js} (80%)
rename src/data/{fonts.js => fontOptions.js} (70%)
rename src/data/{templates.js => templateOptions.js} (78%)
create mode 100644 src/modals/sections/ImportModal.js
diff --git a/.eslintrc b/.eslintrc
index 68499025..4792df35 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,6 +1,7 @@
{
"globals": {
"document": true,
+ "FileReader": true,
"localStorage": true
},
"extends": ["airbnb", "prettier"],
diff --git a/package-lock.json b/package-lock.json
index fa762c1f..cf1b33d1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1089,14 +1089,14 @@
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
},
"@firebase/analytics": {
- "version": "0.3.8",
- "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.8.tgz",
- "integrity": "sha512-HpNRBJHnrGq5jtVTNRgA8Ozng2ilt0pkej8D5EvXoaylu80U+ICKLBlIT8TdUSEfkXC/RPjvLXg6vn/sq/CyqA==",
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.9.tgz",
+ "integrity": "sha512-l4dNskm8uQ+UqO6Lw+fuyO1enZBXUV6xNMxeVABEnVrp3wOP90KKb/ZwYgleAxF1It52lorcTtkA1YFpv3iEIQ==",
"requires": {
"@firebase/analytics-types": "0.3.1",
- "@firebase/component": "0.1.15",
- "@firebase/installations": "0.4.13",
- "@firebase/logger": "0.2.5",
+ "@firebase/component": "0.1.16",
+ "@firebase/installations": "0.4.14",
+ "@firebase/logger": "0.2.6",
"@firebase/util": "0.2.50",
"tslib": "^1.11.1"
}
@@ -1107,13 +1107,13 @@
"integrity": "sha512-63vVJ5NIBh/JF8l9LuPrQYSzFimk7zYHySQB4Dk9rVdJ8kV/vGQoVTvRu1UW05sEc2Ug5PqtEChtTHU+9hvPcA=="
},
"@firebase/app": {
- "version": "0.6.7",
- "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.7.tgz",
- "integrity": "sha512-6NpIZ3iMrCR2XOShK5oi3YYB0GXX5yxVD8p3+2N+X4CF5cERyIrDRf8+YXOFgr+bDHSbVcIyzpWv6ijhg4MJlw==",
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.8.tgz",
+ "integrity": "sha512-Tm7Pi6Dtpx4FFKcpm0jcrZ/qI9oREBxmP3pWlw1jgDW4syRJHmN9/5DYvfFk6FAhj3FrY8E/6F+ngWJfqONotQ==",
"requires": {
"@firebase/app-types": "0.6.1",
- "@firebase/component": "0.1.15",
- "@firebase/logger": "0.2.5",
+ "@firebase/component": "0.1.16",
+ "@firebase/logger": "0.2.6",
"@firebase/util": "0.2.50",
"dom-storage": "2.1.0",
"tslib": "^1.11.1",
@@ -1126,9 +1126,9 @@
"integrity": "sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg=="
},
"@firebase/auth": {
- "version": "0.14.7",
- "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.7.tgz",
- "integrity": "sha512-NTQY9luV70XUA6zGYOWloDSaOT+l0/R4u3W7ptqVCfZNc4DAt7euUkTbj7SDD14902sHF54j+tk5kmpEmMd0jA==",
+ "version": "0.14.8",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.8.tgz",
+ "integrity": "sha512-LufoWcFpYAoCUkFDKSELH69xI8NdOjNTUFKvWfADZN7ysr4dpPdDs2ZYnH67FqcMb0tX+Jdx6vWrF6VZ37AAJQ==",
"requires": {
"@firebase/auth-types": "0.10.1"
}
@@ -1144,23 +1144,23 @@
"integrity": "sha512-/+gBHb1O9x/YlG7inXfxff/6X3BPZt4zgBv4kql6HEmdzNQCodIRlEYnI+/da+lN+dha7PjaFH7C7ewMmfV7rw=="
},
"@firebase/component": {
- "version": "0.1.15",
- "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.15.tgz",
- "integrity": "sha512-HqFb1qQl1vtlUMIzPM15plNz27jqM8DWjuQQuGeDfG+4iRRflwKfgNw1BOyoP4kQ8vOBCL7t/71yPXSomNdJdQ==",
+ "version": "0.1.16",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.16.tgz",
+ "integrity": "sha512-FvffvFN0LWgv1H/FIyruTECOL69Dhy+JfwoTq+mV39V8Mz9lNpo41etonL5AOr7KmXxYJVbNwkx0L9Ei88i7JA==",
"requires": {
"@firebase/util": "0.2.50",
"tslib": "^1.11.1"
}
},
"@firebase/database": {
- "version": "0.6.6",
- "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.6.tgz",
- "integrity": "sha512-TqUJOaCATF/h3wpqhPT9Fz1nZI6gBv/M2pHZztUjX4A9o9Bq93NyqUurYiZnGB7zpSkEADFCVT4f0VBrWdHlNw==",
+ "version": "0.6.7",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.7.tgz",
+ "integrity": "sha512-vm0ch2zNSoHfXWnDG6WVjf0p/BdXOMBL1lAfkGu3DYH/Rkl4p97x57w0WNOURNfL4GY2LIqScSYKCidV7jqTog==",
"requires": {
"@firebase/auth-interop-types": "0.1.5",
- "@firebase/component": "0.1.15",
+ "@firebase/component": "0.1.16",
"@firebase/database-types": "0.5.1",
- "@firebase/logger": "0.2.5",
+ "@firebase/logger": "0.2.6",
"@firebase/util": "0.2.50",
"faye-websocket": "0.11.3",
"tslib": "^1.11.1"
@@ -1175,13 +1175,13 @@
}
},
"@firebase/firestore": {
- "version": "1.15.5",
- "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.15.5.tgz",
- "integrity": "sha512-unkRIC2hL2Ge5er/Hj43aUYiEKlW5bpju8TnIaF33avg/wZpSsmtVrMlAQVkBWFhvWeYpJSr2QOzNLa1bQvuCA==",
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.16.0.tgz",
+ "integrity": "sha512-RsgGIP9e6HW5soEHIuo0CGVFpeTKe0hqjrgOLk92W0mjL6irzBlqmd5HcGMY4F5QiZryc2vMT1/3LvRhkUyf8g==",
"requires": {
- "@firebase/component": "0.1.15",
- "@firebase/firestore-types": "1.11.0",
- "@firebase/logger": "0.2.5",
+ "@firebase/component": "0.1.16",
+ "@firebase/firestore-types": "1.12.0",
+ "@firebase/logger": "0.2.6",
"@firebase/util": "0.2.50",
"@firebase/webchannel-wrapper": "0.2.41",
"@grpc/grpc-js": "^1.0.0",
@@ -1190,16 +1190,16 @@
}
},
"@firebase/firestore-types": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-1.11.0.tgz",
- "integrity": "sha512-hD7+cmMUvT5OJeWVrcRkE87PPuj/0/Wic6bntCopJE1WIX/Dm117AUkHgKd3S7Ici6DLp4bdlx1MjjwWL5942w=="
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-1.12.0.tgz",
+ "integrity": "sha512-OqNxVb63wPZdUc7YnpacAW1WNIMSKERSewCRi+unCQ0YI0KNfrDSypyGCyel+S3GdOtKMk9KnvDknaGbnaFX4g=="
},
"@firebase/functions": {
- "version": "0.4.47",
- "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.47.tgz",
- "integrity": "sha512-wiyMezW1EYq80Uk15M4poapCG10PjN5UJEY0jJr7DhCnDAoADMGlsIYFYio60+biGreij5/hpOybw5mU9WpXUw==",
+ "version": "0.4.48",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.48.tgz",
+ "integrity": "sha512-BwI/JzO/f/nquKG1IS3VqmwMaKEhvM58/08vTnp46krHBsOYqsdD9T2amz+HXGT9fe2HhDsUhgFE8D00S0vqbg==",
"requires": {
- "@firebase/component": "0.1.15",
+ "@firebase/component": "0.1.16",
"@firebase/functions-types": "0.3.17",
"@firebase/messaging-types": "0.4.5",
"isomorphic-fetch": "2.2.1",
@@ -1212,11 +1212,11 @@
"integrity": "sha512-DGR4i3VI55KnYk4IxrIw7+VG7Q3gA65azHnZxo98Il8IvYLr2UTBlSh72dTLlDf25NW51HqvJgYJDKvSaAeyHQ=="
},
"@firebase/installations": {
- "version": "0.4.13",
- "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.13.tgz",
- "integrity": "sha512-Sic7BtWgdUwk+Z1C4L49Edkhzaol/ijEIdv0pkHfjedIPirIU2V8CJ5qykx2y4aTiyVbdFqfjIpp1c6A6W3GBA==",
+ "version": "0.4.14",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.14.tgz",
+ "integrity": "sha512-hQPsaU7wdTq3CFMtFQwZy6LgdXZAkXoUToV4O+ekPbjM65QzaGVogJVU8O2H6ADXoq37SarcUXKe86pcUWdFLA==",
"requires": {
- "@firebase/component": "0.1.15",
+ "@firebase/component": "0.1.16",
"@firebase/installations-types": "0.3.4",
"@firebase/util": "0.2.50",
"idb": "3.0.2",
@@ -1229,17 +1229,17 @@
"integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q=="
},
"@firebase/logger": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.5.tgz",
- "integrity": "sha512-qqw3m0tWs/qrg7axTZG/QZq24DIMdSY6dGoWuBn08ddq7+GLF5HiqkRj71XznYeUUbfRq5W9C/PSFnN4JxX+WA=="
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz",
+ "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw=="
},
"@firebase/messaging": {
- "version": "0.6.19",
- "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.19.tgz",
- "integrity": "sha512-PhqK69m70G+GGgvbdnGz2+PyoqfmR5b+nouj1JV+HgyBCjMAhF8rDYQzCWWgy4HaWbLoS/xW6AZUKG20Kv2H1A==",
+ "version": "0.6.20",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.20.tgz",
+ "integrity": "sha512-1MqyljXnbFBeHYhL6QInVM9aO5MW820yhNmOIVxk58wNXq4tOQLzqnKuvlgZ+ttgqlDzrIYiVf3EOHh5DptttQ==",
"requires": {
- "@firebase/component": "0.1.15",
- "@firebase/installations": "0.4.13",
+ "@firebase/component": "0.1.16",
+ "@firebase/installations": "0.4.14",
"@firebase/messaging-types": "0.4.5",
"@firebase/util": "0.2.50",
"idb": "3.0.2",
@@ -1252,13 +1252,13 @@
"integrity": "sha512-sux4fgqr/0KyIxqzHlatI04Ajs5rc3WM+WmtCpxrKP1E5Bke8xu/0M+2oy4lK/sQ7nov9z15n3iltAHCgTRU3Q=="
},
"@firebase/performance": {
- "version": "0.3.8",
- "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.3.8.tgz",
- "integrity": "sha512-jODXrtFLyfnRiBehHuMBmsBtMv38U9sTictRxJSz+9JahvWYm1AF0YDzPlfeyYj+kxM6+S5wdQxUaPVdcWAvWg==",
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.3.9.tgz",
+ "integrity": "sha512-Fj22DZXRhhKv1OSUzDxX7AqpJUcDld6tzXK1yxOC8e3v1DFPQMQdM9FoG1m1b/Vrqa6pCCqnqG6gh6VPnEcAzQ==",
"requires": {
- "@firebase/component": "0.1.15",
- "@firebase/installations": "0.4.13",
- "@firebase/logger": "0.2.5",
+ "@firebase/component": "0.1.16",
+ "@firebase/installations": "0.4.14",
+ "@firebase/logger": "0.2.6",
"@firebase/performance-types": "0.0.13",
"@firebase/util": "0.2.50",
"tslib": "^1.11.1"
@@ -1287,13 +1287,13 @@
}
},
"@firebase/remote-config": {
- "version": "0.1.24",
- "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.24.tgz",
- "integrity": "sha512-/Kd+I5mNPI2wJJFySOC8Mjj4lRnEwZhU0RteuVlzFCDWWEyTE//r+p2TLAufQ9J+Fd3Ru5fVMFLNyU8k71Viiw==",
+ "version": "0.1.25",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.25.tgz",
+ "integrity": "sha512-8YWefBhy77HMbWXWdbenalx+IDY/XkS+iURQ9qRYvSIFYx6RL04DzlakZNOY9CQAcxTA+cTSt4NNlhjopBjf2Q==",
"requires": {
- "@firebase/component": "0.1.15",
- "@firebase/installations": "0.4.13",
- "@firebase/logger": "0.2.5",
+ "@firebase/component": "0.1.16",
+ "@firebase/installations": "0.4.14",
+ "@firebase/logger": "0.2.6",
"@firebase/remote-config-types": "0.1.9",
"@firebase/util": "0.2.50",
"tslib": "^1.11.1"
@@ -1305,11 +1305,11 @@
"integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA=="
},
"@firebase/storage": {
- "version": "0.3.37",
- "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.37.tgz",
- "integrity": "sha512-RLbiRQlnvXRP/30OaEiUoRHBxZygqrZyotPPWD2WmD3JMM9qGTVpYNQ092mqL3R8ViyejwlpjlPvrDo7Z9BzgQ==",
+ "version": "0.3.38",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.38.tgz",
+ "integrity": "sha512-gWVQr5xqrU3cfhhwbAE+9iJ0XMvzbxWMvteKurn5cRNaGbmSob/O/ISOAvsQgPnk+K9zPMd2OwyzaTOl9PEMrw==",
"requires": {
- "@firebase/component": "0.1.15",
+ "@firebase/component": "0.1.16",
"@firebase/storage-types": "0.3.12",
"@firebase/util": "0.2.50",
"tslib": "^1.11.1"
@@ -1369,9 +1369,9 @@
}
},
"@grpc/grpc-js": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.1.tgz",
- "integrity": "sha512-mhZRszS0SKwnWPJaNyrECePZ9U7vaHFGqrzxQbWinWR3WznBIU+nmh2L5J3elF+lp5DEUIzARXkifbs6LQVAHA==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.2.tgz",
+ "integrity": "sha512-k2u86Bkm/3xrjUaSWeIyzXScBt/cC8uE7BznR0cpueQi11R33W6qfJdMrkrsmSHirp5likR55JSXUrcWG6ybHA==",
"requires": {
"semver": "^6.2.0"
}
@@ -8021,23 +8021,23 @@
}
},
"firebase": {
- "version": "7.15.5",
- "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.15.5.tgz",
- "integrity": "sha512-yeXo3KDp/ZWO0/Uyen99cUvGM76femebmyNOBTHcGSDkBXvIGth6235KhclxLROIKCC5b3YNwmKX11tbaC6RJg==",
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.16.0.tgz",
+ "integrity": "sha512-fYimLYkY0SS/jv4+ZnSp5u2+QdtwsTtLwPUfmWiKQnjqas1M5mqhQr3QB7vPQuSANhC3UJZZ5KPxLbFomMJLcA==",
"requires": {
- "@firebase/analytics": "0.3.8",
- "@firebase/app": "0.6.7",
+ "@firebase/analytics": "0.3.9",
+ "@firebase/app": "0.6.8",
"@firebase/app-types": "0.6.1",
- "@firebase/auth": "0.14.7",
- "@firebase/database": "0.6.6",
- "@firebase/firestore": "1.15.5",
- "@firebase/functions": "0.4.47",
- "@firebase/installations": "0.4.13",
- "@firebase/messaging": "0.6.19",
- "@firebase/performance": "0.3.8",
+ "@firebase/auth": "0.14.8",
+ "@firebase/database": "0.6.7",
+ "@firebase/firestore": "1.16.0",
+ "@firebase/functions": "0.4.48",
+ "@firebase/installations": "0.4.14",
+ "@firebase/messaging": "0.6.20",
+ "@firebase/performance": "0.3.9",
"@firebase/polyfill": "0.3.36",
- "@firebase/remote-config": "0.1.24",
- "@firebase/storage": "0.3.37",
+ "@firebase/remote-config": "0.1.25",
+ "@firebase/storage": "0.3.38",
"@firebase/util": "0.2.50"
}
},
@@ -19528,9 +19528,9 @@
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
},
"whatwg-fetch": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.1.1.tgz",
- "integrity": "sha512-UlBvc5VApYAwNutfXFeuC9Jp3QCMazcqobfNqSK/RghRr3F8b0+i/QELUlEPsHjDHfijio6H5KPJcZwYXhuZsA=="
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.2.0.tgz",
+ "integrity": "sha512-SdGPoQMMnzVYThUbSrEvqTlkvC1Ux27NehaJ/GUHBfNrh5Mjg+1/uRyFMwVnxO2MrikMWvWAqUGgQOfVU4hT7w=="
},
"which": {
"version": "1.3.1",
diff --git a/package.json b/package.json
index 6f0bd3d5..553257ee 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
"array-move": "^2.2.2",
"classnames": "^2.2.6",
"dotenv": "^8.2.0",
- "firebase": "^7.15.5",
+ "firebase": "^7.16.0",
"formik": "^2.1.4",
"gatsby": "^2.24.1",
"gatsby-image": "^2.4.13",
diff --git a/src/components/builder/lists/List.js b/src/components/builder/lists/List.js
index 24f92c3b..958f8b24 100644
--- a/src/components/builder/lists/List.js
+++ b/src/components/builder/lists/List.js
@@ -53,13 +53,9 @@ const List = ({
)}
-
+
+ Add New
+
);
};
diff --git a/src/components/builder/right/sections/Actions.js b/src/components/builder/right/sections/Actions.js
index 90750ea6..8ed9a5cd 100644
--- a/src/components/builder/right/sections/Actions.js
+++ b/src/components/builder/right/sections/Actions.js
@@ -1,25 +1,52 @@
-import React, { memo } from 'react';
+import React, { memo, useContext } from 'react';
import { MdImportExport } from 'react-icons/md';
+import { clone } from 'lodash';
import Heading from '../../../shared/Heading';
import Button from '../../../shared/Button';
import styles from './Actions.module.css';
import Input from '../../../shared/Input';
+import ModalContext from '../../../../contexts/ModalContext';
+import { useSelector } from '../../../../contexts/ResumeContext';
const Actions = () => {
+ const state = useSelector();
+ const { emitter, events } = useContext(ModalContext);
+
+ const handleImport = () => emitter.emit(events.IMPORT_MODAL);
+
+ const handleExportToJson = () => {
+ const backupObj = clone(state);
+ delete backupObj.id;
+ const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(
+ JSON.stringify(backupObj),
+ )}`;
+ const dlAnchor = document.getElementById('downloadAnchor');
+ dlAnchor.setAttribute('href', dataStr);
+ dlAnchor.setAttribute('download', `RxResume_${state.id}.json`);
+ dlAnchor.click();
+ };
+
+ const getSharableUrl = () => {
+ const shareId = state.id.split('-')[0];
+ return `https://rxresu.me/r/${shareId}`;
+ };
+
return (
Actions
-
Import from Other Sources
+
Import Your Resume
You can import your information from various sources like JSON Resume
- or your LinkedIn profile to autofill most of the data for your resume.
+ or your LinkedIn to autofill most of the data for your resume.
-
+
+ Import
+
@@ -32,21 +59,27 @@ const Actions = () => {
-
-
+ Save as PDF
+
+ Export as JSON
+
+
+
+ Download Exported JSON
+
@@ -59,7 +92,7 @@ const Actions = () => {
-
+ Load Demo Data
@@ -73,7 +106,7 @@ const Actions = () => {
-
+ Delete Account
diff --git a/src/components/builder/right/sections/Colors.js b/src/components/builder/right/sections/Colors.js
index 54492cd7..ab1584dd 100644
--- a/src/components/builder/right/sections/Colors.js
+++ b/src/components/builder/right/sections/Colors.js
@@ -1,7 +1,7 @@
/* eslint-disable jsx-a11y/control-has-associated-label */
import React, { memo } from 'react';
import { useDispatch } from '../../../../contexts/ResumeContext';
-import colors from '../../../../data/colors';
+import colorOptions from '../../../../data/colorOptions';
import { handleKeyUp } from '../../../../utils';
import Heading from '../../../shared/Heading';
import Input from '../../../shared/Input';
@@ -25,7 +25,7 @@ const Colors = () => {
Colors
- {colors.map((color) => (
+ {colorOptions.map((color) => (
{
Fonts
- {fonts.map((x) => (
+ {fontOptions.map((x) => (
{
Templates
- {templates.map((x) => (
+ {templateOptions.map((x) => (
{
{user ? (
-
+
+ Go to App
+
) : (
)}
+ >
+ GitHub
+
diff --git a/src/components/shared/Button.js b/src/components/shared/Button.js
index 1be02e03..aadf13eb 100644
--- a/src/components/shared/Button.js
+++ b/src/components/shared/Button.js
@@ -3,7 +3,15 @@ import React, { memo } from 'react';
import { handleKeyUp } from '../../utils';
import styles from './Button.module.css';
-const Button = ({ icon, title, onClick, outline, className, isLoading }) => {
+const Button = ({
+ icon,
+ onClick,
+ outline,
+ children,
+ className,
+ isLoading,
+ isDelete,
+}) => {
const Icon = icon;
return (
@@ -12,10 +20,11 @@ const Button = ({ icon, title, onClick, outline, className, isLoading }) => {
onClick={isLoading ? undefined : onClick}
className={cx(styles.container, className, {
[styles.outline]: outline,
+ [styles.delete]: isDelete,
})}
>
{icon &&
}
- {isLoading ? 'Loading...' : title}
+ {isLoading ? 'Loading...' : children}
);
};
diff --git a/src/components/shared/Button.module.css b/src/components/shared/Button.module.css
index 0d613204..3fdf744f 100644
--- a/src/components/shared/Button.module.css
+++ b/src/components/shared/Button.module.css
@@ -29,3 +29,15 @@
.container.outline:focus {
@apply outline-none;
}
+
+.container.delete {
+ @apply bg-red-600 border-red-600 text-white;
+}
+
+.container.delete:hover {
+ @apply bg-red-700 border-red-700;
+}
+
+.container.delete:focus {
+ @apply outline-none;
+}
\ No newline at end of file
diff --git a/src/components/shared/Input.js b/src/components/shared/Input.js
index 512ded05..9ac96d8f 100644
--- a/src/components/shared/Input.js
+++ b/src/components/shared/Input.js
@@ -4,7 +4,6 @@ import React, { memo, useEffect, useState } from 'react';
import { FaAngleDown } from 'react-icons/fa';
import { MdClose, MdOpenInNew } from 'react-icons/md';
import { v4 as uuidv4 } from 'uuid';
-import { IoIosCopy } from 'react-icons/io';
import { useDispatch, useSelector } from '../../contexts/ResumeContext';
import { handleKeyUp } from '../../utils';
import styles from './Input.module.css';
diff --git a/src/constants/ModalEvents.js b/src/constants/ModalEvents.js
index c491d19f..8bc8c407 100644
--- a/src/constants/ModalEvents.js
+++ b/src/constants/ModalEvents.js
@@ -10,6 +10,7 @@ const ModalEvents = {
HOBBY_MODAL: 'hobby_modal',
LANGUAGE_MODAL: 'language_modal',
REFERENCE_MODAL: 'reference_modal',
+ IMPORT_MODAL: 'import_modal',
};
export default ModalEvents;
diff --git a/src/contexts/DatabaseContext.js b/src/contexts/DatabaseContext.js
index 0c989c47..32940f93 100644
--- a/src/contexts/DatabaseContext.js
+++ b/src/contexts/DatabaseContext.js
@@ -14,18 +14,18 @@ const DEBOUNCE_WAIT_TIME = 4000;
const defaultState = {
isOffline: false,
isUpdating: false,
+ createResume: () => {},
+ deleteResume: () => {},
getResume: async () => {},
getResumes: async () => {},
- createResume: () => {},
updateResume: async () => {},
debouncedUpdateResume: async () => {},
- debouncedUpdateMetadata: async () => {},
- deleteResume: () => {},
};
const DatabaseContext = createContext(defaultState);
const DatabaseProvider = ({ children }) => {
+ const [resumeId, setResumeId] = useState(false);
const [isOffline, setOffline] = useState(false);
const [isUpdating, setUpdating] = useState(false);
const { user } = useContext(UserContext);
@@ -38,6 +38,7 @@ const DatabaseProvider = ({ children }) => {
}, []);
const getResume = async (id) => {
+ setResumeId(id);
const snapshot = await firebase
.database()
.ref(`users/${user.uid}/resumes/${id}`)
@@ -71,13 +72,11 @@ const DatabaseProvider = ({ children }) => {
};
const updateResume = async (resume) => {
- const { id } = resume;
-
setUpdating(true);
await firebase
.database()
- .ref(`users/${user.uid}/resumes/${id}`)
+ .ref(`users/${user.uid}/resumes/${resumeId}`)
.update({
...resume,
updatedAt: firebase.database.ServerValue.TIMESTAMP,
@@ -88,22 +87,6 @@ const DatabaseProvider = ({ children }) => {
const debouncedUpdateResume = debounce(updateResume, DEBOUNCE_WAIT_TIME);
- const updateMetadata = async (resumeId, metadata) => {
- setUpdating(true);
-
- await firebase
- .database()
- .ref(`users/${user.uid}/resumes/${resumeId}`)
- .update({
- metadata,
- updatedAt: firebase.database.ServerValue.TIMESTAMP,
- });
-
- setUpdating(false);
- };
-
- const debouncedUpdateMetadata = debounce(updateMetadata, DEBOUNCE_WAIT_TIME);
-
const deleteResume = (id) => {
firebase.database().ref(`users/${user.uid}/resumes/${id}`).remove();
};
@@ -116,9 +99,8 @@ const DatabaseProvider = ({ children }) => {
getResume,
createResume,
updateResume,
- debouncedUpdateResume,
- debouncedUpdateMetadata,
deleteResume,
+ debouncedUpdateResume,
}}
>
{children}
diff --git a/src/contexts/ResumeContext.js b/src/contexts/ResumeContext.js
index 208d24a9..a9669f75 100644
--- a/src/contexts/ResumeContext.js
+++ b/src/contexts/ResumeContext.js
@@ -90,6 +90,11 @@ const ResumeProvider = ({ children }) => {
debouncedUpdateResume(newState);
return newState;
+ case 'on_import':
+ newState = { id: state.id, ...payload };
+ debouncedUpdateResume(newState);
+ return newState;
+
case 'set_data':
return payload;
diff --git a/src/data/colors.js b/src/data/colorOptions.js
similarity index 80%
rename from src/data/colors.js
rename to src/data/colorOptions.js
index 29051447..bd231af7 100644
--- a/src/data/colors.js
+++ b/src/data/colorOptions.js
@@ -1,4 +1,4 @@
-const colors = [
+const colorOptions = [
'#f44336',
'#E91E63',
'#9C27B0',
@@ -17,4 +17,4 @@ const colors = [
'#FF5722',
];
-export default colors;
+export default colorOptions;
diff --git a/src/data/fonts.js b/src/data/fontOptions.js
similarity index 70%
rename from src/data/fonts.js
rename to src/data/fontOptions.js
index 1fba06e1..50992055 100644
--- a/src/data/fonts.js
+++ b/src/data/fontOptions.js
@@ -1,4 +1,4 @@
-const fonts = [
+const fontOptions = [
'Lato',
'Montserrat',
'Nunito',
@@ -9,4 +9,4 @@ const fonts = [
'Titillium Web',
];
-export default fonts;
+export default fontOptions;
diff --git a/src/data/templates.js b/src/data/templateOptions.js
similarity index 78%
rename from src/data/templates.js
rename to src/data/templateOptions.js
index a70bbb75..8bcda2f7 100644
--- a/src/data/templates.js
+++ b/src/data/templateOptions.js
@@ -1,4 +1,4 @@
-const templates = [
+const templateOptions = [
{
id: 'onyx',
name: 'Onyx',
@@ -11,4 +11,4 @@ const templates = [
},
];
-export default templates;
+export default templateOptions;
diff --git a/src/modals/AuthModal.js b/src/modals/AuthModal.js
index c2bd96e3..164b7b5b 100644
--- a/src/modals/AuthModal.js
+++ b/src/modals/AuthModal.js
@@ -39,23 +39,25 @@ const AuthModal = () => {
const loggedInAction = (
<>
-
-
+
+ Logout
+
+
+ Go to App
+
>
);
const loggedOutAction = (
-
+
+ Sign in with Google
+
);
return (
{getMessage()}
diff --git a/src/modals/BaseModal.js b/src/modals/BaseModal.js
index 121825e5..b4b82cf4 100644
--- a/src/modals/BaseModal.js
+++ b/src/modals/BaseModal.js
@@ -9,7 +9,7 @@ import { handleKeyUp } from '../utils';
import styles from './BaseModal.module.css';
const BaseModal = forwardRef(
- ({ title, state, children, action, onDestroy }, ref) => {
+ ({ title, state, children, action, hideActions = false, onDestroy }, ref) => {
const [open, setOpen] = state;
const handleClose = () => {
@@ -44,16 +44,15 @@ const BaseModal = forwardRef(
{children}
-
-
+ {!hideActions && (
+
+
+ Cancel
+
- {action}
-
+ {action}
+
+ )}
diff --git a/src/modals/DataModal.js b/src/modals/DataModal.js
index 960582c3..fe044f46 100644
--- a/src/modals/DataModal.js
+++ b/src/modals/DataModal.js
@@ -79,7 +79,9 @@ const DataModal = ({
: title.create;
const submitAction = (
-
onSubmit(values)} />
+ onSubmit(values)}>
+ {getTitle}
+
);
const onDestroy = () => {
diff --git a/src/modals/ModalRegistrar.js b/src/modals/ModalRegistrar.js
index 0205c786..68133d99 100644
--- a/src/modals/ModalRegistrar.js
+++ b/src/modals/ModalRegistrar.js
@@ -5,6 +5,7 @@ import AwardModal from './sections/AwardModal';
import CertificateModal from './sections/CertificateModal';
import EducationModal from './sections/EducationModal';
import HobbyModal from './sections/HobbyModal';
+import ImportModal from './sections/ImportModal';
import LanguageModal from './sections/LanguageModal';
import ReferenceModal from './sections/ReferenceModal';
import SkillModal from './sections/SkillModal';
@@ -25,6 +26,7 @@ const ModalRegistrar = () => {
+
>
);
};
diff --git a/src/modals/sections/ImportModal.js b/src/modals/sections/ImportModal.js
new file mode 100644
index 00000000..c5954b84
--- /dev/null
+++ b/src/modals/sections/ImportModal.js
@@ -0,0 +1,95 @@
+import React, { memo, useContext, useEffect, useState, useRef } from 'react';
+import { Tooltip } from '@material-ui/core';
+import ModalContext from '../../contexts/ModalContext';
+import BaseModal from '../BaseModal';
+import Button from '../../components/shared/Button';
+import { useDispatch } from '../../contexts/ResumeContext';
+
+const ImportModal = () => {
+ const fileInputRef = useRef(null);
+ const [open, setOpen] = useState(false);
+ const dispatch = useDispatch();
+
+ const { emitter, events } = useContext(ModalContext);
+
+ useEffect(() => {
+ const unbind = emitter.on(events.IMPORT_MODAL, () => setOpen(true));
+
+ return () => unbind();
+ }, [emitter, events]);
+
+ const importReactiveResumeJson = (event) => {
+ const fr = new FileReader();
+ fr.addEventListener('load', () => {
+ const payload = JSON.parse(fr.result);
+ dispatch({ type: 'on_import', payload });
+ setOpen(false);
+ });
+ fr.readAsText(event.target.files[0]);
+ };
+
+ return (
+
+
+
+ Import from Reactive Resume
+
+
+
+ Reactive Resume has it's own schema format to make the most of
+ all the customizable capabilities it has to offer. If you'd like
+ to import a backup of your resume made with this app, just upload the
+ file using the button below.
+
+
+
fileInputRef.current.click()}>
+ Select File
+
+
+
+
+
+
+
+
Import from JSON Resume
+
+
+ JSON Resume is an open standard
+ for resume schema structure. If you are one of the many enthusiasts
+ who have their resume ready in this format, all it takes it just one
+ click to get started with Reactive Resume.
+
+
+
+
+ Select File
+
+
+
+
+
+
+
+
Import from LinkedIn
+
+
+ You can import a JSON that was exported from Reactive Resume by
+ clicking on the button below and selecting the appropriate file.
+
+
+
+
+ Select File
+
+
+
+
+ );
+};
+
+export default memo(ImportModal);