Compare commits

...

33 Commits

Author SHA1 Message Date
9caad3bc0b chore(release): 3.4.1 2022-04-30 13:01:59 +02:00
5bdb92b1cf fix(typeorm): update typeorm to latest 0.2.x for secpatch 2022-04-30 13:01:45 +02:00
87d381fe8e feat(all): upgrade to v3.4.0 2022-04-30 12:58:17 +02:00
ccfb4d3cb0 Merge pull request #867 from Tomiiwa/Table-of-Contents
[DOC] Added Table of Contents to ReadMe
2022-04-30 09:11:08 +02:00
763074a86c Added Table of Contents to ReadMe 2022-04-29 16:41:52 +01:00
0f46895711 Merge pull request #861 from AmruthPillai/dependabot/github_actions/actions/checkout-3.0.2
chore(deps): bump actions/checkout from 3.0.1 to 3.0.2
2022-04-25 09:34:20 +02:00
aa736af0f5 Merge pull request #858 from AmruthPillai/dependabot/gradle/app/org.jetbrains.kotlin.android-1.6.21
chore(deps): bump org.jetbrains.kotlin.android from 1.6.20 to 1.6.21 in /app
2022-04-25 09:33:53 +02:00
1d9056f935 chore(deps): bump actions/checkout from 3.0.1 to 3.0.2
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3.0.1...v3.0.2)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-25 03:11:03 +00:00
9cadd603f3 chore(deps): bump org.jetbrains.kotlin.android in /app
Bumps org.jetbrains.kotlin.android from 1.6.20 to 1.6.21.

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin.android
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-25 03:08:55 +00:00
b7b62d7bd0 Merge pull request #853 from AmruthPillai/i18n_main
New Crowdin updates
2022-04-24 08:06:24 +02:00
820e6c90d3 New translations modals.json (Greek) 2022-04-22 15:06:52 +02:00
ea642d1b60 New translations landing.json (Greek) 2022-04-22 15:06:51 +02:00
ec006779a8 New translations common.json (Greek) 2022-04-22 15:06:47 +02:00
515be23c44 New translations dashboard.json (Greek) 2022-04-22 15:06:46 +02:00
c11aec8b44 Merge pull request #851 from AmruthPillai/i18n_main
New Crowdin updates
2022-04-22 07:14:41 +02:00
3c2147e72c New translations landing.json (Swedish) 2022-04-21 21:01:56 +02:00
15a35e6243 New translations modals.json (Swedish) 2022-04-21 21:01:53 +02:00
d53a5a492c New translations landing.json (Swedish) 2022-04-21 20:00:31 +02:00
0810e5ae6a Merge pull request #842 from AmruthPillai/i18n_main
New Crowdin updates
2022-04-20 09:21:40 +02:00
881b183db5 Merge pull request #844 from AmruthPillai/dependabot/github_actions/actions/checkout-3.0.1
chore(deps): bump actions/checkout from 3.0.0 to 3.0.1
2022-04-20 09:21:32 +02:00
15cea02872 Delete close-stale.yml 2022-04-19 06:45:45 +02:00
c195561df0 Merge pull request #843 from augustocardoso07/fix/page-counter
Fix page counter in the center section
2022-04-18 18:15:24 +02:00
fc725cfc0c chore(deps): bump actions/checkout from 3.0.0 to 3.0.1
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-18 02:30:45 +00:00
9f54516e8c Fix page counter in the center section 2022-04-17 21:09:55 -03:00
68a4cd9635 New translations builder.json (Swedish) 2022-04-17 19:42:51 +02:00
ff01802f2f New translations common.json (Swedish) 2022-04-17 19:42:49 +02:00
bb900bc2e1 New translations dashboard.json (Swedish) 2022-04-17 19:42:48 +02:00
459f82b66b Merge pull request #828 from AmruthPillai/i18n_main
New Crowdin updates
2022-04-11 07:48:37 +02:00
4b382243e4 New translations modals.json (Odia) 2022-04-10 12:17:28 +02:00
af074085d1 New translations landing.json (Odia) 2022-04-10 12:17:25 +02:00
0c8c872668 New translations dashboard.json (Odia) 2022-04-10 12:17:25 +02:00
ddb29bb40d New translations common.json (Odia) 2022-04-10 12:17:23 +02:00
aecb627ab7 New translations builder.json (Odia) 2022-04-10 12:17:22 +02:00
79 changed files with 25100 additions and 1302 deletions

View File

@ -1,4 +1,4 @@
ARG VARIANT="16-bullseye"
ARG VARIANT="lts-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}

View File

@ -1,16 +0,0 @@
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '0 0 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v5.0.0
with:
stale-pr-message: 'This PR is stale because it has been open for 30 days with no activity. Remove the stale label or comment on this PR, otherwise it would be closed in 5 days.'
stale-issue-message: 'This issue is stale because it has been open for 30 days with no activity. Remove the stale label or comment on this issue, otherwise it would be closed in 5 days.'
days-before-stale: 30
days-before-close: 5

View File

@ -11,7 +11,7 @@ jobs:
steps:
- name: Checkout the repository
uses: actions/checkout@v3.0.0
uses: actions/checkout@v3.0.2
- id: version
name: Get Version
@ -55,7 +55,7 @@ jobs:
steps:
- name: Checkout the repository
uses: actions/checkout@v3.0.0
uses: actions/checkout@v3.0.2
- id: version
name: Get Version

View File

