mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-10 20:42:29 +10:00
Compare commits
64 Commits
v3.6.7
...
v3.6.8-pat
| Author | SHA1 | Date | |
|---|---|---|---|
| 3a7b98d30e | |||
| 284a39aa77 | |||
| c14c9955dd | |||
| 4de787157a | |||
| 6bc6425a01 | |||
| 6051305908 | |||
| 5e13253454 | |||
| c1fd2b40e3 | |||
| fccf7a7b56 | |||
| 5098b094db | |||
| 7c1eb74aca | |||
| 7f9ede8ff0 | |||
| 172b23e429 | |||
| f287ca6183 | |||
| 7548e36aaf | |||
| 2f754616b4 | |||
| dc51f6f9b2 | |||
| 0cdac1d657 | |||
| c3cfe8ae7b | |||
| 08435c173b | |||
| 62cc2d6eac | |||
| 5a6f6e2b6c | |||
| 2dfa8c04a1 | |||
| 63e3f94d2d | |||
| 7f45a8cb7f | |||
| 4377ebb811 | |||
| ed3af6975b | |||
| 7904905a8b | |||
| bd2e6d2bf2 | |||
| ae4e9e688e | |||
| 78c45b7019 | |||
| 9a2fbbec4e | |||
| 93d751d9be | |||
| 9926ed2262 | |||
| 62220d20e7 | |||
| 2f6108cd29 | |||
| 7aeed37869 | |||
| ed99659b7b | |||
| 5e33d00910 | |||
| c00d0341e6 | |||
| 511ae036c2 | |||
| 1642ec9ba2 | |||
| 1115bc2b69 | |||
| 27e5c7811c | |||
| 3b739f0bb7 | |||
| d937ba2056 | |||
| de110d7de1 | |||
| b03229b5e0 | |||
| 280fc73c7b | |||
| 677ad2a115 | |||
| f394b26d18 | |||
| aab4e2e941 | |||
| f0f552a635 | |||
| 136e143e12 | |||
| 857e4b8670 | |||
| ff03d41d97 | |||
| 2bad37aaf3 | |||
| 3a40fbf78b | |||
| 49c638fb18 | |||
| 50e8d60773 | |||
| bf157a8d1a | |||
| c4f5955fcd | |||
| 86d33b0f21 | |||
| 56bca30639 |
16
.github/workflows/docker-build-push.yml
vendored
16
.github/workflows/docker-build-push.yml
vendored
@ -15,13 +15,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.2
|
||||
uses: actions/checkout@v3.1.0
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- id: version
|
||||
name: Get Version
|
||||
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
|
||||
run: echo "version=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2.0.0
|
||||
@ -54,9 +54,9 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: |
|
||||
amruthpillai/reactive-resume:client-latest
|
||||
amruthpillai/reactive-resume:client-${{ steps.version.outputs.tag }}
|
||||
amruthpillai/reactive-resume:client-${{ env.version }}
|
||||
ghcr.io/amruthpillai/reactive-resume:client-latest
|
||||
ghcr.io/amruthpillai/reactive-resume:client-${{ steps.version.outputs.tag }}
|
||||
ghcr.io/amruthpillai/reactive-resume:client-${{ env.version }}
|
||||
|
||||
server:
|
||||
name: Server
|
||||
@ -68,13 +68,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.2
|
||||
uses: actions/checkout@v3.1.0
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- id: version
|
||||
name: Get Version
|
||||
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
|
||||
run: echo "version=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2.0.0
|
||||
@ -107,6 +107,6 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: |
|
||||
amruthpillai/reactive-resume:server-latest
|
||||
amruthpillai/reactive-resume:server-${{ steps.version.outputs.tag }}
|
||||
amruthpillai/reactive-resume:server-${{ env.version }}
|
||||
ghcr.io/amruthpillai/reactive-resume:server-latest
|
||||
ghcr.io/amruthpillai/reactive-resume:server-${{ steps.version.outputs.tag }}
|
||||
ghcr.io/amruthpillai/reactive-resume:server-${{ env.version }}
|
||||
|
||||
84
.github/workflows/docker-build.yml
vendored
84
.github/workflows/docker-build.yml
vendored
@ -1,84 +0,0 @@
|
||||
name: Build Docker Image
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
client:
|
||||
name: Client
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2.0.0
|
||||
|
||||
- id: buildx
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2.0.0
|
||||
with:
|
||||
install: true
|
||||
|
||||
- id: variables
|
||||
name: Get Short SHA
|
||||
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
|
||||
- name: Build Client Image
|
||||
uses: docker/build-push-action@v3.1.1
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
file: client/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: |
|
||||
amruthpillai/reactive-resume:client-latest
|
||||
amruthpillai/reactive-resume:client-${{ steps.variables.outputs.sha_short }}
|
||||
ghcr.io/amruthpillai/reactive-resume:client-latest
|
||||
ghcr.io/amruthpillai/reactive-resume:client-${{ steps.variables.outputs.sha_short }}
|
||||
|
||||
server:
|
||||
name: Server
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.0.2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2.0.0
|
||||
|
||||
- id: buildx
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2.0.0
|
||||
with:
|
||||
install: true
|
||||
|
||||
- id: variables
|
||||
name: Get Short SHA
|
||||
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
|
||||
- name: Build Server Image
|
||||
uses: docker/build-push-action@v3.1.1
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
file: server/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: |
|
||||
amruthpillai/reactive-resume:server-latest
|
||||
amruthpillai/reactive-resume:server-${{ steps.variables.outputs.sha_short }}
|
||||
ghcr.io/amruthpillai/reactive-resume:server-latest
|
||||
ghcr.io/amruthpillai/reactive-resume:server-${{ steps.variables.outputs.sha_short }}
|
||||
@ -2,7 +2,7 @@ FROM node:lts-alpine AS base
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk add --no-cache g++ git curl make python3 \
|
||||
RUN apk add --no-cache g++ git curl make python3 libc6-compat \
|
||||
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
|
||||
|
||||
FROM base as dependencies
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
}
|
||||
|
||||
&.break::after {
|
||||
content: 'A4 Page Break';
|
||||
content: 'Page Break';
|
||||
top: calc(297mm - 19px);
|
||||
|
||||
@apply absolute w-full border-b border-dashed border-neutral-800/75;
|
||||
@ -28,6 +28,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.format-letter {
|
||||
width: 216mm;
|
||||
min-height: 279mm;
|
||||
|
||||
&.break::after {
|
||||
top: calc(279mm - 19px);
|
||||
}
|
||||
}
|
||||
|
||||
.markdown {
|
||||
ul {
|
||||
padding-left: 1.5em;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { CustomCSS, Theme, Typography } from '@reactive-resume/schema';
|
||||
import { CustomCSS, PageConfig, ThemeConfig, Typography } from '@reactive-resume/schema';
|
||||
import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
@ -23,9 +23,10 @@ const Page: React.FC<Props> = ({ page, showPageNumbers = false }) => {
|
||||
const resume = useAppSelector((state) => state.resume.present);
|
||||
const breakLine: boolean = useAppSelector((state) => state.build.page.breakLine);
|
||||
|
||||
const theme: Theme = get(resume, 'metadata.theme');
|
||||
const theme: ThemeConfig = get(resume, 'metadata.theme');
|
||||
const customCSS: CustomCSS = get(resume, 'metadata.css');
|
||||
const template: string = get(resume, 'metadata.template');
|
||||
const pageConfig: PageConfig = get(resume, 'metadata.page');
|
||||
const typography: Typography = get(resume, 'metadata.typography');
|
||||
|
||||
const themeCSS = useMemo(() => !isEmpty(theme) && generateThemeStyles(theme), [theme]);
|
||||
@ -33,12 +34,13 @@ const Page: React.FC<Props> = ({ page, showPageNumbers = false }) => {
|
||||
const TemplatePage: React.FC<PageProps> | null = useMemo(() => templateMap[template].component, [template]);
|
||||
|
||||
return (
|
||||
<div data-page={page + 1} className={styles.container}>
|
||||
<div className={styles.container} data-page={page + 1} data-format={pageConfig?.format || 'A4'}>
|
||||
<div
|
||||
className={clsx({
|
||||
reset: true,
|
||||
[styles.page]: true,
|
||||
[styles.break]: breakLine,
|
||||
[styles['format-letter']]: pageConfig?.format === 'Letter',
|
||||
[css(themeCSS)]: true,
|
||||
[css(typographyCSS)]: true,
|
||||
[css(customCSS.value)]: customCSS.visible,
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
Switch,
|
||||
TextField,
|
||||
} from '@mui/material';
|
||||
import { DateConfig, Resume } from '@reactive-resume/schema';
|
||||
import { DateConfig, PageConfig, Resume } from '@reactive-resume/schema';
|
||||
import dayjs from 'dayjs';
|
||||
import get from 'lodash/get';
|
||||
import { useRouter } from 'next/router';
|
||||
@ -47,10 +47,11 @@ const Settings = () => {
|
||||
const id: number = useMemo(() => get(resume, 'id'), [resume]);
|
||||
const slug: string = useMemo(() => get(resume, 'slug'), [resume]);
|
||||
const username: string = useMemo(() => get(resume, 'user.username'), [resume]);
|
||||
const pageConfig: PageConfig = useMemo(() => get(resume, 'metadata.page'), [resume]);
|
||||
const dateConfig: DateConfig = useMemo(() => get(resume, 'metadata.date'), [resume]);
|
||||
|
||||
const isDarkMode = useMemo(() => theme === 'dark', [theme]);
|
||||
const exampleString = useMemo(() => `Eg. ${dayjs().utc().format(dateConfig.format)}`, [dateConfig.format]);
|
||||
const exampleDateString = useMemo(() => `Eg. ${dayjs().utc().format(dateConfig.format)}`, [dateConfig.format]);
|
||||
const themeString = useMemo(() => (isDarkMode ? 'Matte Black Everything' : 'As bright as your future'), [isDarkMode]);
|
||||
|
||||
const { mutateAsync: loadSampleDataMutation } = useMutation<Resume, ServerError, LoadSampleDataParams>(
|
||||
@ -60,6 +61,9 @@ const Settings = () => {
|
||||
|
||||
const handleSetTheme = (value: boolean) => dispatch(setTheme({ theme: value ? 'dark' : 'light' }));
|
||||
|
||||
const handleChangePageFormat = (value: PageConfig['format'] | null) =>
|
||||
dispatch(setResumeState({ path: 'metadata.page.format', value }));
|
||||
|
||||
const handleChangeDateFormat = (value: string | null) =>
|
||||
dispatch(setResumeState({ path: 'metadata.date.format', value }));
|
||||
|
||||
@ -118,13 +122,13 @@ const Settings = () => {
|
||||
primary={t<string>('builder.rightSidebar.sections.settings.global.date.primary')}
|
||||
secondary={t<string>('builder.rightSidebar.sections.settings.global.date.secondary')}
|
||||
/>
|
||||
<Autocomplete<string, false, boolean, false>
|
||||
<Autocomplete<string, false, true, false>
|
||||
disableClearable
|
||||
className="my-2 w-full"
|
||||
options={dateFormatOptions}
|
||||
value={dateConfig.format}
|
||||
onChange={(_, value) => handleChangeDateFormat(value)}
|
||||
renderInput={(params) => <TextField {...params} helperText={exampleString} />}
|
||||
renderInput={(params) => <TextField {...params} helperText={exampleDateString} />}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
@ -134,7 +138,7 @@ const Settings = () => {
|
||||
primary={t<string>('builder.rightSidebar.sections.settings.global.language.primary')}
|
||||
secondary={t<string>('builder.rightSidebar.sections.settings.global.language.secondary')}
|
||||
/>
|
||||
<Autocomplete<Language, false, boolean, false>
|
||||
<Autocomplete<Language, false, true, false>
|
||||
disableClearable
|
||||
className="my-2 w-full"
|
||||
options={languages}
|
||||
@ -159,6 +163,23 @@ const Settings = () => {
|
||||
{t<string>('builder.rightSidebar.sections.settings.page.heading')}
|
||||
</ListSubheader>
|
||||
|
||||
<ListItem className="flex-col">
|
||||
<ListItemText
|
||||
className="w-full"
|
||||
primary={t<string>('builder.rightSidebar.sections.settings.page.format.primary')}
|
||||
secondary={t<string>('builder.rightSidebar.sections.settings.page.format.secondary')}
|
||||
/>
|
||||
<Autocomplete<PageConfig['format'], false, true, false>
|
||||
disableClearable
|
||||
defaultValue="A4"
|
||||
className="my-2 w-full"
|
||||
options={['A4', 'Letter']}
|
||||
value={pageConfig?.format || 'A4'}
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
onChange={(_, value) => handleChangePageFormat(value)}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<ListItemText
|
||||
primary={t<string>('builder.rightSidebar.sections.settings.page.orientation.primary')}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Theme as ThemeType } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
@ -16,7 +16,7 @@ const Theme = () => {
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const { background, text, primary } = useAppSelector<ThemeType>((state) =>
|
||||
const { background, text, primary } = useAppSelector<ThemeConfig>((state) =>
|
||||
get(state.resume.present, 'metadata.theme')
|
||||
);
|
||||
|
||||
|
||||
@ -162,15 +162,14 @@ const LoginModal: React.FC = () => {
|
||||
{!FLAG_DISABLE_SIGNUPS && (
|
||||
<p className="text-xs">
|
||||
<Trans t={t} i18nKey="modals.auth.login.register-text">
|
||||
If you don't have one, you can <a onClick={handleCreateAccount}>create an account</a> here.
|
||||
If you don't have one, you can <a onClick={handleCreateAccount}>create an account here.</a>
|
||||
</Trans>
|
||||
</p>
|
||||
)}
|
||||
|
||||
<p className="text-xs">
|
||||
<Trans t={t} i18nKey="modals.auth.login.recover-text">
|
||||
In case you have forgotten your password, you can <a onClick={handleRecoverAccount}>recover your account</a>
|
||||
here.
|
||||
In case you have forgotten your password, you can <a onClick={handleRecoverAccount}>recover your account here.</a>
|
||||
</Trans>
|
||||
</p>
|
||||
</BaseModal>
|
||||
|
||||
@ -93,7 +93,7 @@ const AwardModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="title"
|
||||
control={control}
|
||||
@ -177,6 +177,7 @@ const AwardModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -93,7 +93,7 @@ const CertificateModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
@ -177,6 +177,7 @@ const CertificateModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -110,7 +110,7 @@ const CustomModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="title"
|
||||
control={control}
|
||||
@ -282,6 +282,7 @@ const CustomModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -106,7 +106,7 @@ const EducationModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="institution"
|
||||
control={control}
|
||||
@ -255,6 +255,7 @@ const EducationModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -84,7 +84,7 @@ const InterestModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
@ -114,6 +114,7 @@ const InterestModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -85,7 +85,7 @@ const LanguageModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
@ -150,6 +150,7 @@ const LanguageModal: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -89,7 +89,7 @@ const ProfileModal: React.FC = () => {
|
||||
handleClose={handleClose}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="network"
|
||||
control={control}
|
||||
@ -136,6 +136,7 @@ const ProfileModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -102,7 +102,7 @@ const ProjectModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
@ -225,6 +225,7 @@ const ProjectModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -93,7 +93,7 @@ const PublicationModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
@ -177,6 +177,7 @@ const PublicationModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -90,7 +90,7 @@ const ReferenceModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
@ -162,6 +162,7 @@ const ReferenceModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -88,7 +88,7 @@ const SkillModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
@ -166,6 +166,8 @@ const SkillModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -99,7 +99,7 @@ const VolunteerModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="organization"
|
||||
control={control}
|
||||
@ -208,6 +208,7 @@ const VolunteerModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -99,7 +99,7 @@ const WorkModal: React.FC = () => {
|
||||
heading={isEditMode ? editText : addText}
|
||||
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
|
||||
>
|
||||
<form className="my-2 grid grid-cols-2 gap-4">
|
||||
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="name"
|
||||
control={control}
|
||||
@ -208,6 +208,7 @@ const WorkModal: React.FC = () => {
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<input type="submit" style={{ display: 'none' }} />
|
||||
</form>
|
||||
</BaseModal>
|
||||
);
|
||||
|
||||
@ -13,22 +13,22 @@
|
||||
"@emotion/css": "^11.10.0",
|
||||
"@emotion/react": "^11.10.4",
|
||||
"@emotion/styled": "^11.10.4",
|
||||
"@hello-pangea/dnd": "^16.0.0",
|
||||
"@hookform/resolvers": "2.9.8",
|
||||
"@hello-pangea/dnd": "^16.0.1",
|
||||
"@hookform/resolvers": "2.9.9",
|
||||
"@monaco-editor/react": "^4.4.6",
|
||||
"@mui/icons-material": "^5.10.6",
|
||||
"@mui/lab": "^5.0.0-alpha.102",
|
||||
"@mui/material": "^5.10.8",
|
||||
"@mui/system": "^5.10.8",
|
||||
"@mui/icons-material": "^5.10.9",
|
||||
"@mui/lab": "^5.0.0-alpha.103",
|
||||
"@mui/material": "^5.10.9",
|
||||
"@mui/system": "^5.10.9",
|
||||
"@mui/x-date-pickers": "5.0.4",
|
||||
"@next/env": "^12.3.1",
|
||||
"@react-oauth/google": "^0.2.8",
|
||||
"@reduxjs/toolkit": "^1.8.5",
|
||||
"axios": "^1.1.0",
|
||||
"@reduxjs/toolkit": "^1.8.6",
|
||||
"axios": "^1.1.2",
|
||||
"clsx": "^1.2.1",
|
||||
"dayjs": "^1.11.5",
|
||||
"downloadjs": "^1.4.7",
|
||||
"joi": "^17.6.2",
|
||||
"joi": "^17.6.3",
|
||||
"lodash": "^4.17.21",
|
||||
"md5-hex": "^4.0.0",
|
||||
"monaco-editor": "^0.34.0",
|
||||
@ -43,7 +43,7 @@
|
||||
"react-hook-form": "^7.37.0",
|
||||
"react-hot-toast": "2.4.0",
|
||||
"react-hotkeys-hook": "^3.4.7",
|
||||
"react-icons": "^4.4.0",
|
||||
"react-icons": "^4.6.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-query": "^3.39.2",
|
||||
"react-redux": "^8.0.4",
|
||||
@ -64,7 +64,7 @@
|
||||
"@tailwindcss/typography": "^0.5.7",
|
||||
"@types/downloadjs": "^1.4.3",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"@types/node": "^18.8.3",
|
||||
"@types/node": "^18.11.0",
|
||||
"@types/react": "^18.0.21",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@types/react-redux": "^7.1.24",
|
||||
@ -75,8 +75,8 @@
|
||||
"csstype": "^3.1.1",
|
||||
"eslint-config-next": "^12.3.1",
|
||||
"eslint-plugin-tailwindcss": "^3.6.2",
|
||||
"next-sitemap": "^3.1.23",
|
||||
"postcss": "^8.4.17",
|
||||
"next-sitemap": "^3.1.25",
|
||||
"postcss": "^8.4.18",
|
||||
"sass": "^1.55.0",
|
||||
"tailwindcss": "^3.1.8",
|
||||
"typescript": "^4.8.4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "ቅንብሮች",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "የወረቀት መጠን",
|
||||
"secondary": "ከቆመበት ቀጥል ገጾችዎ ልኬቶችን ይወስናል"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "መስመር መቁረጫ",
|
||||
"secondary": "የA4 ገጽ ቁመትን ለመለየት በሁሉም ገጾች ላይ መስመር አሳይ"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "الإعدادات",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "حجم الورق",
|
||||
"secondary": "تحدد أبعاد صفحات سيرتك الذاتية"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "خط فاصل",
|
||||
"secondary": "اعرض خط في كل الصفحات لتحديد ارتفاع صفحة A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Настройки",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Размер на хартията",
|
||||
"secondary": "Определя размерите на вашите страници с автобиография"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Линия на прекъсване",
|
||||
"secondary": "Показване на линия на всички страници за обозначаване на височината на страница A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "সেটিংস",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "কাগজের আকার",
|
||||
"secondary": "আপনার জীবনবৃত্তান্ত পৃষ্ঠাগুলির মাত্রা নির্ধারণ করে"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "লাইন ভেঙ্গে ফেলুন",
|
||||
"secondary": "একটি A4 পৃষ্ঠার উচ্চতা চিহ্নিত করতে সমস্ত পৃষ্ঠায় একটি লাইন দেখান৷"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Configuració",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Mida del paper",
|
||||
"secondary": "Determina les dimensions de les pàgines del vostre currículum"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Línia de trencament",
|
||||
"secondary": "Mostra una línia a totes les pàgines per marcar l'alçada d'una pàgina A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Nastavení",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Velikost papíru",
|
||||
"secondary": "Určuje rozměry stránek vašeho životopisu"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Nový řádek",
|
||||
"secondary": "Zobrazit čáru na všech stránkách pro označení výšky stránky A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Indstillinger",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Papirstørrelse",
|
||||
"secondary": "Bestemmer dimensionerne på dine CV-sider"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Brudlinje",
|
||||
"secondary": "Vis en streg på alle sider for at markere højden på en A4-side"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Einstellungen",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Papier größe",
|
||||
"secondary": "Legt die Abmessungen Ihrer Lebenslaufseiten fest"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Linie anhalten",
|
||||
"secondary": "Zeile auf allen Seiten anzeigen, um die Höhe einer A4-Seite zu markieren"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Ρυθμίσεις",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Μέγεθος χαρτιού",
|
||||
"secondary": "Καθορίζει τις διαστάσεις των σελίδων του βιογραφικού σας"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Γραμμή διακοπής",
|
||||
"secondary": "Εμφάνιση μιας γραμμής σε όλες τις σελίδες για να επισημάνετε το ύψος μιας σελίδας Α4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Settings",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Paper Size",
|
||||
"secondary": "Determines the dimensions of your resume pages"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Break Line",
|
||||
"secondary": "Show a line on all pages to mark the height of an A4 page"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Preferencias",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Tamaño de papel",
|
||||
"secondary": "Determina las dimensiones de las páginas de tu currículum."
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Linea de separación",
|
||||
"secondary": "Mostrar una línea en todas las páginas para marcar la altura de una página A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "تنظیمات",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "اندازه کاغذ",
|
||||
"secondary": "ابعاد صفحات رزومه شما را تعیین می کند"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "خط شکست",
|
||||
"secondary": "برای مشخص کردن ارتفاع صفحه A4 یک خط در همه صفحات نشان داده شود"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Asetukset",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Paperikoko",
|
||||
"secondary": "Määrittää ansioluettelosi sivujen mitat"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Katkoviiva",
|
||||
"secondary": "Näytä viiva kaikilla sivuilla A4-sivun korkeuden merkitsemiseksi"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Paramètres",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Taille de papier",
|
||||
"secondary": "Détermine les dimensions de vos pages de CV"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Indicateur de changement de page",
|
||||
"secondary": "Afficher une ligne sur toutes les pages pour marquer la hauteur d'une feuille A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "הגדרות",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "גודל נייר",
|
||||
"secondary": "קובע את הממדים של דפי קורות החיים שלך"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "קו עצירה",
|
||||
"secondary": "הצג קו בכל הדפים כדי לסמן את גובהו של דף A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "समायोजन",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "काग़ज़ का आकार",
|
||||
"secondary": "आपके रेज़्यूमे पृष्ठों के आयाम निर्धारित करता है"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "अंतराल वाली लकीर",
|
||||
"secondary": "A4 पृष्ठ की ऊंचाई को चिह्नित करने के लिए सभी पृष्ठों पर एक पंक्ति दिखाएं"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Beállítások",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Papírméret",
|
||||
"secondary": "Meghatározza az önéletrajzi oldalak méreteit"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Törésvonal",
|
||||
"secondary": "Mutasson egy vonalat az összes oldalon, hogy megjelölje egy A4-es oldal magasságát"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Pengaturan",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Ukuran kertas",
|
||||
"secondary": "Menentukan dimensi halaman resume Anda"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Break Line",
|
||||
"secondary": "Tampilkan garis di semua halaman untuk menandai ketinggian halaman A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Impostazioni",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Dimensioni del foglio",
|
||||
"secondary": "Determina le dimensioni delle pagine del tuo curriculum"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Linea di interruzione",
|
||||
"secondary": "Mostra su tutte le pagine una linea che indica l'altezza di un foglio A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "設定",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "用紙サイズ",
|
||||
"secondary": "履歴書ページのサイズを決定します"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "ブレイクライン",
|
||||
"secondary": "A4ページの高さを示す線を全ページに表示する。"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "ការកំណត់",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "ទំហំក្រដាស",
|
||||
"secondary": "កំណត់វិមាត្រនៃទំព័រប្រវត្តិរូបរបស់អ្នក។"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "បំបែកបន្ទាត់",
|
||||
"secondary": "បង្ហាញបន្ទាត់នៅលើទំព័រទាំងអស់ដើម្បីសម្គាល់កម្ពស់នៃទំព័រ A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "ಅಳವಡಿಕೆಗಳು",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "ಕಾಗದದ ಗಾತ್ರ",
|
||||
"secondary": "ನಿಮ್ಮ ರೆಸ್ಯೂಮ್ ಪುಟಗಳ ಆಯಾಮಗಳನ್ನು ನಿರ್ಧರಿಸುತ್ತದೆ"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "ಬ್ರೇಕ್ ಲೈನ್",
|
||||
"secondary": "A4 ಪುಟದ ಎತ್ತರವನ್ನು ಗುರುತಿಸಲು ಎಲ್ಲಾ ಪುಟಗಳಲ್ಲಿ ಒಂದು ಸಾಲನ್ನು ತೋರಿಸಿ"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "설정",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "용지 크기",
|
||||
"secondary": "이력서 페이지의 크기를 결정합니다."
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "브레이크 라인",
|
||||
"secondary": "A4 페이지의 높이를 표시하기 위해 모든 페이지에 선 표시"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "ക്രമീകരണങ്ങള്",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "പേപ്പർ വലിപ്പം",
|
||||
"secondary": "നിങ്ങളുടെ റെസ്യൂമെ പേജുകളുടെ അളവുകൾ നിർണ്ണയിക്കുന്നു"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "ബ്രേക്ക് ലൈൻ",
|
||||
"secondary": "A4 പേജിന്റെ ഉയരം അടയാളപ്പെടുത്താൻ എല്ലാ പേജുകളിലും ഒരു വരി കാണിക്കുക"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "सेटिंग्ज",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "कागदाचा आकार",
|
||||
"secondary": "तुमच्या रेझ्युमे पेजेसची परिमाणे निर्धारित करते"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "ब्रेक लाइन",
|
||||
"secondary": "A4 पृष्ठाची उंची चिन्हांकित करण्यासाठी सर्व पृष्ठांवर एक ओळ दर्शवा"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "सेटिङहरू",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "कागज आकार",
|
||||
"secondary": "तपाईंको पुन: सुरुवात पृष्ठहरूको आयामहरू निर्धारण गर्दछ"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "ब्रेक लाइन",
|
||||
"secondary": "A4 पृष्ठको उचाइ चिन्ह लगाउन सबै पृष्ठहरूमा रेखा देखाउनुहोस्"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Instellingen",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Papiergrootte",
|
||||
"secondary": "Bepaalt de afmetingen van uw cv-pagina's"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Breek Lijn",
|
||||
"secondary": "Toon een lijn op alle pagina's om de hoogte van een A4-pagina te markeren"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Innstillinger",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Papir størrelse",
|
||||
"secondary": "Bestemmer dimensjonene til CV-sidene dine"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Break Line",
|
||||
"secondary": "Vis en linje på alle sider for å markere høyden på en A4-side"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "ସେଟିଂସ୍",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "କାଗଜ ଆକାର |",
|
||||
"secondary": "ତୁମର ରିଜ୍ୟୁମ୍ ପୃଷ୍ଠାଗୁଡ଼ିକର ପରିମାଣ ନିର୍ଣ୍ଣୟ କରେ |"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "ବ୍ରେକ୍ ଲାଇନ୍",
|
||||
"secondary": "A4 ପୃଷ୍ଠାର ଉଚ୍ଚତା ଚିହ୍ନିତ କରିବାକୁ ସମସ୍ତ ପୃଷ୍ଠାରେ ଏକ ରେଖା ଦେଖାନ୍ତୁ ।"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Ustawienia",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Rozmiar papieru",
|
||||
"secondary": "Określa wymiary twoich stron CV"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Inteligentne dopasowanie linii",
|
||||
"secondary": "Pokaż linię na wszystkich stronach, aby oznaczyć wysokość strony A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Configurações",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Tamanho do papel",
|
||||
"secondary": "Determina as dimensões das suas páginas de currículo"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Linha de quebra",
|
||||
"secondary": "Mostrar uma linha em todas as páginas para marcar a altura de uma página A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Setări",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Dimensiunea hartiei",
|
||||
"secondary": "Determină dimensiunile paginilor de CV"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Linia de pauză",
|
||||
"secondary": "Afișați o linie pe toate paginile pentru a marca înălțimea unei pagini A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Настройки",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Размер бумаги",
|
||||
"secondary": "Определяет размеры страниц вашего резюме"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Линия разрыва",
|
||||
"secondary": "Показывать линию, обозначающую высоту страницы A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Podešavanja",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Величина папира",
|
||||
"secondary": "Одређује димензије страница вашег животописа"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Prelomi Redova",
|
||||
"secondary": "Pokaži liniju na svakoj stranici kako bi se obeležila visina A4 stranice"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Inställningar",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Pappersformat",
|
||||
"secondary": "Bestämmer måtten på dina CV-sidor"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Radbrytning",
|
||||
"secondary": "Visa en linje på alla sidor för att markera höjden på en A4-sida"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "அமைப்புகள்",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "காகித அளவு",
|
||||
"secondary": "உங்கள் ரெஸ்யூம் பக்கங்களின் பரிமாணங்களைத் தீர்மானிக்கிறது"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "பிரேக் லைன்",
|
||||
"secondary": "A4 பக்கத்தின் உயரத்தைக் குறிக்க அனைத்துப் பக்கங்களிலும் ஒரு வரியைக் காட்டு"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Ayarlar",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Kağıt boyutu",
|
||||
"secondary": "Özgeçmiş sayfalarınızın boyutlarını belirler"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Ara Hat",
|
||||
"secondary": "A4 sayfasının yüksekliğini işaretlemek için tüm sayfalarda bir çizgi göster"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Налаштування",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Розмір паперу",
|
||||
"secondary": "Визначає розміри сторінок вашого резюме"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Розривати рядки",
|
||||
"secondary": "Показати лінію на всіх сторінках, для позначення розміру сторінки А4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "Cài đặt",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "Khổ giấy",
|
||||
"secondary": "Xác định kích thước của các trang sơ yếu lý lịch của bạn"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "Ngắt dòng",
|
||||
"secondary": "Hiển thị một dòng chữ trên tất cả các trang để đánh dấu chiều cao của trang A4"
|
||||
|
||||
@ -290,6 +290,10 @@
|
||||
},
|
||||
"heading": "设置",
|
||||
"page": {
|
||||
"format": {
|
||||
"primary": "纸张尺寸",
|
||||
"secondary": "确定简历页面的尺寸"
|
||||
},
|
||||
"break-line": {
|
||||
"primary": "换行",
|
||||
"secondary": "在所有页面上显示一条线以标记 A4 页面的高度"
|
||||
|
||||
@ -18,8 +18,8 @@ export type LoginWithGoogleParams = {
|
||||
|
||||
export type RegisterParams = {
|
||||
name: string;
|
||||
username: string;
|
||||
email: string;
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import { useMemo } from 'react';
|
||||
@ -17,7 +17,7 @@ const Castform: React.FC<PageProps> = ({ page }) => {
|
||||
const isFirstPage = useMemo(() => page === 0, [page]);
|
||||
|
||||
const layout: string[][] = useAppSelector((state) => state.resume.present.metadata.layout[page]);
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
|
||||
const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]);
|
||||
const color = useMemo(() => (contrast === 'dark' ? theme.text : theme.background), [theme, contrast]);
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { darken } from '@mui/material';
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useAppSelector } from '@/store/hooks';
|
||||
|
||||
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const darkerPrimary = useMemo(() => darken(theme.primary, 0.2), [theme.primary]);
|
||||
|
||||
return (
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
@ -19,7 +19,7 @@ export const MastheadSidebar: React.FC = () => {
|
||||
const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
|
||||
(state) => state.resume.present.basics
|
||||
);
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]);
|
||||
const color = useMemo(() => (contrast === 'dark' ? theme.text : theme.background), [theme, contrast]);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { alpha } from '@mui/material';
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import { useMemo } from 'react';
|
||||
@ -18,7 +18,7 @@ const Gengar: React.FC<PageProps> = ({ page }) => {
|
||||
const isFirstPage = useMemo(() => page === 0, [page]);
|
||||
|
||||
const layout: string[][] = useAppSelector((state) => state.resume.present.metadata.layout[page]);
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]);
|
||||
const backgroundColor: string = useMemo(() => alpha(theme.primary, 0.15), [theme.primary]);
|
||||
const color = useMemo(() => (contrast === 'dark' ? theme.text : theme.background), [theme, contrast]);
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import { useAppSelector } from '@/store/hooks';
|
||||
|
||||
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
|
||||
return (
|
||||
<h3
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
|
||||
import { alpha } from '@mui/material';
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import clsx from 'clsx';
|
||||
import get from 'lodash/get';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
@ -20,7 +20,7 @@ export const MastheadSidebar: React.FC = () => {
|
||||
const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
|
||||
(state) => state.resume.present.basics
|
||||
);
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]);
|
||||
const iconColor = useMemo(() => (contrast === 'dark' ? theme.text : theme.background), [theme, contrast]);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { alpha } from '@mui/material';
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
import isArray from 'lodash/isArray';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
@ -13,7 +13,7 @@ type Props = {
|
||||
};
|
||||
|
||||
const BadgeDisplay: React.FC<Props> = ({ items }) => {
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]);
|
||||
|
||||
if (!isArray(items) || isEmpty(items)) return null;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import { useAppSelector } from '@/store/hooks';
|
||||
|
||||
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
|
||||
return (
|
||||
<h3
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
import isArray from 'lodash/isArray';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
@ -12,7 +12,7 @@ type Props = {
|
||||
};
|
||||
|
||||
const BadgeDisplay: React.FC<Props> = ({ items }) => {
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]);
|
||||
|
||||
if (!isArray(items) || isEmpty(items)) return null;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import { useAppSelector } from '@/store/hooks';
|
||||
|
||||
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
|
||||
return (
|
||||
<h2
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
|
||||
import { alpha } from '@mui/material';
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
@ -16,7 +16,7 @@ const Masthead: React.FC = () => {
|
||||
const { name, photo, headline, summary, email, phone, birthdate, website, location, profiles } = useAppSelector(
|
||||
(state) => state.resume.present.basics
|
||||
);
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import { useAppSelector } from '@/store/hooks';
|
||||
|
||||
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
|
||||
return (
|
||||
<h4 className="mb-2 font-bold uppercase" style={{ color: theme.primary }}>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import { useAppSelector } from '@/store/hooks';
|
||||
|
||||
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
|
||||
return (
|
||||
<h3
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
|
||||
import { Theme } from '@reactive-resume/schema';
|
||||
import { ThemeConfig } from '@reactive-resume/schema';
|
||||
import get from 'lodash/get';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import { useMemo } from 'react';
|
||||
@ -62,7 +62,7 @@ export const MastheadSidebar: React.FC = () => {
|
||||
};
|
||||
|
||||
export const MastheadMain: React.FC = () => {
|
||||
const theme: Theme = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const theme: ThemeConfig = useAppSelector((state) => get(state.resume.present, 'metadata.theme', {}));
|
||||
const contrast = useMemo(() => getContrastColor(theme.primary), [theme.primary]);
|
||||
|
||||
const { name, summary, headline } = useAppSelector((state) => state.resume.present.basics);
|
||||
|
||||
3
client/utils/string.ts
Normal file
3
client/utils/string.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const capitalize = (str: string) => {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
};
|
||||
@ -1,4 +1,4 @@
|
||||
import { Theme, Typography } from '@reactive-resume/schema';
|
||||
import { ThemeConfig, Typography } from '@reactive-resume/schema';
|
||||
import { RgbColor } from 'react-colorful';
|
||||
|
||||
import { hexColorPattern } from '@/config/colors';
|
||||
@ -27,7 +27,7 @@ export const generateTypographyStyles = ({ family, size }: Typography): string =
|
||||
h6 { font-size: ${size.heading / 3.5}px; line-height: ${size.heading / 3.5}px; }
|
||||
`;
|
||||
|
||||
export const generateThemeStyles = ({ text, background, primary }: Theme): string => `
|
||||
export const generateThemeStyles = ({ text, background, primary }: ThemeConfig): string => `
|
||||
color: ${text};
|
||||
background-color: ${background};
|
||||
--primary-color: ${primary};
|
||||
|
||||
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "reactive-resume",
|
||||
"version": "3.6.7",
|
||||
"version": "3.6.8+1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "env-cmd --silent turbo run dev",
|
||||
@ -17,12 +17,12 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"env-cmd": "^10.1.0",
|
||||
"turbo": "^1.5.5"
|
||||
"turbo": "^1.5.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.39.0",
|
||||
"@typescript-eslint/parser": "^5.39.0",
|
||||
"eslint": "^8.24.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.0",
|
||||
"@typescript-eslint/parser": "^5.40.0",
|
||||
"eslint": "^8.25.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-simple-import-sort": "^8.0.0",
|
||||
"prettier": "^2.7.1",
|
||||
|
||||
1490
pnpm-lock.yaml
generated
1490
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
BIN
schema/.DS_Store
vendored
BIN
schema/.DS_Store
vendored
Binary file not shown.
@ -9,7 +9,7 @@
|
||||
"build": "tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.24.0",
|
||||
"eslint": "^8.25.0",
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,10 +3,14 @@ export type CustomCSS = {
|
||||
visible: boolean;
|
||||
};
|
||||
|
||||
export type Theme = {
|
||||
export type PageConfig = {
|
||||
format: 'A4' | 'Letter';
|
||||
};
|
||||
|
||||
export type ThemeConfig = {
|
||||
text: string;
|
||||
background: string;
|
||||
primary: string;
|
||||
background: string;
|
||||
};
|
||||
|
||||
export type TypeCategory = 'heading' | 'body';
|
||||
@ -27,6 +31,7 @@ export type Metadata = {
|
||||
date: DateConfig;
|
||||
layout: string[][][]; // page.column.section
|
||||
template: string;
|
||||
theme: Theme;
|
||||
theme: ThemeConfig;
|
||||
page?: PageConfig;
|
||||
typography: Typography;
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@ FROM node:lts-alpine AS base
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk add --no-cache g++ git curl make python3 \
|
||||
RUN apk add --no-cache g++ git curl make python3 libc6-compat \
|
||||
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
|
||||
|
||||
FROM base AS dependencies
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
"start": "node dist/main"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.186.0",
|
||||
"@aws-sdk/client-s3": "^3.188.0",
|
||||
"@nestjs/axios": "^0.1.0",
|
||||
"@nestjs/common": "^9.1.4",
|
||||
"@nestjs/config": "^2.2.0",
|
||||
@ -23,14 +23,14 @@
|
||||
"@nestjs/typeorm": "^9.0.1",
|
||||
"@types/passport": "^1.0.11",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cache-manager": "^5.0.0",
|
||||
"cache-manager": "^5.0.1",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.13.2",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"csvtojson": "^2.0.10",
|
||||
"dayjs": "^1.11.5",
|
||||
"google-auth-library": "^8.5.2",
|
||||
"joi": "^17.6.2",
|
||||
"joi": "^17.6.3",
|
||||
"lodash": "^4.17.21",
|
||||
"multer": "^1.4.4",
|
||||
"nanoid": "^3.3.4",
|
||||
@ -41,7 +41,7 @@
|
||||
"passport-local": "^1.0.0",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"pg": "^8.8.0",
|
||||
"playwright-chromium": "^1.26.1",
|
||||
"playwright-chromium": "^1.27.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.5.7",
|
||||
@ -57,7 +57,7 @@
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/node": "^18.8.3",
|
||||
"@types/node": "^18.11.0",
|
||||
"@types/nodemailer": "^6.4.6",
|
||||
"@types/passport-jwt": "^3.0.7",
|
||||
"@types/passport-local": "^1.0.34",
|
||||
|
||||
@ -932,6 +932,9 @@ export class IntegrationsService {
|
||||
body: get(jsonResume, 'metadata.fontSize'),
|
||||
},
|
||||
},
|
||||
page: {
|
||||
format: 'A4',
|
||||
},
|
||||
theme: {
|
||||
background: get(jsonResume, 'metadata.colors.background'),
|
||||
primary: get(jsonResume, 'metadata.colors.primary'),
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { SchedulerRegistry } from '@nestjs/schedule';
|
||||
import { PageConfig } from '@reactive-resume/schema';
|
||||
import { mkdir, unlink, writeFile } from 'fs/promises';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { join } from 'path';
|
||||
@ -35,13 +36,18 @@ export class PrinterService implements OnModuleInit, OnModuleDestroy {
|
||||
await page.goto(`${url}/${username}/${slug}/printer?secretKey=${secretKey}`);
|
||||
await page.waitForSelector('html.wf-active');
|
||||
|
||||
const resumePages = await page.$$eval('[data-page]', (pages) => {
|
||||
return pages.map((page, index) => ({
|
||||
const pageFormat: PageConfig['format'] = await page.$$eval(
|
||||
'[data-page]',
|
||||
(pages) => pages[0].getAttribute('data-format') as PageConfig['format']
|
||||
);
|
||||
|
||||
const resumePages = await page.$$eval('[data-page]', (pages) =>
|
||||
pages.map((page, index) => ({
|
||||
pageNumber: index + 1,
|
||||
innerHTML: page.innerHTML,
|
||||
height: page.clientHeight,
|
||||
}));
|
||||
});
|
||||
}))
|
||||
);
|
||||
|
||||
const pdf = await PDFDocument.create();
|
||||
const directory = join(__dirname, '..', 'assets/exports');
|
||||
@ -52,9 +58,9 @@ export class PrinterService implements OnModuleInit, OnModuleDestroy {
|
||||
await page.evaluate((page) => (document.body.innerHTML = page.innerHTML), resumePages[index]);
|
||||
|
||||
const buffer = await page.pdf({
|
||||
width: '210mm',
|
||||
printBackground: true,
|
||||
height: resumePages[index].height,
|
||||
width: pageFormat === 'A4' ? '210mm' : '216mm',
|
||||
});
|
||||
|
||||
const pageDoc = await PDFDocument.load(buffer);
|
||||
|
||||
@ -138,6 +138,9 @@ const defaultState: Partial<Resume> = {
|
||||
date: {
|
||||
format: 'MMMM DD, YYYY',
|
||||
},
|
||||
page: {
|
||||
format: 'A4',
|
||||
},
|
||||
layout: [
|
||||
[
|
||||
['work', 'education', 'projects', 'volunteer', 'references'],
|
||||
|
||||
Reference in New Issue
Block a user