Compare commits

...

61 Commits

Author SHA1 Message Date
779d22101f chore(release): 3.5.3 2022-08-11 20:21:55 +02:00
ef240b2110 add Bulgarian language, update dependencies 2022-08-11 20:21:19 +02:00
32bb7354a4 Merge pull request #969 from AmruthPillai/i18n_main
New Crowdin updates
2022-08-11 20:12:06 +02:00
0dcbad1f8a New translations modals.json (Bulgarian) 2022-08-11 10:27:23 +02:00
a74921b27a New translations builder.json (Bulgarian) 2022-08-11 10:27:21 +02:00
d4f47423c9 New translations common.json (Bulgarian) 2022-08-11 10:27:20 +02:00
03f9a6543c New translations dashboard.json (Bulgarian) 2022-08-11 10:27:18 +02:00
eb89cfcf5d New translations landing.json (Bulgarian) 2022-08-11 10:27:17 +02:00
c52ef9ecb7 Merge pull request #965 from AmruthPillai/dependabot/github_actions/docker/build-push-action-3.1.1
chore(deps): bump docker/build-push-action from 3.1.0 to 3.1.1
2022-08-08 05:53:47 +02:00
c499abbb88 chore(deps): bump docker/build-push-action from 3.1.0 to 3.1.1
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-08 02:15:50 +00:00
1a7ee88ecd chore(release): 3.5.2 2022-08-04 16:15:29 +02:00
16d19eb70f feat(client): 💫 add Finnish language support 2022-08-04 16:13:49 +02:00
331346b99c chore(dependencies): ⬆️ upgrading dependencies to latest versions 2022-08-04 16:10:33 +02:00
95d265f672 Merge pull request #956 from AmruthPillai/i18n_main
New Crowdin updates
2022-08-04 16:09:46 +02:00
315c7d6328 New translations modals.json (Finnish) 2022-07-31 22:22:32 +02:00
490e174564 New translations common.json (Finnish) 2022-07-31 22:22:30 +02:00
b5cde79f8b New translations builder.json (Finnish) 2022-07-31 22:22:29 +02:00
d50f14bb78 New translations dashboard.json (Finnish) 2022-07-31 22:22:28 +02:00
c13a751c1a New translations landing.json (Finnish) 2022-07-31 22:22:26 +02:00
5c37fc55d5 New translations builder.json (Indonesian) 2022-07-30 17:08:34 +02:00
48a0f90597 chore(release): 3.5.1 2022-07-30 13:01:00 +02:00
05d3f1f06f fix(server): don't initialize sendgrid if the apikey is empty 2022-07-30 12:57:35 +02:00
4d43f6a642 feat(client): ask for confirmation when resetting a resume 2022-07-30 12:56:40 +02:00
f7363ccdd7 Merge branch 'main' of github.com:AmruthPillai/Reactive-Resume 2022-07-30 12:56:13 +02:00
07c91e9ac2 feat(docker): remove ports from postgres docker instance 2022-07-30 12:56:04 +02:00
cbe08f1d2c Merge pull request #950 from AmruthPillai/dependabot/github_actions/docker/build-push-action-3.1.0
chore(deps): bump docker/build-push-action from 3.0.0 to 3.1.0
2022-07-30 12:43:46 +02:00
c2617a8277 Merge pull request #944 from AmruthPillai/i18n_main
New Crowdin updates
2022-07-30 12:43:36 +02:00
fe72d2de41 chore(release): 3.5.0 2022-07-30 12:42:31 +02:00
23667e218f chore(deps): updating project dependencies to their latest versions 2022-07-30 12:41:37 +02:00
977fa72dde fix(client): 🐛 fix mui rendering of utc dates 2022-07-30 12:21:05 +02:00
5197f954c0 fix(client): 🐛 attempt to fix the one-off date issue
use utc functions from dayjs to correspond to the same date on the server
2022-07-31 02:13:08 -08:00
58341e4cd2 New translations builder.json (Serbian (Cyrillic)) 2022-07-28 13:44:38 +02:00
1559703567 chore(deps): bump docker/build-push-action from 3.0.0 to 3.1.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.0.0...v3.1.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 02:24:03 +00:00
0a1fd50d07 New translations dashboard.json (Norwegian) 2022-07-17 03:00:38 +02:00
1c19062c63 chore(release): 3.4.8 2022-07-13 11:08:14 +02:00
25cf594eb9 feat(google): add toast to display error message from google 2022-07-13 11:05:27 +02:00
1c3beee6cd chore(deps): update dependencies 2022-07-13 09:40:29 +02:00
95c3d4c315 Merge pull request #937 from AmruthPillai/dependabot/gradle/app/org.jetbrains.kotlin.android-1.7.10
chore(deps): bump org.jetbrains.kotlin.android from 1.7.0 to 1.7.10 in /app
2022-07-12 15:33:31 +02:00
85df339e56 chore(deps): bump org.jetbrains.kotlin.android in /app
Bumps [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) from 1.7.0 to 1.7.10.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/v1.7.10/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.7.0...v1.7.10)

---
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-07-11 02:40:56 +00:00
d61ad44ebc chore(release): 3.4.7 2022-07-01 01:04:52 +02:00
ccb1eff749 chore(mui): migrate from mui/lab to mui/x-date-pickers 2022-07-01 01:04:03 +02:00
bfb48e3aa7 fix(mui): update mui datepickers to newer package 2022-07-01 01:01:27 +02:00
e2e08ad390 Merge branch 'main' of github.com:AmruthPillai/Reactive-Resume 2022-07-01 00:50:17 +02:00
f0dda06af3 Merge pull request #932 from AmruthPillai/i18n_main
New Crowdin updates
2022-07-01 00:50:10 +02:00
4c4e77e21d New translations common.json (Portuguese) 2022-07-01 00:48:52 +02:00
f364ae8929 New translations common.json (Indonesian) 2022-07-01 00:48:49 +02:00
b52f292d89 New translations dashboard.json (Indonesian) 2022-07-01 00:48:32 +02:00
8cac7f907c New translations modals.json (Hebrew) 2022-07-01 00:48:25 +02:00
a18a60679f New translations builder.json (Hebrew) 2022-07-01 00:48:04 +02:00
5cc6a81b8c New translations landing.json (Hebrew) 2022-07-01 00:48:02 +02:00
6ff212b698 New translations dashboard.json (Hebrew) 2022-07-01 00:48:00 +02:00
56bcec5196 chore(deps): update dependencies across all projects 2022-07-01 00:46:41 +02:00
12019f90e9 Merge pull request #928 from ravindra3003/main
UpdateTutorial
2022-07-01 00:27:29 +02:00
7e6e69ed49 Update create-resume.mdx 2022-06-23 13:14:16 +05:30
a09a945e17 Update create-account.mdx 2022-06-23 13:12:21 +05:30
df714dc8de Update create-account.mdx 2022-06-22 15:47:01 +05:30
28b63ef0c7 Update create-account.mdx 2022-06-22 15:16:45 +05:30
1b594dac61 Update create-resume.mdx 2022-06-22 15:00:18 +05:30
dd34a30ee0 Update create-account.mdx 2022-06-22 12:09:18 +05:30
0af398ceed Update create-account.mdx 2022-06-22 11:45:45 +05:30
04abd2cacc Update create-account.mdx 2022-06-22 11:37:15 +05:30
57 changed files with 5445 additions and 5354 deletions

View File

@ -31,7 +31,7 @@ jobs:
password: ${{ secrets.GH_TOKEN }}
- name: Build and Push Client Image
uses: docker/build-push-action@v3.0.0
uses: docker/build-push-action@v3.1.1
with:
context: .
push: true
@ -68,7 +68,7 @@ jobs:
password: ${{ secrets.GH_TOKEN }}
- name: Build and Push Server Image
uses: docker/build-push-action@v3.0.0
uses: docker/build-push-action@v3.1.1
with:
context: .
push: true

2
.npmrc Normal file
View File

@ -0,0 +1,2 @@
auto-install-peers=true
strict-peer-dependencies=false

View File

@ -21,5 +21,11 @@
"i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
"i18n-ally.sortKeys": true,
"scss.validate": false
"scss.validate": false,
"conventionalCommits.scopes": [
"client",
"server",
"docker",
"dependencies"
]
}

View File

