mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-13 16:22:59 +10:00
- implement actions section
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"globals": {
|
"globals": {
|
||||||
"document": true,
|
"document": true,
|
||||||
|
"FileReader": true,
|
||||||
"localStorage": true
|
"localStorage": true
|
||||||
},
|
},
|
||||||
"extends": ["airbnb", "prettier"],
|
"extends": ["airbnb", "prettier"],
|
||||||
|
|||||||
166
package-lock.json
generated
166
package-lock.json
generated
@ -1089,14 +1089,14 @@
|
|||||||
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
|
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
|
||||||
},
|
},
|
||||||
"@firebase/analytics": {
|
"@firebase/analytics": {
|
||||||
"version": "0.3.8",
|
"version": "0.3.9",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.9.tgz",
|
||||||
"integrity": "sha512-HpNRBJHnrGq5jtVTNRgA8Ozng2ilt0pkej8D5EvXoaylu80U+ICKLBlIT8TdUSEfkXC/RPjvLXg6vn/sq/CyqA==",
|
"integrity": "sha512-l4dNskm8uQ+UqO6Lw+fuyO1enZBXUV6xNMxeVABEnVrp3wOP90KKb/ZwYgleAxF1It52lorcTtkA1YFpv3iEIQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/analytics-types": "0.3.1",
|
"@firebase/analytics-types": "0.3.1",
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/installations": "0.4.13",
|
"@firebase/installations": "0.4.14",
|
||||||
"@firebase/logger": "0.2.5",
|
"@firebase/logger": "0.2.6",
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"tslib": "^1.11.1"
|
"tslib": "^1.11.1"
|
||||||
}
|
}
|
||||||
@ -1107,13 +1107,13 @@
|
|||||||
"integrity": "sha512-63vVJ5NIBh/JF8l9LuPrQYSzFimk7zYHySQB4Dk9rVdJ8kV/vGQoVTvRu1UW05sEc2Ug5PqtEChtTHU+9hvPcA=="
|
"integrity": "sha512-63vVJ5NIBh/JF8l9LuPrQYSzFimk7zYHySQB4Dk9rVdJ8kV/vGQoVTvRu1UW05sEc2Ug5PqtEChtTHU+9hvPcA=="
|
||||||
},
|
},
|
||||||
"@firebase/app": {
|
"@firebase/app": {
|
||||||
"version": "0.6.7",
|
"version": "0.6.8",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.8.tgz",
|
||||||
"integrity": "sha512-6NpIZ3iMrCR2XOShK5oi3YYB0GXX5yxVD8p3+2N+X4CF5cERyIrDRf8+YXOFgr+bDHSbVcIyzpWv6ijhg4MJlw==",
|
"integrity": "sha512-Tm7Pi6Dtpx4FFKcpm0jcrZ/qI9oREBxmP3pWlw1jgDW4syRJHmN9/5DYvfFk6FAhj3FrY8E/6F+ngWJfqONotQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/app-types": "0.6.1",
|
"@firebase/app-types": "0.6.1",
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/logger": "0.2.5",
|
"@firebase/logger": "0.2.6",
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"dom-storage": "2.1.0",
|
"dom-storage": "2.1.0",
|
||||||
"tslib": "^1.11.1",
|
"tslib": "^1.11.1",
|
||||||
@ -1126,9 +1126,9 @@
|
|||||||
"integrity": "sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg=="
|
"integrity": "sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg=="
|
||||||
},
|
},
|
||||||
"@firebase/auth": {
|
"@firebase/auth": {
|
||||||
"version": "0.14.7",
|
"version": "0.14.8",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.7.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.8.tgz",
|
||||||
"integrity": "sha512-NTQY9luV70XUA6zGYOWloDSaOT+l0/R4u3W7ptqVCfZNc4DAt7euUkTbj7SDD14902sHF54j+tk5kmpEmMd0jA==",
|
"integrity": "sha512-LufoWcFpYAoCUkFDKSELH69xI8NdOjNTUFKvWfADZN7ysr4dpPdDs2ZYnH67FqcMb0tX+Jdx6vWrF6VZ37AAJQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/auth-types": "0.10.1"
|
"@firebase/auth-types": "0.10.1"
|
||||||
}
|
}
|
||||||
@ -1144,23 +1144,23 @@
|
|||||||
"integrity": "sha512-/+gBHb1O9x/YlG7inXfxff/6X3BPZt4zgBv4kql6HEmdzNQCodIRlEYnI+/da+lN+dha7PjaFH7C7ewMmfV7rw=="
|
"integrity": "sha512-/+gBHb1O9x/YlG7inXfxff/6X3BPZt4zgBv4kql6HEmdzNQCodIRlEYnI+/da+lN+dha7PjaFH7C7ewMmfV7rw=="
|
||||||
},
|
},
|
||||||
"@firebase/component": {
|
"@firebase/component": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.15.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.16.tgz",
|
||||||
"integrity": "sha512-HqFb1qQl1vtlUMIzPM15plNz27jqM8DWjuQQuGeDfG+4iRRflwKfgNw1BOyoP4kQ8vOBCL7t/71yPXSomNdJdQ==",
|
"integrity": "sha512-FvffvFN0LWgv1H/FIyruTECOL69Dhy+JfwoTq+mV39V8Mz9lNpo41etonL5AOr7KmXxYJVbNwkx0L9Ei88i7JA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"tslib": "^1.11.1"
|
"tslib": "^1.11.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@firebase/database": {
|
"@firebase/database": {
|
||||||
"version": "0.6.6",
|
"version": "0.6.7",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.6.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.7.tgz",
|
||||||
"integrity": "sha512-TqUJOaCATF/h3wpqhPT9Fz1nZI6gBv/M2pHZztUjX4A9o9Bq93NyqUurYiZnGB7zpSkEADFCVT4f0VBrWdHlNw==",
|
"integrity": "sha512-vm0ch2zNSoHfXWnDG6WVjf0p/BdXOMBL1lAfkGu3DYH/Rkl4p97x57w0WNOURNfL4GY2LIqScSYKCidV7jqTog==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/auth-interop-types": "0.1.5",
|
"@firebase/auth-interop-types": "0.1.5",
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/database-types": "0.5.1",
|
"@firebase/database-types": "0.5.1",
|
||||||
"@firebase/logger": "0.2.5",
|
"@firebase/logger": "0.2.6",
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"faye-websocket": "0.11.3",
|
"faye-websocket": "0.11.3",
|
||||||
"tslib": "^1.11.1"
|
"tslib": "^1.11.1"
|
||||||
@ -1175,13 +1175,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@firebase/firestore": {
|
"@firebase/firestore": {
|
||||||
"version": "1.15.5",
|
"version": "1.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.15.5.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.16.0.tgz",
|
||||||
"integrity": "sha512-unkRIC2hL2Ge5er/Hj43aUYiEKlW5bpju8TnIaF33avg/wZpSsmtVrMlAQVkBWFhvWeYpJSr2QOzNLa1bQvuCA==",
|
"integrity": "sha512-RsgGIP9e6HW5soEHIuo0CGVFpeTKe0hqjrgOLk92W0mjL6irzBlqmd5HcGMY4F5QiZryc2vMT1/3LvRhkUyf8g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/firestore-types": "1.11.0",
|
"@firebase/firestore-types": "1.12.0",
|
||||||
"@firebase/logger": "0.2.5",
|
"@firebase/logger": "0.2.6",
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"@firebase/webchannel-wrapper": "0.2.41",
|
"@firebase/webchannel-wrapper": "0.2.41",
|
||||||
"@grpc/grpc-js": "^1.0.0",
|
"@grpc/grpc-js": "^1.0.0",
|
||||||
@ -1190,16 +1190,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@firebase/firestore-types": {
|
"@firebase/firestore-types": {
|
||||||
"version": "1.11.0",
|
"version": "1.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-1.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-1.12.0.tgz",
|
||||||
"integrity": "sha512-hD7+cmMUvT5OJeWVrcRkE87PPuj/0/Wic6bntCopJE1WIX/Dm117AUkHgKd3S7Ici6DLp4bdlx1MjjwWL5942w=="
|
"integrity": "sha512-OqNxVb63wPZdUc7YnpacAW1WNIMSKERSewCRi+unCQ0YI0KNfrDSypyGCyel+S3GdOtKMk9KnvDknaGbnaFX4g=="
|
||||||
},
|
},
|
||||||
"@firebase/functions": {
|
"@firebase/functions": {
|
||||||
"version": "0.4.47",
|
"version": "0.4.48",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.47.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.48.tgz",
|
||||||
"integrity": "sha512-wiyMezW1EYq80Uk15M4poapCG10PjN5UJEY0jJr7DhCnDAoADMGlsIYFYio60+biGreij5/hpOybw5mU9WpXUw==",
|
"integrity": "sha512-BwI/JzO/f/nquKG1IS3VqmwMaKEhvM58/08vTnp46krHBsOYqsdD9T2amz+HXGT9fe2HhDsUhgFE8D00S0vqbg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/functions-types": "0.3.17",
|
"@firebase/functions-types": "0.3.17",
|
||||||
"@firebase/messaging-types": "0.4.5",
|
"@firebase/messaging-types": "0.4.5",
|
||||||
"isomorphic-fetch": "2.2.1",
|
"isomorphic-fetch": "2.2.1",
|
||||||
@ -1212,11 +1212,11 @@
|
|||||||
"integrity": "sha512-DGR4i3VI55KnYk4IxrIw7+VG7Q3gA65azHnZxo98Il8IvYLr2UTBlSh72dTLlDf25NW51HqvJgYJDKvSaAeyHQ=="
|
"integrity": "sha512-DGR4i3VI55KnYk4IxrIw7+VG7Q3gA65azHnZxo98Il8IvYLr2UTBlSh72dTLlDf25NW51HqvJgYJDKvSaAeyHQ=="
|
||||||
},
|
},
|
||||||
"@firebase/installations": {
|
"@firebase/installations": {
|
||||||
"version": "0.4.13",
|
"version": "0.4.14",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.13.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.14.tgz",
|
||||||
"integrity": "sha512-Sic7BtWgdUwk+Z1C4L49Edkhzaol/ijEIdv0pkHfjedIPirIU2V8CJ5qykx2y4aTiyVbdFqfjIpp1c6A6W3GBA==",
|
"integrity": "sha512-hQPsaU7wdTq3CFMtFQwZy6LgdXZAkXoUToV4O+ekPbjM65QzaGVogJVU8O2H6ADXoq37SarcUXKe86pcUWdFLA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/installations-types": "0.3.4",
|
"@firebase/installations-types": "0.3.4",
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"idb": "3.0.2",
|
"idb": "3.0.2",
|
||||||
@ -1229,17 +1229,17 @@
|
|||||||
"integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q=="
|
"integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q=="
|
||||||
},
|
},
|
||||||
"@firebase/logger": {
|
"@firebase/logger": {
|
||||||
"version": "0.2.5",
|
"version": "0.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz",
|
||||||
"integrity": "sha512-qqw3m0tWs/qrg7axTZG/QZq24DIMdSY6dGoWuBn08ddq7+GLF5HiqkRj71XznYeUUbfRq5W9C/PSFnN4JxX+WA=="
|
"integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw=="
|
||||||
},
|
},
|
||||||
"@firebase/messaging": {
|
"@firebase/messaging": {
|
||||||
"version": "0.6.19",
|
"version": "0.6.20",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.19.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.20.tgz",
|
||||||
"integrity": "sha512-PhqK69m70G+GGgvbdnGz2+PyoqfmR5b+nouj1JV+HgyBCjMAhF8rDYQzCWWgy4HaWbLoS/xW6AZUKG20Kv2H1A==",
|
"integrity": "sha512-1MqyljXnbFBeHYhL6QInVM9aO5MW820yhNmOIVxk58wNXq4tOQLzqnKuvlgZ+ttgqlDzrIYiVf3EOHh5DptttQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/installations": "0.4.13",
|
"@firebase/installations": "0.4.14",
|
||||||
"@firebase/messaging-types": "0.4.5",
|
"@firebase/messaging-types": "0.4.5",
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"idb": "3.0.2",
|
"idb": "3.0.2",
|
||||||
@ -1252,13 +1252,13 @@
|
|||||||
"integrity": "sha512-sux4fgqr/0KyIxqzHlatI04Ajs5rc3WM+WmtCpxrKP1E5Bke8xu/0M+2oy4lK/sQ7nov9z15n3iltAHCgTRU3Q=="
|
"integrity": "sha512-sux4fgqr/0KyIxqzHlatI04Ajs5rc3WM+WmtCpxrKP1E5Bke8xu/0M+2oy4lK/sQ7nov9z15n3iltAHCgTRU3Q=="
|
||||||
},
|
},
|
||||||
"@firebase/performance": {
|
"@firebase/performance": {
|
||||||
"version": "0.3.8",
|
"version": "0.3.9",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.3.9.tgz",
|
||||||
"integrity": "sha512-jODXrtFLyfnRiBehHuMBmsBtMv38U9sTictRxJSz+9JahvWYm1AF0YDzPlfeyYj+kxM6+S5wdQxUaPVdcWAvWg==",
|
"integrity": "sha512-Fj22DZXRhhKv1OSUzDxX7AqpJUcDld6tzXK1yxOC8e3v1DFPQMQdM9FoG1m1b/Vrqa6pCCqnqG6gh6VPnEcAzQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/installations": "0.4.13",
|
"@firebase/installations": "0.4.14",
|
||||||
"@firebase/logger": "0.2.5",
|
"@firebase/logger": "0.2.6",
|
||||||
"@firebase/performance-types": "0.0.13",
|
"@firebase/performance-types": "0.0.13",
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"tslib": "^1.11.1"
|
"tslib": "^1.11.1"
|
||||||
@ -1287,13 +1287,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@firebase/remote-config": {
|
"@firebase/remote-config": {
|
||||||
"version": "0.1.24",
|
"version": "0.1.25",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.24.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.25.tgz",
|
||||||
"integrity": "sha512-/Kd+I5mNPI2wJJFySOC8Mjj4lRnEwZhU0RteuVlzFCDWWEyTE//r+p2TLAufQ9J+Fd3Ru5fVMFLNyU8k71Viiw==",
|
"integrity": "sha512-8YWefBhy77HMbWXWdbenalx+IDY/XkS+iURQ9qRYvSIFYx6RL04DzlakZNOY9CQAcxTA+cTSt4NNlhjopBjf2Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/installations": "0.4.13",
|
"@firebase/installations": "0.4.14",
|
||||||
"@firebase/logger": "0.2.5",
|
"@firebase/logger": "0.2.6",
|
||||||
"@firebase/remote-config-types": "0.1.9",
|
"@firebase/remote-config-types": "0.1.9",
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"tslib": "^1.11.1"
|
"tslib": "^1.11.1"
|
||||||
@ -1305,11 +1305,11 @@
|
|||||||
"integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA=="
|
"integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA=="
|
||||||
},
|
},
|
||||||
"@firebase/storage": {
|
"@firebase/storage": {
|
||||||
"version": "0.3.37",
|
"version": "0.3.38",
|
||||||
"resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.37.tgz",
|
"resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.38.tgz",
|
||||||
"integrity": "sha512-RLbiRQlnvXRP/30OaEiUoRHBxZygqrZyotPPWD2WmD3JMM9qGTVpYNQ092mqL3R8ViyejwlpjlPvrDo7Z9BzgQ==",
|
"integrity": "sha512-gWVQr5xqrU3cfhhwbAE+9iJ0XMvzbxWMvteKurn5cRNaGbmSob/O/ISOAvsQgPnk+K9zPMd2OwyzaTOl9PEMrw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/component": "0.1.15",
|
"@firebase/component": "0.1.16",
|
||||||
"@firebase/storage-types": "0.3.12",
|
"@firebase/storage-types": "0.3.12",
|
||||||
"@firebase/util": "0.2.50",
|
"@firebase/util": "0.2.50",
|
||||||
"tslib": "^1.11.1"
|
"tslib": "^1.11.1"
|
||||||
@ -1369,9 +1369,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@grpc/grpc-js": {
|
"@grpc/grpc-js": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.2.tgz",
|
||||||
"integrity": "sha512-mhZRszS0SKwnWPJaNyrECePZ9U7vaHFGqrzxQbWinWR3WznBIU+nmh2L5J3elF+lp5DEUIzARXkifbs6LQVAHA==",
|
"integrity": "sha512-k2u86Bkm/3xrjUaSWeIyzXScBt/cC8uE7BznR0cpueQi11R33W6qfJdMrkrsmSHirp5likR55JSXUrcWG6ybHA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"semver": "^6.2.0"
|
"semver": "^6.2.0"
|
||||||
}
|
}
|
||||||
@ -8021,23 +8021,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"firebase": {
|
"firebase": {
|
||||||
"version": "7.15.5",
|
"version": "7.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/firebase/-/firebase-7.15.5.tgz",
|
"resolved": "https://registry.npmjs.org/firebase/-/firebase-7.16.0.tgz",
|
||||||
"integrity": "sha512-yeXo3KDp/ZWO0/Uyen99cUvGM76femebmyNOBTHcGSDkBXvIGth6235KhclxLROIKCC5b3YNwmKX11tbaC6RJg==",
|
"integrity": "sha512-fYimLYkY0SS/jv4+ZnSp5u2+QdtwsTtLwPUfmWiKQnjqas1M5mqhQr3QB7vPQuSANhC3UJZZ5KPxLbFomMJLcA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@firebase/analytics": "0.3.8",
|
"@firebase/analytics": "0.3.9",
|
||||||
"@firebase/app": "0.6.7",
|
"@firebase/app": "0.6.8",
|
||||||
"@firebase/app-types": "0.6.1",
|
"@firebase/app-types": "0.6.1",
|
||||||
"@firebase/auth": "0.14.7",
|
"@firebase/auth": "0.14.8",
|
||||||
"@firebase/database": "0.6.6",
|
"@firebase/database": "0.6.7",
|
||||||
"@firebase/firestore": "1.15.5",
|
"@firebase/firestore": "1.16.0",
|
||||||
"@firebase/functions": "0.4.47",
|
"@firebase/functions": "0.4.48",
|
||||||
"@firebase/installations": "0.4.13",
|
"@firebase/installations": "0.4.14",
|
||||||
"@firebase/messaging": "0.6.19",
|
"@firebase/messaging": "0.6.20",
|
||||||
"@firebase/performance": "0.3.8",
|
"@firebase/performance": "0.3.9",
|
||||||
"@firebase/polyfill": "0.3.36",
|
"@firebase/polyfill": "0.3.36",
|
||||||
"@firebase/remote-config": "0.1.24",
|
"@firebase/remote-config": "0.1.25",
|
||||||
"@firebase/storage": "0.3.37",
|
"@firebase/storage": "0.3.38",
|
||||||
"@firebase/util": "0.2.50"
|
"@firebase/util": "0.2.50"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -19528,9 +19528,9 @@
|
|||||||
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
|
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
|
||||||
},
|
},
|
||||||
"whatwg-fetch": {
|
"whatwg-fetch": {
|
||||||
"version": "3.1.1",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.2.0.tgz",
|
||||||
"integrity": "sha512-UlBvc5VApYAwNutfXFeuC9Jp3QCMazcqobfNqSK/RghRr3F8b0+i/QELUlEPsHjDHfijio6H5KPJcZwYXhuZsA=="
|
"integrity": "sha512-SdGPoQMMnzVYThUbSrEvqTlkvC1Ux27NehaJ/GUHBfNrh5Mjg+1/uRyFMwVnxO2MrikMWvWAqUGgQOfVU4hT7w=="
|
||||||
},
|
},
|
||||||
"which": {
|
"which": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
"array-move": "^2.2.2",
|
"array-move": "^2.2.2",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"firebase": "^7.15.5",
|
"firebase": "^7.16.0",
|
||||||
"formik": "^2.1.4",
|
"formik": "^2.1.4",
|
||||||
"gatsby": "^2.24.1",
|
"gatsby": "^2.24.1",
|
||||||
"gatsby-image": "^2.4.13",
|
"gatsby-image": "^2.4.13",
|
||||||
|
|||||||
@ -53,13 +53,9 @@ const List = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button outline icon={MdAdd} onClick={handleAdd} className="mt-8 ml-auto">
|
||||||
outline
|
Add New
|
||||||
icon={MdAdd}
|
</Button>
|
||||||
title="Add New"
|
|
||||||
onClick={handleAdd}
|
|
||||||
className="mt-8 ml-auto"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,25 +1,52 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
import { MdImportExport } from 'react-icons/md';
|
import { MdImportExport } from 'react-icons/md';
|
||||||
|
import { clone } from 'lodash';
|
||||||
import Heading from '../../../shared/Heading';
|
import Heading from '../../../shared/Heading';
|
||||||
import Button from '../../../shared/Button';
|
import Button from '../../../shared/Button';
|
||||||
import styles from './Actions.module.css';
|
import styles from './Actions.module.css';
|
||||||
import Input from '../../../shared/Input';
|
import Input from '../../../shared/Input';
|
||||||
|
import ModalContext from '../../../../contexts/ModalContext';
|
||||||
|
import { useSelector } from '../../../../contexts/ResumeContext';
|
||||||
|
|
||||||
const Actions = () => {
|
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 (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<Heading>Actions</Heading>
|
<Heading>Actions</Heading>
|
||||||
|
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<h5>Import from Other Sources</h5>
|
<h5>Import Your Resume</h5>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You can import your information from various sources like JSON 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.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-4 flex">
|
<div className="mt-4 flex">
|
||||||
<Button icon={MdImportExport} title="Import" />
|
<Button icon={MdImportExport} onClick={handleImport}>
|
||||||
|
Import
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -32,21 +59,27 @@ const Actions = () => {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-4 flex">
|
<div className="mt-4 flex">
|
||||||
<Button title="Save as PDF" />
|
<Button>Save as PDF</Button>
|
||||||
<Button outline title="Export as JSON" className="ml-6" />
|
<Button outline className="ml-6" onClick={handleExportToJson}>
|
||||||
|
Export as JSON
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<a id="downloadAnchor" className="hidden">
|
||||||
|
Download Exported JSON
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<h5>Share Your Resume</h5>
|
<h5>Share Your Resume</h5>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The link below will be accessible publicly if you choose, and you can
|
The link below will be accessible publicly if you choose to share it,
|
||||||
share the latest version of your resume to anyone in the world.
|
and viewers would see the latest version of your resume at any time.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Input type="action" value="https://google.com" onClick={() => {}} />
|
<Input type="action" value={getSharableUrl()} onClick={() => {}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -59,7 +92,7 @@ const Actions = () => {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-4 flex">
|
<div className="mt-4 flex">
|
||||||
<Button title="Load Demo Data" />
|
<Button>Load Demo Data</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -73,7 +106,7 @@ const Actions = () => {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-4 flex">
|
<div className="mt-4 flex">
|
||||||
<Button title="Delete Account" />
|
<Button isDelete>Delete Account</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable jsx-a11y/control-has-associated-label */
|
/* eslint-disable jsx-a11y/control-has-associated-label */
|
||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
import { useDispatch } from '../../../../contexts/ResumeContext';
|
import { useDispatch } from '../../../../contexts/ResumeContext';
|
||||||
import colors from '../../../../data/colors';
|
import colorOptions from '../../../../data/colorOptions';
|
||||||
import { handleKeyUp } from '../../../../utils';
|
import { handleKeyUp } from '../../../../utils';
|
||||||
import Heading from '../../../shared/Heading';
|
import Heading from '../../../shared/Heading';
|
||||||
import Input from '../../../shared/Input';
|
import Input from '../../../shared/Input';
|
||||||
@ -25,7 +25,7 @@ const Colors = () => {
|
|||||||
<Heading>Colors</Heading>
|
<Heading>Colors</Heading>
|
||||||
|
|
||||||
<div className="mb-6 grid grid-cols-8 col-gap-2 row-gap-6">
|
<div className="mb-6 grid grid-cols-8 col-gap-2 row-gap-6">
|
||||||
{colors.map((color) => (
|
{colorOptions.map((color) => (
|
||||||
<div
|
<div
|
||||||
key={color}
|
key={color}
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
import { useDispatch, useSelector } from '../../../../contexts/ResumeContext';
|
import { useDispatch, useSelector } from '../../../../contexts/ResumeContext';
|
||||||
import fonts from '../../../../data/fonts';
|
import fontOptions from '../../../../data/fontOptions';
|
||||||
import { handleKeyUp } from '../../../../utils';
|
import { handleKeyUp } from '../../../../utils';
|
||||||
import Heading from '../../../shared/Heading';
|
import Heading from '../../../shared/Heading';
|
||||||
import styles from './Fonts.module.css';
|
import styles from './Fonts.module.css';
|
||||||
@ -25,7 +25,7 @@ const Fonts = () => {
|
|||||||
<Heading>Fonts</Heading>
|
<Heading>Fonts</Heading>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-8">
|
<div className="grid grid-cols-2 gap-8">
|
||||||
{fonts.map((x) => (
|
{fontOptions.map((x) => (
|
||||||
<div
|
<div
|
||||||
key={x}
|
key={x}
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import React, { memo, useContext } from 'react';
|
import React, { memo, useContext } from 'react';
|
||||||
import { useDispatch, useSelector } from '../../../../contexts/ResumeContext';
|
import { useDispatch, useSelector } from '../../../../contexts/ResumeContext';
|
||||||
import templates from '../../../../data/templates';
|
import templateOptions from '../../../../data/templateOptions';
|
||||||
import { handleKeyUp } from '../../../../utils';
|
import { handleKeyUp } from '../../../../utils';
|
||||||
import Heading from '../../../shared/Heading';
|
import Heading from '../../../shared/Heading';
|
||||||
import styles from './Templates.module.css';
|
import styles from './Templates.module.css';
|
||||||
@ -28,7 +28,7 @@ const Templates = () => {
|
|||||||
<Heading>Templates</Heading>
|
<Heading>Templates</Heading>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-8">
|
<div className="grid grid-cols-2 gap-8">
|
||||||
{templates.map((x) => (
|
{templateOptions.map((x) => (
|
||||||
<div
|
<div
|
||||||
key={x.id}
|
key={x.id}
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
|
|||||||
@ -28,21 +28,20 @@ const Hero = () => {
|
|||||||
|
|
||||||
<div className="mt-12 flex">
|
<div className="mt-12 flex">
|
||||||
{user ? (
|
{user ? (
|
||||||
<Button
|
<Button onClick={handleGotoApp} isLoading={loading}>
|
||||||
title="Go to App"
|
Go to App
|
||||||
onClick={handleGotoApp}
|
</Button>
|
||||||
isLoading={loading}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<Button title="Login" onClick={handleLogin} isLoading={loading} />
|
<Button title="Login" onClick={handleLogin} isLoading={loading} />
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
outline
|
outline
|
||||||
className="ml-8"
|
className="ml-8"
|
||||||
title="GitHub"
|
|
||||||
icon={FaGithub}
|
icon={FaGithub}
|
||||||
onClick={toggleDarkMode}
|
onClick={toggleDarkMode}
|
||||||
/>
|
>
|
||||||
|
GitHub
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,7 +3,15 @@ import React, { memo } from 'react';
|
|||||||
import { handleKeyUp } from '../../utils';
|
import { handleKeyUp } from '../../utils';
|
||||||
import styles from './Button.module.css';
|
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;
|
const Icon = icon;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -12,10 +20,11 @@ const Button = ({ icon, title, onClick, outline, className, isLoading }) => {
|
|||||||
onClick={isLoading ? undefined : onClick}
|
onClick={isLoading ? undefined : onClick}
|
||||||
className={cx(styles.container, className, {
|
className={cx(styles.container, className, {
|
||||||
[styles.outline]: outline,
|
[styles.outline]: outline,
|
||||||
|
[styles.delete]: isDelete,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{icon && <Icon size="14" className="mr-3" />}
|
{icon && <Icon size="14" className="mr-3" />}
|
||||||
{isLoading ? 'Loading...' : title}
|
{isLoading ? 'Loading...' : children}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -29,3 +29,15 @@
|
|||||||
.container.outline:focus {
|
.container.outline:focus {
|
||||||
@apply outline-none;
|
@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;
|
||||||
|
}
|
||||||
@ -4,7 +4,6 @@ import React, { memo, useEffect, useState } from 'react';
|
|||||||
import { FaAngleDown } from 'react-icons/fa';
|
import { FaAngleDown } from 'react-icons/fa';
|
||||||
import { MdClose, MdOpenInNew } from 'react-icons/md';
|
import { MdClose, MdOpenInNew } from 'react-icons/md';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { IoIosCopy } from 'react-icons/io';
|
|
||||||
import { useDispatch, useSelector } from '../../contexts/ResumeContext';
|
import { useDispatch, useSelector } from '../../contexts/ResumeContext';
|
||||||
import { handleKeyUp } from '../../utils';
|
import { handleKeyUp } from '../../utils';
|
||||||
import styles from './Input.module.css';
|
import styles from './Input.module.css';
|
||||||
|
|||||||
@ -10,6 +10,7 @@ const ModalEvents = {
|
|||||||
HOBBY_MODAL: 'hobby_modal',
|
HOBBY_MODAL: 'hobby_modal',
|
||||||
LANGUAGE_MODAL: 'language_modal',
|
LANGUAGE_MODAL: 'language_modal',
|
||||||
REFERENCE_MODAL: 'reference_modal',
|
REFERENCE_MODAL: 'reference_modal',
|
||||||
|
IMPORT_MODAL: 'import_modal',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ModalEvents;
|
export default ModalEvents;
|
||||||
|
|||||||
@ -14,18 +14,18 @@ const DEBOUNCE_WAIT_TIME = 4000;
|
|||||||
const defaultState = {
|
const defaultState = {
|
||||||
isOffline: false,
|
isOffline: false,
|
||||||
isUpdating: false,
|
isUpdating: false,
|
||||||
|
createResume: () => {},
|
||||||
|
deleteResume: () => {},
|
||||||
getResume: async () => {},
|
getResume: async () => {},
|
||||||
getResumes: async () => {},
|
getResumes: async () => {},
|
||||||
createResume: () => {},
|
|
||||||
updateResume: async () => {},
|
updateResume: async () => {},
|
||||||
debouncedUpdateResume: async () => {},
|
debouncedUpdateResume: async () => {},
|
||||||
debouncedUpdateMetadata: async () => {},
|
|
||||||
deleteResume: () => {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const DatabaseContext = createContext(defaultState);
|
const DatabaseContext = createContext(defaultState);
|
||||||
|
|
||||||
const DatabaseProvider = ({ children }) => {
|
const DatabaseProvider = ({ children }) => {
|
||||||
|
const [resumeId, setResumeId] = useState(false);
|
||||||
const [isOffline, setOffline] = useState(false);
|
const [isOffline, setOffline] = useState(false);
|
||||||
const [isUpdating, setUpdating] = useState(false);
|
const [isUpdating, setUpdating] = useState(false);
|
||||||
const { user } = useContext(UserContext);
|
const { user } = useContext(UserContext);
|
||||||
@ -38,6 +38,7 @@ const DatabaseProvider = ({ children }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const getResume = async (id) => {
|
const getResume = async (id) => {
|
||||||
|
setResumeId(id);
|
||||||
const snapshot = await firebase
|
const snapshot = await firebase
|
||||||
.database()
|
.database()
|
||||||
.ref(`users/${user.uid}/resumes/${id}`)
|
.ref(`users/${user.uid}/resumes/${id}`)
|
||||||
@ -71,13 +72,11 @@ const DatabaseProvider = ({ children }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateResume = async (resume) => {
|
const updateResume = async (resume) => {
|
||||||
const { id } = resume;
|
|
||||||
|
|
||||||
setUpdating(true);
|
setUpdating(true);
|
||||||
|
|
||||||
await firebase
|
await firebase
|
||||||
.database()
|
.database()
|
||||||
.ref(`users/${user.uid}/resumes/${id}`)
|
.ref(`users/${user.uid}/resumes/${resumeId}`)
|
||||||
.update({
|
.update({
|
||||||
...resume,
|
...resume,
|
||||||
updatedAt: firebase.database.ServerValue.TIMESTAMP,
|
updatedAt: firebase.database.ServerValue.TIMESTAMP,
|
||||||
@ -88,22 +87,6 @@ const DatabaseProvider = ({ children }) => {
|
|||||||
|
|
||||||
const debouncedUpdateResume = debounce(updateResume, DEBOUNCE_WAIT_TIME);
|
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) => {
|
const deleteResume = (id) => {
|
||||||
firebase.database().ref(`users/${user.uid}/resumes/${id}`).remove();
|
firebase.database().ref(`users/${user.uid}/resumes/${id}`).remove();
|
||||||
};
|
};
|
||||||
@ -116,9 +99,8 @@ const DatabaseProvider = ({ children }) => {
|
|||||||
getResume,
|
getResume,
|
||||||
createResume,
|
createResume,
|
||||||
updateResume,
|
updateResume,
|
||||||
debouncedUpdateResume,
|
|
||||||
debouncedUpdateMetadata,
|
|
||||||
deleteResume,
|
deleteResume,
|
||||||
|
debouncedUpdateResume,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@ -90,6 +90,11 @@ const ResumeProvider = ({ children }) => {
|
|||||||
debouncedUpdateResume(newState);
|
debouncedUpdateResume(newState);
|
||||||
return newState;
|
return newState;
|
||||||
|
|
||||||
|
case 'on_import':
|
||||||
|
newState = { id: state.id, ...payload };
|
||||||
|
debouncedUpdateResume(newState);
|
||||||
|
return newState;
|
||||||
|
|
||||||
case 'set_data':
|
case 'set_data':
|
||||||
return payload;
|
return payload;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const colors = [
|
const colorOptions = [
|
||||||
'#f44336',
|
'#f44336',
|
||||||
'#E91E63',
|
'#E91E63',
|
||||||
'#9C27B0',
|
'#9C27B0',
|
||||||
@ -17,4 +17,4 @@ const colors = [
|
|||||||
'#FF5722',
|
'#FF5722',
|
||||||
];
|
];
|
||||||
|
|
||||||
export default colors;
|
export default colorOptions;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
const fonts = [
|
const fontOptions = [
|
||||||
'Lato',
|
'Lato',
|
||||||
'Montserrat',
|
'Montserrat',
|
||||||
'Nunito',
|
'Nunito',
|
||||||
@ -9,4 +9,4 @@ const fonts = [
|
|||||||
'Titillium Web',
|
'Titillium Web',
|
||||||
];
|
];
|
||||||
|
|
||||||
export default fonts;
|
export default fontOptions;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
const templates = [
|
const templateOptions = [
|
||||||
{
|
{
|
||||||
id: 'onyx',
|
id: 'onyx',
|
||||||
name: 'Onyx',
|
name: 'Onyx',
|
||||||
@ -11,4 +11,4 @@ const templates = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default templates;
|
export default templateOptions;
|
||||||
@ -39,23 +39,25 @@ const AuthModal = () => {
|
|||||||
|
|
||||||
const loggedInAction = (
|
const loggedInAction = (
|
||||||
<>
|
<>
|
||||||
<Button outline className="mr-8" title="Logout" onClick={logout} />
|
<Button outline className="mr-8" onClick={logout}>
|
||||||
<Button title="Go to App" onClick={handleGotoApp} />
|
Logout
|
||||||
|
</Button>
|
||||||
|
<Button title="" onClick={handleGotoApp}>
|
||||||
|
Go to App
|
||||||
|
</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const loggedOutAction = (
|
const loggedOutAction = (
|
||||||
<Button
|
<Button isLoading={isLoading} onClick={handleSignInWithGoogle}>
|
||||||
isLoading={isLoading}
|
Sign in with Google
|
||||||
title="Sign in with Google"
|
</Button>
|
||||||
onClick={handleSignInWithGoogle}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseModal
|
<BaseModal
|
||||||
state={[open, setOpen]}
|
|
||||||
title={getTitle()}
|
title={getTitle()}
|
||||||
|
state={[open, setOpen]}
|
||||||
action={user ? loggedInAction : loggedOutAction}
|
action={user ? loggedInAction : loggedOutAction}
|
||||||
>
|
>
|
||||||
<p>{getMessage()}</p>
|
<p>{getMessage()}</p>
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { handleKeyUp } from '../utils';
|
|||||||
import styles from './BaseModal.module.css';
|
import styles from './BaseModal.module.css';
|
||||||
|
|
||||||
const BaseModal = forwardRef(
|
const BaseModal = forwardRef(
|
||||||
({ title, state, children, action, onDestroy }, ref) => {
|
({ title, state, children, action, hideActions = false, onDestroy }, ref) => {
|
||||||
const [open, setOpen] = state;
|
const [open, setOpen] = state;
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
@ -44,16 +44,15 @@ const BaseModal = forwardRef(
|
|||||||
|
|
||||||
<div className={styles.body}>{children}</div>
|
<div className={styles.body}>{children}</div>
|
||||||
|
|
||||||
|
{!hideActions && (
|
||||||
<div className={styles.actions}>
|
<div className={styles.actions}>
|
||||||
<Button
|
<Button outline className="mr-8" onClick={handleClose}>
|
||||||
outline
|
Cancel
|
||||||
title="Cancel"
|
</Button>
|
||||||
className="mr-8"
|
|
||||||
onClick={handleClose}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{action}
|
{action}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Fade>
|
</Fade>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@ -79,7 +79,9 @@ const DataModal = ({
|
|||||||
: title.create;
|
: title.create;
|
||||||
|
|
||||||
const submitAction = (
|
const submitAction = (
|
||||||
<Button type="submit" title={getTitle} onClick={() => onSubmit(values)} />
|
<Button type="submit" onClick={() => onSubmit(values)}>
|
||||||
|
{getTitle}
|
||||||
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
||||||
const onDestroy = () => {
|
const onDestroy = () => {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import AwardModal from './sections/AwardModal';
|
|||||||
import CertificateModal from './sections/CertificateModal';
|
import CertificateModal from './sections/CertificateModal';
|
||||||
import EducationModal from './sections/EducationModal';
|
import EducationModal from './sections/EducationModal';
|
||||||
import HobbyModal from './sections/HobbyModal';
|
import HobbyModal from './sections/HobbyModal';
|
||||||
|
import ImportModal from './sections/ImportModal';
|
||||||
import LanguageModal from './sections/LanguageModal';
|
import LanguageModal from './sections/LanguageModal';
|
||||||
import ReferenceModal from './sections/ReferenceModal';
|
import ReferenceModal from './sections/ReferenceModal';
|
||||||
import SkillModal from './sections/SkillModal';
|
import SkillModal from './sections/SkillModal';
|
||||||
@ -25,6 +26,7 @@ const ModalRegistrar = () => {
|
|||||||
<HobbyModal />
|
<HobbyModal />
|
||||||
<LanguageModal />
|
<LanguageModal />
|
||||||
<ReferenceModal />
|
<ReferenceModal />
|
||||||
|
<ImportModal />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
95
src/modals/sections/ImportModal.js
Normal file
95
src/modals/sections/ImportModal.js
Normal file
@ -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 (
|
||||||
|
<BaseModal hideActions state={[open, setOpen]} title="Import Data">
|
||||||
|
<div>
|
||||||
|
<h5 className="text-xl font-semibold mb-4">
|
||||||
|
Import from Reactive Resume
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Button className="mt-5" onClick={() => fileInputRef.current.click()}>
|
||||||
|
Select File
|
||||||
|
</Button>
|
||||||
|
<input
|
||||||
|
ref={fileInputRef}
|
||||||
|
type="file"
|
||||||
|
className="hidden"
|
||||||
|
onChange={importReactiveResumeJson}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr className="my-8" />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h5 className="text-xl font-semibold mb-4">Import from JSON Resume</h5>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="https://jsonresume.org/">JSON Resume</a> 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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Tooltip title="Coming Soon" placement="right" arrow>
|
||||||
|
<div className="mt-5 inline-block">
|
||||||
|
<Button className="opacity-50">Select File</Button>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr className="my-8" />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h5 className="text-xl font-semibold mb-4">Import from LinkedIn</h5>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You can import a JSON that was exported from Reactive Resume by
|
||||||
|
clicking on the button below and selecting the appropriate file.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Tooltip title="Coming Soon" placement="right" arrow>
|
||||||
|
<div className="mt-5 inline-block">
|
||||||
|
<Button className="opacity-50">Select File</Button>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</BaseModal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ImportModal);
|
||||||
Reference in New Issue
Block a user