- implement donation link, in about section

This commit is contained in:
Amruth Pillai
2020-07-14 17:24:59 +05:30
parent 851d6ef020
commit af955bbf55
6 changed files with 106 additions and 63 deletions

View File

@ -7,29 +7,38 @@ function timeout(ms) {
return new Promise((resolve) => setTimeout(resolve, ms)); return new Promise((resolve) => setTimeout(resolve, ms));
} }
exports.printSinglePageResume = functions.https.onCall( exports.printResume = functions.https.onCall(async ({ id, type }, { auth }) => {
async ({ id }, { auth }) => { if (!id) {
if (!id) { throw new functions.https.HttpsError(
throw new functions.https.HttpsError( 'invalid-argument',
'invalid-argument', 'The function must be called with argument "id" containing the resume ID.',
'The function must be called with one arguments "id" containing the resume ID.', );
); }
}
if (!auth) { if (!type || type !== 'single' || type !== 'multi') {
throw new functions.https.HttpsError( throw new functions.https.HttpsError(
'failed-precondition', 'invalid-argument',
'The function must be called while authenticated.', 'The function must be called with argument "type" containing the type of resume.',
); );
} }
const browser = await puppeteer.launch({ if (!auth) {
headless: true, throw new functions.https.HttpsError(
}); 'failed-precondition',
const page = await browser.newPage(); 'The function must be called while authenticated.',
await page.goto(BASE_URL + id); );
await timeout(5000); }
await page.emulateMediaType('print');
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 height = await page.evaluate(() => {
const { body } = document; const { body } = document;
const html = document.documentElement; const html = document.documentElement;
@ -44,45 +53,19 @@ exports.printSinglePageResume = functions.https.onCall(
return maxHeight; return maxHeight;
}); });
const pdf = await page.pdf({ pdf = await page.pdf({
printBackground: true, printBackground: true,
width: `21cm`, width: `21cm`,
height: `${height}px`, height: `${height}px`,
pageRanges: '1', pageRanges: '1',
}); });
await browser.close(); } else if (type === 'multi') {
return Buffer.from(pdf).toString('base64'); pdf = await page.pdf({
},
);
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({
format: 'A4', format: 'A4',
printBackground: true, printBackground: true,
}); });
await browser.close(); }
return Buffer.from(pdf).toString('base64');
}, await browser.close();
); return Buffer.from(pdf).toString('base64');
});

View File

@ -9,6 +9,7 @@ import Layout from './sections/Layout';
import Templates from './sections/Templates'; import Templates from './sections/Templates';
import Actions from './sections/Actions'; import Actions from './sections/Actions';
import Settings from './sections/Settings'; import Settings from './sections/Settings';
import About from './sections/About';
const getComponent = (id) => { const getComponent = (id) => {
switch (id) { switch (id) {
@ -24,6 +25,8 @@ const getComponent = (id) => {
return Actions; return Actions;
case 'settings': case 'settings':
return Settings; return Settings;
case 'about':
return About;
default: default:
throw new Error(); throw new Error();
} }

View File

@ -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 (
<section>
<Heading>About</Heading>
<div className={styles.container}>
<h5>Donate to Reactive Resume</h5>
<p className="leading-loose">
As you know, every nook and cranny of this app is free and
open-source, but servers don&apos;t pay for themselves.
</p>
<p className="leading-loose">
I try to do what I can, but if you found the app helpful, or
you&apos;re in a better position than the others who depend on this
project for their first job, please consider donating{' '}
<span className="font-semibold">
as little as $5 to help keep the project alive
</span>{' '}
:)
</p>
<div className="mt-4 flex">
<a
href="https://www.buymeacoffee.com/AmruthPillai"
rel="noreferrer"
target="_blank"
>
<Button icon={FaCoffee}>Buy me a coffee!</Button>
</a>
</div>
</div>
</section>
);
};
export default memo(About);

View File

@ -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;
}

View File

@ -3,6 +3,7 @@ import {
MdDashboard, MdDashboard,
MdFontDownload, MdFontDownload,
MdImportExport, MdImportExport,
MdInfo,
MdSettings, MdSettings,
MdStyle, MdStyle,
} from 'react-icons/md'; } from 'react-icons/md';
@ -38,4 +39,9 @@ export default [
name: 'Settings', name: 'Settings',
icon: MdSettings, icon: MdSettings,
}, },
{
id: 'about',
name: 'About',
icon: MdInfo,
},
]; ];

View File

@ -38,20 +38,16 @@ const ExportModal = () => {
const handleSinglePageDownload = async () => { const handleSinglePageDownload = async () => {
setLoadingSingle(true); setLoadingSingle(true);
const printSinglePageResume = firebase const printResume = firebase.functions().httpsCallable('printResume');
.functions() const { data } = await printResume({ id: state.id, type: 'single' });
.httpsCallable('printSinglePageResume');
const { data } = await printSinglePageResume({ id: state.id });
const blob = b64toBlob(data, 'application/pdf'); const blob = b64toBlob(data, 'application/pdf');
openFile(blob); openFile(blob);
}; };
const handleMultiPageDownload = async () => { const handleMultiPageDownload = async () => {
setLoadingMulti(true); setLoadingMulti(true);
const printMultiPageResume = firebase const printResume = firebase.functions().httpsCallable('printResume');
.functions() const { data } = await printResume({ id: state.id, type: 'multi' });
.httpsCallable('printMultiPageResume');
const { data } = await printMultiPageResume({ id: state.id });
const blob = b64toBlob(data, 'application/pdf'); const blob = b64toBlob(data, 'application/pdf');
openFile(blob); openFile(blob);
}; };