From af955bbf5541e2af959888cdc2a3013e94d11cfd Mon Sep 17 00:00:00 2001 From: Amruth Pillai Date: Tue, 14 Jul 2020 17:24:59 +0530 Subject: [PATCH] - implement donation link, in about section --- functions/index.js | 93 ++++++++----------- src/components/builder/right/RightSidebar.js | 3 + .../builder/right/sections/About.js | 44 +++++++++ .../builder/right/sections/About.module.css | 11 +++ src/data/rightSections.js | 6 ++ src/modals/sections/ExportModal.js | 12 +-- 6 files changed, 106 insertions(+), 63 deletions(-) create mode 100644 src/components/builder/right/sections/About.js create mode 100644 src/components/builder/right/sections/About.module.css diff --git a/functions/index.js b/functions/index.js index a27e82c8..03be6fc8 100644 --- a/functions/index.js +++ b/functions/index.js @@ -7,29 +7,38 @@ function timeout(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } -exports.printSinglePageResume = functions.https.onCall( - async ({ id }, { auth }) => { - if (!id) { - throw new functions.https.HttpsError( - 'invalid-argument', - 'The function must be called with one arguments "id" containing the resume ID.', - ); - } +exports.printResume = functions.https.onCall(async ({ id, type }, { auth }) => { + if (!id) { + throw new functions.https.HttpsError( + 'invalid-argument', + 'The function must be called with argument "id" containing the resume ID.', + ); + } - if (!auth) { - throw new functions.https.HttpsError( - 'failed-precondition', - 'The function must be called while authenticated.', - ); - } + if (!type || type !== 'single' || type !== 'multi') { + throw new functions.https.HttpsError( + 'invalid-argument', + 'The function must be called with argument "type" containing the type of resume.', + ); + } - const browser = await puppeteer.launch({ - headless: true, - }); - const page = await browser.newPage(); - await page.goto(BASE_URL + id); - await timeout(5000); - await page.emulateMediaType('print'); + if (!auth) { + throw new functions.https.HttpsError( + 'failed-precondition', + 'The function must be called while authenticated.', + ); + } + + const browser = await puppeteer.launch({ + headless: true, + }); + const page = await browser.newPage(); + await page.goto(BASE_URL + id); + await timeout(5000); + await page.emulateMediaType('print'); + let pdf; + + if (type === 'single') { const height = await page.evaluate(() => { const { body } = document; const html = document.documentElement; @@ -44,45 +53,19 @@ exports.printSinglePageResume = functions.https.onCall( return maxHeight; }); - const pdf = await page.pdf({ + pdf = await page.pdf({ printBackground: true, width: `21cm`, height: `${height}px`, pageRanges: '1', }); - await browser.close(); - return Buffer.from(pdf).toString('base64'); - }, -); - -exports.printMultiPageResume = functions.https.onCall( - async ({ id }, { auth }) => { - if (!id) { - throw new functions.https.HttpsError( - 'invalid-argument', - 'The function must be called with one arguments "id" containing the resume ID.', - ); - } - - if (!auth) { - throw new functions.https.HttpsError( - 'failed-precondition', - 'The function must be called while authenticated.', - ); - } - - const browser = await puppeteer.launch({ - headless: true, - }); - const page = await browser.newPage(); - await page.goto(BASE_URL + id); - await timeout(5000); - await page.emulateMediaType('print'); - const pdf = await page.pdf({ + } else if (type === 'multi') { + pdf = await page.pdf({ format: 'A4', printBackground: true, }); - await browser.close(); - return Buffer.from(pdf).toString('base64'); - }, -); + } + + await browser.close(); + return Buffer.from(pdf).toString('base64'); +}); diff --git a/src/components/builder/right/RightSidebar.js b/src/components/builder/right/RightSidebar.js index 1eed06be..d97caff5 100644 --- a/src/components/builder/right/RightSidebar.js +++ b/src/components/builder/right/RightSidebar.js @@ -9,6 +9,7 @@ import Layout from './sections/Layout'; import Templates from './sections/Templates'; import Actions from './sections/Actions'; import Settings from './sections/Settings'; +import About from './sections/About'; const getComponent = (id) => { switch (id) { @@ -24,6 +25,8 @@ const getComponent = (id) => { return Actions; case 'settings': return Settings; + case 'about': + return About; default: throw new Error(); } diff --git a/src/components/builder/right/sections/About.js b/src/components/builder/right/sections/About.js new file mode 100644 index 00000000..ba78267f --- /dev/null +++ b/src/components/builder/right/sections/About.js @@ -0,0 +1,44 @@ +import React, { memo } from 'react'; +import { FaCoffee } from 'react-icons/fa'; +import Button from '../../../shared/Button'; +import Heading from '../../../shared/Heading'; +import styles from './About.module.css'; + +const About = () => { + return ( +
+ About + +
+
Donate to Reactive Resume
+ +

+ As you know, every nook and cranny of this app is free and + open-source, but servers don't pay for themselves. +

+ +

+ I try to do what I can, but if you found the app helpful, or + you're in a better position than the others who depend on this + project for their first job, please consider donating{' '} + + as little as $5 to help keep the project alive + {' '} + :) +

+ +
+ + + +
+
+
+ ); +}; + +export default memo(About); diff --git a/src/components/builder/right/sections/About.module.css b/src/components/builder/right/sections/About.module.css new file mode 100644 index 00000000..7943f429 --- /dev/null +++ b/src/components/builder/right/sections/About.module.css @@ -0,0 +1,11 @@ +.container { + @apply bg-primary-100 rounded grid gap-5 p-8; +} + +.container h5 { + @apply text-lg font-semibold; +} + +.container p { + @apply text-sm font-medium; +} \ No newline at end of file diff --git a/src/data/rightSections.js b/src/data/rightSections.js index c05e431b..eeb61d69 100644 --- a/src/data/rightSections.js +++ b/src/data/rightSections.js @@ -3,6 +3,7 @@ import { MdDashboard, MdFontDownload, MdImportExport, + MdInfo, MdSettings, MdStyle, } from 'react-icons/md'; @@ -38,4 +39,9 @@ export default [ name: 'Settings', icon: MdSettings, }, + { + id: 'about', + name: 'About', + icon: MdInfo, + }, ]; diff --git a/src/modals/sections/ExportModal.js b/src/modals/sections/ExportModal.js index e037882d..2851a249 100644 --- a/src/modals/sections/ExportModal.js +++ b/src/modals/sections/ExportModal.js @@ -38,20 +38,16 @@ const ExportModal = () => { const handleSinglePageDownload = async () => { setLoadingSingle(true); - const printSinglePageResume = firebase - .functions() - .httpsCallable('printSinglePageResume'); - const { data } = await printSinglePageResume({ id: state.id }); + const printResume = firebase.functions().httpsCallable('printResume'); + const { data } = await printResume({ id: state.id, type: 'single' }); const blob = b64toBlob(data, 'application/pdf'); openFile(blob); }; const handleMultiPageDownload = async () => { setLoadingMulti(true); - const printMultiPageResume = firebase - .functions() - .httpsCallable('printMultiPageResume'); - const { data } = await printMultiPageResume({ id: state.id }); + const printResume = firebase.functions().httpsCallable('printResume'); + const { data } = await printResume({ id: state.id, type: 'multi' }); const blob = b64toBlob(data, 'application/pdf'); openFile(blob); };