Compare commits

...

8 Commits

21 changed files with 72 additions and 23 deletions

View File

@ -2,8 +2,28 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [3.1.4](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.1.3...v3.1.4) (2022-03-12)
### Bug Fixes
* **client:** exported pdf did not contain "Present" keyword with translations ([cf670af](https://github.com/AmruthPillai/Reactive-Resume/commit/cf670af4035dc9b462cf5b1aad06ca089cf1d40c))
* **client:** fix issues raised through lgtm alerts ([dfccb31](https://github.com/AmruthPillai/Reactive-Resume/commit/dfccb3130f889934d31196226be3d33e772f323b))
### [3.1.3](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.1.2...v3.1.3) (2022-03-12)
### Bug Fixes
* **server:** reform url for pdf generation and download ([6d55f91](https://github.com/AmruthPillai/Reactive-Resume/commit/6d55f917eab3cb2f5f3a90c5a18f03b625d60021)), closes [#661](https://github.com/AmruthPillai/Reactive-Resume/issues/661)
### [3.1.2](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.1.1...v3.1.2) (2022-03-12)
### CI
* **docker:**: include traefik routing and proxy to ensure server connections pass in local ([11cb066](https://github.com/AmruthPillai/Reactive-Resume/commit/11cb066573c6917857b79c028b97fcda1acaf90a))
### [3.1.1](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.1.0...v3.1.1) (2022-03-12)

View File

@ -4,6 +4,7 @@
![Project Version](https://img.shields.io/github/package-json/v/AmruthPillai/Reactive-Resume?style=flat-square)
![Project License](https://img.shields.io/github/license/AmruthPillai/Reactive-Resume?style=flat-square)
[![Crowdin](https://badges.crowdin.net/reactive-resume/localized.svg)](https://translate.rxresu.me)
[![Docker Pulls](https://img.shields.io/docker/pulls/amruthpillai/reactive-resume?style=flat-square)](https://hub.docker.com/r/amruthpillai/reactive-resume)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FAmruthPillai%2FReactive-Resume.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2FAmruthPillai%2FReactive-Resume?ref=badge_shield)

View File

@ -66,6 +66,7 @@ const Settings = () => {
const code = value?.code || 'en';
document.cookie = `NEXT_LOCALE=${code}; path=/; expires=2147483647`;
dispatch(setResumeState({ path: 'metadata.locale', value: code }));
push({ pathname, query }, asPath, { locale: code });
};

View File

@ -1,4 +1,4 @@
import { Theme } from '@reactive-resume/schema';
import { Theme as ThemeType } 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<Theme>((state) => get(state.resume, 'metadata.theme'));
const { background, text, primary } = useAppSelector<ThemeType>((state) => get(state.resume, 'metadata.theme'));
const handleChange = (property: string, color: string) => {
dispatch(setResumeState({ path: `metadata.theme.${property}`, value: color }));

View File

@ -1,8 +1,8 @@
import { Testimony } from '@/data/testimonials';
import { Testimony as TestimonyType } from '@/data/testimonials';
import styles from './Testimony.module.scss';
type Props = Testimony;
type Props = TestimonyType;
const Testimony: React.FC<Props> = ({ name, message }) => {
return (

View File

@ -5,6 +5,8 @@ import { useTranslation } from 'next-i18next';
import { MouseEvent, useState } from 'react';
import { languages } from '@/config/languages';
import { useAppDispatch } from '@/store/hooks';
import { setResumeState } from '@/store/resume/resumeSlice';
import styles from './LanguageSwitcher.module.scss';
@ -13,6 +15,8 @@ const LanguageSwitcher = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
const handleClick = (event: MouseEvent<HTMLButtonElement>) => setAnchorEl(event.currentTarget);
@ -23,6 +27,8 @@ const LanguageSwitcher = () => {
const { pathname, asPath, query } = router;
document.cookie = `NEXT_LOCALE=${locale}; path=/; expires=2147483647`;
dispatch(setResumeState({ path: 'metadata.locale', value: locale }));
router.push({ pathname, query }, asPath, { locale });
};

View File

@ -3,7 +3,7 @@ export const FONTS_QUERY = 'fonts';
export const RESUMES_QUERY = 'resumes';
// Regular Expressions
export const VALID_URL_REGEX = /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
export const VALID_URL_REGEX = /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/;
// Date Formats
export const FILENAME_TIMESTAMP = 'DDMMYYYYHHmmss';

View File

@ -3,6 +3,7 @@ import clsx from 'clsx';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import { GetServerSideProps, NextPage } from 'next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { useEffect } from 'react';
import Page from '@/components/build/Center/Page';
@ -22,15 +23,19 @@ type Props = {
redirect?: any;
};
export const getServerSideProps: GetServerSideProps<Props | Promise<Props>, QueryParams> = async ({ query }) => {
export const getServerSideProps: GetServerSideProps<Props | Promise<Props>, QueryParams> = async ({
query,
locale,
}) => {
const { username, slug, secretKey } = query as QueryParams;
try {
if (isEmpty(secretKey)) throw new Error('There is no secret key!');
const resume = await fetchResumeByIdentifier({ username, slug, options: { secretKey } });
const displayLocale = resume.metadata.locale || locale || 'en';
return { props: { resume } };
return { props: { resume, ...(await serverSideTranslations(displayLocale, ['common'])) } };
} catch (error) {
return {
redirect: {

View File

@ -1,5 +1,5 @@
import { Email, Link, Phone } from '@mui/icons-material';
import { ListItem, Section } from '@reactive-resume/schema';
import { ListItem, Section as SectionType } from '@reactive-resume/schema';
import get from 'lodash/get';
import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty';
@ -20,7 +20,7 @@ const Section: React.FC<SectionProps> = ({
headlinePath = 'headline',
keywordsPath = 'keywords',
}) => {
const section: Section = useAppSelector((state) => get(state.resume, path, {}));
const section: SectionType = useAppSelector((state) => get(state.resume, path, {}));
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
if (!section.visible) return null;

View File

@ -1,5 +1,5 @@
import { Email, Link, Phone } from '@mui/icons-material';
import { ListItem, Section } from '@reactive-resume/schema';
import { ListItem, Section as SectionType } from '@reactive-resume/schema';
import get from 'lodash/get';
import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty';
@ -20,7 +20,7 @@ const Section: React.FC<SectionProps> = ({
headlinePath = 'headline',
keywordsPath = 'keywords',
}) => {
const section: Section = useAppSelector((state) => get(state.resume, path, {}));
const section: SectionType = useAppSelector((state) => get(state.resume, path, {}));
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const primaryColor: string = useAppSelector((state) => get(state.resume, 'metadata.theme.primary'));

View File

@ -1,5 +1,5 @@
import { Email, Link, Phone } from '@mui/icons-material';
import { ListItem, Section } from '@reactive-resume/schema';
import { ListItem, Section as SectionType } from '@reactive-resume/schema';
import get from 'lodash/get';
import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty';
@ -21,7 +21,7 @@ const Section: React.FC<SectionProps> = ({
headlinePath = 'headline',
keywordsPath = 'keywords',
}) => {
const section: Section = useAppSelector((state) => get(state.resume, path, {}));
const section: SectionType = useAppSelector((state) => get(state.resume, path, {}));
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const primaryColor: string = useAppSelector((state) => get(state.resume, 'metadata.theme.primary'));

View File

@ -1,5 +1,5 @@
import { Email, Phone } from '@mui/icons-material';
import { ListItem, Section } from '@reactive-resume/schema';
import { ListItem, Section as SectionType } from '@reactive-resume/schema';
import get from 'lodash/get';
import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty';
@ -20,7 +20,7 @@ const Section: React.FC<SectionProps> = ({
headlinePath = 'headline',
keywordsPath = 'keywords',
}) => {
const section: Section = useAppSelector((state) => get(state.resume, path, {}));
const section: SectionType = useAppSelector((state) => get(state.resume, path, {}));
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const primaryColor: string = useAppSelector((state) => get(state.resume, 'metadata.theme.primary'));

View File

@ -1,5 +1,5 @@
import { Email, Link, Phone } from '@mui/icons-material';
import { ListItem, Section } from '@reactive-resume/schema';
import { ListItem, Section as SectionType } from '@reactive-resume/schema';
import get from 'lodash/get';
import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty';
@ -20,7 +20,7 @@ const Section: React.FC<SectionProps> = ({
headlinePath = 'headline',
keywordsPath = 'keywords',
}) => {
const section: Section = useAppSelector((state) => get(state.resume, path, {}));
const section: SectionType = useAppSelector((state) => get(state.resume, path, {}));
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const primaryColor: string = useAppSelector((state) => get(state.resume, 'metadata.theme.primary'));

View File

@ -1,5 +1,5 @@
import { Email, Link, Phone } from '@mui/icons-material';
import { ListItem, Section } from '@reactive-resume/schema';
import { ListItem, Section as SectionType } from '@reactive-resume/schema';
import get from 'lodash/get';
import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty';
@ -20,7 +20,7 @@ const Section: React.FC<SectionProps> = ({
headlinePath = 'headline',
keywordsPath = 'keywords',
}) => {
const section: Section = useAppSelector((state) => get(state.resume, path, {}));
const section: SectionType = useAppSelector((state) => get(state.resume, path, {}));
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const primaryColor: string = useAppSelector((state) => get(state.resume, 'metadata.theme.primary'));

View File

@ -9,6 +9,7 @@ import TOCInline from '@theme/TOCInline';
![Project Version](https://img.shields.io/github/package-json/v/AmruthPillai/Reactive-Resume?style=flat-square)
![Project License](https://img.shields.io/github/license/AmruthPillai/Reactive-Resume?style=flat-square)
[![Crowdin](https://badges.crowdin.net/reactive-resume/localized.svg)](https://translate.rxresu.me)
[![Docker Pulls](https://img.shields.io/docker/pulls/amruthpillai/reactive-resume?style=flat-square)](https://hub.docker.com/r/amruthpillai/reactive-resume)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FAmruthPillai%2FReactive-Resume.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2FAmruthPillai%2FReactive-Resume?ref=badge_shield)

View File

@ -33,13 +33,25 @@ pnpm dev
Now, your **frontend** client should be running on [`http://localhost:3000`](http://localhost:3000), your **backend** server on [`http://localhost:3100`](http://localhost:3100) and this **documentation** on [`http://localhost:3200`](http://localhost:3200).
5. Build the project before deploying by running the command:
5. To ensure that the app works currently, a proxy layer has to be made between the client and server. For this, I made use of a Chrome extension called [**Rabbit URL Rewriter**](https://chrome.google.com/webstore/detail/rabbit-url-rewriter/kcbmcmeblpkcndhfhkclggekfblookii?hl=en) to forward my requests made to `localhost:3000/api` to `localhost:3100`. The configuration should look something like this:
```
Website URL: http://localhost:3000
From URL: http://localhost:3000/api/(.*)
To URL: http://localhost:3100/$1
```
![Screenshot 2022-03-12 at 4 07 37 PM](https://user-images.githubusercontent.com/1134738/158023473-d415e696-f027-4bc7-af02-648c4a99b147.png)
Now, you should be able to create accounts, login etc.
6. Build the project before deploying by running the command:
```bash
pnpm build
```
6. Finally, start the production servers for all three workspaces by running:
7. Finally, start the production servers for all three workspaces by running:
```bash
pnpm start

View File

@ -1,6 +1,6 @@
{
"name": "reactive-resume",
"version": "3.1.2",
"version": "3.1.4",
"private": true,
"workspaces": [
"schema",

View File

@ -23,6 +23,7 @@ export type DateConfig = {
export type Metadata = {
css: CustomCSS;
locale: string;
date: DateConfig;
layout: string[][][]; // page.column.section
template: string;

View File

@ -45,7 +45,7 @@ export class PrinterService implements OnModuleInit, OnModuleDestroy {
const pdf = await PDFDocument.create();
const directory = join(__dirname, '..', 'assets/exports');
const filename = `RxResume_PDFExport_${nanoid()}.pdf`;
const publicUrl = `/api/exports/${filename}`;
const publicUrl = `/assets/exports/${filename}`;
for (let index = 0; index < resumePages.length; index++) {
await page.evaluate((page) => (document.body.innerHTML = page.innerHTML), resumePages[index]);

View File

@ -133,6 +133,7 @@ const defaultState: Partial<Resume> = {
background: '#ffffff',
primary: '#f44336',
},
locale: 'en',
date: {
format: 'MMMM DD, YYYY',
},

View File

@ -421,6 +421,7 @@ const sampleData: Partial<Resume> = {
value: '/* Enter custom CSS here */\n\n* {\n outline: 1px solid #000;\n}',
visible: false,
},
locale: 'en',
date: {
format: 'MMMM DD, YYYY',
},