@ -2,6 +2,50 @@
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.5.3](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.5.2...v3.5.3) (2022-08-11)
### [3.5.2](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.5.1...v3.5.2) (2022-08-04)
### Features
* **client:** :dizzy: add Finnish language support ([16d19eb](https://github.com/AmruthPillai/Reactive-Resume/commit/16d19eb70f64f768304f352d0f87102d328b57c1))
### [3.5.1](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.5.0...v3.5.1) (2022-07-30)
### Features
* **client:** :sparkles: ask for confirmation when resetting a resume ([4d43f6a](https://github.com/AmruthPillai/Reactive-Resume/commit/4d43f6a6427198e62e9fcb995f1a28c0ee4de71e))
* **docker:** :zap: remove ports from postgres docker instance ([07c91e9](https://github.com/AmruthPillai/Reactive-Resume/commit/07c91e9ac21e8ef120d08ab92363d8e48a55aaba))
### Bug Fixes
* **server:** :zap: don't initialize sendgrid if the apikey is empty ([05d3f1f](https://github.com/AmruthPillai/Reactive-Resume/commit/05d3f1f06fbffd899269a5c4dea3c52cf408125f))
## [3.5.0](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.4.8...v3.5.0) (2022-07-30)
### Bug Fixes
* **client:** :bug: attempt to fix the one-off date issue ([5197f95](https://github.com/AmruthPillai/Reactive-Resume/commit/5197f954c0baed3daf1c7e2c79b607354ef42024))
* **client:** :bug: fix mui rendering of utc dates ([977fa72](https://github.com/AmruthPillai/Reactive-Resume/commit/977fa72ddeeeebf7463d43a820e85f783489a4dc))
### [3.4.8](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.4.7...v3.4.8) (2022-07-13)
### Features
* **google:** add toast to display error message from google ([25cf594](https://github.com/AmruthPillai/Reactive-Resume/commit/25cf594eb948e1c2d6157028ee1fff2799df5f92))
### [3.4.7](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.4.6...v3.4.7) (2022-06-30)
### Bug Fixes
* **mui:** update mui datepickers to newer package ([bfb48e3](https://github.com/AmruthPillai/Reactive-Resume/commit/bfb48e3aa7e0575922841522edc1d38544d1884f))
### [3.4.6](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.4.5...v3.4.6) (2022-06-19)
## [3.6.0](https://github.com/dvd741-a/Reactive-Resume/compare/v3.3.4...v3.6.0) (2022-06-05)

View File

@ -56,11 +56,13 @@ You have complete control over what goes into your resume, how it looks, what co
- Arabic (اَلْعَرَبِيَّةُ)
- Bengali (বাংলা)
- Bulgarian (български)
- Chinese (中文)
- Czech (čeština)
- Danish (Dansk)
- Dutch (Nederlands)
- English
- Finnish (Suomi)
- French (Français)
- German (Deutsch)
- Greek (Ελληνικά)

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.7.0' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
task clean(type: Delete) {

View File

@ -15,7 +15,7 @@ import dayjs from 'dayjs';
import get from 'lodash/get';
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import { useMemo } from 'react';
import { useMemo, useState } from 'react';
import { useMutation } from 'react-query';
import Heading from '@/components/shared/Heading';
@ -36,6 +36,8 @@ const Settings = () => {
const { locale, ...router } = useRouter();
const [confirmReset, setConfirmReset] = useState(false);
const resume = useAppSelector((state) => state.resume);
const theme = useAppSelector((state) => state.build.theme);
const pages = useAppSelector((state) => state.resume.metadata.layout);
@ -48,7 +50,7 @@ const Settings = () => {
const dateConfig: DateConfig = useMemo(() => get(resume, 'metadata.date'), [resume]);
const isDarkMode = useMemo(() => theme === 'dark', [theme]);
const exampleString = useMemo(() => `Eg. ${dayjs().format(dateConfig.format)}`, [dateConfig.format]);
const exampleString = useMemo(() => `Eg. ${dayjs().utc().format(dateConfig.format)}`, [dateConfig.format]);
const themeString = useMemo(() => (isDarkMode ? 'Matte Black Everything' : 'As bright as your future'), [isDarkMode]);
const { mutateAsync: loadSampleDataMutation } = useMutation<Resume, ServerError, LoadSampleDataParams>(
@ -78,9 +80,14 @@ const Settings = () => {
};
const handleResetResume = async () => {
await resetResumeMutation({ id });
if (!confirmReset) {
return setConfirmReset(true);
}
queryClient.invalidateQueries(`resume/${username}/${slug}`);
await resetResumeMutation({ id });
await queryClient.invalidateQueries(`resume/${username}/${slug}`);
setConfirmReset(false);
};
return (
@ -202,7 +209,11 @@ const Settings = () => {
<DeleteForever />
</ListItemIcon>
<ListItemText
primary={t<string>('builder.rightSidebar.sections.settings.resume.reset.primary')}
primary={
confirmReset
? 'Are you sure?'
: t<string>('builder.rightSidebar.sections.settings.resume.reset.primary')
}
secondary={t<string>('builder.rightSidebar.sections.settings.resume.reset.secondary')}
/>
</ListItemButton>

View File

@ -1,5 +1,5 @@
import { DatePicker } from '@mui/lab';
import { TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import dayjs from 'dayjs';
import { isEmpty } from 'lodash';
import get from 'lodash/get';
@ -63,7 +63,7 @@ const ResumeInput: React.FC<Props> = ({ type = 'text', label, path, className, m
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());
date && dayjs(date).utc().isValid() && onChangeValue(dayjs(date).utc().toISOString());
}}
/>
);

View File

@ -6,6 +6,7 @@ export type Language = {
export const languages: Language[] = [
{ code: 'ar', name: 'Arabic', localName: 'اَلْعَرَبِيَّةُ' },
{ code: 'bg', name: 'Bulgarian', localName: 'български' },
{ code: 'bn', name: 'Bengali', localName: 'বাংলা' },
{ code: 'cs', name: 'Czech', localName: 'čeština' },
{ code: 'da', name: 'Danish', localName: 'Dansk' },
@ -13,6 +14,7 @@ export const languages: Language[] = [
{ code: 'el', name: 'Greek', localName: 'Ελληνικά' },
{ code: 'en', name: 'English' },
{ code: 'es', name: 'Spanish', localName: 'Español' },
{ code: 'fi', name: 'Finnish', localName: 'Suomi' },
{ code: 'fr', name: 'French', localName: 'Français' },
{ code: 'he', name: 'Hebrew', localName: 'Ivrit' },
{ code: 'hi', name: 'Hindi', localName: 'हिन्दी' },

View File

@ -86,17 +86,27 @@ const LoginModal: React.FC = () => {
};
const handleLoginWithGoogle = async () => {
console.log(process.env.PUBLIC_GOOGLE_CLIENT_ID, env('GOOGLE_CLIENT_ID'));
google.accounts.id.initialize({
auto_select: true,
itp_support: true,
client_id: env('GOOGLE_CLIENT_ID'),
callback: async (response: any) => {
await loginWithGoogleMutation({ credential: response.credential });
handleClose();
},
auto_select: false,
});
google.accounts.id.prompt();
google.accounts.id.prompt((notification: any) => {
if (notification.isNotDisplayed() || notification.isSkippedMoment()) {
const reason = notification.getNotDisplayedReason() || notification.getSkippedReason();
toast.error(`Google returned an error while trying to sign in: ${reason}.`);
toast("Please try logging in using email/password, or use another browser that supports Google's One Tap API.");
}
});
};
const PasswordVisibility = (): React.ReactElement => {

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import DatePicker from '@mui/lab/DatePicker';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { Award, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -134,7 +134,7 @@ const AwardModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import DatePicker from '@mui/lab/DatePicker';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { Certificate, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -134,7 +134,7 @@ const CertificateModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import DatePicker from '@mui/lab/DatePicker';
import { Button, Slider, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { Custom } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -150,7 +150,7 @@ const CustomModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField
@ -174,7 +174,7 @@ const CustomModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import DatePicker from '@mui/lab/DatePicker';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { Education, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -173,7 +173,7 @@ const EducationModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField
@ -197,7 +197,7 @@ const EducationModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import DatePicker from '@mui/lab/DatePicker';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { Project, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -143,7 +143,7 @@ const ProjectModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField
@ -167,7 +167,7 @@ const ProjectModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import DatePicker from '@mui/lab/DatePicker';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { Publication, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -134,7 +134,7 @@ const PublicationModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import DatePicker from '@mui/lab/DatePicker';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { SectionPath, Volunteer } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -140,7 +140,7 @@ const VolunteerModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField
@ -164,7 +164,7 @@ const VolunteerModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import DatePicker from '@mui/lab/DatePicker';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { SectionPath, WorkExperience } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -140,7 +140,7 @@ const WorkModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField
@ -164,7 +164,7 @@ const WorkModal: React.FC = () => {
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).isValid() && field.onChange(date.toISOString());
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
}}
renderInput={(params) => (
<TextField

View File

@ -5,6 +5,7 @@ const i18nConfig = {
defaultLocale: 'en',
locales: [
'ar',
'bg',
'bn',
'cs',
'da',
@ -13,6 +14,7 @@ const i18nConfig = {
'en',
'es',
'fa',
'fi',
'fr',
'he',
'hi',

View File

@ -9,74 +9,74 @@
},
"dependencies": {
"@beam-australia/react-env": "^3.1.1",
"@date-io/dayjs": "^2.14.0",
"@emotion/css": "^11.9.0",
"@emotion/react": "^11.9.3",
"@emotion/styled": "^11.9.3",
"@hookform/resolvers": "2.9.1",
"@date-io/dayjs": "^2.15.0",
"@emotion/css": "^11.10.0",
"@emotion/react": "^11.10.0",
"@emotion/styled": "^11.10.0",
"@hookform/resolvers": "2.9.7",
"@monaco-editor/react": "^4.4.5",
"@mui/icons-material": "^5.8.4",
"@mui/lab": "^5.0.0-alpha.86",
"@mui/material": "^5.8.4",
"@mui/system": "^5.8.4",
"@mui/x-date-pickers": "5.0.0-alpha.6",
"@next/env": "^12.1.6",
"@reduxjs/toolkit": "^1.8.2",
"@mui/lab": "^5.0.0-alpha.94",
"@mui/material": "^5.10.0",
"@mui/system": "^5.10.0",
"@mui/x-date-pickers": "5.0.0-beta.5",
"@next/env": "^12.2.4",
"@reduxjs/toolkit": "^1.8.4",
"axios": "^0.27.2",
"clsx": "^1.1.1",
"dayjs": "^1.11.3",
"clsx": "^1.2.1",
"dayjs": "^1.11.4",
"downloadjs": "^1.4.7",
"joi": "^17.6.0",
"lodash": "^4.17.21",
"md5-hex": "^4.0.0",
"monaco-editor": "^0.33.0",
"monaco-editor": "^0.34.0",
"nanoid": "^3.3.4",
"next": "12.1.6",
"next-i18next": "^11.0.0",
"next": "12.2.4",
"next-i18next": "^11.3.0",
"react": "18.2.0",
"react-beautiful-dnd": "^13.1.0",
"react-colorful": "^5.5.1",
"react-colorful": "^5.6.0",
"react-dnd": "16.0.1",
"react-dnd-html5-backend": "16.0.1",
"react-dom": "18.2.0",
"react-hook-form": "^7.32.2",
"react-hot-toast": "2.2.0",
"react-hotkeys-hook": "^3.4.6",
"react-hook-form": "^7.34.0",
"react-hot-toast": "2.3.0",
"react-hotkeys-hook": "^3.4.7",
"react-icons": "^4.4.0",
"react-markdown": "^8.0.3",
"react-query": "^3.39.1",
"react-query": "^3.39.2",
"react-redux": "^8.0.2",
"react-zoom-pan-pinch": "^2.1.3",
"redux": "^4.2.0",
"redux-persist": "^6.0.0",
"redux-saga": "^1.1.3",
"remark-gfm": "^3.0.1",
"sharp": "^0.30.6",
"sharp": "^0.30.7",
"uuid": "^8.3.2",
"webfontloader": "^1.6.28"
},
"devDependencies": {
"@babel/core": "^7.18.5",
"@babel/core": "^7.18.10",
"@reactive-resume/schema": "workspace:*",
"@tailwindcss/typography": "^0.5.2",
"@tailwindcss/typography": "^0.5.4",
"@types/downloadjs": "^1.4.3",
"@types/lodash": "^4.14.182",
"@types/node": "18.0.0",
"@types/react": "18.0.14",
"@types/node": "18.7.1",
"@types/react": "18.0.17",
"@types/react-beautiful-dnd": "^13.1.2",
"@types/react-redux": "^7.1.24",
"@types/tailwindcss": "^3.0.10",
"@types/tailwindcss": "^3.0.11",
"@types/uuid": "^8.3.4",
"@types/webfontloader": "^1.6.34",
"autoprefixer": "^10.4.7",
"autoprefixer": "^10.4.8",
"csstype": "^3.1.0",
"eslint": "^8.18.0",
"eslint-config-next": "12.1.6",
"next-sitemap": "^3.1.1",
"postcss": "^8.4.14",
"eslint": "^8.21.0",
"eslint-config-next": "12.2.4",
"next-sitemap": "^3.1.17",
"postcss": "^8.4.16",
"prettier": "^2.7.1",
"sass": "^1.52.3",
"tailwindcss": "^3.1.3",
"sass": "^1.54.4",
"tailwindcss": "^3.1.8",
"typescript": "^4.7.4"
}
}

View File

@ -1,7 +1,7 @@
import '@/styles/globals.scss';
import DayjsAdapter from '@date-io/dayjs';
import { LocalizationProvider } from '@mui/lab';
import { LocalizationProvider } from '@mui/x-date-pickers';
import type { AppProps } from 'next/app';
import Head from 'next/head';
import Script from 'next/script';
@ -54,7 +54,7 @@ const App: React.FC<AppProps> = ({ Component, pageProps }) => {
</LocalizationProvider>
</ReduxProvider>
<Script src="https://accounts.google.com/gsi/client" />
<Script src="https://accounts.google.com/gsi/client" async defer />
</>
);
};

View File

@ -0,0 +1,361 @@
{
"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": "Наистина ли искате да изтриете това CV? Това действие не може да бъде отменено.",
"share-link": "Трябва да промените видимостта на CV-то си на публична, за да я направите видима за другите."
}
}
},
"leftSidebar": {
"sections": {
"awards": {
"form": {
"awarder": {
"label": "Награждаващ"
}
}
},
"basics": {
"actions": {
"photo-filters": "Филтри за снимата"
},
"heading": "Основни",
"headline": {
"label": "Заглавие"
},
"name": {
"label": "Пълно име"
},
"birthdate": {
"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 се генерира, това може да отнеме до 15 секунди."
},
"normal": {
"primary": "РDF",
"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": "Позволете на всеки с връзка да види това CV",
"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>markdown</1> форматиране."
},
"date": {
"present": "Настояще"
},
"subtitle": "Безплатен инструмент за създаване на автобиография с отворен код.",
"title": "Reactive Resume",
"toast": {
"error": {
"upload-file-size": "Моля, качвайте само файлове с размер под 2 мегабайта.",
"upload-photo-size": "Моля, качвайте само снимки под 2 мегабайта, за предпочитане квадратни."
},
"success": {
"resume-link-copied": "Връзката към автобиографията ви е копирана в клипборда."
}
}
}

View File

@ -0,0 +1,25 @@
{
"create-resume": {
"subtitle": "Започване отначало",
"title": "Създаване на ново CV"
},
"import-external": {
"subtitle": "LinkedIn, JSON резюме, Reactive Resume",
"title": "Импортиране от външни източници"
},
"resume": {
"menu": {
"delete": "Изтрии",
"duplicate": "Дубликирай",
"open": "Отвори",
"rename": "Преименувай",
"share-link": "Споделяне на връзка",
"tooltips": {
"delete": "Наистина ли искате да изтриете това CV? Това действие не може да бъде отменено.",
"share-link": "Трябва да промените видимостта на CV-то си на публична, за да я направите видима за другите."
}
},
"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 резюме",
"languages": "Достъпно на множество езици",
"more": "И още много вълнуващи функции, <1>прочетете всичко за тях тук</1>",
"tracking": "Без проследяване на потребители"
}
},
"links": {
"heading": "Връзки",
"links": {
"donate": "Дарение",
"github": "Програмен код",
"privacy": "Политика за поверителност",
"service": "Условия на ползване"
}
},
"screenshots": {
"heading": "Екранни снимки"
},
"testimonials": {
"heading": "Препоръки",
"body": "Позитивно или негативно, ще се радвам да чуя мнението ви за Reactive Resume и какъв е вашия опитът.<br/>Ето някои от съобщенията, изпратени от потребители по целия свят.",
"contact": "Можете да се свържете с мен чрез <1>моя имейл</1> или чрез формата за контакт на <3>моя уебсайт</3> ."
},
"summary": {
"body": "Reactive Resume е безплатен инструмент за създаване на автобиография/CV с отворен код, който е създаден, за да улесни обикновените задачи за създаване, актуализиране и споделяне на вашата автобиография като 1, 2, 3. С това приложение можете да създавате множество автобиографии, да ги споделяте директно със специалистите по подбор на персонал или приятели чрез уникална връзка, както и ги отпечатате като 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": "Вход чрез Google"
},
"body": "Моля, въведете вашето потребителско име и парола, свързани с вашия акаунт, за да влезете и получите достъп, управлявате и споделяте вашите автобиографии.",
"form": {
"password": {
"label": "Парола"
},
"username": {
"help-text": "Можете също да въведете своя имейл адрес",
"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": "Създай CV/Резюме"
},
"body": "Започнете да създавате автобиографията си, като й дадете име. Може да е във връзка с позицията, за която кандидатствате, или просто любимата ви закуска.",
"form": {
"name": {
"label": "Име"
},
"public": {
"label": "Публично достъпна ли е?"
},
"slug": {
"label": "Слъг"
}
},
"heading": "Създаване на ново CV"
},
"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": "Качете JSON от v2"
},
"body": "Ако имате JSON, който е бил експортиран с текущата версия на Reactive Resume, можете да го импортирате обратно тук, за да получите отново редактируема версия.",
"heading": "Импортиране от Reactive Resume"
}
},
"rename-resume": {
"actions": {
"rename-resume": "Преименуване на резюмето"
},
"form": {
"name": {
"label": "Име"
},
"slug": {
"label": "Слъг"
}
},
"heading": "Преименувайте автобиографията си"
}
}
}

View File

@ -0,0 +1,361 @@
{
"common": {
"actions": {
"add": "Lisää uusi",
"delete": "Poista",
"edit": "Muokkaa"
},
"columns": {
"heading": "Palstat",
"tooltip": "Muut palstojen määrää"
},
"form": {
"date": {
"label": "Päivämäärä"
},
"description": {
"label": "Kuvaus"
},
"email": {
"label": "Sähköposti"
},
"end-date": {
"help-text": "Jätä tämä kenttä tyhjäksi, jos se on vielä esillä",
"label": "Päättymispäivä"
},
"keywords": {
"label": "Avainsanat"
},
"level": {
"label": "Taso"
},
"levelNum": {
"label": "Taso (numero)"
},
"name": {
"label": "Nimi"
},
"phone": {
"label": "Puhelinnumero"
},
"position": {
"label": "Sijainti"
},
"start-date": {
"label": "Alkamispäivä"
},
"subtitle": {
"label": "Alaotsikko"
},
"summary": {
"label": "Yhteenveto"
},
"title": {
"label": "Otsikko"
},
"url": {
"label": "Verkkosivusto"
}
},
"glossary": {
"page": "Sivu"
},
"list": {
"actions": {
"delete": "Poista",
"duplicate": "Monista",
"edit": "Muokkaa"
},
"empty-text": "Tämä luettelo on tyhjä."
},
"tooltip": {
"delete-item": "Haluatko varmasti poistaa tämän kohteen? Tämä on peruuttamaton toimenpide.",
"delete-section": "Poista osio",
"rename-section": "Nimeä osio uudelleen",
"toggle-visibility": "Näkyvyys päälle/pois"
}
},
"controller": {
"tooltip": {
"center-artboard": "Keskitä Kuvataulu",
"copy-link": "Kopioi linkki ansioluetteloon",
"export-pdf": "Vie PDF",
"toggle-orientation": "Vaihda sivun suunta",
"toggle-page-break-line": "Vaihda sivunvaihtoviivaa",
"toggle-sidebars": "Vaihda Sivupalkkeja",
"zoom-in": "Suurenna",
"zoom-out": "Pienennä"
}
},
"header": {
"menu": {
"delete": "Poista",
"duplicate": "Kopioi",
"rename": "Nimeä uudelleen",
"share-link": "Jaa linkki",
"tooltips": {
"delete": "Haluatko varmasti poistaa tämän ansioluettelon? Tämä on peruuttamaton toimenpide.",
"share-link": "Sinun on muutettava ansioluettelosi näkyvyys julkiseksi, jotta se näkyisi muille."
}
}
},
"leftSidebar": {
"sections": {
"awards": {
"form": {
"awarder": {
"label": "Tunnustuksen antaja"
}
}
},
"basics": {
"actions": {
"photo-filters": "Valokuvasuodattimet"
},
"heading": "Perustiedot",
"headline": {
"label": "Otsikko"
},
"name": {
"label": "Koko nimi"
},
"birthdate": {
"label": "Syntymäaika"
},
"photo-filters": {
"effects": {
"border": {
"label": "Kehys"
},
"grayscale": {
"label": "Harmaasävy"
},
"heading": "Efektit"
},
"shape": {
"heading": "Muoto"
},
"size": {
"heading": "Koko (px)"
}
},
"photo-upload": {
"tooltip": {
"remove": "Poista kuva",
"upload": "Lataa valokuva"
}
}
},
"certifications": {
"form": {
"issuer": {
"label": "Myöntäjä"
}
}
},
"education": {
"form": {
"area-study": {
"label": "Opintojen alue"
},
"courses": {
"label": "Kurssit"
},
"degree": {
"label": "Tutkinto"
},
"grade": {
"label": "Arvosana"
},
"institution": {
"label": "Oppilaitos"
}
}
},
"location": {
"address": {
"label": "Osoite"
},
"city": {
"label": "Kaupunki"
},
"country": {
"label": "Maa"
},
"heading": "Sijainti",
"postal-code": {
"label": "Postinumero"
},
"region": {
"label": "Paikkakunta"
}
},
"profiles": {
"form": {
"network": {
"label": "Verkosto"
},
"username": {
"label": "Käyttäjätunnus"
}
},
"heading": "Profiilit",
"heading_one": "Profiili"
},
"publications": {
"form": {
"publisher": {
"label": "Julkaisija"
}
}
},
"references": {
"form": {
"relationship": {
"label": "Suhde suosittelijaan"
}
}
},
"section": {
"heading": "Osio"
},
"volunteer": {
"form": {
"organization": {
"label": "Organisaatio"
}
}
}
}
},
"rightSidebar": {
"sections": {
"css": {
"heading": "Mukautettu CSS"
},
"export": {
"heading": "Vie",
"json": {
"primary": "JSON",
"secondary": "Lataa JSON-versio ansioluettelostasi, jonka voit tuoda takaisin Reactive Resumeen."
},
"pdf": {
"loading": {
"primary": "Luodaan PDF-tiedostoa",
"secondary": "Odota, että PDF-tiedostosi luodaan. Tämä voi kestää jopa 15 sekuntia."
},
"normal": {
"primary": "PDF",
"secondary": "Lataa PDF-tiedosto ansioluettelostasi, jonka voit tulostaa ja lähettää unelmiesi työpaikkaan. Tätä tiedostoa ei voi tuoda takaisin muokattavaksi."
}
}
},
"layout": {
"heading": "Asettelu",
"tooltip": {
"reset-layout": "Nollaa asettelu"
}
},
"links": {
"bugs-features": {
"body": "Estääkö jokin sinua tekemästä ansioluetteloa? Vai onko sinulla mahtava idea lisättäväksi? Nosta ongelma GitHubissa päästäksesi alkuun.",
"button": "GitHub Issues",
"heading": "Bugeja? Ominaisuuspyyntöjä?"
},
"donate": {
"body": "Jos pidit Reactive Resume -sovelluksen käytöstä, harkitse lahjoitusta niin paljon kuin voit, jotta sovellus pysyy toiminnassa ilman mainoksia ja ikuisesti ilmaisena.",
"button": "Osta minulle kahvi",
"heading": "Lahjoita Reaktiiviselle ansioluettelolle"
},
"github": "Lähdekoodi",
"heading": "Linkit"
},
"settings": {
"global": {
"date": {
"primary": "Päivämäärä",
"secondary": "Sovelluksessa käytettävä päivämäärämuoto"
},
"heading": "Yleinen",
"language": {
"primary": "Kieli",
"secondary": "Koko sovelluksessa käytettävä näyttökieli"
},
"theme": {
"primary": "Teema"
}
},
"heading": "Asetukset",
"page": {
"break-line": {
"primary": "Katkoviiva",
"secondary": "Näytä viiva kaikilla sivuilla A4-sivun korkeuden merkitsemiseksi"
},
"heading": "Sivu",
"orientation": {
"disabled": "Ei vaikuta, kun sivuja on vain yksi",
"primary": "Suunta",
"secondary": "Näytetäänkö sivut vaaka- vai pystysuunnassa"
}
},
"resume": {
"heading": "Ansioluettelo",
"reset": {
"primary": "Tyhjennä Kaikki",
"secondary": "Oletko tehnyt liikaa virheitä? Napsauta tätä nollataksesi kaikki muutokset ja aloittaaksesi alusta. Ole varovainen, tätä toimintoa ei voi peruuttaa."
},
"sample": {
"primary": "Lataa näytetiedot",
"secondary": "Etkö ole varma mistä aloittaa? Napsauta tätä ladataksesi näytetietoja nähdäksesi, miltä täydellinen ansioluettelo näyttää."
}
}
},
"sharing": {
"heading": "Jakaminen",
"short-url": {
"label": "Valitse lyhyt URL-osoite"
},
"visibility": {
"subtitle": "Salli kenelle tahansa linkin avulla mahdollisuus tarkastella ansioluetteloasi.",
"title": "Julkinen"
}
},
"templates": {
"heading": "Mallipohjat"
},
"theme": {
"form": {
"background": {
"label": "Taustakuva"
},
"primary": {
"label": "Ensisijainen"
},
"text": {
"label": "Teksti"
}
},
"heading": "Teema"
},
"typography": {
"form": {
"font-family": {
"label": "Kirjasintyyli"
},
"font-size": {
"label": "Fontin koko"
}
},
"heading": "Painatus",
"widgets": {
"body": {
"label": "Runko"
},
"headings": {
"label": "Otsikot"
}
}
}
}
}
}

View File

@ -0,0 +1,29 @@
{
"avatar": {
"menu": {
"greeting": "Hei",
"logout": "Kirjaudu ulos"
}
},
"footer": {
"credit": "<1>Amruth Pillain</1> intohimoprojekti",
"license": "Yhteisön toimesta yhteisöä varten."
},
"markdown": {
"help-text": "Tämä osio tukee <1>markdown-muotoilua</1>."
},
"date": {
"present": "Tänään"
},
"subtitle": "Ilmainen ja avoimeen lähdekoodiin pohjautuva ansioluettelo.",
"title": "Reactive Resume",
"toast": {
"error": {
"upload-file-size": "Lataa vain alle 2 megatavun tiedostoja.",
"upload-photo-size": "Lataa vain alle 2 megatavun kuvia, mieluiten neliönmuotoisia."
},
"success": {
"resume-link-copied": "Linkki ansioluetteloosi on kopioitu leikepöydällesi."
}
}
}

View File

@ -0,0 +1,25 @@
{
"create-resume": {
"subtitle": "Aloita tyhjästä",
"title": "Luo uusi ansioluettelo"
},
"import-external": {
"subtitle": "LinkedIn, JSON Resume, Reactive Resume",
"title": "Tuo ulkoisista lähteistä"
},
"resume": {
"menu": {
"delete": "Poista",
"duplicate": "Monista",
"open": "Avaa",
"rename": "Nimeä uudelleen",
"share-link": "Jaa linkki",
"tooltips": {
"delete": "Haluatko varmasti poistaa tämän ansioluettelon? Tämä on peruuttamaton toimenpide.",
"share-link": "Sinun on muutettava ansioluettelosi näkyvyys julkiseksi, jotta se näkyisi muille."
}
},
"timestamp": "Viimeksi päivitetty: {{timestamp}}"
},
"title": "Hallintapaneeli"
}

View File

@ -0,0 +1,41 @@
{
"actions": {
"app": "Siirry sovellukseen",
"login": "Kirjaudu sisään",
"logout": "Kirjaudu ulos",
"register": "Rekisteröidy"
},
"features": {
"heading": "Ominaisuudet",
"list": {
"ads": "Ei mainoksia",
"export": "Vie ansioluettelosi JSON- tai PDF-muotoon",
"free": "Ilmainen ikuisesti",
"import": "Tuo tietoja LinkedInistä tai JSON tiedostosta",
"languages": "Käytettävissä useilla kielillä",
"more": "Ja paljon muita jännittäviä ominaisuuksia, <1>lue kaikki tästä</1>",
"tracking": "Ei käyttäjän seurantaa"
}
},
"links": {
"heading": "Linkit",
"links": {
"donate": "Lahjoita",
"github": "Lähdekoodi",
"privacy": "Tietosuojakäytäntö",
"service": "Käyttöehdot"
}
},
"screenshots": {
"heading": "Kuvakaappaukset"
},
"testimonials": {
"heading": "Asiakaskokemuksia",
"body": "Hyvä tai huono, haluaisin kuulla mielipiteesi Reactive Resume -ohjelmasta ja siitä, millainen kokemus sinulla on ollut.<br/>Seuraavassa on muutamia käyttäjien eri puolilta maailmaa lähettämiä viestejä.",
"contact": "Voit ottaa minuun yhteyttä <1>sähköpostitse</1> tai <3>verkkosivustoni</3> yhteydenottolomakkeen kautta."
},
"summary": {
"body": "Reactive Resume on ilmainen ja avoimen lähdekoodin ansioluettelon rakentaja, jonka tarkoituksena on tehdä ansioluettelon luomisesta, päivittämisestä ja jakamisesta helppoa kuin 1, 2, 3. Tämän sovelluksen avulla voit luoda useita ansioluetteloita, jakaa ne rekrytoijien tai ystävien kanssa yksilöllisen linkin kautta ja tulostaa ne PDF-muodossa, ja kaikki tämä ilmaiseksi, ilman mainoksia, ilman seurantaa ja menettämättä tietojesi eheyttä ja yksityisyyttä.",
"heading": "Yhteenveto"
}
}

View File

@ -0,0 +1,136 @@
{
"auth": {
"forgot-password": {
"actions": {
"send-email": "Lähetä salasanan palautussähköposti"
},
"body": "Kirjoita vain palautettavaan tiliin liitetty sähköpostiosoite.",
"form": {
"email": {
"label": "Sähköpostiosoite"
}
},
"heading": "Unohditko salasanasi?",
"help-text": "Jos sähköpostiosoitteesi on olemassa, saat sähköpostiviestissä linkin salasanasi palautukseen."
},
"login": {
"actions": {
"login": "Kirjaudu sisään",
"google": "Kirjaudu Google-tilillä"
},
"body": "Anna tiliisi liitetty käyttäjätunnuksesi ja salasanasi kirjautuaksesi sisään ja käyttääksesi, hallitaksesi ja jakaaksesi ansioluettelosi.",
"form": {
"password": {
"label": "Salasana"
},
"username": {
"help-text": "Voit myös syöttää sähköpostiosoitteesi",
"label": "Käyttäjänimi"
}
},
"heading": "Kirjaudu tilillesi",
"recover-text": "Jos olet unohtanut salasanasi, voit <1>palauttaa tilisi</1> täällä.",
"register-text": "Jos sinulla ei ole tiliä, voit <1>luoda tilin</1> täällä."
},
"register": {
"actions": {
"register": "Rekisteröidy",
"google": "Rekisteröidy Google-tilillä"
},
"body": "Anna tietosi luodaksesi uuden käyttäjätilin.",
"form": {
"confirm-password": {
"label": "Vahvista Salasana"
},
"email": {
"label": "Sähköpostiosoite"
},
"name": {
"label": "Koko nimi"
},
"password": {
"label": "Salasana"
},
"username": {
"label": "Käyttäjänimi"
}
},
"heading": "Luo käyttäjätili",
"loginText": "Jos sinulla on jo tili, voit <1>kirjautua sisään täällä</1>."
},
"reset-password": {
"actions": {
"set-password": "Aseta uusi salasana"
},
"body": "Anna uusi salasana tilillesi.",
"form": {
"confirm-password": {
"label": "Vahvista Salasana"
},
"password": {
"label": "Salasana"
}
},
"heading": "Palauta salasanasi"
}
},
"dashboard": {
"create-resume": {
"actions": {
"create-resume": "Luo ansioluettelo"
},
"body": "Aloita ansioluettelosi rakentaminen antamalla sille nimi. Se voi viitata rooliin, johon haet, tai vaikka suosikkivälipalaasi.",
"form": {
"name": {
"label": "Nimi"
},
"public": {
"label": "Onko julkisesti saatavilla?"
},
"slug": {
"label": "Tunniste"
}
},
"heading": "Luo uusi ansioluettelo"
},
"import-external": {
"heading": "Tuo ulkoisista lähteistä",
"json-resume": {
"actions": {
"upload-json": "Lataa JSON"
},
"body": "Jos sinulla on valmiiksi <1>validoitu JSON-ansioluettelo</1>, voit käyttää sitä Reactive Resume -ansioluettelon laatimisen nopeuttamiseen. Napsauta alla olevaa painiketta ja lataa validoitu JSON-tiedosto aloittaaksesi.",
"heading": "Tuo JSON-muotoisesta ansioluettelosta"
},
"linkedin": {
"actions": {
"upload-archive": "Lataa ZIP-tiedosto"
},
"body": "Voit säästää aikaa tuomalla tietosi LinkedInistä ja käyttämällä niitä Reactive Resumen kenttien automaattiseen täyttämiseen. Siirry LinkedInin <1>tietosuojaosioon</1> ja pyydä tietojesi arkistointia. Kun se on saatavilla, lataa alla oleva ZIP-tiedosto.",
"heading": "Tuo LinkedInistä"
},
"reactive-resume": {
"actions": {
"upload-json": "Lataa JSON",
"upload-json-v2": "Lataa JSON v2:sta"
},
"body": "Jos sinulla on JSON, joka on viety Reactive Resume -ohjelman nykyisellä versiolla, voit tuoda sen takaisin tänne saadaksesi muokattavan version uudelleen.",
"heading": "Tuo Reactive Resume -ohjelmalla tehdystä"
}
},
"rename-resume": {
"actions": {
"rename-resume": "Nimeä ansioluettelo uudelleen"
},
"form": {
"name": {
"label": "Nimi"
},
"slug": {
"label": "Tunniste"
}
},
"heading": "Nimeä ansioluettelosi uudelleen"
}
}
}

View File

@ -0,0 +1,361 @@
{
"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": "שם מלא"
},
"birthdate": {
"label": "תאריך לידה"
},
"photo-filters": {
"effects": {
"border": {
"label": "גבול"
},
"grayscale": {
"label": "גווני אפור"
},
"heading": "אפקטים"
},
"shape": {
"heading": "צוּרָה"
},
"size": {
"heading": "גודל (בפיקסלים)"
}
},
"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 של קורות החיים שלך שניתן לייבא חזרה אל קורות חיים ריאקטיביים."
},
"pdf": {
"loading": {
"primary": "יצירת PDF",
"secondary": "המתן עם יצירת ה-PDF שלך, זה עשוי להימשך עד 15 שניות."
},
"normal": {
"primary": "PDF",
"secondary": "הורד קובץ PDF של קורות החיים שלך שתוכל להדפיס ולשלוח לעבודת החלומות שלך. לא ניתן לייבא קובץ זה בחזרה לעריכה נוספת."
}
}
},
"layout": {
"heading": "מַעֲרָך",
"tooltip": {
"reset-layout": "אפס פריסה"
}
},
"links": {
"bugs-features": {
"body": "משהו מונע ממך לעשות קורות חיים? או שיש לכם רעיון מדהים להוסיף? העלה בעיה ב-GitHub כדי להתחיל.",
"button": "בעיות GitHub",
"heading": "באגים? בקשות לתכונה?"
},
"donate": {
"body": "אם אהבתם להשתמש בקורות חיים ריאקטיביים, אנא שקול לתרום ככל שתוכל למען שמירה על האפליקציה ופועלת, ללא פרסומות ובחינם לנצח.",
"button": "תקנה לי קפה",
"heading": "תרומה לקורות חיים ריאקטיביים"
},
"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,25 @@
{
"create-resume": {
"subtitle": "להתחיל מאפס",
"title": "צור קורות חיים חדשים"
},
"import-external": {
"subtitle": "לינקדאין, קורות חיים של JSON, קורות חיים ריאקטיביים",
"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",
"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": "Reactive Resume הוא בונה קורות חיים חינמי וקוד פתוח שנבנה כדי להפוך את המשימות השגרתיות של יצירה, עדכון ושיתוף של קורות החיים שלך לקלות כמו 1, 2, 3. עם האפליקציה הזו, אתה יכול ליצור מספר קורות חיים, לשתף אותם עם מגייסים או חברים דרך קישור ייחודי והדפיס אותו כקובץ 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> מוכן לפעולה, אתה יכול להשתמש בו כדי לעקוב במהירות את הפיתוח שלך בקורות חיים ריאקטיביים. לחץ על הכפתור למטה והעלה קובץ JSON חוקי כדי להתחיל.",
"heading": "ייבוא מ-JSON קורות חיים"
},
"linkedin": {
"actions": {
"upload-archive": "העלה ארכיון ZIP"
},
"body": "אתה יכול לחסוך זמן על ידי ייצוא הנתונים שלך מ-LinkedIn ושימוש בהם למילוי אוטומטי של שדות בקורות חיים תגובתיים. עבור אל <1>פרטיות נתונים</1> מדור בלינקדאין ובקש ארכיון של הנתונים שלך. ברגע שהוא זמין, העלה את קובץ ה-ZIP למטה.",
"heading": "ייבוא מ-LinkedIn"
},
"reactive-resume": {
"actions": {
"upload-json": "העלה JSON",
"upload-json-v2": "העלה JSON מגרסה 2"
},
"body": "אם יש לך JSON שיוצא עם הגרסה הנוכחית של Reactive Resume, תוכל לייבא אותו בחזרה לכאן כדי לקבל שוב גרסה הניתנת לעריכה.",
"heading": "ייבא מ- Reactive Resume"
}
},
"rename-resume": {
"actions": {
"rename-resume": "שנה את שם קורות החיים"
},
"form": {
"name": {
"label": "שם"
},
"slug": {
"label": "סלאג"
}
},
"heading": "שנה את שם קורות החיים שלך"
}
}
}

View File

@ -1,7 +1,7 @@
{
"common": {
"actions": {
"add": "Tambah Baru {{token}}",
"add": "Tambahkan {{token}} Baru",
"delete": "Hapus {{token}}",
"edit": "Ubah {{token}}"
},

View File

@ -16,7 +16,7 @@
"present": "Sekarang"
},
"subtitle": "Pembuat resume open source dan gratis.",
"title": "Reactive Resume",
"title": "\"Reactive Resume\"",
"toast": {
"error": {
"upload-file-size": "Harap unggah hanya file di bawah 2 megabytes.",

View File

@ -4,7 +4,7 @@
"title": "Buat Resume Baru"
},
"import-external": {
"subtitle": "LinkedIn, JSON Resume, Reactive Resume",
"subtitle": "LinkedIn, Resume JSON, Reactive Resume",
"title": "Impor dari sumber luar"
},
"resume": {

View File

@ -0,0 +1,25 @@
{
"create-resume": {
"subtitle": "Start fra begynnelsen",
"title": "Opprett ny CV"
},
"import-external": {
"subtitle": "LinkedIn, JSON Resume, Reactive Resume",
"title": "Importer fra eksterne kilder"
},
"resume": {
"menu": {
"delete": "Slett",
"duplicate": "Dupliser",
"open": "Åpen",
"rename": "Endre navn",
"share-link": "Del lenke",
"tooltips": {
"delete": "Er du sikker på at du vil slette dette resymeet? Dette er en irreversibel handling.",
"share-link": "Du må endre synligheten til resymeet ditt til offentlig for å gjøre det synlig for andre."
}
},
"timestamp": "Sist oppdatert for {{timestamp}} siden"
},
"title": "Oversikt"
}

View File

@ -13,7 +13,7 @@
"help-text": "Esta seção suporta formatação <1>markdown</1>."
},
"date": {
"present": "presente"
"present": "Presente"
},
"subtitle": "Gerador de currículos gratuito e de código aberto.",
"title": "Reactive Resume",

View File

@ -0,0 +1,361 @@
{
"common": {
"actions": {
"add": "Dodaj Novi {{token}}",
"delete": "Obriši {{token}}",
"edit": "Ažuriraj {{token}}"
},
"columns": {
"heading": "Kolone",
"tooltip": "Promeni broj kolona"
},
"form": {
"date": {
"label": "Datum"
},
"description": {
"label": "Opis"
},
"email": {
"label": "Imejl Adresa"
},
"end-date": {
"help-text": "Ostavi ovo polje prazno, ukoliko još postoji",
"label": "Datum kraja"
},
"keywords": {
"label": "Ključne reči"
},
"level": {
"label": "Nivo"
},
"levelNum": {
"label": "Nivo (Broj)"
},
"name": {
"label": "Ime"
},
"phone": {
"label": "Broj Telefona"
},
"position": {
"label": "Pozicija"
},
"start-date": {
"label": "Datum Početka"
},
"subtitle": {
"label": "Podnaslov"
},
"summary": {
"label": "Rezime"
},
"title": {
"label": "Naslov"
},
"url": {
"label": "Veb Sajt"
}
},
"glossary": {
"page": "Stranica"
},
"list": {
"actions": {
"delete": "Obriši",
"duplicate": "Dupliraj",
"edit": "Edituj"
},
"empty-text": "Ova lista je prazna."
},
"tooltip": {
"delete-item": "Da li sigurno želiš da izbrišeš ovu stavku? Ovo je nepovratna akcija.",
"delete-section": "Obriši Sekciju",
"rename-section": "Preimenuj Sekciju",
"toggle-visibility": "Prebaci Vidljivost"
}
},
"controller": {
"tooltip": {
"center-artboard": "Centriraj Kanvas",
"copy-link": "Kopiraj link u rezime",
"export-pdf": "Eksportuj PDF",
"toggle-orientation": "Uključi/Isključi Orijentaciju Stranice",
"toggle-page-break-line": "Uključi/Isključi liniju preloma stranice",
"toggle-sidebars": "Uključi/Isključi Sidebar",
"zoom-in": "Zumiraj",
"zoom-out": "Odzumiraj"
}
},
"header": {
"menu": {
"delete": "Obriši",
"duplicate": "Dupliraj",
"rename": "Preimenuj",
"share-link": "Podeli Link",
"tooltips": {
"delete": "Da li sigurno želiš da obrišeš ovaj rezime? Ovo je nepovratna akcija.",
"share-link": "Moraš da promeniš vidljivost rezimea na javno kako bi bio vidljiv drugima."
}
}
},
"leftSidebar": {
"sections": {
"awards": {
"form": {
"awarder": {
"label": "Dodelio nagradu"
}
}
},
"basics": {
"actions": {
"photo-filters": "Filteri za Slike"
},
"heading": "Osnovno",
"headline": {
"label": "Naslov"
},
"name": {
"label": "Puno Ime"
},
"birthdate": {
"label": "Datum Rođenja"
},
"photo-filters": {
"effects": {
"border": {
"label": "Okvir"
},
"grayscale": {
"label": "Sivi Ton"
},
"heading": "Efekti"
},
"shape": {
"heading": "Oblik"
},
"size": {
"heading": "Veličina (u pikselima)"
}
},
"photo-upload": {
"tooltip": {
"remove": "Obriši Sliku",
"upload": "Učitaj Sliku"
}
}
},
"certifications": {
"form": {
"issuer": {
"label": "Izdavač"
}
}
},
"education": {
"form": {
"area-study": {
"label": "Oblast Edukacije"
},
"courses": {
"label": "Kursevi"
},
"degree": {
"label": "Stepen"
},
"grade": {
"label": "Ocena"
},
"institution": {
"label": "Institucija"
}
}
},
"location": {
"address": {
"label": "Adresa"
},
"city": {
"label": "Grad"
},
"country": {
"label": "Zemlja"
},
"heading": "Lokacija",
"postal-code": {
"label": "Poštanski Broj"
},
"region": {
"label": "Region"
}
},
"profiles": {
"form": {
"network": {
"label": "Mreža"
},
"username": {
"label": "Korisničko ime"
}
},
"heading": "Profili",
"heading_one": "Profil"
},
"publications": {
"form": {
"publisher": {
"label": "Izdavač"
}
}
},
"references": {
"form": {
"relationship": {
"label": "Veza"
}
}
},
"section": {
"heading": "Sekcija"
},
"volunteer": {
"form": {
"organization": {
"label": "Organizacija"
}
}
}
}
},
"rightSidebar": {
"sections": {
"css": {
"heading": "Prilagodi CSS"
},
"export": {
"heading": "Eksportuj",
"json": {
"primary": "JSON",
"secondary": "Preuzmi JSON verziju tvog rezimea koja se može importovati nazad u Reactive Resume."
},
"pdf": {
"loading": {
"primary": "Generišem PDF",
"secondary": "Sačekaj dok se tvoj PDF generiše, ovo može da potraje do 15 sekundi."
},
"normal": {
"primary": "PDF",
"secondary": "Preuzmi PDF verziju rezimea koju možeš da štampaš i pošalješ za svoj posao iz snova. Ovaj fajl se ne može importovati ponovo kako bi se ponovo ažurirao."
}
}
},
"layout": {
"heading": "Izgled",
"tooltip": {
"reset-layout": "Resetuj izgled"
}
},
"links": {
"bugs-features": {
"body": "Nešto de sprečava da napraviš svoj rezime? Ili imaš neku super ideju kao predlog? Kreiraj task na GitHub-u za početak.",
"button": "GitHub Problemi",
"heading": "Bagovi? Zahtevi za novu funkcionalnost?"
},
"donate": {
"body": "Ako ti se sviđa Reactive Resume, razmotri o donaciji kako bi aplikacija nastavila da funkcioniše i bude dostupna, bez reklama i besplatna zauvek.",
"button": "Kupi mi kafu",
"heading": "Doniraj za Reactive Resume"
},
"github": "Izvorni Kod",
"heading": "Linkovi"
},
"settings": {
"global": {
"date": {
"primary": "Datum",
"secondary": "Format datuma koji se koristi u aplikaciji"
},
"heading": "Globalno",
"language": {
"primary": "Jezik",
"secondary": "Jezika prikaza za korišćenje u celoj aplikaciji"
},
"theme": {
"primary": "Tema"
}
},
"heading": "Podešavanja",
"page": {
"break-line": {
"primary": "Prelomi Redova",
"secondary": "Pokaži liniju na svakoj stranici kako bi se obeležila visina A4 stranice"
},
"heading": "Strana",
"orientation": {
"disabled": "Nema efekat kada postoji samo jedna stranica",
"primary": "Orijentacija",
"secondary": "Da li prikazujem stranice horizontalno ili vertikalno"
}
},
"resume": {
"heading": "Rezime",
"reset": {
"primary": "Resetuje sve",
"secondary": "Previše grešaka? Klikni ovde da resetuješ sve izmene i počneš izpočetka. Vodi računa, ova akcija se ne može promeniti."
},
"sample": {
"primary": "Učitaj podatke kao primer",
"secondary": "Ne znaš gde da počneš? Klikni ovde da učitaš podatke kao primer i vidiš kako ceo rezime može da izgleda."
}
}
},
"sharing": {
"heading": "Deljenje",
"short-url": {
"label": "Kao Kratak URL"
},
"visibility": {
"subtitle": "Dozvoli svakom sa linkom da pogleda tvoj rezime",
"title": "Javno"
}
},
"templates": {
"heading": "Šabloni"
},
"theme": {
"form": {
"background": {
"label": "Pozadina"
},
"primary": {
"label": "Glavni"
},
"text": {
"label": "Tekst"
}
},
"heading": "Tema"
},
"typography": {
"form": {
"font-family": {
"label": "Porodica Fontova"
},
"font-size": {
"label": "Veličina Fonta"
}
},
"heading": "Tipografija",
"widgets": {
"body": {
"label": "Sadržaj"
},
"headings": {
"label": "Naslovi"
}
}
}
}
}
}

View File

@ -19,7 +19,7 @@ export const dateFormatOptions: string[] = [
'YYYY',
];
export const getRelativeTime = (timestamp: dayjs.ConfigType): string => dayjs(timestamp).toNow(true);
export const getRelativeTime = (timestamp: dayjs.ConfigType): string => dayjs(timestamp).utc().toNow(true);
export const formatDateString = (date: string | DateRange, formatStr: string): string | null => {
const presentString = i18n?.t<string>('common.date.present') ?? '';
@ -28,9 +28,9 @@ export const formatDateString = (date: string | DateRange, formatStr: string): s
// If `date` is a string
if (isString(date)) {
if (!dayjs(date).isValid()) return null;
if (!dayjs(date).utc().utc().isValid()) return null;
return dayjs(date).format(formatStr);
return dayjs(date).utc().format(formatStr);
}
// If `date` is a DateRange

View File

@ -1,5 +1,6 @@
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import utc from 'dayjs/plugin/utc';
import { useRouter } from 'next/router';
import { useEffect } from 'react';
@ -7,10 +8,12 @@ const DateWrapper: React.FC<React.PropsWithChildren<unknown>> = ({ children }) =
const { locale } = useRouter();
useEffect(() => {
dayjs.extend(utc);
dayjs.extend(relativeTime);
// Locales
require('dayjs/locale/ar');
require('dayjs/locale/bg');
require('dayjs/locale/bn');
require('dayjs/locale/cs');
require('dayjs/locale/da');
@ -19,6 +22,7 @@ const DateWrapper: React.FC<React.PropsWithChildren<unknown>> = ({ children }) =
require('dayjs/locale/en');
require('dayjs/locale/es');
require('dayjs/locale/fa');
require('dayjs/locale/fi');
require('dayjs/locale/fr');
require('dayjs/locale/he');
require('dayjs/locale/hi');

View File

@ -4,12 +4,12 @@ services:
postgres:
image: postgres:14.2-alpine
container_name: postgres
ports:
- 5432:5432
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
ports:
- 5432:5432
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:

View File

@ -46,20 +46,25 @@ You have complete control over what goes into your resume, how it looks, what co
- Arabic (اَلْعَرَبِيَّةُ)
- Bengali (বাংলা)
- Bulgarian (български)
- Chinese (中文)
- Czech (čeština)
- Danish (Dansk)
- Dutch (Nederlands)
- English
- Finnish (Suomi)
- French (Français)
- German (Deutsch)
- Greek (Ελληνικά)
- Hebrew (Ivrit)
- Hindi (हिन्दी)
- Hungarian (Magyar)
- Indonesian (Bahasa Indonesia)
- Italian (Italiano)
- Kannada (ಕನ್ನಡ)
- Malayalam (മലയാളം)
- Odia (ଓଡ଼ିଆ)
- Persian (Farsi)
- Polish (Polski)
- Portuguese (Português)
- Russian (русский)

View File

@ -3,3 +3,9 @@ sidebar_position: 1
---
# Creating an account
Enter your basic information or sign up with a Google account.
<a href="https://rxresu.me" target="_blank">
<img src="https://res.cloudinary.com/dn2mupqo0/image/upload/v1655879734/Register_lnoueb.png" type="image"></img>
</a>

View File

@ -3,3 +3,22 @@ sidebar_position: 2
---
# Create a new resume
To create a new resume from scratch, click on the selected part.
<a href="https://rxresu.me/dashboard">
<img src="https://res.cloudinary.com/dn2mupqo0/image/upload/v1655880844/CreateNew_kxvi9x.png" type="image"></img>
</a>
<p>
After you click on it, enter name and select whether you want it publicly accessible
<img align="center" src="https://res.cloudinary.com/dn2mupqo0/image/upload/v1655884469/on-button_a5kfbz.png" height='25' type="image"></img> or not
<img align="center" src="https://res.cloudinary.com/dn2mupqo0/image/upload/v1655884949/off-button_rrkz3g.png" height='25' type="image"></img> . You can also change it later from the sharing <a href="https://res.cloudinary.com/dn2mupqo0/image/upload/v1655889311/toggle_jcmfix.gif">see where</a>.
</p>
<h3> Now it's look like ⚡</h3>
<a href="https://rxresu.me/dashboard">
<img src="https://res.cloudinary.com/dn2mupqo0/image/upload/v1655882355/Screenshot_2022-06-22_at_12.48.42_PM_dx6714.png" type="image"></img>
</a>

View File

@ -14,14 +14,14 @@
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@algolia/client-search": "^4.13.1",
"@docusaurus/core": "2.0.0-beta.21",
"@docusaurus/preset-classic": "2.0.0-beta.21",
"@mdx-js/react": "2.1.2",
"clsx": "^1.1.1",
"prism-react-renderer": "^1.3.3",
"react": ">=16.13.1 <17.0.0 || >=17.0.0 <18.0.0",
"react-dom": ">=16.8.4 <17.0.0 || >=17.0.0 <18.0.0"
"@algolia/client-search": "^4.14.2",
"@docusaurus/core": "2.0.1",
"@docusaurus/preset-classic": "2.0.1",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"browserslist": {
"production": [
@ -36,7 +36,7 @@
]
},
"devDependencies": {
"@types/react": ">=16.8.0 <19.0.0",
"@types/react": "^17.0.2",
"typescript": "^4.7.4"
}
}

25
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "reactive-resume",
"version": "3.4.6",
"version": "3.5.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "reactive-resume",
"version": "3.4.6",
"version": "3.5.3",
"workspaces": [
"schema",
"client",
@ -28886,6 +28886,21 @@
},
"server/*": {
"extraneous": true
},
"node_modules/@next/swc-freebsd-x64": {
"version": "12.2.0",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.0.tgz",
"integrity": "sha512-gRiAw8g3Akf6niTDLEm1Emfa7jXDjvaAj/crDO8hKASKA4Y1fS4kbi/tyWw5VtoFI4mUzRmCPmZ8eL0tBSG58A==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 10"
}
}
},
"dependencies": {
@ -49808,6 +49823,12 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.2.tgz",
"integrity": "sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA=="
},
"@next/swc-freebsd-x64": {
"version": "12.2.0",
"resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.0.tgz",
"integrity": "sha512-gRiAw8g3Akf6niTDLEm1Emfa7jXDjvaAj/crDO8hKASKA4Y1fS4kbi/tyWw5VtoFI4mUzRmCPmZ8eL0tBSG58A==",
"optional": true
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "reactive-resume",
"version": "3.4.6",
"version": "3.5.3",
"private": true,
"workspaces": [
"schema",
@ -34,20 +34,17 @@
"start": "env-cmd --silent concurrently --kill-others \"pnpm run start:*\""
},
"dependencies": {
"@aws-sdk/client-s3": "^3.113.0",
"@docusaurus/core": "^2.0.0-beta.21",
"@docusaurus/preset-classic": "^2.0.0-beta.21",
"concurrently": "^7.2.2",
"concurrently": "^7.3.0",
"env-cmd": "^10.1.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.28.0",
"@typescript-eslint/parser": "^5.28.0",
"@typescript-eslint/eslint-plugin": "^5.33.0",
"@typescript-eslint/parser": "^5.33.0",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.18.0",
"eslint": "^8.21.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"husky": "^8.0.1",

8249
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.18.0",
"eslint": "^8.21.0",
"typescript": "^4.7.4"
}
}

View File

@ -10,29 +10,29 @@
"lint": "eslint --fix --ext .ts ./src"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.113.0",
"@nestjs/axios": "^0.0.8",
"@nestjs/common": "^8.4.7",
"@nestjs/config": "^2.1.0",
"@nestjs/core": "^8.4.7",
"@nestjs/jwt": "^8.0.1",
"@nestjs/mapped-types": "^1.0.1",
"@nestjs/passport": "^8.2.2",
"@nestjs/platform-express": "^8.4.7",
"@nestjs/schedule": "^2.0.1",
"@nestjs/serve-static": "^2.2.2",
"@nestjs/terminus": "^8.0.8",
"@nestjs/typeorm": "^8.1.4",
"@aws-sdk/client-s3": "^3.145.0",
"@nestjs/axios": "^0.1.0",
"@nestjs/common": "^9.0.9",
"@nestjs/config": "^2.2.0",
"@nestjs/core": "^9.0.9",
"@nestjs/jwt": "^9.0.0",
"@nestjs/mapped-types": "^1.1.0",
"@nestjs/passport": "^9.0.0",
"@nestjs/platform-express": "^9.0.9",
"@nestjs/schedule": "^2.1.0",
"@nestjs/serve-static": "^3.0.0",
"@nestjs/terminus": "^9.1.1",
"@nestjs/typeorm": "^9.0.1",
"@sendgrid/mail": "^7.7.0",
"@types/passport": "^1.0.9",
"@types/passport": "^1.0.10",
"bcrypt": "^5.0.1",
"cache-manager": "^4.0.1",
"cache-manager": "^4.1.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"cookie-parser": "^1.4.6",
"csvtojson": "^2.0.10",
"dayjs": "^1.11.3",
"google-auth-library": "^8.0.2",
"dayjs": "^1.11.4",
"google-auth-library": "^8.1.1",
"joi": "^17.6.0",
"lodash": "^4.17.21",
"multer": "^1.4.4",
@ -43,30 +43,30 @@
"passport-local": "^1.0.0",
"pdf-lib": "^1.17.1",
"pg": "^8.7.3",
"playwright-chromium": "^1.22.2",
"playwright-chromium": "^1.25.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.5.5",
"typeorm": "0.3.6",
"rxjs": "^7.5.6",
"typeorm": "0.3.7",
"uuid": "^8.3.2"
},
"devDependencies": {
"@nestjs/cli": "^8.2.6",
"@nestjs/schematics": "^8.0.11",
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.1",
"@reactive-resume/schema": "workspace:*",
"@types/bcrypt": "^5.0.0",
"@types/cookie-parser": "^1.4.3",
"@types/express": "^4.17.13",
"@types/lodash": "^4.14.182",
"@types/multer": "^1.4.7",
"@types/node": "^18.0.0",
"eslint": "^8.18.0",
"@types/node": "^18.7.1",
"eslint": "^8.21.0",
"prettier": "^2.7.1",
"source-map-support": "^0.5.21",
"ts-loader": "^9.3.0",
"ts-node": "^10.8.1",
"tsconfig-paths": "^4.0.0",
"ts-loader": "^9.3.1",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.1.0",
"typescript": "^4.7.4",
"webpack": "^5.73.0"
"webpack": "^5.74.0"
}
}

View File

@ -7,5 +7,4 @@ export default registerAs('storage', () => ({
urlPrefix: process.env.STORAGE_URL_PREFIX,
accessKey: process.env.STORAGE_ACCESS_KEY,
secretKey: process.env.STORAGE_SECRET_KEY,
s3Enabled: process.env.STORAGE_S3_ENABLED,
}));

View File

@ -15,6 +15,7 @@ import {
} from '@reactive-resume/schema';
import csv from 'csvtojson';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { readFile, unlink } from 'fs/promises';
import { cloneDeep, get, isEmpty, merge } from 'lodash';
import StreamZip from 'node-stream-zip';
@ -28,7 +29,9 @@ import { ResumeService } from '@/resume/resume.service';
@Injectable()
export class IntegrationsService {
constructor(private resumeService: ResumeService) {}
constructor(private resumeService: ResumeService) {
dayjs.extend(utc);
}
async linkedIn(userId: number, path: string): Promise<ResumeEntity> {
let archive: StreamZip.StreamZipAsync;
@ -39,7 +42,7 @@ export class IntegrationsService {
const resume: Partial<Resume> = cloneDeep(defaultState);
// Basics
const timestamp = dayjs().format(FILENAME_TIMESTAMP);
const timestamp = dayjs().utc().format(FILENAME_TIMESTAMP);
merge<Partial<Resume>, DeepPartial<Resume>>(resume, {
name: `Imported from LinkedIn (${timestamp})`,
slug: `imported-from-linkedin-${timestamp}`,
@ -269,7 +272,7 @@ export class IntegrationsService {
const resume: Partial<Resume> = cloneDeep(defaultState);
// Metadata
const timestamp = dayjs().format(FILENAME_TIMESTAMP);
const timestamp = dayjs().utc().format(FILENAME_TIMESTAMP);
merge<Partial<Resume>, DeepPartial<Resume>>(resume, {
name: `Imported from JSON Resume (${timestamp})`,
slug: `imported-from-json-resume-${timestamp}`,
@ -604,7 +607,7 @@ export class IntegrationsService {
const resume: Partial<Resume> = cloneDeep(jsonResume);
// Metadata
const timestamp = dayjs().format(FILENAME_TIMESTAMP);
const timestamp = dayjs().utc().format(FILENAME_TIMESTAMP);
merge<Partial<Resume>, DeepPartial<Resume>>(resume, {
name: `Imported from Reactive Resume (${timestamp})`,
slug: `imported-from-reactive-resume-${timestamp}`,
@ -625,7 +628,7 @@ export class IntegrationsService {
const resume: Partial<Resume> = cloneDeep(defaultState);
// Metadata
const timestamp = dayjs().format(FILENAME_TIMESTAMP);
const timestamp = dayjs().utc().format(FILENAME_TIMESTAMP);
merge<Partial<Resume>, DeepPartial<Resume>>(resume, {
name: `Imported from Reactive Resume V2 (${timestamp})`,
slug: `imported-from-reactive-resume-v2-${timestamp}`,
@ -948,6 +951,6 @@ export class IntegrationsService {
}
private parseDate = (date: string): string => {
return isEmpty(date) ? '' : dayjs(date).toISOString();
return isEmpty(date) ? '' : dayjs(date).utc().toISOString();
};
}

View File

@ -7,7 +7,11 @@ import { User } from '@/users/entities/user.entity';
@Injectable()
export class MailService {
constructor(private configService: ConfigService) {
SendGrid.setApiKey(this.configService.get<string>('sendgrid.apiKey'));
const sendGridApiKey = this.configService.get<string>('sendgrid.apiKey');
if (sendGridApiKey) {
SendGrid.setApiKey(this.configService.get<string>('sendgrid.apiKey'));
}
}
async sendEmail(mail: SendGrid.MailDataRequired) {

View File

@ -4,7 +4,7 @@ import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm';
import { Resume as ResumeSchema } from '@reactive-resume/schema';
import fs from 'fs';
import { pick, sample, set } from 'lodash';
import { isEmpty, pick, sample, set } from 'lodash';
import { nanoid } from 'nanoid';
import { extname } from 'path';
import { Repository } from 'typeorm';
@ -31,7 +31,8 @@ export class ResumeService {
private configService: ConfigService,
private usersService: UsersService
) {
this.s3Enabled = configService.get<string>('storage.s3Enabled') !== 'false';
this.s3Enabled = !isEmpty(configService.get<string>('storage.bucket'));
if (this.s3Enabled) {
this.s3Client = new S3({
endpoint: configService.get<string>('storage.endpoint'),
@ -237,6 +238,7 @@ export class ResumeService {
const filename = new Date().getTime() + extname(file.originalname);
let updatedResume = null;
if (this.s3Enabled) {
const urlPrefix = this.configService.get<string>('storage.urlPrefix');
const key = `uploads/${userId}/${id}/${filename}`;
@ -271,6 +273,7 @@ export class ResumeService {
async deletePhoto(id: number, userId: number) {
const resume = await this.findOne(id, userId);
const publicUrl = resume.basics.photo.url;
if (this.s3Enabled) {
const urlPrefix = this.configService.get<string>('storage.urlPrefix');
const key = publicUrl.replace(urlPrefix, '');
@ -291,6 +294,7 @@ export class ResumeService {
});
}
}
const updatedResume = set(resume, 'basics.photo.url', '');
return this.resumeRepository.save<Resume>(updatedResume);