@ -2,6 +2,15 @@
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.4.1](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.4.0...v3.4.1) (2022-04-30)
### Bug Fixes
* **typeorm:** update typeorm to latest 0.2.x for secpatch ([5bdb92b](https://github.com/AmruthPillai/Reactive-Resume/commit/5bdb92b1cff9e56879f9bbf31801d6554a00a8d5))
### [3.4.0](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.3.3...v3.4.0) (2022-04-30)
### [3.3.4](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.3.3...v3.3.4) (2022-04-09)
### [3.3.3](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.3.2...v3.3.3) (2022-04-09)

View File

@ -15,6 +15,23 @@ Reactive Resume is a free and open source resume builder thats built to make
You have complete control over what goes into your resume, how it looks, what colors, what templates, even the layout in which sections placed. Want a dark mode resume? Its as easy as editing 3 values and youre done. You dont need to wait to see your changes either. Everything you type, everything you change, appears immediately on your resume and gets updated in real time.
## Table of Contents
- [Reactive Resume](#reactive-resume)
- [Go to App | [Docs](https://docs.rxresu.me)](#go-to-app--docs)
- [Table of Contents](#table-of-contents)
- [Features](#features)
- [Languages](#languages)
- [Tutorial](#tutorial)
- [Build from Source](#build-from-source)
- [Contributing](#contributing)
- [Report Bugs and Feature Requests](#report-bugs-and-feature-requests)
- [Donations](#donations)
- [💸 PayPal](#-paypal)
- [Infrastructure](#infrastructure)
- [Contributors Wall](#contributors-wall)
- [License](#license)
## Features
- Free, forever
@ -40,19 +57,23 @@ You have complete control over what goes into your resume, how it looks, what co
- Arabic (اَلْعَرَبِيَّةُ)
- Bengali (বাংলা)
- Chinese (中文)
- Czech (čeština)
- Danish (Dansk)
- Dutch (Nederlands)
- English
- French (Français)
- German (Deutsch)
- Greek (Ελληνικά)
- Hindi (हिन्दी)
- Italian (Italiano)
- Kannada (ಕನ್ನಡ)
- Malayalam (മലയാളം)
- Odia (ଓଡ଼ିଆ)
- Polish (Polski)
- Portuguese (Português)
- Russian (русский)
- Spanish (Español)
- Swedish (Svenska)
- Tamil (தமிழ்)
- Turkish (Türkçe)
- Vietnamese (Tiếng Việt)
@ -79,7 +100,7 @@ This project makes use of [conventional commits](https://www.conventionalcommits
NOTE: Be sure to merge the latest from `main` before making a pull request!
## Bugs? Feature Requests?
## Report Bugs and Feature Requests
Use the [GitHub Issues](https://github.com/AmruthPillai/Reactive-Resume/issues/new/choose) platform to notify me about bugs or new features that you would like to see in Reactive Resume. Please check before creating new issues as there might already be one.

View File

@ -1,7 +1,7 @@
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
id 'org.jetbrains.kotlin.android' version '1.6.20' apply false
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
}
task clean(type: Delete) {

View File

@ -1,4 +1,4 @@
FROM node:17-alpine as dependencies
FROM node:lts-alpine as dependencies
RUN apk add --no-cache curl g++ make python3 \
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
@ -11,7 +11,7 @@ COPY ./client/package.json ./client/package.json
RUN pnpm install --frozen-lockfile
FROM node:17-alpine as builder
FROM node:lts-alpine as builder
RUN apk add --no-cache curl g++ make python3 \
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
@ -27,7 +27,7 @@ COPY --from=dependencies /app/client/node_modules ./client/node_modules
RUN pnpm run build:schema
RUN pnpm run build:client
FROM node:17-alpine as production
FROM node:lts-alpine as production
WORKDIR /app

View File

@ -48,7 +48,7 @@ const Page: React.FC<Props> = ({ page, showPageNumbers = false }) => {
</div>
{showPageNumbers && (
<h4 className={styles.pageNumber}>{`${t<string>('builder.common.glossary.page')} {page + 1}`}</h4>
<h4 className={styles.pageNumber}>{`${t<string>('builder.common.glossary.page')} ${page + 1}`}</h4>
)}
</div>
);

View File

@ -81,14 +81,14 @@ const LeftSidebar = () => {
arrow
key={id}
placement="right"
title={get(sections, `${id}.name`, t<string>(`builder.leftSidebar.sections.${id}.heading`))}
title={get(sections, `${id}.name`, t<string>(`builder.leftSidebar.sections.${id}.heading`)) as string}
>
<IconButton onClick={() => handleClick(id)}>{icon}</IconButton>
</Tooltip>
))}
{customSections.map(({ id }) => (
<Tooltip key={id} title={get(sections, `${id}.name`, '')} placement="right" arrow>
<Tooltip key={id} title={get(sections, `${id}.name`, '') as string} placement="right" arrow>
<IconButton onClick={() => handleClick(id)}>
<Star />
</IconButton>

View File

@ -57,6 +57,12 @@ const Basics = () => {
</div>
</div>
<ResumeInput
type="date"
label={t<string>('builder.leftSidebar.sections.basics.birthdate.label')}
path="basics.birthdate"
className="sm:col-span-2"
/>
<ResumeInput
label={t<string>('builder.common.form.email.label')}
path="basics.email"

View File

@ -117,7 +117,7 @@ const Layout = () => {
[styles.disabled]: !get(resumeSections, `${sectionId}.visible`, true),
})}
>
{get(resumeSections, `${sectionId}.name`, '')}
{get(resumeSections, `${sectionId}.name`, '') as string}
</div>
</div>
)}

View File

@ -5,11 +5,12 @@ import { useRouter } from 'next/router';
import styles from './BaseModal.module.scss';
type Props = {
icon?: React.ReactNode;
isOpen: boolean;
heading: string;
handleClose: () => void;
icon?: React.ReactNode;
children?: React.ReactNode;
footerChildren?: React.ReactNode;
handleClose: () => void;
};
const BaseModal: React.FC<Props> = ({ icon, isOpen, heading, children, handleClose, footerChildren }) => {

View File

@ -76,6 +76,7 @@ const List: React.FC<Props> = ({
return (
<ListItem
key={item.id}
path={path}
item={item}
index={index}
title={title}

View File

@ -17,6 +17,7 @@ interface DragItem {
type Props = {
item: ListItemType;
path: string;
index: number;
title: string;
subtitle?: string;
@ -26,14 +27,14 @@ type Props = {
onDuplicate?: (item: ListItemType) => void;
};
const ListItem: React.FC<Props> = ({ item, index, title, subtitle, onMove, onEdit, onDelete, onDuplicate }) => {
const ListItem: React.FC<Props> = ({ item, path, index, title, subtitle, onMove, onEdit, onDelete, onDuplicate }) => {
const { t } = useTranslation();
const ref = useRef<HTMLDivElement>(null);
const [anchorEl, setAnchorEl] = useState<Element | null>(null);
const [{ handlerId }, drop] = useDrop<DragItem, any, any>({
accept: 'ListItem',
accept: path,
collect(monitor) {
return { handlerId: monitor.getHandlerId() };
},
@ -68,7 +69,7 @@ const ListItem: React.FC<Props> = ({ item, index, title, subtitle, onMove, onEdi
});
const [{ isDragging }, drag] = useDrag({
type: 'ListItem',
type: path,
item: () => {
return { id: item.id, index };
},

View File

@ -1,5 +0,0 @@
import dynamic from 'next/dynamic';
const NoSSR: React.FC = ({ children }) => <>{children}</>;
export default dynamic(() => Promise.resolve(NoSSR), { ssr: false });

View File

@ -1,4 +1,7 @@
import { DatePicker } from '@mui/lab';
import { TextField } from '@mui/material';
import dayjs from 'dayjs';
import { isEmpty } from 'lodash';
import get from 'lodash/get';
import { useEffect, useState } from 'react';
@ -8,7 +11,7 @@ import { setResumeState } from '@/store/resume/resumeSlice';
import MarkdownSupported from './MarkdownSupported';
interface Props {
type?: 'text' | 'textarea';
type?: 'text' | 'textarea' | 'date';
label: string;
path: string;
className?: string;
@ -31,6 +34,11 @@ const ResumeInput: React.FC<Props> = ({ type = 'text', label, path, className, m
dispatch(setResumeState({ path, value: event.target.value }));
};
const onChangeValue = (value: string) => {
setValue(value);
dispatch(setResumeState({ path, value }));
};
if (type === 'textarea') {
return (
<TextField
@ -45,6 +53,22 @@ const ResumeInput: React.FC<Props> = ({ type = 'text', label, path, className, m
);
}
if (type === 'date') {
return (
<DatePicker
openTo="year"
label={label}
value={value}
views={['year', 'month', 'day']}
renderInput={(params) => <TextField {...params} error={false} className={className} />}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && onChangeValue('');
date && dayjs(date).isValid() && onChangeValue(date.toISOString());
}}
/>
);
}
return <TextField type={type} label={label} value={value} onChange={onChange} className={className} />;
};

View File

@ -7,8 +7,10 @@ export type Language = {
export const languages: Language[] = [
{ code: 'ar', name: 'Arabic', localName: 'اَلْعَرَبِيَّةُ' },
{ code: 'bn', name: 'Bengali', localName: 'বাংলা' },
{ code: 'cs', name: 'Czech', localName: 'čeština' },
{ code: 'da', name: 'Danish', localName: 'Dansk' },
{ code: 'de', name: 'German', localName: 'Deutsch' },
{ code: 'el', name: 'Greek', localName: 'Ελληνικά' },
{ code: 'en', name: 'English' },
{ code: 'es', name: 'Spanish', localName: 'Español' },
{ code: 'fr', name: 'French', localName: 'Français' },
@ -17,9 +19,11 @@ export const languages: Language[] = [
{ code: 'kn', name: 'Kannada', localName: 'ಕನ್ನಡ' },
{ code: 'ml', name: 'Malayalam', localName: 'മലയാളം' },
{ code: 'nl', name: 'Dutch', localName: 'Nederlands' },
{ code: 'or', name: 'Odia', localName: 'ଓଡ଼ିଆ' },
{ code: 'pl', name: 'Polish', localName: 'Polski' },
{ code: 'pt', name: 'Portuguese', localName: 'Português' },
{ code: 'ru', name: 'Russian', localName: 'русский' },
{ code: 'sv', name: 'Swedish', localName: 'Svenska' },
{ code: 'ta', name: 'Tamil', localName: 'தமிழ்' },
{ code: 'tr', name: 'Turkish', localName: 'Türkçe' },
{ code: 'vi', name: 'Vietnamese', localName: 'Tiếng Việt' },

View File

@ -6,7 +6,6 @@ import Joi from 'joi';
import { isEmpty } from 'lodash';
import { Trans, useTranslation } from 'next-i18next';
import { useMemo, useState } from 'react';
import { GoogleLoginResponse, GoogleLoginResponseOffline, useGoogleLogin } from 'react-google-login';
import { Controller, useForm } from 'react-hook-form';
import toast from 'react-hot-toast';
import { useIsMutating, useMutation } from 'react-query';
@ -18,6 +17,8 @@ import { ServerError } from '@/services/axios';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { setModalState } from '@/store/modal/modalSlice';
declare const google: any;
type FormData = {
identifier: string;
password: string;
@ -56,15 +57,6 @@ const LoginModal: React.FC = () => {
loginWithGoogle
);
const { signIn } = useGoogleLogin({
clientId: env('GOOGLE_CLIENT_ID'),
onSuccess: async (response: GoogleLoginResponse | GoogleLoginResponseOffline) => {
await loginWithGoogleMutation({ accessToken: (response as GoogleLoginResponse).accessToken });
handleClose();
},
});
const handleClose = () => {
dispatch(setModalState({ modal: 'auth.login', state: { open: false } }));
reset();
@ -93,8 +85,18 @@ const LoginModal: React.FC = () => {
dispatch(setModalState({ modal: 'auth.forgot', state: { open: true } }));
};
const handleLoginWithGoogle = () => {
signIn();
const handleLoginWithGoogle = async () => {
google.accounts.id.initialize({
client_id: env('GOOGLE_CLIENT_ID'),
callback: async (response: any) => {
await loginWithGoogleMutation({ credential: response.credential });
handleClose();
},
auto_select: false,
});
google.accounts.id.prompt();
};
const PasswordVisibility = (): React.ReactElement => {

View File

@ -5,7 +5,6 @@ import { Button, TextField } from '@mui/material';
import Joi from 'joi';
import { isEmpty } from 'lodash';
import { Trans, useTranslation } from 'next-i18next';
import { GoogleLoginResponse, GoogleLoginResponseOffline, useGoogleLogin } from 'react-google-login';
import { Controller, useForm } from 'react-hook-form';
import { useMutation } from 'react-query';
@ -15,6 +14,8 @@ import { ServerError } from '@/services/axios';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { setModalState } from '@/store/modal/modalSlice';
declare const google: any;
type FormData = {
name: string;
username: string;
@ -63,15 +64,6 @@ const RegisterModal: React.FC = () => {
loginWithGoogle
);
const { signIn } = useGoogleLogin({
clientId: env('GOOGLE_CLIENT_ID'),
onSuccess: async (response: GoogleLoginResponse | GoogleLoginResponseOffline) => {
await loginWithGoogleMutation({ accessToken: (response as GoogleLoginResponse).accessToken });
handleClose();
},
});
const handleClose = () => {
dispatch(setModalState({ modal: 'auth.register', state: { open: false } }));
reset();
@ -87,8 +79,18 @@ const RegisterModal: React.FC = () => {
dispatch(setModalState({ modal: 'auth.login', state: { open: true } }));
};
const handleLoginWithGoogle = () => {
signIn();
const handleLoginWithGoogle = async () => {
google.accounts.id.initialize({
client_id: env('GOOGLE_CLIENT_ID'),
callback: async (response: any) => {
await loginWithGoogleMutation({ credential: response.credential });
handleClose();
},
auto_select: false,
});
google.accounts.id.prompt();
};
return (

View File

@ -13,67 +13,66 @@
"@emotion/react": "^11.9.0",
"@emotion/styled": "^11.8.1",
"@hookform/resolvers": "2.8.8",
"@monaco-editor/react": "^4.4.1",
"@mui/icons-material": "^5.6.0",
"@mui/lab": "^5.0.0-alpha.76",
"@mui/material": "^5.6.0",
"@monaco-editor/react": "^4.4.4",
"@mui/icons-material": "^5.6.2",
"@mui/lab": "^5.0.0-alpha.79",
"@mui/material": "^5.6.3",
"@reduxjs/toolkit": "^1.8.1",
"axios": "^0.26.1",
"axios": "^0.27.2",
"clsx": "^1.1.1",
"dayjs": "^1.11.0",
"dayjs": "^1.11.1",
"downloadjs": "^1.4.7",
"joi": "^17.6.0",
"lodash": "^4.17.21",
"md5-hex": "^4.0.0",
"monaco-editor": "^0.33.0",
"nanoid": "^3.3.2",
"next": "12.1.4",
"nanoid": "^3.3.3",
"next": "12.1.5",
"next-i18next": "^11.0.0",
"react": "<18",
"react": "^18",
"react-beautiful-dnd": "^13.1.0",
"react-colorful": "^5.5.1",
"react-dnd": "^15.1.2",
"react-dnd-html5-backend": "^15.1.2",
"react-dom": "<18",
"react-google-login": "^5.2.2",
"react-hook-form": "^7.29.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18",
"react-hook-form": "^7.30.0",
"react-hot-toast": "2.2.0",
"react-hotkeys-hook": "^3.4.4",
"react-icons": "^4.3.1",
"react-markdown": "^8.0.2",
"react-query": "^3.34.19",
"react-redux": "^7.2.8",
"react-markdown": "^8.0.3",
"react-query": "^3.38.0",
"react-redux": "^8.0.1",
"react-zoom-pan-pinch": "^2.1.3",
"redux": "^4.1.2",
"redux": "^4.2.0",
"redux-persist": "^6.0.0",
"redux-saga": "^1.1.3",
"remark-gfm": "^3.0.1",
"sharp": "^0.30.3",
"sharp": "^0.30.4",
"uuid": "^8.3.2",
"webfontloader": "^1.6.28"
},
"devDependencies": {
"@babel/core": "^7.17.9",
"@babel/core": "^7.17.10",
"@reactive-resume/schema": "workspace:*",
"@tailwindcss/typography": "^0.5.2",
"@types/downloadjs": "^1.4.3",
"@types/lodash": "^4.14.181",
"@types/node": "17.0.23",
"@types/react": "<18",
"@types/lodash": "^4.14.182",
"@types/node": "17.0.30",
"@types/react": "^18",
"@types/react-beautiful-dnd": "^13.1.2",
"@types/react-redux": "^7.1.23",
"@types/react-redux": "^7.1.24",
"@types/tailwindcss": "^3.0.10",
"@types/uuid": "^8.3.4",
"@types/webfontloader": "^1.6.34",
"autoprefixer": "^10.4.4",
"autoprefixer": "^10.4.5",
"csstype": "^3.0.11",
"eslint": "^8.12.0",
"eslint-config-next": "12.1.4",
"next-sitemap": "^2.5.19",
"postcss": "^8.4.12",
"eslint": "^8.14.0",
"eslint-config-next": "12.1.5",
"next-sitemap": "^2.5.20",
"postcss": "^8.4.13",
"prettier": "^2.6.2",
"sass": "^1.50.0",
"tailwindcss": "^3.0.23",
"typescript": "<4.6.0"
"sass": "^1.51.0",
"tailwindcss": "^3.0.24",
"typescript": "^4.6.4"
}
}

View File

@ -4,6 +4,7 @@ import DateAdapter from '@mui/lab/AdapterDayjs';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import type { AppProps } from 'next/app';
import Head from 'next/head';
import Script from 'next/script';
import { appWithTranslation } from 'next-i18next';
import { Toaster } from 'react-hot-toast';
import { QueryClientProvider } from 'react-query';
@ -52,6 +53,8 @@ const App: React.FC<AppProps> = ({ Component, pageProps }) => {
</PersistGate>
</LocalizationProvider>
</ReduxProvider>
<Script src="https://accounts.google.com/gsi/client" />
</>
);
};

View File

@ -1,6 +1,6 @@
import { DarkMode, LightMode, Link as LinkIcon } from '@mui/icons-material';
import { Masonry } from '@mui/lab';
import { Button, IconButton } from '@mui/material';
import { Button, IconButton, NoSsr } from '@mui/material';
import type { GetStaticProps, NextPage } from 'next';
import Image from 'next/image';
import Link from 'next/link';
@ -11,7 +11,6 @@ import Testimony from '@/components/landing/Testimony';
import Footer from '@/components/shared/Footer';
import LanguageSwitcher from '@/components/shared/LanguageSwitcher';
import Logo from '@/components/shared/Logo';
import NoSSR from '@/components/shared/NoSSR';
import { screenshots } from '@/config/screenshots';
import { FLAG_DISABLE_SIGNUPS } from '@/constants/flags';
import testimonials from '@/data/testimonials';
@ -59,7 +58,7 @@ const Home: NextPage = () => {
<h2>{t<string>('common.subtitle')}</h2>
<NoSSR>
<NoSsr>
<div className={styles.buttonWrapper}>
{isLoggedIn ? (
<>
@ -81,7 +80,7 @@ const Home: NextPage = () => {
</>
)}
</div>
</NoSSR>
</NoSsr>
</div>
</div>

View File

@ -0,0 +1,29 @@
{
"avatar": {
"menu": {
"greeting": "Γειά σου",
"logout": "Αποσύνδεση"
}
},
"footer": {
"credit": "Ένα έργο με πάθος από τον <1>Amruth Pillai</1>",
"license": "Από την κοινότητα, για την κοινότητα."
},
"markdown": {
"help-text": "Αυτή η ενότητα υποστηρίζει τη μορφοποίηση <1>markdown</1>."
},
"date": {
"present": "Τώρα"
},
"subtitle": "Ένας δωρεάν κατασκευαστής βιογραφικών σημειωμάτων ανοικτού κώδικα.",
"title": "Reactive Resume",
"toast": {
"error": {
"upload-file-size": "Παρακαλούμε ανεβάζετε μόνο αρχεία κάτω των 2 megabytes.",
"upload-photo-size": "Παρακαλούμε ανεβάστε μόνο φωτογραφίες κάτω των 2 megabytes, κατά προτίμηση τετράγωνες."
},
"success": {
"resume-link-copied": "Ένας σύνδεσμος για το βιογραφικό σας αντιγράφηκε."
}
}
}

View File

@ -0,0 +1,25 @@
{
"create-resume": {
"subtitle": "Επανεκκίνηση από την αρχή",
"title": "Δημιουργία νέου βιογραφικού"
},
"import-external": {
"subtitle": "LinkedIn, JSON Resume, Reactive Resume",
"title": "Εισαγωγή από εξωτερικές πηγές"
},
"resume": {
"menu": {
"delete": "Διαγραφή",
"duplicate": "Διπλότυπο",
"open": "Άνοιγμα",
"rename": "Μετονομασία",
"share-link": "Κοινοποίηση συνδέσμου",
"tooltips": {
"delete": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το βιογραφικό; Αυτή είναι μια μη αναστρέψιμη ενέργεια.",
"share-link": "Πρέπει να αλλάξετε την ορατότητα του βιογραφικού σας σε δημόσιο για να το κάνετε ορατό σε άλλους."
}
},
"timestamp": "Τελευταία ενημέρωση πριν από {{timestamp}}"
},
"title": "Πίνακας ελέγχου"
}

View File

@ -0,0 +1,41 @@
{
"actions": {
"app": "Μετάβαση στην εφαρμογή",
"login": "Σύνδεση",
"logout": "Αποσύνδεση",
"register": "Εγγραφή"
},
"features": {
"heading": "Δυνατότητες",
"list": {
"ads": "Χωρίς διαφημίσεις",
"export": "Εξαγωγή του βιογραφικού σας σε μορφή JSON ή PDF",
"free": "Δωρεάν για πάντα",
"import": "Εισαγωγή δεδομένων από το LinkedIn, JSON Resume",
"languages": "Προσβάσιμο σε πολλές γλώσσες",
"more": "Και πολλά άλλα συναρπαστικά χαρακτηριστικά, <1>διαβάστε τα όλα εδώ</1>",
"tracking": "Χωρίς παρακολούθηση χρήστη"
}
},
"links": {
"heading": "Σύνδεσμοι",
"links": {
"donate": "Δωρεά",
"github": "Πηγαίος Κώδικας",
"privacy": "Πολιτική Απορρήτου",
"service": "Όρους παροχής υπηρεσιών"
}
},
"screenshots": {
"heading": "Στιγμιότυπα οθόνης"
},
"testimonials": {
"heading": "Αναφορές",
"body": "Καλή ή κακή, θα ήθελα πολύ να ακούσω τη γνώμη σας για το Reactive Resume και πώς ήταν η εμπειρία σας.<br/>Ακολουθούν μερικά από τα μηνύματα που έστειλαν χρήστες από όλο τον κόσμο.",
"contact": "Μπορείτε να επικοινωνήσετε μαζί μου μέσω <1>του email μου</1> ή μέσω της φόρμας επικοινωνίας στην <3>ιστοσελίδα μου</3>."
},
"summary": {
"body": "Το Reactive Resume είναι ένας δωρεάν κατασκευαστής βιογραφικών σημειωμάτων ανοικτού κώδικα που έχει δημιουργηθεί για να κάνει τις καθημερινές εργασίες δημιουργίας, ενημέρωσης και κοινοποίησης του βιογραφικού σας σημειώματος τόσο εύκολες όσο το 1, 2, 3. Με αυτή την εφαρμογή, μπορείτε να δημιουργήσετε πολλαπλά βιογραφικά, να τα μοιραστείτε με τους υπεύθυνους προσλήψεων ή τους φίλους σας μέσω ενός μοναδικού συνδέσμου και να τα εκτυπώσετε σε μορφή PDF, και όλα αυτά δωρεάν, χωρίς διαφημίσεις, χωρίς παρακολούθηση, χωρίς να χάσετε την ακεραιότητα και το απόρρητο των δεδομένων σας.",
"heading": "Σύνοψη"
}
}

View File

@ -0,0 +1,136 @@
{
"auth": {
"forgot-password": {
"actions": {
"send-email": "Αποστολή email επαναφοράς κωδικού πρόσβασης"
},
"body": "Απλώς εισάγετε τη διεύθυνση ηλεκτρονικού ταχυδρομείου που σχετίζεται με τον λογαριασμό που θέλετε να ανακτήσετε.",
"form": {
"email": {
"label": "Διεύθυνση Email"
}
},
"heading": "Ξεχάσατε τον κωδικό σας;",
"help-text": "Εάν ο λογαριασμός υπάρχει, θα λάβετε ένα email με έναν σύνδεσμο για να επαναφέρετε τον κωδικό πρόσβασής σας."
},
"login": {
"actions": {
"login": "Σύνδεση",
"google": "Συνδεθείτε με το Google"
},
"body": "Εισαγάγετε το όνομα χρήστη και τον κωδικό πρόσβασης που σχετίζονται με τον λογαριασμό σας για να συνδεθείτε και να αποκτήσετε πρόσβαση, να διαχειριστείτε και να μοιραστείτε τα βιογραφικά σας.",
"form": {
"password": {
"label": "Κωδικός πρόσβασης"
},
"username": {
"help-text": "Μπορείτε επίσης να εισάγετε τη διεύθυνση email σας",
"label": "Όνομα χρήστη"
}
},
"heading": "Συνδεθείτε στο λογαριασμό σας",
"recover-text": "Σε περίπτωση που έχετε ξεχάσει τον κωδικό πρόσβασής σας, μπορείτε να <1>ανακτήσετε τον λογαριασμό σας</1> εδώ.",
"register-text": "Αν δεν έχετε, μπορείτε να <1>δημιουργήσετε έναν λογαριασμό</1> εδώ."
},
"register": {
"actions": {
"register": "Εγγραφή",
"google": "Εγγραφή με το Google"
},
"body": "Εισαγάγετε τα προσωπικά σας στοιχεία για να δημιουργήσετε έναν λογαριασμό.",
"form": {
"confirm-password": {
"label": "Επιβεβαίωση Κωδικού Πρόσβασης"
},
"email": {
"label": "Διεύθυνση ηλεκτρονικού ταχυδρομείου"
},
"name": {
"label": "Ονοματεπώνυμο"
},
"password": {
"label": "Κωδικός πρόσβασης"
},
"username": {
"label": "Όνομα χρήστη"
}
},
"heading": "Δημιουργία λογαριασμού",
"loginText": "Αν έχετε ήδη λογαριασμό, μπορείτε να <1>συνδεθείτε εδώ</1>."
},
"reset-password": {
"actions": {
"set-password": "Ορισμός νέου κωδικού πρόσβασης"
},
"body": "Εισάγετε έναν νέο κωδικό πρόσβασης για το λογαριασμό σας.",
"form": {
"confirm-password": {
"label": "Επιβεβαίωση κωδικού πρόσβασης"
},
"password": {
"label": "Κωδικός πρόσβασης"
}
},
"heading": "Επαναφορά του κωδικού πρόσβασής σας"
}
},
"dashboard": {
"create-resume": {
"actions": {
"create-resume": "Δημιουργία βιογραφικού σημειώματος"
},
"body": "Ξεκινήστε να δημιουργείτε το βιογραφικό σας δίνοντάς του ένα όνομα. Θα μπορούσε να αναφέρεται στον ρόλο για τον οποίο κάνετε αίτηση ή απλώς στο αγαπημένο σας σνακ.",
"form": {
"name": {
"label": "Όνομα"
},
"public": {
"label": "Είναι δημόσια προσβάσιμο;"
},
"slug": {
"label": "Slug"
}
},
"heading": "Δημιουργία νέου βιογραφικού σημειώματος"
},
"import-external": {
"heading": "Εισαγωγή από εξωτερικές πηγές",
"json-resume": {
"actions": {
"upload-json": "Μεταφόρτωση JSON"
},
"body": "Αν έχετε έτοιμο ένα <1>επικυρωμένο JSON Resume</1>, μπορείτε να το χρησιμοποιήσετε για να επιταχύνετε την ανάπτυξή σας στο Reactive Resume. Κάντε κλικ στο παρακάτω κουμπί και ανεβάστε ένα έγκυρο αρχείο JSON για να ξεκινήσετε.",
"heading": "Εισαγωγή από JSON Resume"
},
"linkedin": {
"actions": {
"upload-archive": "Ανεβάστε το αρχείο ZIP"
},
"body": "Μπορείτε να εξοικονομήσετε χρόνο εξάγοντας τα δεδομένα σας από το LinkedIn και χρησιμοποιώντας τα για αυτόματη συμπλήρωση πεδίων στο Reactive Resume. Μεταβείτε στην ενότητα <1>Απόρρητο δεδομένων</1> στο LinkedIn και ζητήστε ένα αρχείο των δεδομένων σας. Μόλις είναι διαθέσιμο, ανεβάστε το αρχείο ZIP παρακάτω.",
"heading": "Εισαγωγή από το LinkedIn"
},
"reactive-resume": {
"actions": {
"upload-json": "Μεταφόρτωση JSON",
"upload-json-v2": "Μεταφόρτωση JSON από v2"
},
"body": "Εάν έχετε ένα JSON που εξήχθη με την τρέχουσα έκδοση του Reactive Resume, μπορείτε να το εισάγετε ξανά εδώ για να λάβετε ξανά μια επεξεργάσιμη έκδοση.",
"heading": "Εισαγωγή από Reactive Resume"
}
},
"rename-resume": {
"actions": {
"rename-resume": "Μετονομασία βιογραφικού"
},
"form": {
"name": {
"label": "Ονομα"
},
"slug": {
"label": "Slug"
}
},
"heading": "Μετονομασία του βιογραφικού σας"
}
}
}

View File

@ -119,6 +119,9 @@
"name": {
"label": "Full Name"
},
"birthdate": {
"label": "Date of Birth"
},
"photo-filters": {
"effects": {
"border": {

View File

@ -0,0 +1,358 @@
{
"common": {
"actions": {
"add": "ନୂତନ {{token}} ଯୋଡ଼ନ୍ତୁ ।",
"delete": "{{token}} ଲିଭାନ୍ତୁ ।",
"edit": "{{token}} ସମ୍ପାଦନ କରନ୍ତୁ ।"
},
"columns": {
"heading": "ସ୍ତମ୍ଭଗୁଡିକ",
"tooltip": "ସ୍ତମ୍ଭ ସଂଖ୍ୟା ପରିବର୍ତ୍ତନ କରନ୍ତୁ ।"
},
"form": {
"date": {
"label": "ତାରିଖ"
},
"description": {
"label": "ବର୍ଣ୍ଣନା"
},
"email": {
"label": "ଇମେଲ ଠିକଣା"
},
"end-date": {
"help-text": "ଯଦି ଉପସ୍ଥିତ ଅଛି ତେବେ ଏହି କ୍ଷେତ୍ରକୁ ଖାଲି ଛାଡିଦିଅନ୍ତୁ ।",
"label": "ଶେଷ ତାରିଖ"
},
"keywords": {
"label": "କୀୱାର୍ଡ଼"
},
"level": {
"label": "ସ୍ତର"
},
"levelNum": {
"label": "ସ୍ତର (ସଂଖ୍ୟା)"
},
"name": {
"label": "ନାମ"
},
"phone": {
"label": "ଫୋନ୍ ନମ୍ବର"
},
"position": {
"label": "ଅବସ୍ଥାନ"
},
"start-date": {
"label": "ଆରମ୍ଭ ତାରିଖ"
},
"subtitle": {
"label": "ସବଟାଇଟଲ"
},
"summary": {
"label": "ସାରାଂଶ"
},
"title": {
"label": "ଆଖ୍ୟା"
},
"url": {
"label": "ୱେବସାଇଟ୍"
}
},
"glossary": {
"page": "ପୃଷ୍ଠା"
},
"list": {
"actions": {
"delete": "ବିଲୋପ କରନ୍ତୁ",
"duplicate": "ନକଲ",
"edit": "ସମ୍ପାଦନ କରନ୍ତୁ"
},
"empty-text": "ଏହି ତାଲିକା ଖାଲି ଅଛି ।"
},
"tooltip": {
"delete-item": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ଏହି ଆଇଟମ୍ ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି? ଏହା ଏକ ଅପରିବର୍ତ୍ତନୀୟ କାର୍ଯ୍ୟ ।",
"delete-section": "ବିଭାଗ ବିଲୋପ କରନ୍ତୁ ।",
"rename-section": "ବିଭାଗର ନାମ ପରିବର୍ତ୍ତନ କରନ୍ତୁ ।",
"toggle-visibility": "ଭିଜିବିଲିଟି ଟଗଲ କରନ୍ତୁ ।"
}
},
"controller": {
"tooltip": {
"center-artboard": "କେନ୍ଦ୍ର ଆର୍ଟବୋର୍ଡ",
"copy-link": "ଜାରିରଖିବାକୁ ପାଇଁ ଲିଙ୍କ୍ କପି କରନ୍ତୁ ।",
"export-pdf": "PDF ରପ୍ତାନି କରନ୍ତୁ",
"toggle-orientation": "ପୃଷ୍ଠା ଓରିଏଣ୍ଟେସନ୍ ଟଗଲ କରନ୍ତୁ ।",
"toggle-page-break-line": "ପୃଷ୍ଠା ବ୍ରେକ୍ ଲାଇନ୍ ଟଗଲ କରନ୍ତୁ ।",
"toggle-sidebars": "ସାଇଡ୍ ବାର ଟଗଲ କରନ୍ତୁ ।",
"zoom-in": "ଜୁମ୍ ଇନ୍ କରନ୍ତୁ ।",
"zoom-out": "ଜୁମ୍ ଆଉଟ୍ କରନ୍ତୁ ।"
}
},
"header": {
"menu": {
"delete": "ବିଲୋପ କରନ୍ତୁ",
"duplicate": "ନକଲ",
"rename": "ନାମ ବଦଳାନ୍ତୁ",
"share-link": "ଲିଙ୍କ୍ ଅଂଶୀଦାର କରନ୍ତୁ ।",
"tooltips": {
"delete": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ଏହି ଆଇଟମ୍ ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି? ଏହା ଏକ ଅପରିବର୍ତ୍ତନୀୟ କାର୍ଯ୍ୟ ।",
"share-link": "ଏହାକୁ ଅନ୍ୟମାନଙ୍କ ପାଇଁ ଦୃଶ୍ୟମାନ କରିବା ପାଇଁ ଆପଣଙ୍କର ରେଜ୍ୟୁମର ଦୃଶ୍ୟତାକୁ ସର୍ବସାଧାରଣରେ ପରିବର୍ତ୍ତନ କରିବାକୁ ପଡିବ ।"
}
}
},
"leftSidebar": {
"sections": {
"awards": {
"form": {
"awarder": {
"label": "ପୁରସ୍କାରଦାତା"
}
}
},
"basics": {
"actions": {
"photo-filters": "ଫଟୋ ଫିଲ୍ଟର୍"
},
"heading": "ମୌଳିକ",
"headline": {
"label": "ଶୀର୍ଷକ"
},
"name": {
"label": "ପୁରା ନାମ"
},
"photo-filters": {
"effects": {
"border": {
"label": "ବର୍ଡର"
},
"grayscale": {
"label": "ଗ୍ରେସ୍କେଲ୍‌"
},
"heading": "ପ୍ରଭାବଗୁଡ଼ିକ"
},
"shape": {
"heading": "ଆକୃତି"
},
"size": {
"heading": "ଆକାର (px ରେ)"
}
},
"photo-upload": {
"tooltip": {
"remove": "ଫଟୋ ହଟାନ୍ତୁ",
"upload": "ଫୋଟୋ ଅପଲୋଡ କରନ୍ତୁ"
}
}
},
"certifications": {
"form": {
"issuer": {
"label": "ପ୍ରଦାନକାରୀ"
}
}
},
"education": {
"form": {
"area-study": {
"label": "ଅଧ୍ୟୟନର କ୍ଷେତ୍ର"
},
"courses": {
"label": "ପାଠ୍ୟକ୍ରମ"
},
"degree": {
"label": "ଡିଗ୍ରୀ"
},
"grade": {
"label": "ଗ୍ରେଡ୍"
},
"institution": {
"label": "ସଂସ୍ଥା"
}
}
},
"location": {
"address": {
"label": "ଠିକଣା"
},
"city": {
"label": "ସହର"
},
"country": {
"label": "ଦେଶ"
},
"heading": "ଅବସ୍ଥାନ",
"postal-code": {
"label": "ଡାକ କୋଡ୍"
},
"region": {
"label": "ଅଞ୍ଚଳ"
}
},
"profiles": {
"form": {
"network": {
"label": "ନେଟୱର୍କ"
},
"username": {
"label": "ଉପଯୋଗକର୍ତ୍ତା ନାମ"
}
},
"heading": "ପ୍ରୋଫାଇଲ୍ ଗୁଡ଼ିକ",
"heading_one": "ପ୍ରୋଫାଇଲ୍"
},
"publications": {
"form": {
"publisher": {
"label": "ପ୍ରକାଶକ"
}
}
},
"references": {
"form": {
"relationship": {
"label": "ସମ୍ପର୍କ"
}
}
},
"section": {
"heading": "ବିଭାଗ"
},
"volunteer": {
"form": {
"organization": {
"label": "ସଙ୍ଗଠନ"
}
}
}
}
},
"rightSidebar": {
"sections": {
"css": {
"heading": "କଷ୍ଟମ୍ CSS"
},
"export": {
"heading": "ରପ୍ତାନି କରନ୍ତୁ",
"json": {
"primary": "JSON",
"secondary": "ତୁମର ରିଜ୍ୟୁମର ଏକ JSON ସଂସ୍କରଣ ଡାଉନଲୋଡ୍ କର ଯାହାକି Reactive Resume କୁ ଆମଦାନୀ ହୋଇପାରିବ ।"
},
"pdf": {
"loading": {
"primary": "PDF ସୃଷ୍ଟି କରୁଛି",
"secondary": "ଆପଣଙ୍କର PDF ସୃଷ୍ଟି ହେଉଛି ଦୟାକରି ଅପେକ୍ଷା କରନ୍ତୁ, ଏହା ୧୫ ସେକେଣ୍ଡ ପର୍ଯ୍ୟନ୍ତ ସମୟ ନେଇପାରେ ।"
},
"normal": {
"primary": "PDF",
"secondary": "ଆପଣଙ୍କର ରିଜ୍ୟୁମର ଏକ PDF ଡାଉନଲୋଡ୍ କରନ୍ତୁ ଯାହାକୁ ଆପଣ ଆପଣଙ୍କର ପ୍ରିୟ ନିଯୁକ୍ତିଦାତାଙ୍କୁ ପ୍ରିଣ୍ଟ କରି ପଠାଇ ପାରିବେ । ପରବର୍ତ୍ତୀ ସମ୍ପାଦନା ପାଇଁ ଏହି ଫାଇଲ୍ ପୁନର୍ବାର ଆମଦାନୀ ହୋଇପାରିବ ନାହିଁ ।"
}
}
},
"layout": {
"heading": "ଲେଆଉଟ୍‌",
"tooltip": {
"reset-layout": "ଲେଆଉଟ୍ ରିସେଟ୍ କରନ୍ତୁ"
}
},
"links": {
"bugs-features": {
"body": "ଏକ ରିଜ୍ୟୁମ୍ ତିଆରି କରିବାରେ ଆପଣଙ୍କୁ କିଛି ବାଧା ଦେଉଛି କି? କିମ୍ବା ଯୋଡିବାକୁ ଆପଣଙ୍କର ଏକ ଆଶ୍ଚର୍ଯ୍ୟଜନକ ଧାରଣା ଅଛି କି? ଆରମ୍ଭ କରିବା ପାଇଁ GitHub ରେ ଏକ ସମସ୍ୟା ଉଠାନ୍ତୁ ।",
"button": "GitHub ସମସ୍ୟା",
"heading": "ତ୍ରୁଟି? ବୈଶିଷ୍ଟ୍ୟ ଅନୁରୋଧ?"
},
"donate": {
"body": "ଯଦି ଆପଣ Reactive Resume ବ୍ୟବହାର କରିବାକୁ ପସନ୍ଦ କରନ୍ତି, ଦୟାକରି ବିଜ୍ଞାପନ ବିନା ଏବଂ ସବୁଦିନ ପାଇଁ ମାଗଣା ଆପ୍ କୁ ଚାଲୁରଖିବା ପାଇଁ ଆପଣ ଯେତେ ସମ୍ଭବ ଦାନ କରିବାକୁ ଚିନ୍ତା କରନ୍ତୁ ।",
"button": "ମୋତେ ଏକ କଫି କିଣନ୍ତୁ",
"heading": "Reactive Resume ପାଇଁ ଦାନ କରନ୍ତୁ ।"
},
"github": "ଉତ୍ସ କୋଡ୍",
"heading": "ଲିଙ୍କ୍"
},
"settings": {
"global": {
"date": {
"primary": "ତାରିଖ",
"secondary": "ଆପ୍ ରେ ବ୍ୟବହାର କରିବାକୁ ତାରିଖ ଫର୍ମାଟ୍"
},
"heading": "ଗ୍ଲୋବାଲ୍",
"language": {
"primary": "ଭାଷା",
"secondary": "ଆପ୍ ରେ ବ୍ୟବହାର କରିବାକୁ ଭାଷା ପ୍ରଦର୍ଶନ କରନ୍ତୁ"
},
"theme": {
"primary": "ଥିମ୍"
}
},
"heading": "ସେଟିଂସ୍",
"page": {
"break-line": {
"primary": "ବ୍ରେକ୍ ଲାଇନ୍",
"secondary": "A4 ପୃଷ୍ଠାର ଉଚ୍ଚତା ଚିହ୍ନିତ କରିବାକୁ ସମସ୍ତ ପୃଷ୍ଠାରେ ଏକ ରେଖା ଦେଖାନ୍ତୁ ।"
},
"heading": "ପୃଷ୍ଠା",
"orientation": {
"disabled": "କେବଳ ଗୋଟିଏ ପୃଷ୍ଠା ଥିବାବେଳେ ଏହାର କୌଣସି ପ୍ରଭାବ ନାହିଁ ।",
"primary": "ଓରିଏଣ୍ଟେସନ୍",
"secondary": "ପୃଷ୍ଠାଗୁଡ଼ିକ ଭୂସମାନ୍ତର କିମ୍ବା ଭୂଲମ୍ବ ଭାବରେ ପ୍ରଦର୍ଶିତ ହେବ କି ନାହିଁ ।"
}
},
"resume": {
"heading": "ରେଜ୍ୟୁମ",
"reset": {
"primary": "ସବୁକିଛି ରିସେଟ୍ କରନ୍ତୁ ।",
"secondary": "ବହୁତ ଭୁଲ୍ କରିଛନ୍ତି କି? ସମସ୍ତ ପରିବର୍ତ୍ତନକୁ ରିସେଟ୍ କରିବାକୁ ଏବଂ ଆରମ୍ଭରୁ ଆରମ୍ଭ କରିବାକୁ ଏଠାରେ କ୍ଲିକ୍ କରନ୍ତୁ । ସାବଧାନ ରୁହନ୍ତୁ, ଏହି କାର୍ଯ୍ୟଟି ଅପରିବର୍ତ୍ତନୀୟ ।"
},
"sample": {
"primary": "ନମୁନା ତଥ୍ୟ ଲୋଡ୍ କରନ୍ତୁ ।",
"secondary": "କେଉଁଠାରୁ ଆରମ୍ଭ କରିବେ ନିଶ୍ଚିତ ନୁହଁନ୍ତି? ଏକ ସଂପୂର୍ଣ୍ଣ ରିଜ୍ୟୁମ୍ କିପରି ଦେଖାଯାଉଛି ଦେଖିବା ପାଇଁ କିଛି ନମୁନା ତଥ୍ୟ ଲୋଡ୍ କରିବାକୁ ଏଠାରେ କ୍ଲିକ୍ କରନ୍ତୁ ।"
}
}
},
"sharing": {
"heading": "ଅଂଶୀଦାର",
"short-url": {
"label": "ସଂକ୍ଷିପ୍ତ URL କୁ ପସନ୍ଦ କରନ୍ତୁ ।"
},
"visibility": {
"subtitle": "ଆପଣଙ୍କର ରିଜ୍ୟୁମ୍ ଦେଖିବାକୁ ଲିଙ୍କ୍ ଥିବା କାହାକୁ ଅନୁମତି ଦିଅନ୍ତୁ ।",
"title": "ଜନସାଧାରଣ"
}
},
"templates": {
"heading": "ଟେମ୍ପଲେଟ୍"
},
"theme": {
"form": {
"background": {
"label": "ପୃଷ୍ଠଭୂମି"
},
"primary": {
"label": "ପ୍ରାଥମିକ"
},
"text": {
"label": "ଟେକ୍ସଟ"
}
},
"heading": "ଥିମ୍"
},
"typography": {
"form": {
"font-family": {
"label": "ଫଣ୍ଟ ପରିବାର"
},
"font-size": {
"label": "ଫଣ୍ଟ ଆକାର"
}
},
"heading": "ଟାଇପୋଗ୍ରାଫି",
"widgets": {
"body": {
"label": "ଶରୀର"
},
"headings": {
"label": "ଶିରୋନାମା"
}
}
}
}
}
}

View File

@ -0,0 +1,29 @@
{
"avatar": {
"menu": {
"greeting": "ନମସ୍କାର",
"logout": "ଲଗ ଆଉଟ"
}
},
"footer": {
"credit": "<1> ଅମୃତ ପିଲ୍ଲାଇ</1> ଦ୍ୱାରା ଏକ ଉତ୍ସାହ ପ୍ରୋଜେକ୍ଟ ।",
"license": "ସମ୍ପ୍ରଦାୟ ଦ୍ୱାରା, ସମ୍ପ୍ରଦାୟ ପାଇଁ ।"
},
"markdown": {
"help-text": "ଏହି ବିଭାଗ <1> ମାର୍କଡାଉନ୍ </1> ଫର୍ମାଟିଂକୁ ସମର୍ଥନ କରେ"
},
"date": {
"present": "ବର୍ତ୍ତମାନ"
},
"subtitle": "ଏକ ମାଗଣା ଏବଂ ମୁକ୍ତ ଉତ୍ସ ପୁନଃନିର୍ମାଣକାରୀ ।",
"title": "ଋଆକ୍ଟିଭ ରେଜ୍ୟୁମ",
"toast": {
"error": {
"upload-file-size": "ଦୟାକରି କେବଳ 2 ମେଗାବାଇଟ୍ ରୁ କମ ଆକାରର ଫାଇଲ୍ ଅପଲୋଡ୍ କରନ୍ତୁ ।",
"upload-photo-size": "ଦୟାକରି କେବଳ ମେଗାବାଇଟ୍ ତଳେ ଫଟୋ ଅପଲୋଡ୍ କରନ୍ତୁ ।"
},
"success": {
"resume-link-copied": "ତୁମର ରିଜ୍ୟୁମର ଏକ ଲିଙ୍କ୍ ତୁମର କ୍ଲିପବୋର୍ଡରେ କପି କରାଯାଇଛି ।"
}
}
}

View File

@ -0,0 +1,25 @@
{
"create-resume": {
"subtitle": "ଆରମ୍ଭରୁ ଆରମ୍ଭ କରନ୍ତୁ",
"title": "ନୂତନ ରିଜ୍ୟୁମ୍ ସୃଷ୍ଟି କରନ୍ତୁ"
},
"import-external": {
"subtitle": "LinkedIn, JSON Resume, Reactive Resume",
"title": "ବାହ୍ୟ ଉତ୍ସରୁ ଆମଦାନୀ କରନ୍ତୁ"
},
"resume": {
"menu": {
"delete": "ବିଲୋପ କରନ୍ତୁ",
"duplicate": "ନକଲ",
"open": "ଖୋଲନ୍ତୁ",
"rename": "ନାମ ବଦଳାନ୍ତୁ",
"share-link": "ଲିଙ୍କ୍ ଶେୟର କରନ୍ତୁ",
"tooltips": {
"delete": "ଆପଣ ନିଶ୍ଚିତ କି ଆପଣ ଏହି ଆଇଟମ୍ ଡିଲିଟ୍ କରିବାକୁ ଚାହୁଁଛନ୍ତି? ଏହା ଏକ ଅପରିବର୍ତ୍ତନୀୟ କାର୍ଯ୍ୟ ।",
"share-link": "ଏହାକୁ ଅନ୍ୟମାନଙ୍କ ପାଇଁ ଦୃଶ୍ୟମାନ କରିବା ପାଇଁ ଆପଣଙ୍କର ରେଜ୍ୟୁମର ଦୃଶ୍ୟତାକୁ ସର୍ବସାଧାରଣରେ ପରିବର୍ତ୍ତନ କରିବାକୁ ପଡିବ ।"
}
},
"timestamp": "{{timestamp}} ପୂର୍ବରୁ ଶେଷ ଅଦ୍ୟତନ ହୋଇଛି"
},
"title": "ଡ୍ୟାସବୋର୍ଡ"
}

View File

@ -0,0 +1,41 @@
{
"actions": {
"app": "ଆପ୍ କୁ ଯାଆନ୍ତୁ",
"login": "ଲଗ ଇନ",
"logout": "ଲଗ ଆଉଟ",
"register": "ପଞ୍ଜୀକରଣ କରନ୍ତୁ"
},
"features": {
"heading": "ବୈଶିଷ୍ଟ୍ୟଗୁଡ଼ିକ",
"list": {
"ads": "କୌଣସି ବିଜ୍ଞାପନ ନାହିଁ",
"export": "ତୁମର ରିଜ୍ୟୁମ୍ JSON କିମ୍ବା PDF ଫର୍ମାଟକୁ ରପ୍ତାନି କରନ୍ତୁ",
"free": "ମାଗଣା, ସବୁଦିନ ପାଇଁ",
"import": "LinkedIn, JSON Resume ରୁ ତଥ୍ୟ ଆମଦାନୀ କରନ୍ତୁ",
"languages": "ଏକାଧିକ ଭାଷାରେ ଉପଲବ୍ଧ",
"more": "ଏବଂ ଅଧିକ ରୋମାଞ୍ଚକର ବୈଶିଷ୍ଟ୍ୟଗୁଡିକ, <1>ଏଠାରେ ସମସ୍ତ ବିଷୟରେ ପଢ଼ନ୍ତୁ</1>",
"tracking": "କୌଣସି ଉପଭୋକ୍ତା ଟ୍ରାକିଂ ନାହିଁ"
}
},
"links": {
"heading": "ଲିଙ୍କ୍",
"links": {
"donate": "ଦାନ କରନ୍ତୁ",
"github": "ଉତ୍ସ କୋଡ୍",
"privacy": "ଗୋପନୀୟତା ନୀତି",
"service": "ସେବା ସର୍ତ୍ତାବଳୀ"
}
},
"screenshots": {
"heading": "ସ୍କ୍ରିନସଟ୍"
},
"testimonials": {
"heading": "ପ୍ରଶଂସାପତ୍ର",
"body": "ଭଲ କି ଖରାପ, ମୁଁ ରିଆକ୍ଟିଭ୍ ରିଜ୍ୟୁମ୍ ଉପରେ ଆପଣଙ୍କ ମତାମତ ଶୁଣିବାକୁ ପସନ୍ଦ କରିବି ଏବଂ ଆପଣଙ୍କ ପାଇଁ ଅଭିଜ୍ଞତା କିପରି ହୋଇଛି । <br/>ସମଗ୍ର ବିଶ୍ୱରେ ଉପଭୋକ୍ତାମାନଙ୍କ ଦ୍ୱାରା ପଠାଯାଇଥିବା କିଛି ବାର୍ତ୍ତା ଏଠାରେ ଅଛି ।",
"contact": "ତୁମେ <1>ମୋ ଇମେଲ</1> ମାଧ୍ୟମରେ ମୋ ପାଖରେ ପହଞ୍ଚିପାରିବ । କିମ୍ବା <3> ମୋ ୱେବସାଇଟ୍</3> ର ଯୋଗାଯୋଗ ଫର୍ମ ମାଧ୍ୟମରେ ।"
},
"summary": {
"body": "ରିଆକ୍ଟିଭ୍ ରିଜ୍ୟୁମ୍ ହେଉଛି ଏକ ମାଗଣା ଏବଂ ଓପନ ସୋର୍ସ ରିଜ୍ୟୁମ୍ ବିଲଡର୍ ଯାହା ଆପଣଙ୍କର ରିଜ୍ୟୁମ୍ ସୃଷ୍ଟି କରିବା, ଅପଡେଟ୍ କରିବା ଏବଂ ଅଂଶୀଦାର କରିବାର ସାଧାରଣ କାର୍ଯ୍ୟକୁ ୧, , ୩ ଭଳି ସହଜ କରିବା ପାଇଁ ନିର୍ମିତ, ଏହି ଆପ୍ ସହିତ, ଆପଣ ଏକାଧିକ ରିଜ୍ୟୁମ୍ ସୃଷ୍ଟି କରିପାରିବେ, ନିଯୁକ୍ତିକାରୀ କିମ୍ବା ସାଙ୍ଗମାନଙ୍କ ସହିତ ଅଂଶୀଦାର କରିପାରିବେ । ଆପଣଙ୍କର ତଥ୍ୟର ଅଖଣ୍ଡତା ଏବଂ ଗୋପନୀୟତା ନହରାଇ ଏକ ଅନନ୍ୟ ଲିଙ୍କ୍ ମାଧ୍ୟମରେ, ଏହାକୁ ଏକ PDF ଭାବରେ ମୁଦ୍ରଣ କରନ୍ତୁ, ସମସ୍ତ ମାଗଣାରେ, ବିନା ବିଜ୍ଞାପନ ବା ଉପଭୋକ୍ତା ଟ୍ରାକିଂରେ ।",
"heading": "ସାରାଂଶ"
}
}

View File

@ -0,0 +1,136 @@
{
"auth": {
"forgot-password": {
"actions": {
"send-email": "ପାସୱାର୍ଡ଼ ରିସେଟ ଇମେଲ ପଠାନ୍ତୁ"
},
"body": "ଆପଣ ପୁନରୁଦ୍ଧାର କରିବାକୁ ଚାହୁଁଥିବା ଖାତା ସହିତ ଜଡିତ ଇମେଲ ଠିକଣା ପ୍ରବେଶ କରନ୍ତୁ ।",
"form": {
"email": {
"label": "ଇମେଲ ଠିକଣା"
}
},
"heading": "ପାସୱାର୍ଡ଼ ଭୁଲି ଯାଇଛନ୍ତି?",
"help-text": "ଯଦି ଖାତା ବିଦ୍ୟମାନ ଅଛି, ଆପଣଙ୍କର ପାସୱାର୍ଡ ରିସେଟ୍ କରିବାକୁ ଏକ ଲିଙ୍କ୍ ସହିତ ଏକ ଇମେଲ୍ ପାଇବେ ।"
},
"login": {
"actions": {
"login": "ଲଗ ଇନ",
"google": "ଗୁଗୁଲ୍ ସହିତ ଲଗ୍ଇନ୍ କରନ୍ତୁ"
},
"body": "ଲଗ୍ଇନ୍ ଏବଂ ଆକ୍ସେସ୍, ପରିଚାଳନା ଏବଂ ଅଂଶୀଦାର କରିବା ପାଇଁ ଦୟାକରି ଆପଣଙ୍କର ଖାତା ସହିତ ଜଡିତ ଆପଣଙ୍କର ଉପଯୋଗକର୍ତ୍ତା ନାମ ଏବଂ ପାସୱାର୍ଡ ପ୍ରବେଶ କରନ୍ତୁ ।",
"form": {
"password": {
"label": "ପାସ୍‍ୱାର୍ଡ଼"
},
"username": {
"help-text": "ଆପଣ ଆପଣଙ୍କର ଇମେଲ୍ ଠିକଣା ମଧ୍ୟ ପ୍ରବେଶ କରିପାରିବେ ।",
"label": "ଉପଯୋଗକର୍ତ୍ତା ନାମ"
}
},
"heading": "ଆପଣଙ୍କ ଖାତାକୁ ଲଗ୍ଇନ୍ କରନ୍ତୁ ।",
"recover-text": "ଯଦି ଆପଣ ଆପଣଙ୍କର ପାସୱାର୍ଡ ଭୁଲି ଯାଇଛନ୍ତି, ଆପଣ ଆପଣଙ୍କର ଖାତାକୁ <1>ପୁନରୁଦ୍ଧାର କରିପାରିବେ </1> ଏଠାରେ ।",
"register-text": "ଯଦି ଆପଣଙ୍କର ପାଖରେ ନାହିଁ, ଆପଣ <1> ଏକ ଖାତା ସୃଷ୍ଟି କରିପାରିବେ </1> ଏଠାରେ"
},
"register": {
"actions": {
"register": "ପଞ୍ଜୀକରଣ କରନ୍ତୁ",
"google": "ଗୁଗୁଲ୍ ସହିତ ପଞ୍ଜୀକରଣ କରନ୍ତୁ"
},
"body": "ଏକ ଖାତା ସୃଷ୍ଟି କରିବାକୁ ଦୟାକରି ଆପଣଙ୍କର ବ୍ୟକ୍ତିଗତ ସୂଚନା ପ୍ରବେଶ କରନ୍ତୁ ।",
"form": {
"confirm-password": {
"label": "ପାସୱାର୍ଡ଼ ନିଶ୍ଚିତ କରନ୍ତୁ"
},
"email": {
"label": "ଇମେଲ ଠିକଣା"
},
"name": {
"label": "ପୁରା ନାମ"
},
"password": {
"label": "ପାସ୍‍ୱାର୍ଡ଼"
},
"username": {
"label": "ଉପଯୋଗକର୍ତ୍ତା ନାମ"
}
},
"heading": "ଏକ ଆକାଉଣ୍ଟ ସୃଷ୍ଟି କରନ୍ତୁ",
"loginText": "ଯଦି ଆପଣଙ୍କର ପୂର୍ବରୁ ଏକ ଖାତା ଅଛି, ଆପଣ ଏଠାରେ <1>ଲଗଇନ୍ କରିପାରିବେ</1> ।"
},
"reset-password": {
"actions": {
"set-password": "ଏକ ନୂତନ ପାସୱାର୍ଡ୍ ସେଟ୍‍ କରନ୍ତୁ"
},
"body": "ଆପଣଙ୍କ ଖାତା ପାଇଁ ଏକ ନୂତନ ପାସୱାର୍ଡ ପ୍ରବେଶ କରନ୍ତୁ ।",
"form": {
"confirm-password": {
"label": "ପାସୱାର୍ଡ଼ ନିଶ୍ଚିତ କରନ୍ତୁ"
},
"password": {
"label": "ପାସ୍‍ୱାର୍ଡ଼"
}
},
"heading": "ଆପଣଙ୍କ ପାସୱାର୍ଡ ରିସେଟ୍ କରନ୍ତୁ"
}
},
"dashboard": {
"create-resume": {
"actions": {
"create-resume": "ନୂତନ ରିଜ୍ୟୁମ୍ ସୃଷ୍ଟି କରନ୍ତୁ"
},
"body": "ଏହାକୁ ଏକ ନାମ ଦେଇ ଆପଣଙ୍କର ରିଜ୍ୟୁମ୍ ନିର୍ମାଣ ଆରମ୍ଭ କରନ୍ତୁ । ଆପଣ ଯେଉଁ ଭୂମିକା ପାଇଁ ଆବେଦନ କରୁଛନ୍ତି, କିମ୍ବା କେବଳ ଆପଣଙ୍କର ପ୍ରିୟ ସ୍ନାକ୍ସ ବିଷୟରେ ଏହା ସୂଚିତ ହୋଇପାରେ ।",
"form": {
"name": {
"label": "ନାମ"
},
"public": {
"label": "ସର୍ବସାଧାରଣରେ ଉପଲବ୍ଧ କି?"
},
"slug": {
"label": "ସ୍ଲଗ୍"
}
},
"heading": "ନୂତନ ରିଜ୍ୟୁମ୍ ସୃଷ୍ଟି କରନ୍ତୁ"
},
"import-external": {
"heading": "ବାହ୍ୟ ଉତ୍ସରୁ ଆମଦାନୀ କରନ୍ତୁ",
"json-resume": {
"actions": {
"upload-json": "JSON ଅପଲୋଡ୍ କରନ୍ତୁ ।"
},
"body": "ଯଦି ଆପଣଙ୍କର ଏକ <1> ବୈଧ JSON ରିଜ୍ୟୁମ୍ ଅଛି |</1> ଯିବାକୁ ପ୍ରସ୍ତୁତ, ଆପଣ ଏହାକୁ Reactive Resume ରେ ଆପଣଙ୍କର ବିକାଶକୁ ଫାଷ୍ଟ-ଟ୍ରାକ୍ କରିବାକୁ ବ୍ୟବହାର କରିପାରିବେ । ନିମ୍ନରେ ବଟନ୍ କ୍ଲିକ୍ କରନ୍ତୁ ଏବଂ ଆରମ୍ଭ କରିବାକୁ ଏକ ବୈଧ JSON ଫାଇଲ୍ ଅପଲୋଡ୍ କରନ୍ତୁ ।",
"heading": "JSON Resume ରୁ ଆମଦାନୀ କରନ୍ତୁ"
},
"linkedin": {
"actions": {
"upload-archive": "ZIP ଅଭିଲେଖାଗାର ଅପଲୋଡ୍ କରନ୍ତୁ ।"
},
"body": "LinkedInରୁ ଆପଣଙ୍କର ତଥ୍ୟ ରପ୍ତାନି କରି ଏହାକୁ Reactive Resume ରେ ଅଟୋ-ଫିଲ୍ ଫିଲ୍ଡରେ ବ୍ୟବହାର କରି ଆପଣ ସମୟ ସଞ୍ଚୟ କରିପାରିବେ । <1> ଡାଟା ଗୋପନୀୟତାକୁ ଯାଆନ୍ତୁ</1> LinkedIn ରେ ବିଭାଗ ଏବଂ ଆପଣଙ୍କର ତଥ୍ୟର ଏକ ଅଭିଲେଖାଗାର ପାଇଁ ଅନୁରୋଧ । ଏହା ଉପଲବ୍ଧ ହେବା ପରେ, ନିମ୍ନରେ ZIP ଫାଇଲ୍ ଅପଲୋଡ୍ କରନ୍ତୁ ।",
"heading": "LinkedIn ରୁ ଆମଦାନୀ କରନ୍ତୁ ।"
},
"reactive-resume": {
"actions": {
"upload-json": "JSON ଅପଲୋଡ୍ କରନ୍ତୁ ।",
"upload-json-v2": "V2 ରୁ JSON ଅପଲୋଡ୍ କରନ୍ତୁ ।"
},
"body": "ଯଦି ଆପଣଙ୍କର ଏକ JSON ଅଛି ଯାହା Reactive Resume ର ସାମ୍ପ୍ରତିକ ସଂସ୍କରଣ ସହିତ ରପ୍ତାନି ହୋଇଛି, ଆପଣ ପୁନର୍ବାର ଏକ ସମ୍ପାଦିତ ସଂସ୍କରଣ ପାଇବାକୁ ଏହାକୁ ଏଠାରେ ଆମଦାନି କରିପାରିବେ ।",
"heading": "Reactive Resume ରୁ ଆମଦାନୀ କରନ୍ତୁ"
}
},
"rename-resume": {
"actions": {
"rename-resume": "ରେଜ୍ୟୁମ ନାମ ବଦଳାନ୍ତୁ"
},
"form": {
"name": {
"label": "ନାମ"
},
"slug": {
"label": "ସ୍ଲଗ୍"
}
},
"heading": "ଆପଣଙ୍କର ରେଜ୍ୟୁମ ନାମ ବଦଳାନ୍ତୁ"
}
}
}

View File

@ -0,0 +1,358 @@
{
"common": {
"actions": {
"add": "Lägg till {{token}}",
"delete": "Ta bort {{token}}",
"edit": "Redigera {{token}}"
},
"columns": {
"heading": "Kolumner",
"tooltip": "Ändra antalet kolumner"
},
"form": {
"date": {
"label": "Datum"
},
"description": {
"label": "Beskrivning"
},
"email": {
"label": "E-postadress"
},
"end-date": {
"help-text": "Lämna fältet blankt, om fortfarande aktuellt",
"label": "Slutdatum"
},
"keywords": {
"label": "Nyckelord"
},
"level": {
"label": "Nivå"
},
"levelNum": {
"label": "Nivå (siffror)"
},
"name": {
"label": "Namn"
},
"phone": {
"label": "Telefonnummer"
},
"position": {
"label": "Position"
},
"start-date": {
"label": "Startdatum"
},
"subtitle": {
"label": "Undertitel"
},
"summary": {
"label": "Sammanfattning"
},
"title": {
"label": "Titel"
},
"url": {
"label": "Webbplats"
}
},
"glossary": {
"page": "Sida"
},
"list": {
"actions": {
"delete": "Ta bort",
"duplicate": "Duplicera",
"edit": "Redigera"
},
"empty-text": "Denna lista är tom."
},
"tooltip": {
"delete-item": "Är du säker på att du vill ta bort det här objektet? Detta är en oåterkallelig handling.",
"delete-section": "Ta bort avsnitt",
"rename-section": "Döp om avsnitt",
"toggle-visibility": "Visa/dölj"
}
},
"controller": {
"tooltip": {
"center-artboard": "Centrera Artboard",
"copy-link": "Kopiera länken till CV:et",
"export-pdf": "Exportera som PDF",
"toggle-orientation": "Byt sidans orientering",
"toggle-page-break-line": "Visa/dölj Sidbrytningslinjer",
"toggle-sidebars": "Visa/dölj Sidpanelen",
"zoom-in": "Zooma in",
"zoom-out": "Zooma Ut"
}
},
"header": {
"menu": {
"delete": "Ta bort",
"duplicate": "Duplicera",
"rename": "Ändra Namn",
"share-link": "Dela länk",
"tooltips": {
"delete": "Är du säker du vill ta bort detta CV? Detta går ej att ångra.",
"share-link": "Du måste ändra synligheten av ditt CV till offentligt för att göra det synligt för andra."
}
}
},
"leftSidebar": {
"sections": {
"awards": {
"form": {
"awarder": {
"label": "Utmärkelser"
}
}
},
"basics": {
"actions": {
"photo-filters": "Fotofilter"
},
"heading": "Grunder",
"headline": {
"label": "Rubrik"
},
"name": {
"label": "Fullständigt namn"
},
"photo-filters": {
"effects": {
"border": {
"label": "Kant"
},
"grayscale": {
"label": "Gråskala"
},
"heading": "Effekter"
},
"shape": {
"heading": "Form"
},
"size": {
"heading": "Storlek (i pixlar)"
}
},
"photo-upload": {
"tooltip": {
"remove": "Ta bort bild",
"upload": "Ladda upp bild"
}
}
},
"certifications": {
"form": {
"issuer": {
"label": "Utgivare"
}
}
},
"education": {
"form": {
"area-study": {
"label": "Studieinriktning"
},
"courses": {
"label": "Kurser"
},
"degree": {
"label": "Examen"
},
"grade": {
"label": "Betyg"
},
"institution": {
"label": "Institution"
}
}
},
"location": {
"address": {
"label": "Adress"
},
"city": {
"label": "Ort"
},
"country": {
"label": "Land"
},
"heading": "Plats",
"postal-code": {
"label": "Postnummer"
},
"region": {
"label": "Län"
}
},
"profiles": {
"form": {
"network": {
"label": "Nätverk"
},
"username": {
"label": "Användarnamn"
}
},
"heading": "Profiler",
"heading_one": "Profil"
},
"publications": {
"form": {
"publisher": {
"label": "Utgivare"
}
}
},
"references": {
"form": {
"relationship": {
"label": "Relation"
}
}
},
"section": {
"heading": "Sektion"
},
"volunteer": {
"form": {
"organization": {
"label": "Organisation"
}
}
}
}
},
"rightSidebar": {
"sections": {
"css": {
"heading": "Anpassad CSS"
},
"export": {
"heading": "Exportera",
"json": {
"primary": "JSON",
"secondary": "Ladda ner en JSON-version av ditt CV som kan importeras tillbaka till Reactive Resume."
},
"pdf": {
"loading": {
"primary": "Genererar PDF",
"secondary": "Vänligen vänta medans din PDF genereras, detta kan ta upp till 15 sekunder."
},
"normal": {
"primary": "PDF",
"secondary": "Ladda ner en PDF av ditt CV som du kan skriva ut och skicka till ditt drömjobb. Den här filen kan inte importeras tillbaka för ytterligare redigering."
}
}
},
"layout": {
"heading": "Layout",
"tooltip": {
"reset-layout": "Återställ layout"
}
},
"links": {
"bugs-features": {
"body": "Något som hindrar dig från att göra ett CV? Eller har du en fantastisk idé att lägga till? Starta en issue på GitHub för att komma igång.",
"button": "GitHub Issues",
"heading": "Buggar? Funktionsförslag?"
},
"donate": {
"body": "Om du gillade att använda Reactive Resume, överväg att donera så mycket som möjligt för att hålla appen igång utan annonser och gratis för alltid.",
"button": "Köp mig en kaffe",
"heading": "Donera till Reactive Resume"
},
"github": "Källkod",
"heading": "Länkar"
},
"settings": {
"global": {
"date": {
"primary": "Datum",
"secondary": "Datumformat som ska användas i hela appen"
},
"heading": "Globalt",
"language": {
"primary": "Språk",
"secondary": "Visa det språk som ska användas i hela appen"
},
"theme": {
"primary": "Tema"
}
},
"heading": "Inställningar",
"page": {
"break-line": {
"primary": "Radbrytning",
"secondary": "Visa en linje på alla sidor för att markera höjden på en A4-sida"
},
"heading": "Sida",
"orientation": {
"disabled": "Har ingen effekt när det bara finns en sida",
"primary": "Orientering",
"secondary": "Om sidor ska visas horisontellt eller vertikalt"
}
},
"resume": {
"heading": "CV",
"reset": {
"primary": "Återställ allt",
"secondary": "Har du gjort för många misstag? Klicka här för att återställa alla ändringar och börja om från början. Var försiktig, den här åtgärden kan inte återställas."
},
"sample": {
"primary": "Läs in exempeldata",
"secondary": "Vet du inte var du ska börja? Klicka här för att ladda några exempel för att se hur ett komplett CV ser ut."
}
}
},
"sharing": {
"heading": "Delning",
"short-url": {
"label": "Föredra kort URL"
},
"visibility": {
"subtitle": "Tillåt alla med en länk att se ditt CV",
"title": "Publik"
}
},
"templates": {
"heading": "Mallar"
},
"theme": {
"form": {
"background": {
"label": "Bakgrund"
},
"primary": {
"label": "Primär"
},
"text": {
"label": "Text"
}
},
"heading": "Tema"
},
"typography": {
"form": {
"font-family": {
"label": "Typsnittsfamilj"
},
"font-size": {
"label": "Textstorlek"
}
},
"heading": "Typografi",
"widgets": {
"body": {
"label": "Innehåll"
},
"headings": {
"label": "Rubriker"
}
}
}
}
}
}

View File

@ -0,0 +1,29 @@
{
"avatar": {
"menu": {
"greeting": "Hej",
"logout": "Logga ut"
}
},
"footer": {
"credit": "Ett passionsprojekt av <1>Amruth Pillai</1>",
"license": "Av communityn, för communityn."
},
"markdown": {
"help-text": "Det här avsnittet stöder <1>markdown</1> formatering."
},
"date": {
"present": "Nuvarande"
},
"subtitle": "En CV byggare som är kostnadsfri och under öppen källkod.",
"title": "Reactive Resume",
"toast": {
"error": {
"upload-file-size": "Vänligen ladda endast upp filer under 2 megabyte.",
"upload-photo-size": "Vänligen ladda endast upp bilder under 2 megabyte, helst kvadratiska."
},
"success": {
"resume-link-copied": "En länk till ditt CV har kopierats till ditt urklipp."
}
}
}

View File

@ -0,0 +1,25 @@
{
"create-resume": {
"subtitle": "Börja från grunden",
"title": "Skapa nytt CV"
},
"import-external": {
"subtitle": "LinkedIn, JSON CV, Reactive Resume",
"title": "Importera från externa källor"
},
"resume": {
"menu": {
"delete": "Ta bort",
"duplicate": "Duplicera",
"open": "Öppna",
"rename": "Ändra Namn",
"share-link": "Dela länk",
"tooltips": {
"delete": "Är du säker du vill ta bort detta CV? Detta går ej att ångra.",
"share-link": "Du måste ändra synligheten av ditt CV till offentligt för att göra det synligt för andra."
}
},
"timestamp": "Senast uppdaterad {{timestamp}}"
},
"title": "Dashboard"
}

View File

@ -0,0 +1,41 @@
{
"actions": {
"app": "Till appen",
"login": "Logga in",
"logout": "Logga ut",
"register": "Registrera"
},
"features": {
"heading": "Funktioner",
"list": {
"ads": "Ingen reklam",
"export": "Exportera ditt CV till JSON- eller PDF-format",
"free": "Gratis för alltid",
"import": "Importera data från LinkedIn, JSON CV",
"languages": "Tillgänglig på flera språk",
"more": "Och många fler spännande funktioner, <1>läs allt om det här</1>",
"tracking": "Ingen spårning av användare"
}
},
"links": {
"heading": "Länkar",
"links": {
"donate": "Donera",
"github": "Källkod",
"privacy": "Sekretesspolicy",
"service": "Användarvillkor"
}
},
"screenshots": {
"heading": "Skärmdumpar"
},
"testimonials": {
"heading": "Rekommendationer",
"body": "Bra eller dåligt, jag skulle älska att höra din åsikt om Reactive Resume och hur upplevelsen har varit för dig.<br/>Här är några av de meddelanden som skickas in av användare över hela världen.",
"contact": "Du kan nå mig via <1>min e-post</1> eller genom kontaktformuläret på <3>min hemsida</3> ."
},
"summary": {
"body": "Reactive Resume är en gratis och öppen källkodsbyggare för CV som är gjord för att göra de vardagliga uppgifterna som att skapa, uppdatera och dela ditt CV så enkelt som 1, 2, 3. Med den här appen kan du skapa flera CV, dela dem med rekryterare eller vänner genom en unik länk och skriva ut den som en PDF, helt gratis, inga annonser, ingen spårning och utan att förlora integriteten för dina data.",
"heading": "Sammanfattning"
}
}

View File

@ -0,0 +1,136 @@
{
"auth": {
"forgot-password": {
"actions": {
"send-email": "Skicka e-post för återställning av lösenord"
},
"body": "Ange bara e-postadressen som är kopplad till kontot du vill återställa.",
"form": {
"email": {
"label": "E-postadress"
}
},
"heading": "Glömt ditt lösenord?",
"help-text": "Om kontot finns får du ett e-postmeddelande med en länk för att återställa ditt lösenord."
},
"login": {
"actions": {
"login": "Logga in",
"google": "Logga in med Google"
},
"body": "Vänligen ange ditt användarnamn och lösenord som är kopplat till ditt konto för att logga in och komma åt, hantera och dela dina CV.",
"form": {
"password": {
"label": "Lösenord"
},
"username": {
"help-text": "Du kan också ange din e-postadress",
"label": "Användarnamn"
}
},
"heading": "Logga in på ditt konto",
"recover-text": "Om du har glömt ditt lösenord kan du <1>återställa ditt konto</1> här.",
"register-text": "Om du inte har ett kan du <1>skapa ett konto</1> här."
},
"register": {
"actions": {
"register": "Registrera",
"google": "Registrera dig med Google"
},
"body": "Ange dina personliga uppgifter för att skapa ett konto.",
"form": {
"confirm-password": {
"label": "Bekräfta lösenord"
},
"email": {
"label": "E-postadress"
},
"name": {
"label": "Fullständigt namn"
},
"password": {
"label": "Lösenord"
},
"username": {
"label": "Användarnamn"
}
},
"heading": "Skapa ett konto",
"loginText": "Om du redan har ett konto kan du <1>logga in här</1> ."
},
"reset-password": {
"actions": {
"set-password": "Ange nytt lösenord"
},
"body": "Ange ett nytt lösenord för ditt konto.",
"form": {
"confirm-password": {
"label": "Bekräfta lösenord"
},
"password": {
"label": "Lösenord"
}
},
"heading": "Återställ ditt lösenord"
}
},
"dashboard": {
"create-resume": {
"actions": {
"create-resume": "Skapa CV"
},
"body": "Börja bygga ditt CV genom att ge det ett namn. Det kan vara med hänvisning till rollen du söker, eller bara ditt favoritmellanmål.",
"form": {
"name": {
"label": "Namn"
},
"public": {
"label": "Är allmänt tillgängligt?"
},
"slug": {
"label": "Permalänk"
}
},
"heading": "Skapa ett nytt CV"
},
"import-external": {
"heading": "Importera från externa källor",
"json-resume": {
"actions": {
"upload-json": "Ladda upp JSON"
},
"body": "Om du har ett <1>validerat JSON CV</1> redo att användas, kan du använda det för att snabba upp din utveckling på Reactive Resume. Klicka på knappen nedan och ladda upp en giltig JSON-fil för att börja.",
"heading": "Importera från JSON CV"
},
"linkedin": {
"actions": {
"upload-archive": "Ladda upp ZIP-arkiv"
},
"body": "Du kan spara tid genom att exportera dina uppgifter från LinkedIn och använda dem för att automatiskt fylla i fälten i Reactive Resume. Gå till avsnittet <1>Dataintegritet</1> på LinkedIn och begär ett arkiv av dina uppgifter. När det är tillgängligt laddar du upp ZIP-filen nedan.",
"heading": "Importera från LinkedIn"
},
"reactive-resume": {
"actions": {
"upload-json": "Ladda upp JSON",
"upload-json-v2": "Ladda upp JSON från v2"
},
"body": "Om du har en JSON som exporterades med den aktuella versionen av Reactive Resume, kan du importera den tillbaka hit för att få en redigerbar version igen.",
"heading": "Importera från Reactive Resume"
}
},
"rename-resume": {
"actions": {
"rename-resume": "Byt namn på CV"
},
"form": {
"name": {
"label": "Namn"
},
"slug": {
"label": "Permalänk"
}
},
"heading": "Byt namn på ditt CV"
}
}
}

View File

@ -1,43 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url><loc>https://rxresu.me</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/meta/privacy</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/meta/service</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/ar/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/bn/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/da/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/de/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/es/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/fr/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/hi/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/it/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/kn/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.972Z</lastmod></url>
<url><loc>https://rxresu.me/ml/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/nl/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/pl/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/pt/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/ru/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/ta/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/tr/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/vi/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/zh/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/ar</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/bn</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/da</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/de</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/es</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/fr</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/hi</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/it</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/kn</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/ml</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/nl</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/pl</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/pt</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/ru</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/ta</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/tr</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/vi</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me/zh</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-08T08:32:21.973Z</lastmod></url>
<url><loc>https://rxresu.me</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/meta/privacy</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/meta/service</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/ar/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/bn/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/da/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/de/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/es/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/fr/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/hi/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/it/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/kn/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/ml/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/nl/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/pl/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/pt/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/ru/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/ta/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/tr/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/vi/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/zh/dashboard</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/ar</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/bn</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/da</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/de</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/es</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/fr</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/hi</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/it</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/kn</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/ml</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/nl</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/pl</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/pt</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/ru</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/ta</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/tr</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/vi</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
<url><loc>https://rxresu.me/zh</loc><changefreq>monthly</changefreq><priority>0.7</priority><lastmod>2022-04-30T10:56:16.825Z</lastmod></url>
</urlset>

View File

@ -13,7 +13,7 @@ export type LoginParams = {
};
export type LoginWithGoogleParams = {
accessToken: string;
credential: string;
};
export type RegisterParams = {

View File

@ -1,4 +1,4 @@
import _axios, { AxiosError } from 'axios';
import _axios from 'axios';
import Router from 'next/router';
import { logout } from '@/store/auth/authSlice';
@ -27,7 +27,7 @@ axios.interceptors.request.use((config) => {
axios.interceptors.response.use(
(response) => response,
(error: AxiosError) => {
(error) => {
const { response } = error;
if (response) {

View File

@ -5,7 +5,7 @@ import { useMemo } from 'react';
import { useAppSelector } from '@/store/hooks';
const Heading: React.FC = ({ children }) => {
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const theme: Theme = useAppSelector((state) => get(state.resume, 'metadata.theme', {}));
const darkerPrimary = useMemo(() => darken(theme.primary, 0.2), [theme.primary]);

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css';
import { Email, Phone, Public, Room } from '@mui/icons-material';
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
import { Theme } from '@reactive-resume/schema';
import clsx from 'clsx';
import get from 'lodash/get';
@ -9,12 +9,14 @@ import { useMemo } from 'react';
import Markdown from '@/components/shared/Markdown';
import { useAppSelector } from '@/store/hooks';
import DataDisplay from '@/templates/shared/DataDisplay';
import { formatDateString } from '@/utils/date';
import getProfileIcon from '@/utils/getProfileIcon';
import { getContrastColor } from '@/utils/styles';
import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
export const MastheadSidebar: React.FC = () => {
const { name, headline, photo, email, phone, website, location, profiles } = useAppSelector(
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.basics
);
const theme: Theme = useAppSelector((state) => get(state.resume, 'metadata.theme', {}));
@ -43,6 +45,10 @@ export const MastheadSidebar: React.FC = () => {
{formatLocation(location)}
</DataDisplay>
<DataDisplay icon={<Cake />} className="!gap-2 text-xs">
{formatDateString(birthdate, dateFormat)}
</DataDisplay>
<DataDisplay icon={<Email />} className="!gap-2 text-xs" link={`mailto:${email}`}>
{email}
</DataDisplay>

View File

@ -3,7 +3,7 @@ import get from 'lodash/get';
import { useAppSelector } from '@/store/hooks';
const Heading: React.FC = ({ children }) => {
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const theme: Theme = useAppSelector((state) => get(state.resume, 'metadata.theme', {}));
return (

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css';
import { Email, Phone, Public, Room } from '@mui/icons-material';
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
import { alpha } from '@mui/material';
import { Theme } from '@reactive-resume/schema';
import clsx from 'clsx';
@ -10,12 +10,14 @@ import { useMemo } from 'react';
import Markdown from '@/components/shared/Markdown';
import { useAppSelector } from '@/store/hooks';
import DataDisplay from '@/templates/shared/DataDisplay';
import { formatDateString } from '@/utils/date';
import getProfileIcon from '@/utils/getProfileIcon';
import { getContrastColor } from '@/utils/styles';
import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
export const MastheadSidebar: React.FC = () => {
const { name, headline, photo, email, phone, website, location, profiles } = useAppSelector(
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.basics
);
const theme: Theme = useAppSelector((state) => get(state.resume, 'metadata.theme', {}));
@ -44,6 +46,10 @@ export const MastheadSidebar: React.FC = () => {
{formatLocation(location)}
</DataDisplay>
<DataDisplay icon={<Cake />} className="!gap-2 text-xs">
{formatDateString(birthdate, dateFormat)}
</DataDisplay>
<DataDisplay icon={<Email />} className="!gap-2 text-xs" link={`mailto:${email}`}>
{email}
</DataDisplay>

View File

@ -3,7 +3,7 @@ import get from 'lodash/get';
import { useAppSelector } from '@/store/hooks';
const Heading: React.FC = ({ children }) => {
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const theme: Theme = useAppSelector((state) => get(state.resume, 'metadata.theme', {}));
return (

View File

@ -1,16 +1,18 @@
import { Email, Phone, Public, Room } from '@mui/icons-material';
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import Markdown from '@/components/shared/Markdown';
import { useAppSelector } from '@/store/hooks';
import DataDisplay from '@/templates/shared/DataDisplay';
import { formatDateString } from '@/utils/date';
import getProfileIcon from '@/utils/getProfileIcon';
import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
export const MastheadSidebar: React.FC = () => {
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const primaryColor: string = useAppSelector((state) => get(state.resume, 'metadata.theme.primary'));
const { name, headline, photo, email, phone, website, location, profiles } = useAppSelector(
const { name, headline, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.basics
);
@ -36,6 +38,10 @@ export const MastheadSidebar: React.FC = () => {
{formatLocation(location)}
</DataDisplay>
<DataDisplay icon={<Cake />} className="text-xs">
{formatDateString(birthdate, dateFormat)}
</DataDisplay>
<DataDisplay icon={<Email />} className="text-xs" link={`mailto:${email}`}>
{email}
</DataDisplay>

View File

@ -1,4 +1,4 @@
const Heading: React.FC = ({ children }) => {
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
return <h3 className="my-2 inline-block border-b px-5 pb-2">{children}</h3>;
};

View File

@ -1,14 +1,17 @@
import { Email, Phone, Public, Room } from '@mui/icons-material';
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import React from 'react';
import { useAppSelector } from '@/store/hooks';
import DataDisplay from '@/templates/shared/DataDisplay';
import { formatDateString } from '@/utils/date';
import getProfileIcon from '@/utils/getProfileIcon';
import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
const Masthead = () => {
const { name, photo, email, phone, website, headline, location, profiles } = useAppSelector(
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const { name, photo, email, phone, website, birthdate, headline, location, profiles } = useAppSelector(
(state) => state.resume.basics
);
@ -32,6 +35,8 @@ const Masthead = () => {
</div>
<div className="flex flex-wrap justify-center gap-3">
<DataDisplay icon={<Cake />}>{formatDateString(birthdate, dateFormat)}</DataDisplay>
<DataDisplay icon={<Email />} link={`mailto:${email}`}>
{email}
</DataDisplay>

View File

@ -1,5 +1,3 @@
.page {}
.container {
@apply grid grid-cols-2 gap-8 px-6 py-4;

View File

@ -3,7 +3,7 @@ import get from 'lodash/get';
import { useAppSelector } from '@/store/hooks';
const Heading: React.FC = ({ children }) => {
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const theme: Theme = useAppSelector((state) => get(state.resume, 'metadata.theme', {}));
return (

View File

@ -1,4 +1,4 @@
import { Email, Phone, Public, Room } from '@mui/icons-material';
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
import { alpha } from '@mui/material';
import { Theme } from '@reactive-resume/schema';
import get from 'lodash/get';
@ -6,11 +6,13 @@ import isEmpty from 'lodash/isEmpty';
import { useAppSelector } from '@/store/hooks';
import DataDisplay from '@/templates/shared/DataDisplay';
import { formatDateString } from '@/utils/date';
import getProfileIcon from '@/utils/getProfileIcon';
import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
const Masthead: React.FC = () => {
const { name, photo, headline, summary, email, phone, website, location, profiles } = useAppSelector(
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const { name, photo, headline, summary, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.basics
);
const theme: Theme = useAppSelector((state) => get(state.resume, 'metadata.theme', {}));
@ -48,6 +50,12 @@ const Masthead: React.FC = () => {
id="Masterhead_data"
style={{ backgroundColor: alpha(theme.primary, 0.4), gridTemplateColumns: `repeat(2, minmax(0, 1fr))` }}
>
<DataDisplay icon={<Room />} className="col-span-2">
{formatLocation(location)}
</DataDisplay>
<DataDisplay icon={<Cake />}>{formatDateString(birthdate, dateFormat)}</DataDisplay>
<DataDisplay icon={<Email />} link={`mailto:${email}`}>
{email}
</DataDisplay>
@ -60,8 +68,6 @@ const Masthead: React.FC = () => {
{website}
</DataDisplay>
<DataDisplay icon={<Room />}>{formatLocation(location)}</DataDisplay>
{profiles.map(({ id, username, network, url }) => (
<DataDisplay key={id} icon={getProfileIcon(network)} link={url && addHttp(url)}>
{username}

View File

@ -3,7 +3,7 @@ import get from 'lodash/get';
import { useAppSelector } from '@/store/hooks';
const Heading: React.FC = ({ children }) => {
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const theme: Theme = useAppSelector((state) => get(state.resume, 'metadata.theme', {}));
return (

View File

@ -1,13 +1,16 @@
import { Email, Phone, Public, Room } from '@mui/icons-material';
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import { useAppSelector } from '@/store/hooks';
import DataDisplay from '@/templates/shared/DataDisplay';
import { formatDateString } from '@/utils/date';
import getProfileIcon from '@/utils/getProfileIcon';
import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
const Masthead: React.FC = () => {
const { name, photo, email, phone, website, headline, location, profiles } = useAppSelector(
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const { name, photo, email, phone, website, birthdate, headline, location, profiles } = useAppSelector(
(state) => state.resume.basics
);
@ -33,6 +36,10 @@ const Masthead: React.FC = () => {
</DataDisplay>
<div className="flex items-center gap-2">
<DataDisplay icon={<Cake />} className="text-xs">
{formatDateString(birthdate, dateFormat)}
</DataDisplay>
<DataDisplay icon={<Email />} className="text-xs" link={`mailto:${email}`}>
{email}
</DataDisplay>

View File

@ -3,7 +3,7 @@ import get from 'lodash/get';
import { useAppSelector } from '@/store/hooks';
const Heading: React.FC = ({ children }) => {
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const theme: Theme = useAppSelector((state) => get(state.resume, 'metadata.theme', {}));
return (

View File

@ -1,4 +1,4 @@
import { Email, Phone, Public, Room } from '@mui/icons-material';
import { Cake, Email, Phone, Public, Room } from '@mui/icons-material';
import { Theme } from '@reactive-resume/schema';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
@ -7,12 +7,16 @@ import { useMemo } from 'react';
import Markdown from '@/components/shared/Markdown';
import { useAppSelector } from '@/store/hooks';
import DataDisplay from '@/templates/shared/DataDisplay';
import { formatDateString } from '@/utils/date';
import getProfileIcon from '@/utils/getProfileIcon';
import { getContrastColor } from '@/utils/styles';
import { addHttp, formatLocation, getPhotoClassNames } from '@/utils/template';
export const MastheadSidebar: React.FC = () => {
const { name, photo, email, phone, website, location, profiles } = useAppSelector((state) => state.resume.basics);
const dateFormat: string = useAppSelector((state) => get(state.resume, 'metadata.date.format'));
const { name, photo, email, phone, birthdate, website, location, profiles } = useAppSelector(
(state) => state.resume.basics
);
return (
<div className="col-span-2 grid justify-items-left gap-4">
@ -31,6 +35,10 @@ export const MastheadSidebar: React.FC = () => {
{formatLocation(location)}
</DataDisplay>
<DataDisplay icon={<Cake />} className="text-xs">
{formatDateString(birthdate, dateFormat)}
</DataDisplay>
<DataDisplay icon={<Email />} className="text-xs" link={`mailto:${email}`}>
{email}
</DataDisplay>

View File

@ -7,7 +7,7 @@ type Props = {
className?: string;
};
const DataDisplay: React.FC<Props> = ({ icon, link, className, children }) => {
const DataDisplay: React.FC<React.PropsWithChildren<Props>> = ({ icon, link, className, children }) => {
if (isEmpty(children)) return null;
if (!isEmpty(link)) {

View File

@ -6,6 +6,7 @@ import {
FaFacebookF,
FaGithub,
FaGitlab,
FaHackerrank,
FaInstagram,
FaLinkedinIn,
FaSkype,
@ -16,20 +17,24 @@ import {
FaXing,
FaYoutube,
} from 'react-icons/fa';
import { SiCodechef, SiCodeforces } from 'react-icons/si';
const profileIconMap: Record<string, JSX.Element> = {
facebook: <FaFacebookF />,
twitter: <FaTwitter />,
linkedin: <FaLinkedinIn />,
dribbble: <FaDribbble />,
soundcloud: <FaSoundcloud />,
github: <FaGithub />,
instagram: <FaInstagram />,
stackoverflow: <FaStackOverflow />,
behance: <FaBehance />,
codechef: <SiCodechef />,
codeforces: <SiCodeforces />,
dribbble: <FaDribbble />,
facebook: <FaFacebookF />,
github: <FaGithub />,
gitlab: <FaGitlab />,
telegram: <FaTelegram />,
hackerrank: <FaHackerrank />,
instagram: <FaInstagram />,
linkedin: <FaLinkedinIn />,
skype: <FaSkype />,
soundcloud: <FaSoundcloud />,
stackoverflow: <FaStackOverflow />,
telegram: <FaTelegram />,
twitter: <FaTwitter />,
xing: <FaXing />,
youtube: <FaYoutube />,
};

View File

@ -3,7 +3,7 @@ import relativeTime from 'dayjs/plugin/relativeTime';
import { useRouter } from 'next/router';
import { useEffect } from 'react';
const DateWrapper: React.FC = ({ children }) => {
const DateWrapper: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const { locale } = useRouter();
useEffect(() => {
@ -12,8 +12,10 @@ const DateWrapper: React.FC = ({ children }) => {
// Locales
require('dayjs/locale/ar');
require('dayjs/locale/bn');
require('dayjs/locale/cs');
require('dayjs/locale/da');
require('dayjs/locale/de');
require('dayjs/locale/el');
require('dayjs/locale/en');
require('dayjs/locale/es');
require('dayjs/locale/fr');
@ -25,6 +27,7 @@ const DateWrapper: React.FC = ({ children }) => {
require('dayjs/locale/pl');
require('dayjs/locale/pt');
require('dayjs/locale/ru');
require('dayjs/locale/sv');
require('dayjs/locale/ta');
require('dayjs/locale/tr');
require('dayjs/locale/vi');

View File

@ -4,7 +4,7 @@ import { useCallback, useEffect } from 'react';
import { useAppSelector } from '@/store/hooks';
const FontWrapper: React.FC = ({ children }) => {
const FontWrapper: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const typography = useAppSelector((state) => get(state.resume, 'metadata.typography'));
const loadFonts = useCallback(async () => {

View File

@ -3,7 +3,7 @@ import { useHotkeys } from 'react-hotkeys-hook';
import { toggleSidebar } from '@/store/build/buildSlice';
import { useAppDispatch } from '@/store/hooks';
const HotkeysWrapper: React.FC = ({ children }) => {
const HotkeysWrapper: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const dispatch = useAppDispatch();
useHotkeys('ctrl+/, cmd+/', () => {

View File

@ -5,7 +5,7 @@ import { darkTheme, lightTheme } from '@/config/theme';
import { setTheme } from '@/store/build/buildSlice';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
const ThemeWrapper: React.FC = ({ children }) => {
const ThemeWrapper: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const dispatch = useAppDispatch();
const theme = useAppSelector((state) => state.build.theme);

View File

@ -3,7 +3,7 @@ import FontWrapper from './FontWrapper';
import HotkeysWrapper from './HotkeysWrapper';
import ThemeWrapper from './ThemeWrapper';
const WrapperRegistry: React.FC = ({ children }) => {
const WrapperRegistry: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
return (
<ThemeWrapper>
<FontWrapper>

View File

@ -47,19 +47,23 @@ You have complete control over what goes into your resume, how it looks, what co
- Arabic (اَلْعَرَبِيَّةُ)
- Bengali (বাংলা)
- Chinese (中文)
- Czech (čeština)
- Danish (Dansk)
- Dutch (Nederlands)
- English
- French (Français)
- German (Deutsch)
- Greek (Ελληνικά)
- Hindi (हिन्दी)
- Italian (Italiano)
- Kannada (ಕನ್ನಡ)
- Malayalam (മലയാളം)
- Odia (ଓଡ଼ିଆ)
- Polish (Polski)
- Portuguese (Português)
- Russian (русский)
- Spanish (Español)
- Swedish (Svenska)
- Tamil (தமிழ்)
- Turkish (Türkçe)
- Vietnamese (Tiếng Việt)

View File

@ -127,13 +127,15 @@ This field is only required if the Google Login functionality is important to yo
### `GOOGLE_API_KEY`
**Required**: `yes`
**Required**: `no`
**Description:** Google API Key used for fetching Google Fonts
Within the resume builder, there's a section where you can pick any font from the Google Fonts Library. To fetch the names and IDs of these fonts, we depend on the Google Fonts API. It does not cost any payment, or the need to enter credit card information to create or use this API.
You can get your own key here: https://developers.google.com/fonts/docs/developer_api
If you do not have a Google API Key, it was make use of the cached response JSON that's stored within the project source. Please note that this cache is not updated and may not have all the latest fonts that Google Fonts has to offer.
## SendGrid
The server makes use of SendGrid to send the password reset email to those who have forgotten their password. **This section is completely optional for those who do not require this functionality.**

View File

@ -17,11 +17,11 @@
"@algolia/client-search": "^4.13.0",
"@docusaurus/core": "2.0.0-beta.18",
"@docusaurus/preset-classic": "2.0.0-beta.18",
"@mdx-js/react": "^2.1.1",
"@mdx-js/react": "1.6.22",
"clsx": "^1.1.1",
"prism-react-renderer": "^1.3.1",
"react": "<18",
"react-dom": "<18"
"react": "17.0.2",
"react-dom": "17.0.2"
},
"browserslist": {
"production": [
@ -36,6 +36,6 @@
]
},
"devDependencies": {
"@types/react": "<18"
"@types/react": "17.0.2"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "reactive-resume",
"version": "3.3.4",
"version": "3.4.1",
"private": true,
"workspaces": [
"schema",
@ -38,10 +38,10 @@
"env-cmd": "^10.1.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.18.0",
"@typescript-eslint/parser": "^5.18.0",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.12.0",
"eslint": "^8.14.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.0.0",
@ -50,6 +50,6 @@
"husky": "^7.0.4",
"prettier": "^2.6.2",
"standard-version": "^9.3.2",
"typescript": "<4.6.0"
"typescript": "^4.6.4"
}
}

2389
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
"lint": "eslint --fix --ext .ts ./src"
},
"devDependencies": {
"eslint": "^8.12.0",
"typescript": "<4.6.0"
"eslint": "^8.14.0",
"typescript": "^4.6.4"
}
}

View File

@ -35,6 +35,7 @@ export type Basics = {
phone: string;
website: string;
headline: string;
birthdate: string;
summary: string;
location: Location;
profiles: Profile[];

View File

@ -1,4 +1,4 @@
FROM node:17-alpine as dependencies
FROM node:lts-alpine as dependencies
RUN apk add --no-cache g++ curl make python3 \
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
@ -11,7 +11,7 @@ COPY ./server/package.json ./server/package.json
RUN pnpm install --frozen-lockfile
FROM node:17-alpine as builder
FROM node:lts-alpine as builder
RUN apk add --no-cache g++ curl make python3 \
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm

View File

@ -10,7 +10,7 @@
"lint": "eslint --fix --ext .ts ./src"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.67.0",
"@aws-sdk/client-s3": "^3.81.0",
"@nestjs/axios": "^0.0.7",
"@nestjs/common": "^8.4.4",
"@nestjs/config": "^2.0.0",
@ -31,23 +31,23 @@
"class-validator": "^0.13.2",
"cookie-parser": "^1.4.6",
"csvtojson": "^2.0.10",
"dayjs": "^1.11.0",
"googleapis": "^100.0.0",
"dayjs": "^1.11.1",
"google-auth-library": "^8.0.2",
"joi": "^17.6.0",
"lodash": "^4.17.21",
"multer": "^1.4.4",
"nanoid": "^3.3.2",
"nanoid": "^3.3.3",
"node-stream-zip": "^1.15.0",
"passport": "^0.5.2",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"pdf-lib": "^1.17.1",
"pg": "^8.7.3",
"playwright-chromium": "^1.20.2",
"playwright-chromium": "^1.21.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.5.5",
"typeorm": "^0.2.34",
"typeorm": "0.2.45",
"uuid": "^8.3.2"
},
"devDependencies": {
@ -55,17 +55,17 @@
"@nestjs/schematics": "^8.0.10",
"@reactive-resume/schema": "workspace:*",
"@types/bcrypt": "^5.0.0",
"@types/cookie-parser": "^1.4.2",
"@types/cookie-parser": "^1.4.3",
"@types/express": "^4.17.13",
"@types/multer": "^1.4.7",
"@types/node": "^17.0.23",
"eslint": "^8.12.0",
"@types/node": "^17.0.30",
"eslint": "^8.14.0",
"prettier": "^2.6.2",
"source-map-support": "^0.5.21",
"ts-loader": "^9.2.8",
"ts-loader": "^9.2.9",
"ts-node": "^10.7.0",
"tsconfig-paths": "^3.14.1",
"typescript": "<4.6.0",
"typescript": "^4.6.4",
"webpack": "^5.72.0"
}
}

View File

@ -21,8 +21,8 @@ export class AuthController {
}
@Post('google')
async loginWithGoogle(@Body('accessToken') googleAccessToken: string) {
const user = await this.authService.authenticateWithGoogle(googleAccessToken);
async loginWithGoogle(@Body('credential') credential: string) {
const user = await this.authService.authenticateWithGoogle(credential);
const accessToken = this.authService.getAccessToken(user.id);
return { user, accessToken };

View File

@ -4,7 +4,7 @@ import { JwtService } from '@nestjs/jwt';
import { SchedulerRegistry } from '@nestjs/schedule';
import bcrypt from 'bcrypt';
import { randomInt } from 'crypto';
import { google } from 'googleapis';
import { OAuth2Client } from 'google-auth-library';
import { PostgresErrorCode } from '@/database/errorCodes.enum';
import { CreateGoogleUserDto } from '@/users/dto/create-google-user.dto';
@ -107,17 +107,16 @@ export class AuthService {
return this.usersService.findById(payload.id);
}
async authenticateWithGoogle(googleAccessToken: string) {
async authenticateWithGoogle(credential: string) {
const clientID = this.configService.get<string>('google.clientID');
const clientSecret = this.configService.get<string>('google.clientSecret');
const OAuthClient = new google.auth.OAuth2(clientID, clientSecret);
OAuthClient.setCredentials({ access_token: googleAccessToken });
const { email } = await OAuthClient.getTokenInfo(googleAccessToken);
const OAuthClient = new OAuth2Client(clientID, clientSecret);
const client = await OAuthClient.verifyIdToken({ idToken: credential });
const userPayload = client.getPayload();
try {
const user = await this.usersService.findByEmail(email);
const user = await this.usersService.findByEmail(userPayload.email);
return user;
} catch (error: any) {
@ -125,14 +124,12 @@ export class AuthService {
throw new HttpException(error, HttpStatus.BAD_GATEWAY);
}
const UserInfoClient = google.oauth2('v2').userinfo;
const { data } = await UserInfoClient.get({ auth: OAuthClient });
const username = data.email.split('@')[0];
const username = userPayload.email.split('@')[0];
const createUserDto: CreateGoogleUserDto = {
name: `${data.given_name} ${data.family_name}`,
name: `${userPayload.given_name} ${userPayload.family_name}`,
username,
email: data.email,
email: userPayload.email,
provider: 'google',
};

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@ import { Font } from '@reactive-resume/schema';
import { get } from 'lodash';
import { firstValueFrom } from 'rxjs';
import cachedResponse from './assets/cachedResponse.json';
@Injectable()
export class FontsService {
constructor(private configService: ConfigService, private httpService: HttpService) {}
@ -13,8 +15,14 @@ export class FontsService {
const apiKey = this.configService.get<string>('google.apiKey');
const url = 'https://www.googleapis.com/webfonts/v1/webfonts?key=' + apiKey;
const response = await firstValueFrom(this.httpService.get(url));
const data = get(response.data, 'items', []);
let data = [];
if (apiKey) {
const response = await firstValueFrom(this.httpService.get(url));
data = get(response.data, 'items', []);
} else {
data = cachedResponse;
}
return data;
}

View File

@ -10,6 +10,7 @@ const defaultState: Partial<Resume> = {
basics: {
email: '',
headline: '',
birthdate: '',
photo: {
url: '',
visible: true,

View File

@ -5,6 +5,7 @@ const sampleData: Partial<Resume> = {
name: 'Alexis Jones',
email: 'alexis.jones@gmail.com',
phone: '+1 800 1200 3820',
birthdate: '1995-08-06T00:00:00.000Z',
photo: {
url: `/images/sample-photo.jpg`,
filters: {

View File

@ -35,6 +35,8 @@ export class ResumeController {
@UseGuards(JwtAuthGuard)
@Get()
async findAllByUser(@User('id') userId: number) {
console.log('findAllByUser', userId);
return this.resumeService.findAllByUser(userId);
}

View File

@ -15,6 +15,7 @@
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"resolveJsonModule": true,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,