Compare commits

..

439 Commits

Author SHA1 Message Date
b4381a22f3 remove VERSION env dependency from server 2023-04-06 15:03:53 +02:00
ba6ca4d220 update build commands for pnpm on Dockerfile 2023-04-06 14:42:36 +02:00
5486906b05 use corepack to install pnpm, over regular method 2023-04-06 13:08:51 +02:00
7348b295cb upgrade gradle version from 7.4.0 to 7.4.2 2023-04-06 12:40:57 +02:00
025762fdf6 update Gradle distributions on Android App 2023-04-06 11:58:00 +02:00
96411cdb90 remove turbo from the workspace 2023-04-06 11:50:28 +02:00
9c0c6076b3 update pnpm in dockerfile 2023-04-05 09:25:28 +02:00
36bf729161 update dependencies, fix typescript issues, optimize lodash imports 2023-04-05 09:06:49 +02:00
3a430ad98c bump up version to 3.6.19 2023-04-04 23:47:28 +02:00
90a8610dd7 update dependencies 2023-04-04 23:47:02 +02:00
d62ddab140 Merge pull request #1276 from AmruthPillai/dependabot/gradle/app/org.jetbrains.kotlin.android-1.8.20
Bump org.jetbrains.kotlin.android from 1.8.10 to 1.8.20 in /app
2023-04-04 12:53:30 +02:00
ca0186bb67 Merge pull request #1268 from AmruthPillai/dependabot/docker/server/playwright-v1.32.1-focal
Bump playwright from v1.30.0-focal to v1.32.1-focal in /server
2023-04-04 12:44:15 +02:00
88ac8389ea Merge pull request #1267 from AmruthPillai/dependabot/github_actions/actions/checkout-3.5.0
Bump actions/checkout from 3.3.0 to 3.5.0
2023-04-04 11:38:14 +02:00
2f3864fff2 Merge pull request #1254 from AmruthPillai/dependabot/github_actions/docker/setup-buildx-action-2.5.0
Bump docker/setup-buildx-action from 2.4.0 to 2.5.0
2023-04-04 11:38:03 +02:00
7878e52cc4 Merge pull request #1227 from AmruthPillai/i18n_main
New Crowdin updates
2023-04-04 11:37:51 +02:00
08b1967a4e Bump org.jetbrains.kotlin.android from 1.8.10 to 1.8.20 in /app
Bumps [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) from 1.8.10 to 1.8.20.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/commits)

---
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>
2023-04-03 03:02:02 +00:00
b870ca8297 New translations dashboard.json (Korean) 2023-04-01 21:34:54 +02:00
1507c54671 New translations common.json (Korean) 2023-04-01 21:34:53 +02:00
0984ca4daf New translations modals.json (Korean) 2023-04-01 21:34:51 +02:00
438798f8de New translations landing.json (Korean) 2023-04-01 21:34:49 +02:00
27aadb8948 New translations builder.json (Korean) 2023-04-01 21:34:47 +02:00
244a4118cf New translations common.json (Korean) 2023-04-01 20:24:02 +02:00
cde320ce46 New translations dashboard.json (Hebrew) 2023-03-30 11:44:14 +02:00
4772df7618 New translations modals.json (Hebrew) 2023-03-30 11:44:11 +02:00
ecb95b35f3 New translations landing.json (Hebrew) 2023-03-30 11:44:07 +02:00
24b09af563 New translations builder.json (Hebrew) 2023-03-30 11:44:03 +02:00
9471fb4169 New translations dashboard.json (Hebrew) 2023-03-30 10:38:01 +02:00
2f296d6f08 New translations common.json (Hebrew) 2023-03-30 10:38:00 +02:00
cd3d3caa15 New translations modals.json (Hebrew) 2023-03-30 10:37:57 +02:00
440eefe46e Bump playwright from v1.30.0-focal to v1.32.1-focal in /server
Bumps playwright from v1.30.0-focal to v1.32.1-focal.

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 02:59:00 +00:00
5787e2badb Bump actions/checkout from 3.3.0 to 3.5.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0.
- [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.3.0...v3.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 02:58:28 +00:00
c235e5ab16 Bump docker/setup-buildx-action from 2.4.0 to 2.5.0
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.4.0 to 2.5.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2.4.0...v2.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-13 02:59:14 +00:00
f584c70f27 New translations landing.json (Danish) 2023-02-17 04:15:04 +05:30
3aa0279519 New translations builder.json (Danish) 2023-02-17 04:15:00 +05:30
6830aec2f9 New translations landing.json (Danish) 2023-02-17 01:27:01 +05:30
9a3d7af325 New translations common.json (French) 2023-02-12 19:25:54 +05:30
52f7e8557f New translations modals.json (French) 2023-02-12 19:25:50 +05:30
12c17d1c7c New translations landing.json (French) 2023-02-12 19:25:47 +05:30
67918187a1 New translations builder.json (French) 2023-02-12 19:25:46 +05:30
dcbc0c2b45 New translations dashboard.json (French) 2023-02-12 16:57:35 +05:30
26b6a741c2 New translations builder.json (French) 2023-02-12 16:57:29 +05:30
d7064129e8 Merge pull request #1225 from raphaelcangucu/feature.pt-BR
Translation fixes on LeftSideBar
2023-02-10 08:33:56 +05:30
279dd36a13 Fix translations for other languages 2023-02-08 19:19:48 -03:00
49e47b28de fix date and start to translate to pt-br 2023-02-08 15:43:23 -03:00
a782343e0a Merge pull request #1218 from AmruthPillai/dependabot/gradle/app/org.jetbrains.kotlin.android-1.8.10
Bump org.jetbrains.kotlin.android from 1.8.0 to 1.8.10 in /app
2023-02-08 02:03:17 +05:30
1e7821a46d Merge pull request #1217 from AmruthPillai/dependabot/github_actions/docker/setup-buildx-action-2.4.0
Bump docker/setup-buildx-action from 2.3.0 to 2.4.0
2023-02-08 02:03:08 +05:30
f7bea5a218 Merge pull request #1216 from AmruthPillai/dependabot/github_actions/docker/build-push-action-4.0.0
Bump docker/build-push-action from 3.3.0 to 4.0.0
2023-02-08 02:02:57 +05:30
05fa4f3192 Merge pull request #1190 from AmruthPillai/i18n_main
New Crowdin updates
2023-02-08 02:02:46 +05:30
ed357f0ebc Merge pull request #1215 from C4illin/main
Add ISO 8601 option
2023-02-08 02:02:36 +05:30
1774832a58 Bump org.jetbrains.kotlin.android from 1.8.0 to 1.8.10 in /app
Bumps [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) from 1.8.0 to 1.8.10.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/v1.8.10/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.8.0...v1.8.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>
2023-02-06 02:25:09 +00:00
2837befd52 Bump docker/setup-buildx-action from 2.3.0 to 2.4.0
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2.3.0...v2.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 02:20:21 +00:00
38d866c0c2 Bump docker/build-push-action from 3.3.0 to 4.0.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.3.0 to 4.0.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.3.0...v4.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 02:20:16 +00:00
87c7acf4f1 New translations modals.json (Swedish) 2023-02-06 01:53:14 +01:00
1bd68118ce New translations landing.json (Swedish) 2023-02-06 01:53:11 +01:00
5c34b28c80 New translations builder.json (Swedish) 2023-02-06 01:53:08 +01:00
c550183720 Add ISO 8601 option 2023-02-05 23:28:21 +01:00
3605579b1b Merge pull request #1206 from AmruthPillai/dependabot/github_actions/docker/setup-buildx-action-2.3.0
Bump docker/setup-buildx-action from 2.2.1 to 2.3.0
2023-01-30 08:40:37 +01:00
fa2e28688f Merge pull request #1207 from AmruthPillai/dependabot/docker/server/playwright-v1.30.0-focal
Bump playwright from v1.29.2-focal to v1.30.0-focal in /server
2023-01-30 08:40:27 +01:00
20f1031e28 Bump playwright from v1.29.2-focal to v1.30.0-focal in /server
Bumps playwright from v1.29.2-focal to v1.30.0-focal.

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 02:17:52 +00:00
292cb6d0ed Bump docker/setup-buildx-action from 2.2.1 to 2.3.0
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.2.1 to 2.3.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2.2.1...v2.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 02:16:52 +00:00
45f2dc1cfc Merge pull request #1195 from busches/castform-masthead-spacing
fix: extra whitespace in Castform header
2023-01-23 13:10:56 +01:00
e319dd3e3d fix: extra whitespace in Castform header
Using the Castform template without a summary, still has extra whitespace for the summary. This commit fixes the extra whitespace to not appear when no summary is present.
2023-01-22 17:48:27 -06:00
9678f7a6e5 New translations modals.json (Portuguese) 2023-01-22 22:58:07 +01:00
0cca4e21fb New translations landing.json (Portuguese) 2023-01-22 22:58:04 +01:00
f6758f191d New translations builder.json (Portuguese) 2023-01-22 22:58:01 +01:00
983662f877 New translations common.json (German) 2023-01-21 00:50:00 +01:00
c7fc28a5c5 New translations modals.json (German) 2023-01-21 00:49:57 +01:00
1f7c33e805 New translations common.json (German) 2023-01-20 23:41:22 +01:00
437cc331a8 New translations landing.json (German) 2023-01-20 23:41:15 +01:00
aef51375b8 New translations builder.json (German) 2023-01-20 23:41:14 +01:00
bdd65968e5 New translations dashboard.json (Spanish) 2023-01-20 19:04:27 +01:00
061a789c18 New translations modals.json (Spanish) 2023-01-20 19:04:23 +01:00
68507d0501 New translations builder.json (Spanish) 2023-01-20 19:04:19 +01:00
1e28c5adfa New translations modals.json (Romanian) 2023-01-20 10:41:28 +01:00
3b09550ebd New translations landing.json (Romanian) 2023-01-20 10:41:25 +01:00
16aef9cbec New translations builder.json (Romanian) 2023-01-20 10:41:22 +01:00
b24da90ba7 bump up version to 3.6.18 2023-01-19 07:55:12 +01:00
2aa7dbd3ad Merge pull request #1188 from AmruthPillai/feat/implement-self-serve-account-deletion
[Feature] Implement Self-Serve Account Deletion
2023-01-19 07:53:49 +01:00
9f8f2c4b8b remove console.log 2023-01-19 07:52:59 +01:00
5331ecccc1 i18n-ize the user profile modal 2023-01-19 07:51:43 +01:00
f2ec86940c Merge branch 'main' into feat/implement-self-serve-account-deletion 2023-01-19 07:34:11 +01:00
cd74e707ba update dependencies 2023-01-19 07:33:15 +01:00
ff101dbfac [Feature] Implement Self-Serve Account Deletion 2023-01-19 00:11:15 +01:00
5024c19f87 fix error messages not displaying toasts sometimes, add axios error interceptors 2023-01-18 21:36:05 +01:00
c9850b5815 Merge pull request #1183 from AmruthPillai/i18n_main
New Crowdin updates
2023-01-18 20:37:54 +01:00
6fe4e7d7e1 Merge pull request #1184 from AmruthPillai/dependabot/github_actions/docker/build-push-action-3.3.0
Bump docker/build-push-action from 3.2.0 to 3.3.0
2023-01-16 10:53:29 +01:00
a5b8b91e82 Bump docker/build-push-action from 3.2.0 to 3.3.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.2.0...v3.3.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>
2023-01-16 02:33:23 +00:00
cc7095adc3 New translations landing.json (Spanish) 2023-01-16 01:53:40 +01:00
e2703f55aa New translations builder.json (Spanish) 2023-01-16 01:53:37 +01:00
8c5849c988 Merge pull request #1172 from AmruthPillai/dependabot/github_actions/actions/checkout-3.3.0
Bump actions/checkout from 3.2.0 to 3.3.0
2023-01-09 10:02:35 +01:00
5322ab2420 Merge pull request #1173 from AmruthPillai/dependabot/docker/server/playwright-v1.29.2-focal
Bump playwright from v1.29.1-focal to v1.29.2-focal in /server
2023-01-09 10:02:27 +01:00
b84e6bcfb1 Bump playwright from v1.29.1-focal to v1.29.2-focal in /server
Bumps playwright from v1.29.1-focal to v1.29.2-focal.

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 02:06:20 +00:00
a4ab0174c7 Bump actions/checkout from 3.2.0 to 3.3.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0.
- [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.2.0...v3.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 02:05:40 +00:00
7e93b5a757 update dependencies 2023-01-04 22:15:13 +01:00
044820fa71 Update README.md 2023-01-04 16:05:30 +01:00
322178e8a4 Merge pull request #1165 from JadinHeaston/main
Fixing unconditional ```http://``` prefix.
2023-01-03 23:22:17 +01:00
6358fbad30 Adding check for ``addHttp()` to see if `mailto:` or `tel:`` is present.Signed-off-by: Jadin Heaston <jadin.heaston@como.gov> 2023-01-03 13:57:07 -06:00
d342c0a9af fix axios type issue 2023-01-03 17:17:35 +01:00
63084eebb4 feat(dependencies): ⬆️ update dependencies, fix date display issue, add more profile icons 2023-01-03 17:06:30 +01:00
3b4ea00db8 Merge pull request #1162 from AmruthPillai/dependabot/gradle/app/org.jetbrains.kotlin.android-1.8.0
Bump org.jetbrains.kotlin.android from 1.7.22 to 1.8.0 in /app
2023-01-03 16:51:17 +01:00
c8f7bffe7e Merge pull request #1160 from coolswood/main
fix: Gengar two cols bug
2023-01-03 16:51:09 +01:00
3ff56f89d9 Merge pull request #1158 from AmruthPillai/i18n_main
New Crowdin updates
2023-01-03 16:50:48 +01:00
7fb9f27837 Bump org.jetbrains.kotlin.android from 1.7.22 to 1.8.0 in /app
Bumps [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) from 1.7.22 to 1.8.0.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.7.22...v1.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-02 02:04:34 +00:00
c9685d4ce7 fix: Gengar two cols bug 2022-12-31 10:01:54 +02:00
4dc987e27d New translations landing.json (Persian) 2022-12-30 19:09:41 +01:00
f7af06ae9a New translations builder.json (Persian) 2022-12-30 18:12:15 +01:00
a5c337faa3 Merge pull request #1151 from AmruthPillai/dependabot/github_actions/digitalocean/action-doctl-2.3.0
Bump digitalocean/action-doctl from 2.2.0 to 2.3.0
2022-12-30 11:48:34 +01:00
fc4704f0a6 Merge pull request #1150 from AmruthPillai/dependabot/docker/server/playwright-v1.29.1-focal
Bump playwright from v1.29.0-focal to v1.29.1-focal in /server
2022-12-30 11:48:25 +01:00
d968334ada Merge pull request #1155 from coolswood/main
fix: overflow-y-auto
2022-12-29 21:37:29 +01:00
fea6d23178 fix: overflow-y-auto 2022-12-29 19:37:47 +02:00
3fefc95572 Bump digitalocean/action-doctl from 2.2.0 to 2.3.0
Bumps [digitalocean/action-doctl](https://github.com/digitalocean/action-doctl) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/digitalocean/action-doctl/releases)
- [Commits](https://github.com/digitalocean/action-doctl/compare/v2.2.0...v2.3.0)

---
updated-dependencies:
- dependency-name: digitalocean/action-doctl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 02:04:49 +00:00
b07e7d1213 Bump playwright from v1.29.0-focal to v1.29.1-focal in /server
Bumps playwright from v1.29.0-focal to v1.29.1-focal.

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 02:04:31 +00:00
d47b8bfb03 Merge pull request #1139 from AmruthPillai/dependabot/github_actions/actions/checkout-3.2.0
Bump actions/checkout from 3.1.0 to 3.2.0
2022-12-19 10:22:44 +01:00
5bf7fbdae1 Merge pull request #1140 from AmruthPillai/dependabot/docker/server/playwright-v1.29.0-focal
Bump playwright from v1.28.1-focal to v1.29.0-focal in /server
2022-12-19 10:22:34 +01:00
fca766b382 Bump playwright from v1.28.1-focal to v1.29.0-focal in /server
Bumps playwright from v1.28.1-focal to v1.29.0-focal.

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 02:06:27 +00:00
feadfb1b67 Bump actions/checkout from 3.1.0 to 3.2.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0.
- [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.1.0...v3.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 02:06:19 +00:00
e69000f221 Merge pull request #1137 from AmruthPillai/feat/add-remark-gfm-math-plugins
feat(client):  add github flavored syntax and math equations to markdown support
2022-12-17 10:27:19 +01:00
6b4a54465a feat(client): add github flavored syntax and math equations to markdown support 2022-12-17 10:19:25 +01:00
878659999f Merge pull request #1135 from AmruthPillai/i18n_main
New Crowdin updates
2022-12-17 09:53:13 +01:00
1868c47e30 New translations common.json (Dutch) 2022-12-17 09:48:12 +01:00
51442efc23 New translations common.json (German) 2022-12-17 09:48:07 +01:00
556e962ec5 refactor(client): 📝 add link to subreddit 2022-12-16 22:56:23 +01:00
b5ce67f863 Update README.md 2022-12-16 18:06:46 +01:00
c3ce89dc3a Update README.md 2022-12-16 18:04:22 +01:00
e87930c758 bump version to 3.6.16 2022-12-16 17:59:58 +01:00
815a693e58 Merge pull request #1134 from AmruthPillai/feature/configure-gitpod
Configure Gitpod for easier development and self-hosting
2022-12-16 17:58:50 +01:00
8287fcae96 add gitpod to README.md 2022-12-16 17:58:38 +01:00
cd7fe6c404 Remove .env.gitpod 2022-12-16 15:58:22 +00:00
d47d5dd819 build and run project finally, in gitpod 2022-12-16 16:52:37 +01:00
1919d79e43 fix url host parsing 2022-12-16 15:50:43 +00:00
ab08cd9e34 add sync await/done 2022-12-16 16:46:26 +01:00
2522bdd0a2 add onOpen: ignore to postgres port 2022-12-16 16:42:02 +01:00
f9b6aefffe create .env generation script 2022-12-16 16:39:29 +01:00
2ba6658a0b add CORS to server, input appUrl 2022-12-16 15:04:08 +00:00
dbc46f27a3 add postgres port 2022-12-16 14:12:43 +00:00
f21e1caed1 trying this now 2022-12-16 15:09:43 +01:00
4ffe2a6330 add 2022-12-16 15:03:22 +01:00
1bc0438872 remove 2022-12-16 15:03:06 +01:00
57fb9fdaea add dockerfile support to gitpod.yml 2022-12-16 14:01:17 +00:00
58ce641f18 add postgres to gitpod 2022-12-16 13:56:08 +00:00
5f4e7802e4 Merge branch 'main' into feature/configure-gitpod 2022-12-16 13:44:46 +00:00
42d3109ae1 Merge pull request #1128 from AmruthPillai/dependabot/gradle/app/org.jetbrains.kotlin.android-1.7.22
Bump org.jetbrains.kotlin.android from 1.7.21 to 1.7.22 in /app
2022-12-16 14:43:57 +01:00
f7ca7b97fa Merge pull request #1127 from AmruthPillai/dependabot/docker/server/playwright-v1.28.1-focal
Bump playwright from v1.28.0-focal to v1.28.1-focal in /server
2022-12-16 14:43:51 +01:00
f5d8a54134 Merge pull request #1130 from Jack-Kingdom/main
Fix: wait for networkidle event to ensure image load
2022-12-16 14:43:43 +01:00
eaec14dc62 initial gitpod configuration 2022-12-16 13:42:03 +00:00
c93b3264cd Bump playwright from v1.28.0-focal to v1.28.1-focal in /server
Bumps playwright from v1.28.0-focal to v1.28.1-focal.

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-16 13:34:56 +00:00
bf41aa9c6c feat(sentry): remove sentry integration 2022-12-16 14:34:15 +01:00
8af6bfd5ae Fix: wait for networkidle event to ensure image load 2022-12-10 02:55:38 +08:00
ab08c10874 Bump org.jetbrains.kotlin.android from 1.7.21 to 1.7.22 in /app
Bumps [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) from 1.7.21 to 1.7.22.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.7.21...v1.7.22)

---
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-12-05 02:08:23 +00:00
9af9a0284e set sentry user ID, if available and applicable 2022-12-03 00:15:08 +01:00
716a05032d one more attempt to fix sentry auth issue 2022-12-02 23:54:25 +01:00
43e43e7d76 one more attempt to fix sentry auth issue 2022-12-02 23:44:51 +01:00
c91af3668d attempt to fix sentry auth issue 2022-12-02 23:32:04 +01:00
52f41f0b3b bump version to v3.6.15 2022-12-02 23:22:54 +01:00
3b709d606b Merge pull request #1120 from AmruthPillai/feature/sentry-integration
[Feature] Sentry Integration (Optional for Self Hosted)
2022-12-02 23:21:59 +01:00
2e5fafac62 remove unnecessary envs 2022-12-02 23:21:00 +01:00
ea2aee2d25 add release version to sentry ci process 2022-12-02 23:16:48 +01:00
e36fbb5f64 Update .env.example 2022-12-02 22:13:07 +01:00
5221ef707b Merge branch 'main' into feature/sentry-integration 2022-12-02 22:10:58 +01:00
f0df806f01 remove link underline style 2022-12-02 22:10:08 +01:00
9d01d6a833 update version ot 3.6.14 2022-12-02 13:59:13 +01:00
1914ebb9ae fix links in PDF 2022-12-02 13:55:56 +01:00
686dba90c9 Merge pull request #1114 from tryallthethings/pdf-template-fix
Fix for links in PDFs, template fix
2022-12-02 13:41:37 +01:00
95dc3bf571 Merge pull request #1108 from tryallthethings/translation-fix
Translation fix
2022-12-02 13:37:35 +01:00
1c8fdbf848 Merge pull request #1107 from tryallthethings/main
fix: made some missing texts translatable
2022-12-02 13:37:25 +01:00
d8357c9959 Fix: Every other instance of invoked clsx hence adding it here as well. 2022-11-26 14:37:48 +01:00
90e994377b Fix: Adding quotation marks seems to fix #1112 2022-11-26 14:36:56 +01:00
82c6ee6d5d fix: Updated German translation. A lot of minor changes as well as rephrasing of whole sentences. This translation is now also 100% formal, instead of a mix of formal and informal. 2022-11-25 18:42:37 +01:00
7b615e73c3 fix: Changed German language description to formal 2022-11-25 18:42:00 +01:00
268e4a87fe Revert "fix: made some missing texts translatable"
This reverts commit deb4e0a0de.
2022-11-25 18:39:09 +01:00
73f8eb84c9 Revert "fix: Updated German translation. A lot of minor changes as well as rephrasing of whole sentences."
This reverts commit e0a42fd928.
2022-11-25 18:39:07 +01:00
a31ef89996 Revert "fix: Changed German language description to formal"
This reverts commit d6bca7ebab.
2022-11-25 18:38:55 +01:00
d6bca7ebab fix: Changed German language description to formal 2022-11-25 18:29:55 +01:00
e0a42fd928 fix: Updated German translation. A lot of minor changes as well as rephrasing of whole sentences. 2022-11-25 18:27:28 +01:00
deb4e0a0de fix: made some missing texts translatable
BREAKING CHANGE: locales without the new fields will display the field name
2022-11-25 18:22:29 +01:00
a687062866 Merge pull request #1105 from tryallthethings/patch-3
Update date.ts
2022-11-25 18:10:11 +01:00
700439c8a8 Update date.ts
Added a common date format for Germany.
2022-11-25 18:00:08 +01:00
fb09283e53 add some more properties for sentry 2022-11-25 13:07:40 +01:00
88ac365e03 use v1.28.0-focal instead of next-jammy 2022-11-25 11:52:14 +01:00
aec78cf875 lay the ground work for sentry integration 2022-11-25 11:32:57 +01:00
77c587681b using fetch instead of axios, should fix the issue 2022-11-24 22:25:23 +01:00
7ac8b906d9 add await 2022-11-24 22:16:00 +01:00
e9a5f86a6a using fetch instead of axios, server side 2022-11-24 22:14:01 +01:00
7238a3b50e some more logs 2022-11-24 22:01:00 +01:00
ebe13fa82e push a bunch of console.logs 2022-11-24 21:45:42 +01:00
6ee290a625 add logs to check what's wrong 2022-11-24 21:31:43 +01:00
69f2b7070f remove arm64 support for the time being, because of upstream support 2022-11-24 21:09:32 +01:00
11bea1c7c4 updating version to v3.6.13 2022-11-24 20:35:28 +01:00
68a1dc65c1 update pnpm-lock.yaml 2022-11-24 17:04:11 +01:00
4b1ce539d5 remove sentry integration 2022-11-24 16:58:36 +01:00
a6fbb8191d Update docker-build-push.yml 2022-11-24 16:32:22 +01:00
552ff281b8 I have no idea what I'm doing here. 2022-11-24 16:29:36 +01:00
54fad2f6d8 update docker-build-push.yml 2022-11-24 16:20:40 +01:00
78edcd7d0e fix typo in github workflow 2022-11-24 16:02:39 +01:00
a8034b21d5 attempting to fix github actions 2022-11-24 15:58:27 +01:00
f0e95905d2 trying out env instead of secrets 2022-11-24 15:44:28 +01:00
69a5276614 attempt to fix locale issue 2022-11-24 15:40:49 +01:00
2e62eea351 fix sentry issue: 28c5a41aea3c4435902046e56c435e56 2022-11-24 15:38:21 +01:00
13d972b8f3 update docker-build-push.yaml 2022-11-24 15:15:35 +01:00
03cb198e95 move from env to secrets 2022-11-24 15:11:55 +01:00
67ee55b502 fix env for sentry auth token 2022-11-24 15:01:33 +01:00
b5998d7f3a pass sentry token to docker build push step 2022-11-24 14:58:26 +01:00
f71cf99b77 remove .git from .dockerignore 2022-11-24 13:27:43 +01:00
a2092a6a39 revert version back to 3.6.12 2022-11-24 12:58:15 +01:00
43c09666a0 add sentry CLI to github actions 2022-11-24 11:42:03 +01:00
0da23f95fd Merge pull request #1101 from stonespheres/patch-1
Fix link typo
2022-11-24 11:25:17 +01:00
e8f44e2142 update pnpm-lock.yaml 2022-11-24 11:23:37 +01:00
fbb237e982 Fix link typo
Bad practice on my part for last commit - did not check before push.
Link under table of contents fixed and now directs to the documentation at https://docs.rxresu.me
2022-11-24 18:22:57 +08:00
7f7c1d7b87 update version to 3.6.13 2022-11-24 11:21:45 +01:00
be0b7f20f9 integrate sentry for error logging 2022-11-24 11:21:30 +01:00
0672988fff Merge pull request #1100 from stonespheres/patch-1
Fixed formatting and typos on README.md
2022-11-24 11:01:38 +01:00
75dad60cb5 Fixed formatting and typos on README.md
- Under Table of Contents: Fixed the formatting error for the link to the docs.
- Under Languages: fixed typo Ukranian -> Ukrainian
- Under Building from Source: ...head over to the doc's -> head over to the docs
2022-11-24 17:47:29 +08:00
0140e3fce0 update version to 3.6.12 2022-11-23 15:20:34 +01:00
42d0e14b98 fix styling issues and theme cascades across all templates 2022-11-23 15:20:04 +01:00
9a42d684fb add branching deploy condition 2022-11-23 14:15:36 +01:00
ab6ad65445 update github actions to a more streamlined workflow using gh matrix 2022-11-23 14:10:14 +01:00
b613764ccc fix matrix variable name 2022-11-23 13:59:25 +01:00
ac44d0489f change name of test action so as to not trigger further actions 2022-11-23 13:56:59 +01:00
c57e6fbbb8 fix versioning of github action package 2022-11-23 13:56:22 +01:00
6c6da215c8 add on: [workflow_dispatch] to test github action 2022-11-23 13:55:15 +01:00
be700c7629 Testing a new streamlined GitHub Actions workflow 2022-11-23 13:53:41 +01:00
b697f73492 fix #1096 2022-11-23 13:11:29 +01:00
3106f94989 - update version to v.3.6.11
- update dependencies to latest versions
2022-11-23 13:04:59 +01:00
50f41f73d5 Add detailed description to page title, to increase SEO 2022-11-23 12:57:07 +01:00
83e3f59e68 fix #1082 2022-11-23 12:47:29 +01:00
056c61e985 resolves #1061, resolves #1027, resolves #1007, resolves #1001, resolves #987, resolves #890, resolves #882, resolves #837 2022-11-23 12:24:17 +01:00
d1a1b68302 fix #1095: make PDF_DELETION_TIME optional, add default value 2022-11-23 11:51:28 +01:00
6bd7b9a50f Merge pull request #1092 from GETandSELECT/main
Update common.json - tiny translation error to German
2022-11-23 11:41:54 +01:00
e6967aab88 Update common.json 2022-11-22 10:03:14 +00:00
47e96803e3 fix password recovery link 2022-11-19 09:37:23 +01:00
f9ef4d0a64 fix max width of description 2022-11-18 09:42:59 +01:00
c4b4e6013f Merge pull request #1073 from AmruthPillai/dependabot/gradle/app/org.jetbrains.kotlin.android-1.7.21
Bump org.jetbrains.kotlin.android from 1.7.20 to 1.7.21 in /app
2022-11-15 11:36:04 +01:00
24bbc46c32 Merge pull request #1075 from RobbeVanslambrouck/main
fix typos in English and Dutch translation
2022-11-15 11:35:54 +01:00
85bc9ef124 fix typos in English and Dutch translation 2022-11-14 17:29:09 +01:00
33755a8573 remove console.log 2022-11-14 10:06:19 +01:00
ab45321889 fixes #1074 2022-11-14 10:05:51 +01:00
940b310f64 Bump org.jetbrains.kotlin.android from 1.7.20 to 1.7.21 in /app
Bumps [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) from 1.7.20 to 1.7.21.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.7.20...v1.7.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-11-14 02:06:07 +00:00
8026241b6c release: v3.6.9 2022-11-13 14:28:47 +01:00
89b35392bd Merge pull request #1060 from sashokbg/feat/multiple_work_sections
feat: additional work sections
2022-11-13 10:28:28 +01:00
62eb239ec4 Merge pull request #1023 from klejejs/main
Add PDF file caching
2022-11-13 10:28:19 +01:00
7fdf8c1f0c Merge pull request #1069 from arvaid/main
fixed grammatical and stylistic errors in Hungarian translation
2022-11-07 09:28:00 +01:00
538697238a fixed grammatical and stylistic errors in Hungarian translation 2022-11-06 14:46:55 +01:00
7bc4a998fe feat: additional work sections 2022-11-03 17:59:15 +01:00
e33df485ab Merge pull request #951 from Leopere/patch-3
Cleanup superfluous docker-compose.yml declarations
2022-11-02 23:36:21 +01:00
36ae54fe17 Merge branch 'main' into patch-3 2022-11-02 23:36:13 +01:00
50958fd6df Merge pull request #1058 from klejejs/fix/zip_file_upload_crash
Fix server crash when non-zip file is uploaded
2022-10-26 07:57:49 +02:00
e9e595f0d0 Fix server crash when non-zip file is uploaded 2022-10-25 22:03:18 +03:00
43ddfba777 Add scheduled deletion for cached PDF files 2022-10-25 21:10:40 +03:00
78a32961d7 Add PDF file caching 2022-10-25 20:16:39 +03:00
9b1f3eda05 Merge pull request #1053 from AmruthPillai/i18n_main
New Crowdin updates
2022-10-24 07:58:36 +02:00
1154621e5c Merge pull request #1057 from AmruthPillai/dependabot/github_actions/docker/setup-buildx-action-2.2.1
Bump docker/setup-buildx-action from 2.1.0 to 2.2.1
2022-10-24 07:58:25 +02:00
e7aeee77a7 Merge pull request #1056 from AmruthPillai/dependabot/github_actions/digitalocean/action-doctl-2.2.0
Bump digitalocean/action-doctl from 2.1.1 to 2.2.0
2022-10-24 07:58:16 +02:00
fab3988a36 Bump docker/setup-buildx-action from 2.1.0 to 2.2.1
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.1.0 to 2.2.1.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2.1.0...v2.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-24 02:53:50 +00:00
354cad88d3 Bump digitalocean/action-doctl from 2.1.1 to 2.2.0
Bumps [digitalocean/action-doctl](https://github.com/digitalocean/action-doctl) from 2.1.1 to 2.2.0.
- [Release notes](https://github.com/digitalocean/action-doctl/releases)
- [Commits](https://github.com/digitalocean/action-doctl/compare/v2.1.1...v2.2.0)

---
updated-dependencies:
- dependency-name: digitalocean/action-doctl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-24 02:53:45 +00:00
876f930f30 New translations builder.json (Indonesian) 2022-10-21 05:55:29 +02:00
5b3ea46f0f Merge pull request #1045 from AmruthPillai/dependabot/github_actions/docker/setup-buildx-action-2.1.0
Bump docker/setup-buildx-action from 2.0.0 to 2.1.0
2022-10-17 10:39:55 +02:00
37a2563c11 Merge pull request #1047 from AmruthPillai/dependabot/github_actions/docker/build-push-action-3.2.0
Bump docker/build-push-action from 3.1.1 to 3.2.0
2022-10-17 10:39:42 +02:00
cb977a146b Merge pull request #1046 from AmruthPillai/dependabot/github_actions/docker/login-action-2.1.0
Bump docker/login-action from 2.0.0 to 2.1.0
2022-10-17 10:39:31 +02:00
72b2551b6d Merge pull request #1044 from AmruthPillai/dependabot/github_actions/docker/setup-qemu-action-2.1.0
Bump docker/setup-qemu-action from 2.0.0 to 2.1.0
2022-10-17 10:39:22 +02:00
c94633e616 Bump docker/build-push-action from 3.1.1 to 3.2.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.1.1...v3.2.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-10-17 02:21:39 +00:00
7fee2d670f Bump docker/login-action from 2.0.0 to 2.1.0
Bumps [docker/login-action](https://github.com/docker/login-action) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2.0.0...v2.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-17 02:21:36 +00:00
837b06eb38 Bump docker/setup-buildx-action from 2.0.0 to 2.1.0
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2.0.0...v2.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-17 02:21:33 +00:00
2b8860b21c Bump docker/setup-qemu-action from 2.0.0 to 2.1.0
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2.0.0...v2.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-17 02:21:31 +00:00
3a7b98d30e Fix issue with variable accessor 2022-10-15 23:47:16 +02:00
284a39aa77 add libc6-compat to dockerfile 2022-10-15 01:27:06 +02:00
c14c9955dd modify docker-build-push action 2022-10-15 01:19:19 +02:00
4de787157a update dependencies 2022-10-15 01:10:10 +02:00
6bc6425a01 Merge pull request #1039 from AmruthPillai/i18n_main
New Crowdin updates
2022-10-15 01:03:08 +02:00
6051305908 New translations builder.json (Turkish) 2022-10-15 00:59:54 +02:00
5e13253454 New translations builder.json (Swedish) 2022-10-15 00:59:53 +02:00
c1fd2b40e3 New translations builder.json (Serbian (Cyrillic)) 2022-10-15 00:59:52 +02:00
fccf7a7b56 New translations builder.json (Russian) 2022-10-15 00:59:51 +02:00
5098b094db New translations builder.json (Portuguese) 2022-10-15 00:59:50 +02:00
7c1eb74aca New translations builder.json (Polish) 2022-10-15 00:59:49 +02:00
7f9ede8ff0 New translations builder.json (Norwegian) 2022-10-15 00:59:48 +02:00
172b23e429 New translations builder.json (Dutch) 2022-10-15 00:59:47 +02:00
f287ca6183 New translations builder.json (Korean) 2022-10-15 00:59:46 +02:00
7548e36aaf New translations builder.json (Japanese) 2022-10-15 00:59:45 +02:00
2f754616b4 New translations builder.json (Ukrainian) 2022-10-15 00:59:44 +02:00
dc51f6f9b2 New translations builder.json (Italian) 2022-10-15 00:59:43 +02:00
0cdac1d657 New translations builder.json (Hebrew) 2022-10-15 00:59:42 +02:00
c3cfe8ae7b New translations builder.json (Finnish) 2022-10-15 00:59:41 +02:00
08435c173b New translations builder.json (Greek) 2022-10-15 00:59:40 +02:00
62cc2d6eac New translations builder.json (German) 2022-10-15 00:59:39 +02:00
5a6f6e2b6c New translations builder.json (Danish) 2022-10-15 00:59:38 +02:00
2dfa8c04a1 New translations builder.json (Czech) 2022-10-15 00:59:37 +02:00
63e3f94d2d New translations builder.json (Catalan) 2022-10-15 00:59:36 +02:00
7f45a8cb7f New translations builder.json (Bulgarian) 2022-10-15 00:59:35 +02:00
4377ebb811 New translations builder.json (Arabic) 2022-10-15 00:59:35 +02:00
ed3af6975b New translations builder.json (Spanish) 2022-10-15 00:59:34 +02:00
7904905a8b New translations builder.json (Hungarian) 2022-10-15 00:59:33 +02:00
bd2e6d2bf2 New translations builder.json (French) 2022-10-15 00:59:32 +02:00
ae4e9e688e New translations builder.json (Chinese Simplified) 2022-10-15 00:59:31 +02:00
78c45b7019 New translations builder.json (Indonesian) 2022-10-15 00:59:30 +02:00
9a2fbbec4e New translations builder.json (Vietnamese) 2022-10-15 00:59:25 +02:00
93d751d9be New translations builder.json (Nepali) 2022-10-15 00:59:24 +02:00
9926ed2262 New translations builder.json (Odia) 2022-10-15 00:59:23 +02:00
62220d20e7 New translations builder.json (Kannada) 2022-10-15 00:59:22 +02:00
2f6108cd29 New translations builder.json (Malayalam) 2022-10-15 00:59:21 +02:00
7aeed37869 New translations builder.json (Hindi) 2022-10-15 00:59:20 +02:00
ed99659b7b New translations builder.json (Marathi) 2022-10-15 00:59:19 +02:00
5e33d00910 New translations builder.json (Bengali) 2022-10-15 00:59:18 +02:00
c00d0341e6 New translations builder.json (Tamil) 2022-10-15 00:59:17 +02:00
511ae036c2 New translations builder.json (Khmer) 2022-10-15 00:59:16 +02:00
1642ec9ba2 New translations builder.json (Persian) 2022-10-15 00:59:15 +02:00
1115bc2b69 New translations builder.json (Amharic) 2022-10-15 00:59:14 +02:00
27e5c7811c New translations builder.json (Romanian) 2022-10-15 00:59:13 +02:00
3b739f0bb7 New translations common.json (Marathi) 2022-10-15 00:56:28 +02:00
d937ba2056 New translations common.json (Khmer) 2022-10-15 00:56:25 +02:00
de110d7de1 New translations common.json (Vietnamese) 2022-10-15 00:56:23 +02:00
b03229b5e0 New translations common.json (Korean) 2022-10-15 00:56:16 +02:00
280fc73c7b New translations common.json (Hungarian) 2022-10-15 00:56:13 +02:00
677ad2a115 New translations common.json (Odia) 2022-10-15 00:56:12 +02:00
f394b26d18 New translations common.json (Nepali) 2022-10-15 00:56:11 +02:00
aab4e2e941 New translations common.json (Czech) 2022-10-15 00:55:50 +02:00
f0f552a635 Feature: Toggle Page Size between ISO A4 and US Letter 2022-10-15 00:54:59 +02:00
136e143e12 Merge pull request #1032 from kmkhant/main
FIX whole page reload when press enter
2022-10-13 19:16:16 +02:00
857e4b8670 Merge branch 'main' of https://github.com/kmkhant/Reactive-Resume 2022-10-13 20:45:28 +06:30
ff03d41d97 feat:add pressing return(enter) to submit modal 2022-10-13 20:40:51 +06:30
2bad37aaf3 Merge branch 'main' into main 2022-10-13 17:08:08 +06:30
3a40fbf78b Merge pull request #1036 from dnltsk/main
cleanup - removed temp thumbnail file
2022-10-13 09:43:41 +02:00
49c638fb18 Delete .DS_Store 2022-10-12 22:37:08 +02:00
50e8d60773 fix interest form reloads when press enter 2022-10-10 18:24:57 +06:30
bf157a8d1a Merge pull request #1030 from AmruthPillai/dependabot/github_actions/actions/checkout-3.1.0
Bump actions/checkout from 3.0.2 to 3.1.0
2022-10-10 08:31:58 +02:00
c4f5955fcd Merge pull request #1031 from SSHSRN/loginModal
Updated login modal
2022-10-10 08:31:48 +02:00
86d33b0f21 updated login modal
Signed-off-by: SRIHARI S <sshsrn@gmail.com>
2022-10-10 08:17:04 +05:30
56bca30639 Bump actions/checkout from 3.0.2 to 3.1.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.0.2 to 3.1.0.
- [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.2...v3.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-10 02:15:49 +00:00
eed3b76959 ignore axios ts error 2022-10-07 11:04:13 +02:00
615eb3ad5d update dependencies, update version to 3.6.7 2022-10-07 10:44:29 +02:00
b505199319 add Amharic language 2022-10-07 10:31:03 +02:00
91e55e642c Merge pull request #1025 from AmruthPillai/i18n_main
New Crowdin updates
2022-10-07 10:18:53 +02:00
f549d8749a New translations landing.json (French) 2022-10-07 10:18:05 +02:00
f31123659e Merge pull request #1020 from arefathi/amharic-locale
Completed Amharic translations
2022-10-07 10:12:59 +02:00
93633c9415 Completed Amharic translations 2022-10-04 14:14:28 +03:00
19b9fa4857 Merge pull request #1021 from Rohanfizz/main
Fixed digitalOcean Sponsor logo
2022-10-04 10:25:09 +02:00
a5c84214f9 Fixed digitalOcean Sponsor logo 2022-10-03 23:35:26 +05:30
65bb8b5ceb Worked on Amharic translations 2022-10-03 16:15:52 +03:00
06a11a1f2a Merge pull request #1018 from AmruthPillai/dependabot/gradle/app/org.jetbrains.kotlin.android-1.7.20
Bump org.jetbrains.kotlin.android from 1.7.10 to 1.7.20 in /app
2022-10-03 07:20:15 +02:00
53eedc8500 Bump org.jetbrains.kotlin.android from 1.7.10 to 1.7.20 in /app
Bumps [org.jetbrains.kotlin.android](https://github.com/JetBrains/kotlin) from 1.7.10 to 1.7.20.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/v1.7.20/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.7.10...v1.7.20)

---
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-10-03 02:27:56 +00:00
4b2d9d7026 skip React.FC for App 2022-09-15 20:40:19 +02:00
045145ed67 upgrade version to v3.6.6 2022-09-15 19:57:46 +02:00
ec27e5e6ab fix language difference when printing resume 2022-09-15 19:49:57 +02:00
2faa15db5a Merge pull request #997 from AmruthPillai/i18n_main
New Crowdin updates
2022-09-13 07:00:22 +02:00
2c2893d5fc New translations common.json (Khmer) 2022-09-07 04:39:03 +02:00
19c7ebe8a4 Update README.md 2022-09-04 08:12:55 +02:00
c24847ac0b Update README.md 2022-09-04 08:10:54 +02:00
7137694832 update app version to 3.6.5 2022-08-29 20:44:24 +02:00
049de38da2 fix local storage upload of photo/avatar 2022-08-29 20:44:07 +02:00
17019e446b Update FUNDING.yml 2022-08-29 19:57:16 +02:00
d73ee7b7f8 reformat docker setup to remove traefik dependency 2022-08-29 09:03:23 +02:00
2c95dc2ac8 Merge pull request #990 from AymaneBoukrouh/main
update landing.json
2022-08-29 07:48:54 +02:00
e148dd3e82 Merge pull request #1 from AymaneBoukrouh/AymaneBoukrouh-fr-locale-fix
update landing.json
2022-08-28 21:42:43 +01:00
0aa2d61c55 update landing.json
Fix typo (mauvaiss -> mauvaise)
Fix innacuracy (pistage -> traçabilité), pistage (tracking) means car track, and not user tracking.
2022-08-28 21:40:07 +01:00
0b2c1ffd26 add ko, mr locales 2022-08-28 16:22:14 +02:00
a531e8cd89 Merge pull request #989 from AmruthPillai/i18n_main
New Crowdin updates
2022-08-28 15:50:51 +02:00
152e386141 New translations landing.json (Odia) 2022-08-28 15:50:22 +02:00
87189cd045 New translations landing.json (Kannada) 2022-08-28 15:50:21 +02:00
114b04a740 New translations landing.json (Malayalam) 2022-08-28 15:50:20 +02:00
383cde53df New translations landing.json (Bengali) 2022-08-28 15:50:19 +02:00
9bf98d3c49 New translations landing.json (Tamil) 2022-08-28 15:50:18 +02:00
e62f0a3f5e New translations landing.json (Persian) 2022-08-28 15:50:17 +02:00
10fb7b143a New translations landing.json (Indonesian) 2022-08-28 15:50:16 +02:00
67ba58e798 New translations landing.json (Vietnamese) 2022-08-28 15:50:15 +02:00
179cf99f83 New translations landing.json (Chinese Simplified) 2022-08-28 15:50:14 +02:00
81a51d487b New translations landing.json (Turkish) 2022-08-28 15:50:13 +02:00
b41b50565a New translations landing.json (Hindi) 2022-08-28 15:50:13 +02:00
8cd073eb62 New translations landing.json (Swedish) 2022-08-28 15:50:12 +02:00
f4f8502703 New translations landing.json (Russian) 2022-08-28 15:50:03 +02:00
0d079d7b24 New translations landing.json (Portuguese) 2022-08-28 15:50:02 +02:00
167f7c902f New translations landing.json (Polish) 2022-08-28 15:49:50 +02:00
7c630df927 New translations landing.json (Dutch) 2022-08-28 15:49:49 +02:00
b391c561e5 New translations landing.json (Italian) 2022-08-28 15:49:48 +02:00
4dbe015fbf New translations landing.json (Hungarian) 2022-08-28 15:49:47 +02:00
bae35b2614 New translations landing.json (Hebrew) 2022-08-28 15:49:46 +02:00
8b7719a198 New translations landing.json (Finnish) 2022-08-28 15:49:46 +02:00
39cf238de3 New translations landing.json (Greek) 2022-08-28 15:49:45 +02:00
98855ae230 New translations landing.json (German) 2022-08-28 15:49:44 +02:00
ab92cbf21e New translations landing.json (Danish) 2022-08-28 15:49:43 +02:00
388ab4e29a New translations landing.json (Czech) 2022-08-28 15:49:42 +02:00
bb18c59018 New translations landing.json (Arabic) 2022-08-28 15:49:41 +02:00
217ab6ab93 New translations landing.json (French) 2022-08-28 15:49:40 +02:00
12690b33d7 New translations landing.json (Spanish) 2022-08-28 15:49:36 +02:00
bff5173701 New translations builder.json (Indonesian) 2022-08-28 15:49:34 +02:00
821813d90d New translations builder.json (Vietnamese) 2022-08-28 15:49:33 +02:00
b1d3c4da5b New translations builder.json (Chinese Simplified) 2022-08-28 15:49:32 +02:00
39f962b440 New translations builder.json (Swedish) 2022-08-28 15:49:31 +02:00
b1cfd4b7c8 New translations builder.json (Serbian (Cyrillic)) 2022-08-28 15:49:31 +02:00
c98d4a6004 New translations builder.json (Russian) 2022-08-28 15:49:30 +02:00
a5ec1f8609 New translations builder.json (Portuguese) 2022-08-28 15:49:29 +02:00
b2c897660d New translations builder.json (Polish) 2022-08-28 15:49:28 +02:00
c1a7fe7354 New translations builder.json (Dutch) 2022-08-28 15:49:27 +02:00
b628c4a21b New translations builder.json (Italian) 2022-08-28 15:49:26 +02:00
5fb4935146 New translations builder.json (Persian) 2022-08-28 15:49:25 +02:00
ae5280435d New translations builder.json (Hungarian) 2022-08-28 15:49:24 +02:00
6451609d8f New translations builder.json (Finnish) 2022-08-28 15:49:24 +02:00
edfe79f580 New translations builder.json (Greek) 2022-08-28 15:49:23 +02:00
5d7318d46d New translations builder.json (German) 2022-08-28 15:49:22 +02:00
77428c1661 New translations builder.json (Danish) 2022-08-28 15:49:21 +02:00
a2e075df39 New translations builder.json (Czech) 2022-08-28 15:49:20 +02:00
63af1d2b69 New translations builder.json (Arabic) 2022-08-28 15:49:19 +02:00
99c5016762 New translations builder.json (Spanish) 2022-08-28 15:49:18 +02:00
44ff6caf27 New translations builder.json (French) 2022-08-28 15:49:17 +02:00
7d2981f7ce New translations landing.json (Bulgarian) 2022-08-28 15:49:16 +02:00
fcc5dd4bad New translations builder.json (Hebrew) 2022-08-28 15:49:15 +02:00
a9fb995d39 New translations builder.json (Tamil) 2022-08-28 15:49:14 +02:00
31a85bfaa6 New translations builder.json (Hindi) 2022-08-28 15:49:13 +02:00
51151a601e New translations builder.json (Bengali) 2022-08-28 15:49:08 +02:00
9931b22313 New translations builder.json (Odia) 2022-08-28 15:49:04 +02:00
fdf6b76c21 New translations builder.json (Kannada) 2022-08-28 15:49:03 +02:00
b4696301ed New translations builder.json (Malayalam) 2022-08-28 15:49:02 +02:00
294d7b5dab New translations builder.json (Bulgarian) 2022-08-28 15:49:00 +02:00
0430920f56 New translations landing.json (Catalan) 2022-08-28 15:48:59 +02:00
5444b4f5ab New translations landing.json (Romanian) 2022-08-28 15:48:58 +02:00
d649b7fc08 New translations dashboard.json (Marathi) 2022-08-28 15:48:58 +02:00
20b39c0b35 New translations dashboard.json (Korean) 2022-08-28 15:48:56 +02:00
8b87b054ee New translations common.json (Marathi) 2022-08-28 15:48:53 +02:00
5eb68e9e21 New translations landing.json (Japanese) 2022-08-28 15:48:53 +02:00
ec2606d625 New translations common.json (Korean) 2022-08-28 15:48:51 +02:00
9055010f61 New translations builder.json (Marathi) 2022-08-28 15:48:49 +02:00
9763b5c270 New translations builder.json (Ukrainian) 2022-08-28 15:48:48 +02:00
75c3bfe9e5 New translations builder.json (Norwegian) 2022-08-28 15:48:47 +02:00
7f39247655 New translations builder.json (Korean) 2022-08-28 15:48:46 +02:00
d6f11e7807 New translations builder.json (Japanese) 2022-08-28 15:48:45 +02:00
361a1e65d0 New translations builder.json (Catalan) 2022-08-28 15:48:44 +02:00
6fddbe0c59 New translations landing.json (Korean) 2022-08-28 15:48:43 +02:00
3412711f27 New translations landing.json (Serbian (Cyrillic)) 2022-08-28 15:48:42 +02:00
a4bfc17431 New translations landing.json (Khmer) 2022-08-28 15:48:41 +02:00
7c698ef9d2 New translations builder.json (Khmer) 2022-08-28 15:48:40 +02:00
e929faf9b0 New translations builder.json (Turkish) 2022-08-28 15:48:39 +02:00
e3ff18b6dd New translations landing.json (Nepali) 2022-08-28 15:48:37 +02:00
2734493ca4 New translations landing.json (Norwegian) 2022-08-28 15:48:36 +02:00
f0015143c6 New translations builder.json (Nepali) 2022-08-28 15:48:35 +02:00
8d97b195a0 New translations modals.json (Korean) 2022-08-28 15:48:33 +02:00
f30692196a New translations landing.json (Marathi) 2022-08-28 15:48:31 +02:00
242278edd1 New translations landing.json (Ukrainian) 2022-08-28 15:48:30 +02:00
162759c716 New translations modals.json (Marathi) 2022-08-28 15:48:29 +02:00
f0c6bd16f5 New translations builder.json (Romanian) 2022-08-28 15:48:28 +02:00
fac8a9d4ff fix ul > li styles, add docs link to pages 2022-08-28 15:38:52 +02:00
fc0b69796f Cleanup superfluous docker-compose.yml declarations 2022-07-25 10:15:03 -04:00
258 changed files with 11024 additions and 5328 deletions

View File

@ -1,7 +1,9 @@
# Android App
/app
# Build Artifacts
dist
.next
.turbo
/server/dist
/client/.next
# IDEs
.vscode
@ -16,12 +18,9 @@ CHANGELOG.md
CODE_OF_CONDUCT.md
# Project Dependencies
node_modules
**/node_modules
# Docker
Dockerfile
.dockerignore
docker-compose.yml
# Android App
/app

View File

@ -1,11 +1,7 @@
# Turbo Cache (Optional)
TURBO_TEAM=
TURBO_TOKEN=
# Server + Client
TZ=UTC
PUBLIC_URL=http://client:3000
PUBLIC_SERVER_URL=http://server:3100
PUBLIC_URL=http://localhost:3000
PUBLIC_SERVER_URL=http://localhost:3100
PUBLIC_GOOGLE_CLIENT_ID=
# Server + Database
@ -15,7 +11,7 @@ POSTGRES_PASSWORD=postgres
# Server
SECRET_KEY=
POSTGRES_HOST=postgres
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_SSL_CERT=
JWT_SECRET=
@ -34,6 +30,7 @@ STORAGE_ENDPOINT=
STORAGE_URL_PREFIX=
STORAGE_ACCESS_KEY=
STORAGE_SECRET_KEY=
PDF_DELETION_TIME=345600000
# Flags (Client)
PUBLIC_FLAG_DISABLE_SIGNUPS=false
# Client
PUBLIC_FLAG_DISABLE_SIGNUPS=false

View File

@ -2,23 +2,11 @@
"ignorePatterns": ["/app"],
"parser": "@typescript-eslint/parser",
"extends": ["plugin:@typescript-eslint/recommended"],
"plugins": ["@typescript-eslint/eslint-plugin", "simple-import-sort", "unused-imports"],
"plugins": ["@typescript-eslint/eslint-plugin", "simple-import-sort"],
"rules": {
// ESLint
"no-unused-vars": "off",
// Unused Imports
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
"vars": "all",
"args": "none",
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_"
}
],
// Simple Import Sort
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
@ -26,6 +14,7 @@
// TypeScript ESLint
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off"

1
.github/FUNDING.yml vendored
View File

@ -1 +1,2 @@
github: AmruthPillai
custom: https://paypal.me/RajaRajanA

View File

@ -8,14 +8,21 @@ on:
- completed
jobs:
deploy:
on-success:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Install DigitalOcean CLI
uses: digitalocean/action-doctl@v2.1.1
uses: digitalocean/action-doctl@v2.3.0
with:
token: ${{ secrets.DIGITALOCEAN_TOKEN }}
- name: Create Deployment with Latest Version
run: doctl apps create-deployment ${{ secrets.DIGITALOCEAN_APP_ID }} --wait --force-rebuild
on-failure:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
steps:
- name: Abruptly end the worklfow
run: exit 1

View File

@ -1,112 +1,58 @@
name: Build and Push Docker Image
on:
workflow_dispatch:
release:
types: [published]
jobs:
client:
name: Client
build_matrix:
name: Build and Push Docker Image
runs-on: ubuntu-latest
env:
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
strategy:
matrix:
image: [client, server]
steps:
- name: Checkout the repository
uses: actions/checkout@v3.0.2
with:
fetch-depth: 2
uses: actions/checkout@v3.5.0
- id: version
name: Get Version
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
name: App Version
uses: martinbeentjes/npm-get-version-action@v1.2.3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
uses: docker/setup-qemu-action@v2.1.0
with:
platforms: amd64
- id: buildx
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.0.0
with:
install: true
uses: docker/setup-buildx-action@v2.5.0
- name: Login to Docker Hub
uses: docker/login-action@v2.0.0
uses: docker/login-action@v2.1.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2.0.0
uses: docker/login-action@v2.1.0
with:
registry: ghcr.io
username: $GITHUB_REPOSITORY_OWNER
password: ${{ secrets.GH_TOKEN }}
- name: Build and Push Client Image
uses: docker/build-push-action@v3.1.1
- name: Build and Push Docker Image
uses: docker/build-push-action@v4.0.0
with:
context: .
push: true
file: client/Dockerfile
platforms: linux/amd64,linux/arm64
platforms: linux/amd64
file: ${{ matrix.image }}/Dockerfile
tags: |
amruthpillai/reactive-resume:client-latest
amruthpillai/reactive-resume:client-${{ steps.version.outputs.tag }}
ghcr.io/amruthpillai/reactive-resume:client-latest
ghcr.io/amruthpillai/reactive-resume:client-${{ steps.version.outputs.tag }}
server:
name: Server
runs-on: ubuntu-latest
env:
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.0.2
with:
fetch-depth: 2
- id: version
name: Get Version
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- id: buildx
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.0.0
with:
install: true
- name: Login to Docker Hub
uses: docker/login-action@v2.0.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2.0.0
with:
registry: ghcr.io
username: $GITHUB_REPOSITORY_OWNER
password: ${{ secrets.GH_TOKEN }}
- name: Build and Push Server Image
uses: docker/build-push-action@v3.1.1
with:
context: .
push: true
file: server/Dockerfile
platforms: linux/amd64,linux/arm64
tags: |
amruthpillai/reactive-resume:server-latest
amruthpillai/reactive-resume:server-${{ steps.version.outputs.tag }}
ghcr.io/amruthpillai/reactive-resume:server-latest
ghcr.io/amruthpillai/reactive-resume:server-${{ steps.version.outputs.tag }}
amruthpillai/reactive-resume:${{ matrix.image }}-latest
amruthpillai/reactive-resume:${{ matrix.image }}-${{ steps.version.outputs.current-version }}
ghcr.io/amruthpillai/reactive-resume:${{ matrix.image }}-latest
ghcr.io/amruthpillai/reactive-resume:${{ matrix.image }}-${{ steps.version.outputs.current-version }}

View File

@ -1,84 +0,0 @@
name: Build Docker Image
on: pull_request
jobs:
client:
name: Client
runs-on: ubuntu-latest
env:
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.0.2
with:
fetch-depth: 2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- id: buildx
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.0.0
with:
install: true
- id: variables
name: Get Short SHA
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- name: Build Client Image
uses: docker/build-push-action@v3.1.1
with:
context: .
push: false
file: client/Dockerfile
platforms: linux/amd64,linux/arm64
tags: |
amruthpillai/reactive-resume:client-latest
amruthpillai/reactive-resume:client-${{ steps.variables.outputs.sha_short }}
ghcr.io/amruthpillai/reactive-resume:client-latest
ghcr.io/amruthpillai/reactive-resume:client-${{ steps.variables.outputs.sha_short }}
server:
name: Server
runs-on: ubuntu-latest
env:
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.0.2
with:
fetch-depth: 2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
- id: buildx
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.0.0
with:
install: true
- id: variables
name: Get Short SHA
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- name: Build Server Image
uses: docker/build-push-action@v3.1.1
with:
context: .
push: false
file: server/Dockerfile
platforms: linux/amd64,linux/arm64
tags: |
amruthpillai/reactive-resume:server-latest
amruthpillai/reactive-resume:server-${{ steps.variables.outputs.sha_short }}
ghcr.io/amruthpillai/reactive-resume:server-latest
ghcr.io/amruthpillai/reactive-resume:server-${{ steps.variables.outputs.sha_short }}

5
.gitignore vendored
View File

@ -1,6 +1,7 @@
# Environment Variables
.env
.env.*
!.env.gitpod
!.env.example
# Project Dependencies
@ -9,5 +10,5 @@ node_modules
# macOS
.DS_Store
# Turbo
.turbo
# Intellij
.idea

41
.gitpod.yml Normal file
View File

@ -0,0 +1,41 @@
tasks:
- name: Run PostgreSQL Database
command: docker run --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=postgres -d postgres
- name: Install Project Dependencies
command: |
pnpm install
pnpm dlx playwright install --with-deps chromium
gp sync-done deps
- name: Generate Environment Variables
init: gp sync-await deps
command: |
if [ -f .env ]; then
echo "Found .env in workspace, skipping generation"
else
pnpm generate-env
fi
gp sync-done env
- name: Build and Run Project
init: gp sync-await env
command: |
pnpm build
pnpm start
ports:
# PostgreSQL
- port: 5432
onOpen: ignore
visibility: private
# Client
- port: 3100
onOpen: ignore
visibility: public
# Client
- port: 3000
onOpen: open-browser
visibility: public

View File

@ -1,4 +1,4 @@
<img src="https://github.com/AmruthPillai/Reactive-Resume/blob/main/docs/static/logo.svg" alt="Reactive Resume" width="256px" height="256px" />
<img src="https://rxresu.me/images/logos/logo.png" alt="Reactive Resume" width="256px" height="256px" />
# Reactive Resume
@ -6,7 +6,8 @@
[![Project License](https://img.shields.io/github/license/AmruthPillai/Reactive-Resume?style=flat-square)](https://github.com/AmruthPillai/Reactive-Resume/blob/main/LICENSE)
[![Crowdin](https://badges.crowdin.net/reactive-resume/localized.svg)](https://translate.rxresu.me)
[![Docker Pulls](https://img.shields.io/docker/pulls/amruthpillai/reactive-resume?style=flat-square)](https://hub.docker.com/r/amruthpillai/reactive-resume)
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/AmruthPillai/Reactive-Resume/Build%20and%20Push%20Docker%20Image?label=docker%20build&style=flat-square)
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/AmruthPillai/Reactive-Resume/docker-build-push.yml?branch=main&label=docker%20build&style=flat-square)
[![Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/AmruthPillai/Reactive-Resume)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FAmruthPillai%2FReactive-Resume.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2FAmruthPillai%2FReactive-Resume?ref=badge_shield)
## [Go to App](https://rxresu.me) | [Docs](https://docs.rxresu.me)
@ -18,7 +19,7 @@ You have complete control over what goes into your resume, how it looks, what co
## Table of Contents
- [Reactive Resume](#reactive-resume)
- [Go to App | [Docs](https://docs.rxresu.me)](#go-to-app--docs)
- [Go to App | Docs](#go-to-app--docs)
- [Table of Contents](#table-of-contents)
- [Features](#features)
- [Languages](#languages)
@ -27,7 +28,8 @@ You have complete control over what goes into your resume, how it looks, what co
- [Contributing](#contributing)
- [Report Bugs and Feature Requests](#report-bugs-and-feature-requests)
- [Donations](#donations)
- [💸 PayPal](#-paypal)
- [GitHub Sponsor](#github-sponsor)
- [PayPal](#paypal)
- [Infrastructure](#infrastructure)
- [Contributors Wall](#contributors-wall)
- [License](#license)
@ -54,9 +56,11 @@ You have complete control over what goes into your resume, how it looks, what co
## Languages
- Amharic (አማርኛ)
- Arabic (اَلْعَرَبِيَّةُ)
- Bengali (বাংলা)
- Bulgarian (български)
- Catalan (Valencian)
- Chinese (中文)
- Czech (čeština)
- Danish (Dansk)
@ -71,17 +75,26 @@ You have complete control over what goes into your resume, how it looks, what co
- Hungarian (Magyar)
- Indonesian (Bahasa Indonesia)
- Italian (Italiano)
- Japanese (日本語)
- Kannada (ಕನ್ನಡ)
- Khmer (ភាសាខ្មែរ)
- Korean (한국어)
- Malayalam (മലയാളം)
- Marathi (मराठी)
- Nepali (नेपाली)
- Norwegian (Norsk)
- Odia (ଓଡ଼ିଆ)
- Persian (Farsi)
- Persian (فارسی)
- Polish (Polski)
- Portuguese (Português)
- Romanian (limba română)
- Russian (русский)
- Serbian (српски језик)
- Spanish (Español)
- Swedish (Svenska)
- Tamil (தமிழ்)
- Turkish (Türkçe)
- Ukrainian (Українська мова)
- Vietnamese (Tiếng Việt)
Help by [translating Reactive Resume](https://translate.rxresu.me) to your language!
@ -92,7 +105,11 @@ The docs include an extensive [Tutorial](https://docs.rxresu.me/tutorial) sectio
## Build from Source
For extensive information on how to build the app on your local machine, head over to the docs's [Source Code](https://docs.rxresu.me/source-code) section.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/AmruthPillai/Reactive-Resume)
Initially building the image and project on Gitpod will take at least ~10 minutes, so please be patient on first launch.
For extensive information on how to build the app on your local machine, head over to the docs [Source Code](https://docs.rxresu.me/source-code) section.
## Contributing
@ -114,7 +131,12 @@ Use the [GitHub Issues](https://github.com/AmruthPillai/Reactive-Resume/issues/n
Reactive Resume would be nothing without the folks who supported me and kept the project alive in the beginning, and your continued support is what keeps me going. If you found Reactive Resume to be useful, helpful or just insightful and appreciate the effort I took to make the project, please consider donating as little or as much as you can.
### [💸 PayPal](https://paypal.me/RajaRajanA)
### [GitHub Sponsor](https://github.com/sponsors/AmruthPillai)
### [PayPal](https://paypal.me/RajaRajanA)
## GitHub Star History
[![Star History Chart](https://api.star-history.com/svg?repos=AmruthPillai/Reactive-Resume&type=Date)](https://star-history.com/#AmruthPillai/Reactive-Resume&Date)
## Infrastructure

View File

@ -12,8 +12,8 @@ android {
targetSdk 32
versionCode 3
versionName "1.0"
resConfigs 'en'
resConfigs "en"
}
buildTypes {
@ -38,6 +38,7 @@ android {
buildFeatures {
viewBinding true
}
namespace 'me.rxresu.app'
}
dependencies {

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="me.rxresu.app">
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>

View File

@ -6,7 +6,6 @@ import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private lateinit var webView: WebView
private var url = "https://rxresu.me"

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.10' apply false
id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.20' apply false
}
task clean(type: Delete) {

View File

@ -1,6 +1,6 @@
#Wed Mar 09 21:34:49 CET 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

View File

@ -1,5 +1,6 @@
{
"extends": ["../.eslintrc.json", "next/core-web-vitals", "plugin:tailwindcss/recommended"],
"plugins": ["unused-imports"],
"ignorePatterns": [".next", "__ENV.js"],
"settings": {
"next": {
@ -14,6 +15,18 @@
// React Hooks
"react-hooks/exhaustive-deps": "off",
// Unused Imports
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
"vars": "all",
"args": "none",
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_"
}
],
// Tailwind CSS
"tailwindcss/no-custom-classname": ["warn", { "whitelist": ["preview-mode", "printer-mode", "markdown"] }]
}

2
client/.gitignore vendored
View File

@ -39,4 +39,4 @@ yarn-error.log*
__ENV.js
# next-sitemap
sitemap*.xml
sitemap*.xml

View File

@ -2,12 +2,12 @@ FROM node:lts-alpine AS base
WORKDIR /app
RUN apk add --no-cache g++ git curl make python3 \
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
RUN apk add --no-cache g++ git make curl python3 libc6-compat \
&& corepack enable && corepack prepare pnpm@latest --activate
FROM base as dependencies
COPY package.json pnpm-*.yaml turbo.json ./
COPY package.json pnpm-*.yaml ./
COPY ./schema/package.json ./schema/package.json
COPY ./client/package.json ./client/package.json
@ -21,17 +21,12 @@ COPY --from=dependencies /app/node_modules ./node_modules
COPY --from=dependencies /app/schema/node_modules ./schema/node_modules
COPY --from=dependencies /app/client/node_modules ./client/node_modules
ARG TURBO_TEAM
ARG TURBO_TOKEN
ENV TURBO_TEAM $TURBO_TEAM
ENV TURBO_TOKEN $TURBO_TOKEN
RUN pnpm run build --filter client
RUN pnpm run --filter schema build \
&& pnpm run --filter client build
FROM base as production
COPY --from=builder /app/package.json /app/pnpm-*.yaml /app/turbo.json ./
COPY --from=builder /app/package.json /app/pnpm-*.yaml ./
COPY --from=builder /app/client/package.json ./client/package.json
RUN pnpm install --filter client --prod --frozen-lockfile --workspace-root
@ -46,6 +41,6 @@ EXPOSE 3000
ENV PORT 3000
HEALTHCHECK --interval=30s --timeout=20s --retries=3 --start-period=15s \
CMD curl -fSs 127.0.0.1:3000 || exit 1
CMD curl -fSs localhost:3000 || exit 1
CMD [ "pnpm", "run", "start", "--filter", "client" ]
CMD [ "pnpm", "run", "--filter", "client", "start" ]

View File

@ -13,11 +13,12 @@ import {
} from '@mui/icons-material';
import { ButtonBase, Divider, Tooltip, useMediaQuery, useTheme } from '@mui/material';
import clsx from 'clsx';
import { get } from 'lodash';
import dayjs from 'dayjs';
import get from 'lodash/get';
import { useTranslation } from 'next-i18next';
import toast from 'react-hot-toast';
import { useMutation } from 'react-query';
import { ReactZoomPanPinchRef } from 'react-zoom-pan-pinch';
import { ReactZoomPanPinchHandlers } from 'react-zoom-pan-pinch';
import { ActionCreators } from 'redux-undo';
import { ServerError } from '@/services/axios';
@ -28,7 +29,7 @@ import getResumeUrl from '@/utils/getResumeUrl';
import styles from './ArtboardController.module.scss';
const ArtboardController: React.FC<ReactZoomPanPinchRef> = ({ zoomIn, zoomOut, centerView }) => {
const ArtboardController: React.FC<ReactZoomPanPinchHandlers> = ({ zoomIn, zoomOut, centerView }) => {
const { t } = useTranslation();
const theme = useTheme();
@ -67,10 +68,11 @@ const ArtboardController: React.FC<ReactZoomPanPinchRef> = ({ zoomIn, zoomOut, c
const slug = get(resume, 'slug');
const username = get(resume, 'user.username');
const updatedAt = get(resume, 'updatedAt');
const url = await mutateAsync({ username, slug });
const url = await mutateAsync({ username, slug, lastUpdated: dayjs(updatedAt).unix().toString() });
download(`/api${url}`);
download(url);
};
return (

View File

@ -5,7 +5,7 @@
}
.wrapper {
@apply h-full w-full #{!important};
@apply h-full w-full overflow-visible #{!important};
}
.artboard {

View File

@ -53,13 +53,12 @@ const Header = () => {
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
const { mutateAsync: duplicateMutation } = useMutation<Resume, ServerError, DuplicateResumeParams>(duplicateResume);
const { mutateAsync: deleteMutation } = useMutation<void, ServerError, DeleteResumeParams>(deleteResume);
const resume = useAppSelector((state) => state.resume.present);
const { left, right } = useAppSelector((state) => state.build.sidebar);
const { mutateAsync: deleteMutation } = useMutation<void, ServerError, DeleteResumeParams>(deleteResume);
const { mutateAsync: duplicateMutation } = useMutation<Resume, ServerError, DuplicateResumeParams>(duplicateResume);
const name = useMemo(() => get(resume, 'name'), [resume]);
useEffect(() => {

View File

@ -15,7 +15,7 @@
}
&.break::after {
content: 'A4 Page Break';
content: 'Page Break';
top: calc(297mm - 19px);
@apply absolute w-full border-b border-dashed border-neutral-800/75;
@ -28,9 +28,13 @@
}
}
ul {
padding-left: 1.5em;
text-indent: -1.5em;
&.format-letter {
width: 216mm;
min-height: 279mm;
&.break::after {
top: calc(279mm - 19px);
}
}
}

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css';
import { CustomCSS, Theme, Typography } from '@reactive-resume/schema';
import { CustomCSS, PageConfig, ThemeConfig, Typography } from '@reactive-resume/schema';
import clsx from 'clsx';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
@ -23,22 +23,24 @@ const Page: React.FC<Props> = ({ page, showPageNumbers = false }) => {
const resume = useAppSelector((state) => state.resume.present);
const breakLine: boolean = useAppSelector((state) => state.build.page.breakLine);
const theme: Theme = get(resume, 'metadata.theme');
const theme: ThemeConfig = get(resume, 'metadata.theme');
const customCSS: CustomCSS = get(resume, 'metadata.css');
const template: string = get(resume, 'metadata.template');
const typography: Typography = get(resume, 'metadata.typography');
const pageConfig: PageConfig = get(resume, 'metadata.page', {} as PageConfig);
const themeCSS = useMemo(() => !isEmpty(theme) && generateThemeStyles(theme), [theme]);
const typographyCSS = useMemo(() => !isEmpty(typography) && generateTypographyStyles(typography), [typography]);
const TemplatePage: React.FC<PageProps> | null = useMemo(() => templateMap[template].component, [template]);
return (
<div data-page={page + 1} className={styles.container}>
<div className={styles.container} data-page={page + 1} data-format={pageConfig?.format || 'A4'}>
<div
className={clsx({
reset: true,
[styles.page]: true,
[styles.break]: breakLine,
[styles['format-letter']]: pageConfig?.format === 'Letter',
[css(themeCSS)]: true,
[css(typographyCSS)]: true,
[css(customCSS.value)]: customCSS.visible,

View File

@ -1,14 +1,15 @@
import { Add, Star } from '@mui/icons-material';
import { Button, Divider, IconButton, SwipeableDrawer, Tooltip, useMediaQuery, useTheme } from '@mui/material';
import { Section as SectionRecord } from '@reactive-resume/schema';
import cloneDeep from 'lodash/cloneDeep';
import get from 'lodash/get';
import Link from 'next/link';
import { useTranslation } from 'next-i18next';
import { useMemo } from 'react';
import React, { ReactComponentElement, useMemo } from 'react';
import { validate } from 'uuid';
import Logo from '@/components/shared/Logo';
import { getCustomSections, left } from '@/config/sections';
import { getCustomSections, getSectionsByType, left } from '@/config/sections';
import { setSidebarState } from '@/store/build/buildSlice';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { addSection } from '@/store/resume/resumeSlice';
@ -26,6 +27,7 @@ const LeftSidebar = () => {
const isDesktop = useMediaQuery(theme.breakpoints.up('lg'));
const sections = useAppSelector((state) => state.resume.present.sections);
const { open } = useAppSelector((state) => state.build.sidebar.left);
const customSections = useMemo(() => getCustomSections(sections), [sections]);
@ -52,7 +54,49 @@ const LeftSidebar = () => {
items: [],
};
dispatch(addSection({ value: newSection }));
dispatch(addSection({ value: newSection, type: 'custom' }));
};
const sectionsList = () => {
const sectionsComponents: Array<ReactComponentElement<any>> = [];
for (const item of left) {
const id = (item as any).id;
const component = (item as any).component;
const type = component.props.type;
const addMore = !!component.props.addMore;
sectionsComponents.push(
<section key={id} id={id}>
{component}
</section>
);
if (addMore) {
const additionalSections = getSectionsByType(sections, type);
const elements = [];
for (const element of additionalSections) {
const newId = element.id;
const props = cloneDeep(component.props);
props.path = 'sections.' + newId;
props.name = element.name;
props.isDeletable = true;
props.addMore = false;
props.isDuplicated = true;
const newComponent = React.cloneElement(component, props);
elements.push(
<section key={newId} id={`section-${newId}`}>
{newComponent}
</section>
);
}
sectionsComponents.push(...elements);
}
}
return sectionsComponents;
};
return (
@ -65,12 +109,10 @@ const LeftSidebar = () => {
variant={isDesktop ? 'persistent' : 'temporary'}
>
<div className={styles.container}>
<nav className="overflow-y-scroll">
<nav className="overflow-y-auto">
<div>
<Link href="/dashboard">
<a className="inline-flex">
<Logo size={40} />
</a>
<Logo size={40} />
</Link>
<Divider />
</div>
@ -81,15 +123,20 @@ const LeftSidebar = () => {
arrow
key={id}
placement="right"
title={get(sections, `${id}.name`, t<string>(`builder.leftSidebar.sections.${id}.heading`)) as string}
title={t<string>(`builder.leftSidebar.sections.${id}.heading`, get(sections, `${id}.name`))}
>
<IconButton onClick={() => handleClick(id)}>{icon}</IconButton>
</Tooltip>
))}
{customSections.map(({ id }) => (
<Tooltip key={id} title={get(sections, `${id}.name`, '') as string} placement="right" arrow>
<IconButton onClick={() => handleClick(id)}>
<Tooltip
key={id}
title={t<string>(`builder.leftSidebar.sections.${id}.heading`, get(sections, `${id}.name`))}
placement="right"
arrow
>
<IconButton onClick={() => id && handleClick(id)}>
<Star />
</IconButton>
</Tooltip>
@ -100,15 +147,11 @@ const LeftSidebar = () => {
</nav>
<main>
{left.map(({ id, component }) => (
<section key={id} id={id}>
{component}
</section>
))}
{sectionsList()}
{customSections.map(({ id }) => (
<section key={id} id={`section-${id}`}>
<Section path={`sections.${id}`} isEditable isHideable isDeletable />
<Section path={`sections.${id}`} type="custom" isEditable isHideable isDeletable />
</section>
))}

View File

@ -1,6 +1,6 @@
import { Add } from '@mui/icons-material';
import { Button } from '@mui/material';
import { ListItem } from '@reactive-resume/schema';
import { ListItem, Section as SectionRecord, SectionType } from '@reactive-resume/schema';
import clsx from 'clsx';
import get from 'lodash/get';
import { useTranslation } from 'next-i18next';
@ -10,28 +10,34 @@ import Heading from '@/components/shared/Heading';
import List from '@/components/shared/List';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { ModalName, setModalState } from '@/store/modal/modalSlice';
import { duplicateItem } from '@/store/resume/resumeSlice';
import { duplicateItem, duplicateSection } from '@/store/resume/resumeSlice';
import SectionSettings from './SectionSettings';
type Props = {
path: `sections.${string}`;
type?: SectionType;
name?: string;
titleKey?: string;
subtitleKey?: string;
isEditable?: boolean;
isHideable?: boolean;
isDeletable?: boolean;
addMore?: boolean;
isDuplicated?: boolean;
};
const Section: React.FC<Props> = ({
path,
name = 'Section Name',
type = 'basic',
titleKey = 'title',
subtitleKey = 'subtitle',
isEditable = false,
isHideable = false,
isDeletable = false,
addMore = false,
isDuplicated = false,
}) => {
const { t } = useTranslation();
@ -41,22 +47,40 @@ const Section: React.FC<Props> = ({
const visibility = useAppSelector<boolean>((state) => get(state.resume.present, `${path}.visible`, true));
const handleAdd = () => {
const id = path.split('.')[1];
const modal: ModalName = validate(id) ? 'builder.sections.custom' : `builder.${path}`;
const modal: ModalName = `builder.sections.${type}`;
dispatch(setModalState({ modal, state: { open: true, payload: { path } } }));
};
const handleEdit = (item: ListItem) => {
const id = path.split('.')[1];
const modal: ModalName = validate(id) ? 'builder.sections.custom' : `builder.${path}`;
let modal: ModalName = validate(id) ? 'builder.sections.custom' : `builder.${path}`;
const payload = validate(id) ? { path, item } : { item };
if (isDuplicated) {
modal = `builder.sections.${type}`;
payload.path = path;
}
dispatch(setModalState({ modal, state: { open: true, payload } }));
};
const handleDuplicate = (item: ListItem) => dispatch(duplicateItem({ path: `${path}.items`, value: item }));
const handleDuplicateSection = () => {
const newSection: SectionRecord = {
name: `${heading}`,
type: type,
visible: true,
columns: 2,
items: [],
isDuplicated: true,
};
dispatch(duplicateSection({ value: newSection, type }));
};
return (
<>
<Heading path={path} name={name} isEditable={isEditable} isHideable={isHideable} isDeletable={isDeletable} />
@ -74,9 +98,21 @@ const Section: React.FC<Props> = ({
<SectionSettings path={path} />
<Button variant="outlined" startIcon={<Add />} onClick={handleAdd}>
{t<string>('builder.common.actions.add', { token: heading })}
{t<string>('builder.common.actions.add', {
token: t<string>(`builder.leftSidebar.${path}.heading`, heading),
})}
</Button>
</footer>
{addMore ? (
<div className="py-6 text-right">
<Button fullWidth variant="outlined" startIcon={<Add />} onClick={handleDuplicateSection}>
{t<string>('builder.common.actions.duplicate')}
</Button>
</div>
) : (
<></>
)}
</>
);
};

View File

@ -1,5 +1,5 @@
import { Divider, IconButton, SwipeableDrawer, Tooltip, useMediaQuery, useTheme } from '@mui/material';
import { capitalize } from 'lodash';
import capitalize from 'lodash/capitalize';
import { useTranslation } from 'next-i18next';
import Avatar from '@/components/shared/Avatar';
@ -43,7 +43,7 @@ const RightSidebar = () => {
variant={isDesktop ? 'persistent' : 'temporary'}
>
<div className={styles.container}>
<nav className="overflow-y-scroll">
<nav className="overflow-y-auto">
<div>
<Avatar size={40} />
<Divider />

View File

@ -17,7 +17,9 @@ const CustomCSS = () => {
const dispatch = useAppDispatch();
const customCSS: CustomCSSType = useAppSelector((state) => get(state.resume.present, 'metadata.css', {}));
const customCSS: CustomCSSType = useAppSelector((state) =>
get(state.resume.present, 'metadata.css', {} as CustomCSSType)
);
const handleChange = (value: string | undefined) => {
dispatch(setResumeState({ path: 'metadata.css.value', value }));

View File

@ -1,5 +1,6 @@
import { PictureAsPdf, Schema } from '@mui/icons-material';
import { List, ListItem, ListItemButton, ListItemText } from '@mui/material';
import dayjs from 'dayjs';
import get from 'lodash/get';
import pick from 'lodash/pick';
import { useTranslation } from 'next-i18next';
@ -45,10 +46,11 @@ const Export = () => {
const slug = get(resume, 'slug');
const username = get(resume, 'user.username');
const updatedAt = get(resume, 'updatedAt');
const url = await mutateAsync({ username, slug });
const url = await mutateAsync({ username, slug, lastUpdated: dayjs(updatedAt).unix().toString() });
download(`/api${url}`);
download(url);
};
return (

View File

@ -3,7 +3,7 @@ import { Button } from '@mui/material';
import { useTranslation } from 'next-i18next';
import Heading from '@/components/shared/Heading';
import { DONATION_URL, GITHUB_ISSUES_URL, GITHUB_URL } from '@/constants/index';
import { DOCS_URL, DONATION_URL, GITHUB_ISSUES_URL, GITHUB_URL, REDDIT_URL } from '@/constants/index';
import styles from './Links.module.scss';
@ -49,6 +49,18 @@ const Links = () => {
{t<string>('builder.rightSidebar.sections.links.github')}
</Button>
</a>
<a href={REDDIT_URL} target="_blank" rel="noreferrer">
<Button variant="text" startIcon={<Link />}>
{t<string>('builder.rightSidebar.sections.links.reddit')}
</Button>
</a>
<a href={DOCS_URL} target="_blank" rel="noreferrer">
<Button variant="text" startIcon={<Link />}>
{t<string>('builder.rightSidebar.sections.links.docs')}
</Button>
</a>
</div>
</div>
</>

View File

@ -10,7 +10,7 @@ import {
Switch,
TextField,
} from '@mui/material';
import { DateConfig, Resume } from '@reactive-resume/schema';
import { DateConfig, PageConfig, Resume } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import get from 'lodash/get';
import { useRouter } from 'next/router';
@ -48,9 +48,10 @@ const Settings = () => {
const slug: string = useMemo(() => get(resume, 'slug'), [resume]);
const username: string = useMemo(() => get(resume, 'user.username'), [resume]);
const dateConfig: DateConfig = useMemo(() => get(resume, 'metadata.date'), [resume]);
const pageConfig: PageConfig | undefined = useMemo(() => get(resume, 'metadata.page'), [resume]);
const isDarkMode = useMemo(() => theme === 'dark', [theme]);
const exampleString = useMemo(() => `Eg. ${dayjs().utc().format(dateConfig.format)}`, [dateConfig.format]);
const exampleDateString = useMemo(() => `Eg. ${dayjs().format(dateConfig.format)}`, [dateConfig.format]);
const themeString = useMemo(() => (isDarkMode ? 'Matte Black Everything' : 'As bright as your future'), [isDarkMode]);
const { mutateAsync: loadSampleDataMutation } = useMutation<Resume, ServerError, LoadSampleDataParams>(
@ -60,6 +61,9 @@ const Settings = () => {
const handleSetTheme = (value: boolean) => dispatch(setTheme({ theme: value ? 'dark' : 'light' }));
const handleChangePageFormat = (value: PageConfig['format'] | null) =>
dispatch(setResumeState({ path: 'metadata.page.format', value }));
const handleChangeDateFormat = (value: string | null) =>
dispatch(setResumeState({ path: 'metadata.date.format', value }));
@ -94,7 +98,7 @@ const Settings = () => {
<>
<Heading path="metadata.settings" name={t<string>('builder.rightSidebar.sections.settings.heading')} />
<List sx={{ padding: 0 }}>
<List disablePadding>
{/* Global Settings */}
<>
<ListSubheader disableSticky className="rounded">
@ -118,13 +122,13 @@ const Settings = () => {
primary={t<string>('builder.rightSidebar.sections.settings.global.date.primary')}
secondary={t<string>('builder.rightSidebar.sections.settings.global.date.secondary')}
/>
<Autocomplete<string, false, boolean, false>
<Autocomplete<string, false, true, false>
disableClearable
className="my-2 w-full"
options={dateFormatOptions}
value={dateConfig.format}
onChange={(_, value) => handleChangeDateFormat(value)}
renderInput={(params) => <TextField {...params} helperText={exampleString} />}
renderInput={(params) => <TextField {...params} helperText={exampleDateString} />}
/>
</ListItem>
@ -134,7 +138,7 @@ const Settings = () => {
primary={t<string>('builder.rightSidebar.sections.settings.global.language.primary')}
secondary={t<string>('builder.rightSidebar.sections.settings.global.language.secondary')}
/>
<Autocomplete<Language, false, boolean, false>
<Autocomplete<Language, false, true, false>
disableClearable
className="my-2 w-full"
options={languages}
@ -159,6 +163,23 @@ const Settings = () => {
{t<string>('builder.rightSidebar.sections.settings.page.heading')}
</ListSubheader>
<ListItem className="flex-col">
<ListItemText
className="w-full"
primary={t<string>('builder.rightSidebar.sections.settings.page.format.primary')}
secondary={t<string>('builder.rightSidebar.sections.settings.page.format.secondary')}
/>
<Autocomplete<PageConfig['format'], false, true, false>
disableClearable
defaultValue="A4"
className="my-2 w-full"
options={['A4', 'Letter']}
value={pageConfig?.format || 'A4'}
renderInput={(params) => <TextField {...params} />}
onChange={(_, value) => handleChangePageFormat(value)}
/>
</ListItem>
<ListItem>
<ListItemText
primary={t<string>('builder.rightSidebar.sections.settings.page.orientation.primary')}
@ -191,7 +212,7 @@ const Settings = () => {
{t<string>('builder.rightSidebar.sections.settings.resume.heading')}
</ListSubheader>
<ListItem>
<ListItem disableGutters>
<ListItemButton onClick={handleLoadSampleData}>
<ListItemIcon>
<Anchor />
@ -203,7 +224,7 @@ const Settings = () => {
</ListItemButton>
</ListItem>
<ListItem>
<ListItem disableGutters>
<ListItemButton onClick={handleResetResume}>
<ListItemIcon>
<DeleteForever />

View File

@ -31,7 +31,14 @@ const Templates = () => {
<div key={template.id} className={styles.template}>
<div className={clsx(styles.preview, { [styles.selected]: template.id === currentTemplate })}>
<ButtonBase onClick={() => handleChange(template)}>
<Image src={template.preview} alt={template.name} className="rounded-sm" layout="fill" priority />
<Image
fill
priority
alt={template.name}
src={template.preview}
className="rounded-sm"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</ButtonBase>
</div>

View File

@ -1,4 +1,4 @@
import { Theme as ThemeType } from '@reactive-resume/schema';
import { ThemeConfig } from '@reactive-resume/schema';
import get from 'lodash/get';
import { useTranslation } from 'next-i18next';
@ -16,7 +16,7 @@ const Theme = () => {
const dispatch = useAppDispatch();
const { background, text, primary } = useAppSelector<ThemeType>((state) =>
const { background, text, primary } = useAppSelector<ThemeConfig>((state) =>
get(state.resume.present, 'metadata.theme')
);

View File

@ -16,9 +16,7 @@ type Props = {
const ResumeCard: React.FC<Props> = ({ modal, icon: Icon, title, subtitle }) => {
const dispatch = useAppDispatch();
const handleClick = () => {
dispatch(setModalState({ modal, state: { open: true } }));
};
const handleClick = () => dispatch(setModalState({ modal, state: { open: true } }));
return (
<section className={styles.resume}>

View File

@ -115,9 +115,7 @@ const ResumePreview: React.FC<Props> = ({ resume }) => {
}}
>
<ButtonBase className={styles.preview}>
{resume.image ? (
<Image src={resume.image} alt={resume.name} objectFit="cover" layout="fill" priority />
) : null}
{resume.image ? <Image src={resume.image} alt={resume.name} priority width={400} height={0} /> : null}
</ButtonBase>
</Link>

View File

@ -6,15 +6,17 @@ import { useState } from 'react';
import { logout } from '@/store/auth/authSlice';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { setModalState } from '@/store/modal/modalSlice';
import getGravatarUrl from '@/utils/getGravatarUrl';
import styles from './Avatar.module.scss';
type Props = {
size?: number;
interactive?: boolean;
};
const Avatar: React.FC<Props> = ({ size = 64 }) => {
const Avatar: React.FC<Props> = ({ size = 64, interactive = true }) => {
const router = useRouter();
const { t } = useTranslation();
@ -34,6 +36,11 @@ const Avatar: React.FC<Props> = ({ size = 64 }) => {
setAnchorEl(null);
};
const handleOpenProfile = () => {
dispatch(setModalState({ modal: 'auth.profile', state: { open: true } }));
handleClose();
};
const handleLogout = () => {
dispatch(logout());
handleClose();
@ -43,20 +50,20 @@ const Avatar: React.FC<Props> = ({ size = 64 }) => {
return (
<>
<IconButton onClick={handleOpen}>
<IconButton onClick={handleOpen} disabled={!interactive}>
<Image
width={size}
height={size}
alt={user?.name}
className={styles.avatar}
src={getGravatarUrl(email, size)}
alt={user?.name ?? 'User Avatar'}
/>
</IconButton>
<Menu anchorEl={anchorEl} onClose={handleClose} open={Boolean(anchorEl)}>
<MenuItem>
<MenuItem onClick={handleOpenProfile}>
<div>
<span className="text-xs opacity-50">{t<string>('common.avatar.menu.greeting')}</span>
<span className="text-xs opacity-50">{t<string>('common.avatar.menu.greeting')},</span>
<p>{user?.name}</p>
</div>
</MenuItem>

View File

@ -62,7 +62,7 @@ const Heading: React.FC<Props> = ({
{editMode ? (
<TextField size="small" value={heading} className="w-3/4" onChange={handleChange} />
) : (
<h1>{heading}</h1>
<h1>{t<string>(`builder.leftSidebar.${path}.heading`, heading)}</h1>
)}
</div>

View File

@ -4,8 +4,8 @@ type Props = {
size?: 256 | 64 | 48 | 40 | 32;
};
const Logo: React.FC<Props> = ({ size = 64 }) => {
return <Image alt="Reactive Resume" src="/images/logos/logo.svg" className="rounded" width={size} height={size} />;
};
const Logo: React.FC<Props> = ({ size = 64 }) => (
<Image alt="Reactive Resume" src="/images/logos/logo.svg" className="rounded" width={size} height={size} priority />
);
export default Logo;

View File

@ -1,7 +1,9 @@
import clsx from 'clsx';
import { isEmpty } from 'lodash';
import isEmpty from 'lodash/isEmpty';
import ReactMarkdown from 'react-markdown';
import rehypeKatex from 'rehype-katex';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
type Props = {
children?: string;
@ -12,7 +14,11 @@ const Markdown: React.FC<Props> = ({ className, children }) => {
if (!children || isEmpty(children)) return null;
return (
<ReactMarkdown remarkPlugins={[remarkGfm]} className={clsx('markdown', className)}>
<ReactMarkdown
className={clsx('markdown', className)}
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeKatex]}
>
{children}
</ReactMarkdown>
);

View File

@ -1,7 +1,6 @@
import { TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import dayjs from 'dayjs';
import { isEmpty } from 'lodash';
import get from 'lodash/get';
import { useEffect, useState } from 'react';
@ -58,12 +57,13 @@ const ResumeInput: React.FC<Props> = ({ type = 'text', label, path, className, m
<DatePicker
openTo="year"
label={label}
value={value}
value={dayjs(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).utc().isValid() && onChangeValue(dayjs(date).utc().toISOString());
slots={{
textField: (params) => <TextField {...params} error={false} className={className} />,
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && onChangeValue(dayjs(date).format('YYYY-MM-DD'));
}}
/>
);

View File

@ -2,23 +2,25 @@ export type Language = {
code: string;
name: string;
localName?: string;
isRTL?: boolean;
};
export const languages: Language[] = [
{ code: 'ar', name: 'Arabic', localName: 'اَلْعَرَبِيَّةُ' },
{ code: 'am', name: 'Amharic', localName: 'አማርኛ' },
{ code: 'ar', name: 'Arabic', localName: 'اَلْعَرَبِيَّةُ', isRTL: true },
{ code: 'bg', name: 'Bulgarian', localName: 'български' },
{ code: 'bn', name: 'Bengali', localName: 'বাংলা' },
{ code: 'ca', name: 'Catalan', localName: 'Valencian' },
{ code: 'cs', name: 'Czech', localName: 'čeština' },
{ code: 'da', name: 'Danish', localName: 'Dansk' },
{ code: 'de', name: 'German', localName: 'Deutsch' },
{ code: 'de', name: 'German', localName: 'Deutsch Formell / Sie' },
{ code: 'el', name: 'Greek', localName: 'Ελληνικά' },
{ code: 'en', name: 'English' },
{ code: 'es', name: 'Spanish', localName: 'Español' },
{ code: 'fa', name: 'Persian', localName: 'فارسی' },
{ code: 'fa', name: 'Persian', localName: 'فارسی', isRTL: true },
{ code: 'fi', name: 'Finnish', localName: 'Suomi' },
{ code: 'fr', name: 'French', localName: 'Français' },
{ code: 'he', name: 'Hebrew', localName: 'Ivrit' },
{ code: 'he', name: 'Hebrew', localName: 'Ivrit', isRTL: true },
{ code: 'hi', name: 'Hindi', localName: 'हिन्दी' },
{ code: 'hu', name: 'Hungarian', localName: 'Magyar' },
{ code: 'id', name: 'Indonesian', localName: 'Bahasa Indonesia' },
@ -26,13 +28,16 @@ export const languages: Language[] = [
{ code: 'ja', name: 'Japanese', localName: '日本語' },
{ code: 'km', name: 'Khmer', localName: 'ភាសាខ្មែរ' },
{ code: 'kn', name: 'Kannada', localName: 'ಕನ್ನಡ' },
{ code: 'ko', name: 'Korean', localName: '한국어' },
{ code: 'ml', name: 'Malayalam', localName: 'മലയാളം' },
{ code: 'mr', name: 'Marathi', localName: 'मराठी' },
{ code: 'ne', name: 'Nepali', localName: 'नेपाली' },
{ code: 'nl', name: 'Dutch', localName: 'Nederlands' },
{ code: 'no', name: 'Norwegian', localName: 'Norsk' },
{ code: 'or', name: 'Odia', localName: 'ଓଡ଼ିଆ' },
{ code: 'pl', name: 'Polish', localName: 'Polski' },
{ code: 'pt', name: 'Portuguese', localName: 'Português' },
{ code: 'pt-BR', name: 'Brazilian Portuguese', localName: 'Brasil' },
{ code: 'ro', name: 'Romanian', localName: 'limba română' },
{ code: 'ru', name: 'Russian', localName: 'русский' },
{ code: 'sr', name: 'Serbian', localName: 'српски језик' },

View File

@ -23,7 +23,7 @@ import {
VolunteerActivism,
Work,
} from '@mui/icons-material';
import { Section as SectionRecord } from '@reactive-resume/schema';
import { Section as SectionRecord, SectionType } from '@reactive-resume/schema';
import isEmpty from 'lodash/isEmpty';
import Basics from '@/components/build/LeftSidebar/sections/Basics';
@ -60,59 +60,136 @@ export const left: SidebarSection[] = [
{
id: 'work',
icon: <Work />,
component: <Section path="sections.work" titleKey="name" subtitleKey="position" isEditable isHideable />,
component: (
<Section
type={'work'}
addMore={true}
path="sections.work"
titleKey="name"
subtitleKey="position"
isEditable
isHideable
/>
),
},
{
id: 'education',
icon: <School />,
component: <Section path="sections.education" titleKey="institution" subtitleKey="area" isEditable isHideable />,
component: (
<Section
type={'education'}
path="sections.education"
titleKey="institution"
subtitleKey="area"
isEditable
isHideable
/>
),
},
{
id: 'awards',
icon: <EmojiEvents />,
component: <Section path="sections.awards" titleKey="title" subtitleKey="awarder" isEditable isHideable />,
component: (
<Section type={'awards'} path="sections.awards" titleKey="title" subtitleKey="awarder" isEditable isHideable />
),
},
{
id: 'certifications',
icon: <CardGiftcard />,
component: <Section path="sections.certifications" titleKey="name" subtitleKey="issuer" isEditable isHideable />,
component: (
<Section
type={'certifications'}
path="sections.certifications"
titleKey="name"
subtitleKey="issuer"
isEditable
isHideable
/>
),
},
{
id: 'publications',
icon: <MenuBook />,
component: <Section path="sections.publications" titleKey="name" subtitleKey="publisher" isEditable isHideable />,
component: (
<Section
type={'publications'}
path="sections.publications"
titleKey="name"
subtitleKey="publisher"
isEditable
isHideable
/>
),
},
{
id: 'skills',
icon: <Architecture />,
component: <Section path="sections.skills" titleKey="name" subtitleKey="level" isEditable isHideable />,
component: (
<Section type={'skills'} path="sections.skills" titleKey="name" subtitleKey="level" isEditable isHideable />
),
},
{
id: 'languages',
icon: <Language />,
component: <Section path="sections.languages" titleKey="name" subtitleKey="level" isEditable isHideable />,
component: (
<Section type={'languages'} path="sections.languages" titleKey="name" subtitleKey="level" isEditable isHideable />
),
},
{
id: 'interests',
icon: <Sailing />,
component: <Section path="sections.interests" titleKey="name" subtitleKey="keywords" isEditable isHideable />,
component: (
<Section
type={'interests'}
path="sections.interests"
titleKey="name"
subtitleKey="keywords"
isEditable
isHideable
/>
),
},
{
id: 'volunteer',
icon: <VolunteerActivism />,
component: (
<Section path="sections.volunteer" titleKey="organization" subtitleKey="position" isEditable isHideable />
<Section
type={'volunteer'}
path="sections.volunteer"
titleKey="organization"
subtitleKey="position"
isEditable
isHideable
/>
),
},
{
id: 'projects',
icon: <Coffee />,
component: <Section path="sections.projects" titleKey="name" subtitleKey="description" isEditable isHideable />,
component: (
<Section
type={'projects'}
path="sections.projects"
titleKey="name"
subtitleKey="description"
isEditable
isHideable
/>
),
},
{
id: 'references',
icon: <Groups />,
component: <Section path="sections.references" titleKey="name" subtitleKey="relationship" isEditable isHideable />,
component: (
<Section
type={'references'}
path="sections.references"
titleKey="name"
subtitleKey="relationship"
isEditable
isHideable
/>
),
},
];
@ -164,7 +241,19 @@ export const right: SidebarSection[] = [
},
];
export const getCustomSections = (sections: Record<string, SectionRecord>): Array<Required<SectionRecord>> => {
export const getSectionsByType = (sections: Record<string, SectionRecord>, type: SectionType): SectionRecord[] => {
if (isEmpty(sections)) return [];
return Object.entries(sections).reduce((acc, [id, section]) => {
if (section.type.startsWith(type) && section.isDuplicated) {
return [...acc, { ...section, id }];
}
return acc;
}, [] as SectionRecord[]);
};
export const getCustomSections = (sections: Record<string, SectionRecord>): SectionRecord[] => {
if (isEmpty(sections)) return [];
return Object.entries(sections).reduce((acc, [id, section]) => {
@ -173,7 +262,7 @@ export const getCustomSections = (sections: Record<string, SectionRecord>): Arra
}
return acc;
}, [] as Array<Required<SectionRecord>>);
}, [] as SectionRecord[]);
};
const sections = [...left, ...right];

View File

@ -9,9 +9,15 @@ export const VALID_URL_REGEX = /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}
export const FILENAME_TIMESTAMP = 'DDMMYYYYHHmmss';
// Links
export const DOCS_URL = 'https://docs.rxresu.me';
export const DONATION_URL = 'https://paypal.me/RajaRajanA';
export const TRANSLATE_URL = 'https://translate.rxresu.me/';
export const DIGITALOCEAN_URL = 'https://pillai.xyz/digitalocean';
export const REDDIT_URL = 'https://www.reddit.com/r/reactiveresume/';
export const GITHUB_URL = 'https://github.com/AmruthPillai/Reactive-Resume';
export const PRODUCT_HUNT_URL = 'https://www.producthunt.com/posts/reactive-resume-v3';
export const GITHUB_ISSUES_URL = 'https://github.com/AmruthPillai/Reactive-Resume/issues/new/choose';
// Default Error Message
export const DEFAULT_ERROR_MESSAGE =
'Something went wrong while performing this action, please report this issue on GitHub.';

View File

@ -4,7 +4,7 @@ import { Login, Visibility, VisibilityOff } from '@mui/icons-material';
import { Button, IconButton, InputAdornment, TextField } from '@mui/material';
import { CredentialResponse, GoogleLogin } from '@react-oauth/google';
import Joi from 'joi';
import { isEmpty } from 'lodash';
import isEmpty from 'lodash/isEmpty';
import { Trans, useTranslation } from 'next-i18next';
import { useMemo, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
@ -62,14 +62,7 @@ const LoginModal: React.FC = () => {
};
const onSubmit = async ({ identifier, password }: FormData) => {
await loginMutation(
{ identifier, password },
{
onError: (error) => {
toast.error(error.message);
},
}
);
await loginMutation({ identifier, password });
handleClose();
};
@ -86,14 +79,14 @@ const LoginModal: React.FC = () => {
const handleLoginWithGoogle = async (response: CredentialResponse) => {
if (response.credential) {
await loginWithGoogleMutation({ credential: response.credential }, { onError: handleLoginWithGoogleError });
await loginWithGoogleMutation({ credential: response.credential }, { onError: handleGoogleLoginError });
handleClose();
}
};
const handleLoginWithGoogleError = () => {
toast("Please try logging in using email/password, or use another browser that supports Google's One Tap API.");
const handleGoogleLoginError = () => {
toast.error("Google doesn't seem to be responding, please try logging in using email/password instead.");
};
const PasswordVisibility = (): React.ReactElement => {
@ -117,7 +110,7 @@ const LoginModal: React.FC = () => {
footerChildren={
<div className="flex gap-4">
{!isEmpty(env('GOOGLE_CLIENT_ID')) && (
<GoogleLogin onSuccess={handleLoginWithGoogle} onError={handleLoginWithGoogleError} />
<GoogleLogin onSuccess={handleLoginWithGoogle} onError={handleGoogleLoginError} />
)}
<Button type="submit" onClick={handleSubmit(onSubmit)} disabled={isLoading}>
@ -162,15 +155,15 @@ const LoginModal: React.FC = () => {
{!FLAG_DISABLE_SIGNUPS && (
<p className="text-xs">
<Trans t={t} i18nKey="modals.auth.login.register-text">
If you don&apos;t have one, you can <a onClick={handleCreateAccount}>create an account</a> here.
If you don&apos;t have one, you can <a onClick={handleCreateAccount}>create an account here.</a>
</Trans>
</p>
)}
<p className="text-xs">
<Trans t={t} i18nKey="modals.auth.login.recover-text">
In case you have forgotten your password, you can <a onClick={handleRecoverAccount}>recover your account</a>
here.
In case you have forgotten your password, you can
<a onClick={handleRecoverAccount}>recover your account here.</a>
</Trans>
</p>
</BaseModal>

View File

@ -4,7 +4,7 @@ import { HowToReg } from '@mui/icons-material';
import { Button, TextField } from '@mui/material';
import { CredentialResponse, GoogleLogin } from '@react-oauth/google';
import Joi from 'joi';
import { isEmpty } from 'lodash';
import isEmpty from 'lodash/isEmpty';
import { Trans, useTranslation } from 'next-i18next';
import { Controller, useForm } from 'react-hook-form';
import toast from 'react-hot-toast';
@ -81,14 +81,14 @@ const RegisterModal: React.FC = () => {
const handleLoginWithGoogle = async (response: CredentialResponse) => {
if (response.credential) {
await loginWithGoogleMutation({ credential: response.credential }, { onError: handleLoginWithGoogleError });
await loginWithGoogleMutation({ credential: response.credential }, { onError: handleGoogleLoginError });
handleClose();
}
};
const handleLoginWithGoogleError = () => {
toast("Please try logging in using email/password, or use another browser that supports Google's One Tap API.");
const handleGoogleLoginError = () => {
toast("Google doesn't seem to be responding, please try logging in using email/password instead.");
};
return (
@ -100,7 +100,7 @@ const RegisterModal: React.FC = () => {
footerChildren={
<div className="flex gap-4">
{!isEmpty(env('GOOGLE_CLIENT_ID')) && (
<GoogleLogin onSuccess={handleLoginWithGoogle} onError={handleLoginWithGoogleError} />
<GoogleLogin onSuccess={handleLoginWithGoogle} onError={handleGoogleLoginError} />
)}
<Button type="submit" onClick={handleSubmit(onSubmit)} disabled={isLoading}>

View File

@ -0,0 +1,159 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { CrisisAlert, ManageAccounts } from '@mui/icons-material';
import { Button, Divider, TextField } from '@mui/material';
import Joi from 'joi';
import { useRouter } from 'next/router';
import { Trans, useTranslation } from 'next-i18next';
import { useEffect, useMemo, useState } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { useMutation } from 'react-query';
import Avatar from '@/components/shared/Avatar';
import BaseModal from '@/components/shared/BaseModal';
import { deleteAccount, updateProfile, UpdateProfileParams } from '@/services/auth';
import { ServerError } from '@/services/axios';
import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { setModalState } from '@/store/modal/modalSlice';
type FormData = {
name: string;
email: string;
};
const defaultState: FormData = {
name: '',
email: '',
};
const schema = Joi.object({
name: Joi.string().required(),
email: Joi.string()
.email({ tlds: { allow: false } })
.required(),
});
const UserProfileModal = () => {
const router = useRouter();
const { t } = useTranslation();
const dispatch = useAppDispatch();
const [deleteText, setDeleteText] = useState<string>('');
const isDeleteTextValid = useMemo(() => deleteText.toLowerCase() === 'delete', [deleteText]);
const user = useAppSelector((state) => state.auth.user);
const { open: isOpen } = useAppSelector((state) => state.modal['auth.profile']);
const { mutateAsync: deleteAccountMutation } = useMutation<void, ServerError>(deleteAccount);
const { mutateAsync: updateProfileMutation } = useMutation<void, ServerError, UpdateProfileParams>(updateProfile);
const { reset, getFieldState, control, handleSubmit } = useForm<FormData>({
defaultValues: defaultState,
resolver: joiResolver(schema),
});
useEffect(() => {
if (user && !getFieldState('name').isTouched && !getFieldState('email').isTouched) {
reset({ name: user.name, email: user.email });
}
}, [user]);
const handleClose = () => {
dispatch(setModalState({ modal: 'auth.profile', state: { open: false } }));
};
const handleUpdate = handleSubmit(async (data) => {
handleClose();
await updateProfileMutation({ name: data.name });
});
const handleDelete = async () => {
await deleteAccountMutation();
handleClose();
router.push('/');
};
return (
<BaseModal isOpen={isOpen} handleClose={handleClose} heading="Your Account" icon={<ManageAccounts />}>
<div className="grid gap-4">
<form className="grid gap-4 xl:w-2/3">
<div className="flex items-center gap-4">
<Avatar interactive={false} />
<div className="grid flex-1 gap-1.5">
<Controller
name="name"
control={control}
render={({ field, fieldState }) => (
<TextField
autoFocus
label={t('modals.auth.profile.form.name.label')}
error={!!fieldState.error}
helperText={fieldState.error?.message}
{...field}
/>
)}
/>
<p className="pl-4 text-[10.25px] opacity-50">
<Trans t={t} i18nKey="modals.auth.profile.form.avatar.help-text">
You can update your profile picture on{' '}
<a href="https://gravatar.com/" target="_blank" rel="noreferrer">
Gravatar
</a>
</Trans>
</p>
</div>
</div>
<Controller
name="email"
control={control}
render={({ field, fieldState }) => (
<TextField
disabled
label={t('modals.auth.profile.form.email.label')}
error={!!fieldState.error}
helperText={t('modals.auth.profile.form.email.help-text')}
{...field}
/>
)}
/>
<div>
<Button onClick={handleUpdate}>{t('modals.auth.profile.actions.save')}</Button>
</div>
</form>
<div className="my-2">
<Divider />
</div>
<div className="flex items-center gap-2">
<CrisisAlert />
<h5 className="font-medium">{t('modals.auth.profile.delete-account.heading')}</h5>
</div>
<p className="text-xs opacity-75">{t('modals.auth.profile.delete-account.body', { keyword: 'delete' })}</p>
<div className="flex max-w-xs flex-col gap-4">
<TextField
value={deleteText}
placeholder="Type 'delete' to confirm"
onChange={(e) => setDeleteText(e.target.value)}
/>
<div>
<Button variant="contained" color="error" disabled={!isDeleteTextValid} onClick={handleDelete}>
{t('modals.auth.profile.delete-account.actions.delete')}
</Button>
</div>
</div>
</div>
</BaseModal>
);
};
export default UserProfileModal;

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { Award, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -93,7 +93,7 @@ const AwardModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="title"
control={control}
@ -128,21 +128,23 @@ const AwardModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
)}
/>
)}
/>
@ -177,6 +179,7 @@ const AwardModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { Certificate, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -93,7 +93,7 @@ const CertificateModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
@ -128,21 +128,23 @@ const CertificateModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
)}
/>
)}
/>
@ -177,6 +179,7 @@ const CertificateModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import { Button, Slider, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { Custom } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -60,13 +60,14 @@ const CustomModal: React.FC = () => {
const dispatch = useAppDispatch();
const heading = useAppSelector((state) => get(state.resume.present, `${path}.name`));
const { open: isOpen, payload } = useAppSelector((state) => state.modal['builder.sections.custom']);
const path: string = get(payload, 'path', '');
const path: string = get(payload, 'path', 'sections.custom');
const item: FormData = get(payload, 'item', null);
const isEditMode = useMemo(() => !!item, [item]);
const heading = useAppSelector((state) => get(state.resume.present, `${path}.name`));
const addText = useMemo(() => t<string>('builder.common.actions.add', { token: heading }), [t, heading]);
const editText = useMemo(() => t<string>('builder.common.actions.edit', { token: heading }), [t, heading]);
@ -110,7 +111,7 @@ const CustomModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="title"
control={control}
@ -144,21 +145,23 @@ const CustomModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.start-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
)}
/>
)}
/>
@ -168,21 +171,23 @@ const CustomModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.end-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || t<string>('builder.common.form.end-date.help-text')}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || 'Leave this field blank, if still present'}
/>
)}
/>
)}
/>
@ -260,9 +265,9 @@ const CustomModal: React.FC = () => {
multiline
minRows={3}
maxRows={6}
label={t<string>('builder.common.form.summary.label')}
className="col-span-2"
error={!!fieldState.error}
label={t<string>('builder.common.form.summary.label')}
helperText={fieldState.error?.message || <MarkdownSupported />}
{...field}
/>
@ -282,6 +287,7 @@ const CustomModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { Education, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -106,7 +106,7 @@ const EducationModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="institution"
control={control}
@ -167,21 +167,23 @@ const EducationModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.start-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
)}
/>
)}
/>
@ -191,21 +193,23 @@ const EducationModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.end-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || t<string>('builder.common.form.end-date.help-text')}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || t<string>('builder.common.form.end-date.help-text')}
/>
)}
/>
)}
/>
@ -255,6 +259,7 @@ const EducationModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -84,7 +84,7 @@ const InterestModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
@ -114,6 +114,7 @@ const InterestModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -85,7 +85,7 @@ const LanguageModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
@ -150,6 +150,7 @@ const LanguageModal: React.FC = () => {
</div>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -89,7 +89,7 @@ const ProfileModal: React.FC = () => {
handleClose={handleClose}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="network"
control={control}
@ -136,6 +136,7 @@ const ProfileModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { Project, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -102,7 +102,7 @@ const ProjectModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
@ -137,21 +137,23 @@ const ProjectModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.start-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
)}
/>
)}
/>
@ -161,21 +163,23 @@ const ProjectModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.end-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || t<string>('builder.common.form.end-date.help-text')}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || 'Leave this field blank, if still present'}
/>
)}
/>
)}
/>
@ -225,6 +229,7 @@ const ProjectModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { Publication, SectionPath } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -93,7 +93,7 @@ const PublicationModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
@ -128,21 +128,23 @@ const PublicationModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
)}
/>
)}
/>
@ -177,6 +179,7 @@ const PublicationModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -90,7 +90,7 @@ const ReferenceModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
@ -162,6 +162,7 @@ const ReferenceModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -88,7 +88,7 @@ const SkillModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
@ -166,6 +166,8 @@ const SkillModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -1,7 +1,7 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { SectionPath, Volunteer } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
@ -99,7 +99,7 @@ const VolunteerModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="organization"
control={control}
@ -134,21 +134,23 @@ const VolunteerModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.start-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
)}
/>
)}
/>
@ -158,21 +160,23 @@ const VolunteerModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.end-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || t<string>('builder.common.form.end-date.help-text')}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || 'Leave this field blank, if still present'}
/>
)}
/>
)}
/>
@ -208,6 +212,7 @@ const VolunteerModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -1,8 +1,8 @@
import { joiResolver } from '@hookform/resolvers/joi';
import { Add, DriveFileRenameOutline } from '@mui/icons-material';
import { Button, TextField } from '@mui/material';
import { DatePicker } from '@mui/x-date-pickers';
import { SectionPath, WorkExperience } from '@reactive-resume/schema';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { WorkExperience } from '@reactive-resume/schema';
import dayjs from 'dayjs';
import Joi from 'joi';
import get from 'lodash/get';
@ -20,8 +20,6 @@ import { addItem, editItem } from '@/store/resume/resumeSlice';
type FormData = WorkExperience;
const path: SectionPath = 'sections.work';
const defaultState: FormData = {
name: '',
position: '',
@ -50,14 +48,23 @@ const WorkModal: React.FC = () => {
const dispatch = useAppDispatch();
const heading = useAppSelector((state) => get(state.resume.present, `${path}.name`));
const { open: isOpen, payload } = useAppSelector((state) => state.modal[`builder.${path}`]);
const { open: isOpen, payload } = useAppSelector((state) => state.modal['builder.sections.work']);
const path: string = get(payload, 'path', 'sections.work');
const item: FormData = get(payload, 'item', null);
const heading = useAppSelector((state) => get(state.resume.present, `${path}.name`));
const isEditMode = useMemo(() => !!item, [item]);
const addText = useMemo(() => t<string>('builder.common.actions.add', { token: heading }), [t, heading]);
const editText = useMemo(() => t<string>('builder.common.actions.edit', { token: heading }), [t, heading]);
const addText = useMemo(
() => t<string>('builder.common.actions.add', { token: t<string>(`builder.leftSidebar.${path}.heading`, heading) }),
[t, heading]
);
const editText = useMemo(
() =>
t<string>('builder.common.actions.edit', { token: t<string>(`builder.leftSidebar.${path}.heading`, heading) }),
[t, heading]
);
const { reset, control, handleSubmit } = useForm<FormData>({
defaultValues: defaultState,
@ -77,7 +84,7 @@ const WorkModal: React.FC = () => {
const handleClose = () => {
dispatch(
setModalState({
modal: `builder.${path}`,
modal: 'builder.sections.work',
state: { open: false },
})
);
@ -99,7 +106,7 @@ const WorkModal: React.FC = () => {
heading={isEditMode ? editText : addText}
footerChildren={<Button onClick={handleSubmit(onSubmit)}>{isEditMode ? editText : addText}</Button>}
>
<form className="my-2 grid grid-cols-2 gap-4">
<form className="my-2 grid grid-cols-2 gap-4" onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
@ -134,21 +141,23 @@ const WorkModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.start-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || params.inputProps?.placeholder}
/>
)}
/>
)}
/>
@ -158,21 +167,23 @@ const WorkModal: React.FC = () => {
control={control}
render={({ field, fieldState }) => (
<DatePicker
{...field}
openTo="year"
inputRef={field.ref}
label={t<string>('builder.common.form.end-date.label')}
value={dayjs(field.value)}
views={['year', 'month', 'day']}
onChange={(date: Date | null, keyboardInputValue: string | undefined) => {
isEmpty(keyboardInputValue) && field.onChange('');
date && dayjs(date).utc().isValid() && field.onChange(dayjs(date).utc().toISOString());
slots={{
textField: (params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || t<string>('builder.common.form.end-date.help-text')}
/>
),
}}
onChange={(date: dayjs.Dayjs | null) => {
date && dayjs(date).isValid() && field.onChange(dayjs(date).format('YYYY-MM-DD'));
}}
renderInput={(params) => (
<TextField
{...params}
error={!!fieldState.error}
helperText={fieldState.error?.message || t<string>('builder.common.form.end-date.help-text')}
/>
)}
/>
)}
/>
@ -208,6 +219,7 @@ const WorkModal: React.FC = () => {
/>
)}
/>
<input type="submit" style={{ display: 'none' }} />
</form>
</BaseModal>
);

View File

@ -6,7 +6,6 @@ import Joi from 'joi';
import { useTranslation } from 'next-i18next';
import { useEffect } from 'react';
import { Controller, useForm } from 'react-hook-form';
import toast from 'react-hot-toast';
import { useMutation } from 'react-query';
import BaseModal from '@/components/shared/BaseModal';
@ -66,15 +65,10 @@ const CreateResumeModal: React.FC = () => {
}, [name, setValue]);
const onSubmit = async ({ name, slug, isPublic }: FormData) => {
try {
await mutateAsync({ name, slug, public: isPublic });
await mutateAsync({ name, slug, public: isPublic });
await queryClient.invalidateQueries(RESUMES_QUERY);
await queryClient.invalidateQueries(RESUMES_QUERY);
handleClose();
} catch (error: any) {
toast.error(error.message);
}
handleClose();
};
const handleClose = () => {

View File

@ -68,8 +68,8 @@ const ImportExternalModal: React.FC = () => {
}
await mutateAsync({ integration, file });
queryClient.invalidateQueries(RESUMES_QUERY);
handleClose();
}
};

View File

@ -8,6 +8,7 @@ import ForgotPasswordModal from './auth/ForgotPasswordModal';
import LoginModal from './auth/LoginModal';
import RegisterModal from './auth/RegisterModal';
import ResetPasswordModal from './auth/ResetPasswordModal';
import UserProfileModal from './auth/UserProfileModal';
import AwardModal from './builder/sections/AwardModal';
import CertificateModal from './builder/sections/CertificateModal';
import CustomModal from './builder/sections/CustomModal';
@ -49,6 +50,7 @@ const ModalWrapper: React.FC = () => {
<RegisterModal />
<ForgotPasswordModal />
<ResetPasswordModal />
<UserProfileModal />
{/* Dashboard */}
<CreateResumeModal />

View File

@ -4,6 +4,7 @@ const i18nConfig = {
i18n: {
defaultLocale: 'en',
locales: [
'am',
'ar',
'bg',
'bn',
@ -25,13 +26,16 @@ const i18nConfig = {
'ja',
'km',
'kn',
'ko',
'ml',
'mr',
'ne',
'nl',
'no',
'or',
'pl',
'pt',
'pt-BR',
'ro',
'ru',
'sr',

View File

@ -15,19 +15,6 @@ const nextConfig = {
domains: ['cdn.rxresu.me', 'www.gravatar.com'],
},
async rewrites() {
if (process.env.NODE_ENV === 'development') {
return [
{
source: '/api/:path*',
destination: 'http://localhost:3100/:path*',
},
];
}
return [];
},
// Hack to make Tailwind darkMode 'class' strategy with CSS Modules
// Ref: https://github.com/tailwindlabs/tailwindcss/issues/3258#issuecomment-968368156
webpack: (config) => {

View File

@ -9,75 +9,74 @@
},
"dependencies": {
"@beam-australia/react-env": "^3.1.1",
"@date-io/dayjs": "^2.15.0",
"@emotion/css": "^11.10.0",
"@emotion/react": "^11.10.0",
"@emotion/styled": "^11.10.0",
"@hello-pangea/dnd": "^16.0.0",
"@hookform/resolvers": "2.9.7",
"@monaco-editor/react": "^4.4.5",
"@mui/icons-material": "^5.10.2",
"@mui/lab": "^5.0.0-alpha.96",
"@mui/material": "^5.10.2",
"@mui/system": "^5.10.2",
"@mui/x-date-pickers": "5.0.0-beta.7",
"@next/env": "^12.2.5",
"@react-oauth/google": "^0.2.6",
"@reduxjs/toolkit": "^1.8.5",
"axios": "^0.27.2",
"@emotion/css": "^11.10.6",
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@hello-pangea/dnd": "^16.2.0",
"@hookform/resolvers": "3.0.1",
"@monaco-editor/react": "^4.4.6",
"@mui/icons-material": "^5.11.16",
"@mui/lab": "^5.0.0-alpha.125",
"@mui/material": "^5.11.16",
"@mui/system": "^5.11.16",
"@mui/x-date-pickers": "6.0.4",
"@react-oauth/google": "^0.9.0",
"@reduxjs/toolkit": "^1.9.3",
"axios": "^1.3.5",
"clsx": "^1.2.1",
"dayjs": "^1.11.5",
"dayjs": "^1.11.7",
"downloadjs": "^1.4.7",
"joi": "^17.6.0",
"joi": "^17.9.1",
"lodash": "^4.17.21",
"md5-hex": "^4.0.0",
"monaco-editor": "^0.34.0",
"nanoid": "^3.3.4",
"next": "12.2.5",
"next-i18next": "^12.0.0",
"monaco-editor": "^0.37.0",
"nanoid": "3.3.4",
"next": "13.2.4",
"next-i18next": "^13.2.2",
"react": "^18.2.0",
"react-colorful": "^5.6.1",
"react-dnd": "16.0.1",
"react-dnd-html5-backend": "16.0.1",
"react-dom": "^18.2.0",
"react-hook-form": "^7.34.2",
"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.2",
"react-redux": "^8.0.2",
"react-zoom-pan-pinch": "^2.1.3",
"redux": "^4.2.0",
"react-hook-form": "^7.43.9",
"react-hot-toast": "2.4.0",
"react-icons": "^4.8.0",
"react-markdown": "^8.0.6",
"react-query": "^3.39.3",
"react-redux": "^8.0.5",
"react-zoom-pan-pinch": "^3.0.6",
"redux": "^4.2.1",
"redux-persist": "^6.0.0",
"redux-saga": "^1.2.1",
"redux-saga": "^1.2.3",
"redux-undo": "^1.0.1",
"rehype-katex": "^6.0.2",
"remark-gfm": "^3.0.1",
"sharp": "^0.30.7",
"uuid": "^8.3.2",
"remark-math": "^5.1.1",
"sharp": "^0.32.0",
"uuid": "^9.0.0",
"webfontloader": "^1.6.28"
},
"devDependencies": {
"@babel/core": "^7.18.13",
"@babel/core": "^7.21.4",
"@reactive-resume/schema": "workspace:*",
"@tailwindcss/typography": "^0.5.4",
"@tailwindcss/typography": "^0.5.9",
"@types/downloadjs": "^1.4.3",
"@types/lodash": "^4.14.184",
"@types/node": "^18.7.13",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@types/react-redux": "^7.1.24",
"@types/tailwindcss": "^3.0.11",
"@types/uuid": "^8.3.4",
"@types/webfontloader": "^1.6.34",
"autoprefixer": "^10.4.8",
"csstype": "^3.1.0",
"eslint-config-next": "^12.2.5",
"eslint-plugin-tailwindcss": "^3.6.0",
"next-sitemap": "^3.1.21",
"postcss": "^8.4.16",
"sass": "^1.54.5",
"tailwindcss": "^3.1.8",
"typescript": "^4.8.2"
"@types/lodash": "^4.14.192",
"@types/node": "^18.15.11",
"@types/react": "^18.0.33",
"@types/react-dom": "^18.0.11",
"@types/react-redux": "^7.1.25",
"@types/uuid": "^9.0.1",
"@types/webfontloader": "^1.6.35",
"autoprefixer": "^10.4.14",
"csstype": "^3.1.2",
"eslint-config-next": "^13.2.4",
"eslint-plugin-tailwindcss": "^3.11.0",
"eslint-plugin-unused-imports": "^2.0.0",
"next-sitemap": "^4.0.6",
"postcss": "^8.4.21",
"sass": "^1.60.0",
"tailwindcss": "^3.3.1",
"typescript": "^5.0.3"
}
}

View File

@ -2,6 +2,7 @@ import { Download, Downloading } from '@mui/icons-material';
import { ButtonBase } from '@mui/material';
import { Resume } from '@reactive-resume/schema';
import clsx from 'clsx';
import dayjs from 'dayjs';
import download from 'downloadjs';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
@ -14,6 +15,7 @@ import toast from 'react-hot-toast';
import { useMutation, useQuery } from 'react-query';
import Page from '@/components/build/Center/Page';
import { DEFAULT_ERROR_MESSAGE } from '@/constants/index';
import { ServerError } from '@/services/axios';
import { printResumeAsPdf, PrintResumeAsPdfParams } from '@/services/printer';
import { fetchResumeByIdentifier } from '@/services/resume';
@ -60,10 +62,12 @@ const Preview: NextPage<Props> = ({ username, slug, resume: initialData }) => {
}, [dispatch, initialData]);
useEffect(() => {
if (!isEmpty(resume) && router.locale !== resume.metadata.locale) {
const locale = get(resume, 'metadata.locale', 'en');
if (!isEmpty(resume) && router.locale !== locale) {
const { pathname, asPath, query } = router;
router.push({ pathname, query }, asPath, { locale: resume.metadata.locale });
router.push({ pathname, query }, asPath, { locale });
}
}, [resume, router]);
@ -96,11 +100,13 @@ const Preview: NextPage<Props> = ({ username, slug, resume: initialData }) => {
const handleDownload = async () => {
try {
const url = await mutateAsync({ username, slug });
const updatedAt = get(resume, 'updatedAt');
download(`/api${url}`);
const url = await mutateAsync({ username, slug, lastUpdated: dayjs(updatedAt).unix().toString() });
download(url);
} catch {
toast.error('Something went wrong, please try again later.');
toast.error(DEFAULT_ERROR_MESSAGE);
}
};

View File

@ -3,6 +3,7 @@ import clsx from 'clsx';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import { GetServerSideProps, NextPage } from 'next';
import { useRouter } from 'next/router';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { useEffect } from 'react';
@ -26,7 +27,7 @@ type Props = {
export const getServerSideProps: GetServerSideProps<Props | Promise<Props>, QueryParams> = async ({
query,
locale,
locale = 'en',
}) => {
const { username, slug, secretKey } = query as QueryParams;
@ -34,7 +35,7 @@ export const getServerSideProps: GetServerSideProps<Props | Promise<Props>, Quer
if (isEmpty(secretKey)) throw new Error('There is no secret key!');
const resume = await fetchResumeByIdentifier({ username, slug, options: { secretKey } });
const displayLocale = resume.metadata.locale || locale || 'en';
const displayLocale = get(resume, 'metadata.locale') ?? locale;
return {
props: {
@ -54,10 +55,20 @@ export const getServerSideProps: GetServerSideProps<Props | Promise<Props>, Quer
};
const Printer: NextPage<Props> = ({ resume: initialData, locale }) => {
const router = useRouter();
const dispatch = useAppDispatch();
const resume = useAppSelector((state) => state.resume.present);
useEffect(() => {
if (router.locale !== locale) {
const { pathname, asPath, query } = router;
router.push({ pathname, query }, asPath, { locale });
}
}, [router, locale]);
useEffect(() => {
if (initialData) dispatch(setResume(initialData));
}, [dispatch, initialData]);

View File

@ -1,8 +1,8 @@
import '@/styles/globals.scss';
import env from '@beam-australia/react-env';
import DayjsAdapter from '@date-io/dayjs';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { GoogleOAuthProvider } from '@react-oauth/google';
import type { AppProps } from 'next/app';
import Head from 'next/head';
@ -18,46 +18,44 @@ import queryClient from '@/services/react-query';
import store, { persistor } from '@/store/index';
import WrapperRegistry from '@/wrappers/index';
const App: React.FC<AppProps> = ({ Component, pageProps }) => {
return (
<>
<Head>
<title>Reactive Resume</title>
const App = ({ Component, pageProps }: AppProps): JSX.Element => (
<>
<Head>
<title>Reactive Resume | A free and open source resume builder</title>
<meta
name="description"
content="Reactive Resume is a free and open source resume builder that's built to make the mundane tasks of creating, updating and sharing your resume as easy as 1, 2, 3."
/>
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<meta
name="description"
content="Reactive Resume is a free and open source resume builder that's built to make the mundane tasks of creating, updating and sharing your resume as easy as 1, 2, 3."
/>
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<ReduxProvider store={store}>
<LocalizationProvider dateAdapter={DayjsAdapter}>
<PersistGate loading={null} persistor={persistor}>
<GoogleOAuthProvider clientId={env('GOOGLE_CLIENT_ID')}>
<QueryClientProvider client={queryClient}>
<WrapperRegistry>
<Loading />
<ReduxProvider store={store}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<PersistGate loading={null} persistor={persistor}>
<GoogleOAuthProvider clientId={env('GOOGLE_CLIENT_ID')}>
<QueryClientProvider client={queryClient}>
<WrapperRegistry>
<Loading />
<Component {...pageProps} />
<Component {...pageProps} />
<ModalWrapper />
<Toaster
position="bottom-right"
toastOptions={{
duration: 4000,
className: 'toast',
}}
/>
</WrapperRegistry>
</QueryClientProvider>
</GoogleOAuthProvider>
</PersistGate>
</LocalizationProvider>
</ReduxProvider>
</>
);
};
<ModalWrapper />
<Toaster
position="bottom-right"
toastOptions={{
duration: 4000,
className: 'toast',
}}
/>
</WrapperRegistry>
</QueryClientProvider>
</GoogleOAuthProvider>
</PersistGate>
</LocalizationProvider>
</ReduxProvider>
</>
);
export default appWithTranslation(App);

View File

@ -1,15 +1,69 @@
import { NextPage } from 'next';
import NextDocument, { DocumentContext, Head, Html, Main, NextScript } from 'next/document';
import Script from 'next/script';
const Document: NextPage = () => (
<Html>
<Head />
<Html lang="en">
<Head>
<Script
id="google-tag-manager"
type="text/javascript"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-M9DK4S4');`,
}}
/>
<Script
id="logo-schema"
type="application/ld+json"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `{
"@context": "https://schema.org",
"@type": "Organization",
"url": "https://rxresu.me",
"logo": "https://rxresu.me/images/logos/logo.svg"
}`,
}}
/>
<Script
id="software-application-schema"
type="application/ld+json"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Reactive Resume",
"operatingSystem": "Windows, macOS, Linux, Android, iOS",
"applicationCategory": "BrowserApplication",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "5",
"ratingCount": "11394"
},
"offers": {
"@type": "Offer",
"price": "0"
}
}`,
}}
/>
</Head>
<body>
<Main />
<NextScript />
<script src="/__ENV.js" />
<noscript
dangerouslySetInnerHTML={{
__html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-M9DK4S4" height="0" width="0" style="display:none;visibility:hidden"></iframe>`,
}}
/>
</body>
</Html>
);

View File

@ -17,13 +17,11 @@ import { fetchResumes } from '@/services/resume';
import { useAppDispatch } from '@/store/hooks';
import styles from '@/styles/pages/Dashboard.module.scss';
export const getStaticProps: GetStaticProps = async ({ locale = 'en' }) => {
return {
props: {
...(await serverSideTranslations(locale, ['common', 'modals', 'dashboard'])),
},
};
};
export const getStaticProps: GetStaticProps = async ({ locale = 'en' }) => ({
props: {
...(await serverSideTranslations(locale, ['common', 'modals', 'dashboard'])),
},
});
const Dashboard: NextPage = () => {
const { t } = useTranslation();
@ -48,9 +46,7 @@ const Dashboard: NextPage = () => {
<header>
<Link href="/">
<a>
<Logo size={40} />
</a>
<Logo size={40} />
</Link>
<Avatar size={40} />
@ -58,15 +54,15 @@ const Dashboard: NextPage = () => {
<main className={styles.resumes}>
<ResumeCard
modal="dashboard.create-resume"
icon={Add}
modal="dashboard.create-resume"
title={t<string>('dashboard.create-resume.title')}
subtitle={t<string>('dashboard.create-resume.subtitle')}
/>
<ResumeCard
modal="dashboard.import-external"
icon={ImportExport}
modal="dashboard.import-external"
title={t<string>('dashboard.import-external.title')}
subtitle={t<string>('dashboard.import-external.subtitle')}
/>

View File

@ -20,15 +20,13 @@ import { useAppDispatch, useAppSelector } from '@/store/hooks';
import { setModalState } from '@/store/modal/modalSlice';
import styles from '@/styles/pages/Home.module.scss';
import { DIGITALOCEAN_URL, DONATION_URL, GITHUB_URL } from '../constants';
import { DIGITALOCEAN_URL, DOCS_URL, DONATION_URL, GITHUB_URL, REDDIT_URL } from '../constants';
export const getStaticProps: GetStaticProps = async ({ locale = 'en' }) => {
return {
props: {
...(await serverSideTranslations(locale, ['common', 'modals', 'landing'])),
},
};
};
export const getStaticProps: GetStaticProps = async ({ locale = 'en' }) => ({
props: {
...(await serverSideTranslations(locale, ['common', 'modals', 'landing'])),
},
});
const Home: NextPage = () => {
const { t } = useTranslation();
@ -39,11 +37,8 @@ const Home: NextPage = () => {
const isLoggedIn = useAppSelector((state) => state.auth.isLoggedIn);
const handleLogin = () => dispatch(setModalState({ modal: 'auth.login', state: { open: true } }));
const handleRegister = () => dispatch(setModalState({ modal: 'auth.register', state: { open: true } }));
const handleToggle = () => dispatch(setTheme({ theme: theme === 'light' ? 'dark' : 'light' }));
const handleLogout = () => dispatch(logout());
return (
@ -117,7 +112,13 @@ const Home: NextPage = () => {
<div className={styles.screenshots}>
{screenshots.map(({ src, alt }) => (
<a key={src} href={src} className={styles.image} target="_blank" rel="noreferrer">
<Image src={src} alt={alt} layout="fill" objectFit="cover" />
<Image
fill
src={src}
alt={alt}
className="object-cover"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</a>
))}
</div>
@ -170,6 +171,18 @@ const Home: NextPage = () => {
</Button>
</a>
<a href={DOCS_URL} target="_blank" rel="noreferrer">
<Button variant="text" startIcon={<LinkIcon />}>
{t<string>('landing.links.links.docs')}
</Button>
</a>
<a href={REDDIT_URL} target="_blank" rel="noreferrer">
<Button variant="text" startIcon={<LinkIcon />}>
{t<string>('landing.links.links.reddit')}
</Button>
</a>
<a href={DONATION_URL} target="_blank" rel="noreferrer">
<Button variant="text" startIcon={<LinkIcon />}>
{t<string>('landing.links.links.donate')}
@ -180,7 +193,13 @@ const Home: NextPage = () => {
<section className={styles.section}>
<a href={DIGITALOCEAN_URL} target="_blank" rel="noreferrer">
<Image src="/images/sponsors/digitalocean.svg" alt="Powered By DigitalOcean" width={200} height={40} />
<Image
src={`/images/sponsors/${theme == 'dark' ? 'digitalocean' : 'digitaloceanLight'}.svg`}
style={{ width: 200, height: 40, objectFit: 'contain' }}
alt="Powered By DigitalOcean"
width={200}
height={40}
/>
</a>
</section>

View File

@ -2,6 +2,7 @@ import { Download, Downloading } from '@mui/icons-material';
import { ButtonBase } from '@mui/material';
import { Resume } from '@reactive-resume/schema';
import clsx from 'clsx';
import dayjs from 'dayjs';
import download from 'downloadjs';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
@ -10,7 +11,6 @@ import Link from 'next/link';
import { useRouter } from 'next/router';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { useEffect } from 'react';
import toast from 'react-hot-toast';
import { useMutation, useQuery } from 'react-query';
import Page from '@/components/build/Center/Page';
@ -68,13 +68,13 @@ const Preview: NextPage<Props> = ({ shortId }) => {
const layout: string[][][] = get(resume, 'metadata.layout', []);
const handleDownload = async () => {
try {
const url = await mutateAsync({ username: resume.user.username, slug: resume.slug });
const url = await mutateAsync({
username: resume.user.username,
slug: resume.slug,
lastUpdated: dayjs(resume.updatedAt).unix().toString(),
});
download(`/api${url}`);
} catch {
toast.error('Something went wrong, please try again later.');
}
download(url);
};
return (

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 604 129" style="enable-background:new 0 0 604 129;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0069ff;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#0069ff;}
</style>
<g>
<g>
<g>
<path class="st0" d="M174.3,3c4.9,0,8.7,2.9,8.7,8.6c0,5.6-3.8,8.5-8.7,8.5h-7.6v11.1h-3.5V3H174.3z M166.7,17.1h7.2
c3,0,5.6-1.8,5.6-5.5c0-3.8-2.5-5.5-5.6-5.5h-7.2V17.1z"/>
<path class="st0" d="M208.8,21.7c0,6.1-4.3,10-9.9,10c-5.6,0-9.9-3.9-9.9-10c0-6.1,4.3-10,9.9-10
C204.5,11.7,208.8,15.6,208.8,21.7z M192.3,21.7c0,4.5,2.9,7.2,6.6,7.2c3.7,0,6.6-2.7,6.6-7.2c0-4.5-2.9-7.1-6.6-7.1
C195.2,14.5,192.3,17.2,192.3,21.7z"/>
<path class="st0" d="M234.4,31.3l-5.2-13.8L224,31.3h-2.6L214.1,12h3.6l5.2,14l5.2-14h2.3l5.3,14l5.2-14h3.5L237,31.3H234.4z"/>
<path class="st0" d="M253,22.9c0.2,3.7,2.6,5.9,6,5.9c2.8,0,4.8-1.3,5.4-3.4l3.2,0.2c-0.8,3.5-4.1,6.1-8.6,6.1
c-5.5,0-9.6-3.7-9.6-10c0-6.3,4-10,9.5-10c5.5,0,8.8,3.7,8.8,9.4v1.8H253z M253,20.3h11.6c-0.1-3.4-2-5.7-5.6-5.7
C255.6,14.5,253.2,16.5,253,20.3z"/>
<path class="st0" d="M285.4,14.9c-3.4,0-5.6,2.3-5.6,5.3v11.1h-3.2V12h3.2v2.9c0.7-1.6,2.5-3.1,5.7-3.1V14.9z"/>
<path class="st0" d="M294.7,22.9c0.2,3.7,2.6,5.9,6,5.9c2.8,0,4.8-1.3,5.4-3.4l3.2,0.2c-0.8,3.5-4.1,6.1-8.6,6.1
c-5.5,0-9.6-3.7-9.6-10c0-6.3,4-10,9.5-10c5.5,0,8.8,3.7,8.8,9.4v1.8H294.7z M294.7,20.3h11.6c-0.1-3.4-2-5.7-5.6-5.7
C297.4,14.5,294.9,16.5,294.7,20.3z"/>
<path class="st0" d="M333.1,31.3v-3.1c-1.1,2-3.6,3.5-6.8,3.5c-5.3,0-9.3-3.8-9.3-10c0-6.2,4-10,9.3-10c3.2,0,5.6,1.4,6.6,3.2V2
h3.2v29.4H333.1z M320.3,21.7c0,4.6,2.8,7.2,6.5,7.2c3.6,0,6.2-2.2,6.2-6.6v-1.1c0-4.3-2.6-6.6-6.2-6.6
C323.1,14.5,320.3,17.1,320.3,21.7z"/>
<path class="st0" d="M361.8,14.9c1.1-1.9,3.4-3.2,6.7-3.2c5.3,0,9.3,3.8,9.3,10c0,6.2-4,10-9.3,10c-3.3,0-5.7-1.5-6.8-3.5v3.1
h-3.1V2h3.2V14.9z M361.9,21.1v1.1c0,4.4,2.6,6.6,6.2,6.6c3.7,0,6.5-2.5,6.5-7.2c0-4.6-2.8-7.1-6.5-7.1
C364.5,14.5,361.9,16.8,361.9,21.1z"/>
<path class="st0" d="M386.3,40.9l4.6-10.7L383.2,12h3.6l5.8,14.5l5.8-14.5h3.6l-12.2,28.9H386.3z"/>
</g>
</g>
<g id="XMLID_2369_">
<g>
<g id="XMLID_281_">
<g id="XMLID_282_">
<g>
<g id="XMLID_283_">
<g id="XMLID_287_">
<path id="XMLID_288_" class="st0" d="M64.4,127l0-24.2c25.6,0,45.5-25.4,35.7-52.3c-3.6-10-11.6-17.9-21.6-21.6
c-27-9.8-52.3,10-52.3,35.7c0,0,0,0,0,0L2,64.7C2,23.8,41.5-8,84.3,5.4c18.7,5.8,33.6,20.7,39.4,39.4
C137,87.6,105.2,127,64.4,127z"/>
</g>
<polygon id="XMLID_286_" class="st1" points="64.4,102.9 40.4,102.9 40.4,78.9 40.4,78.9 64.4,78.9 64.4,78.9 "/>
<polygon id="XMLID_285_" class="st1" points="40.3,121.5 21.8,121.5 21.8,121.5 21.8,102.9 40.4,102.9 40.4,121.5 "/>
<path id="XMLID_284_" class="st1" d="M21.9,102.9H6.3c0,0,0,0,0,0V87.4c0,0,0,0,0,0h15.5c0,0,0,0,0,0V102.9z"/>
</g>
</g>
</g>
</g>
<g id="XMLID_254_">
<path id="XMLID_278_" class="st0" d="M200.9,52.4c-5.5-3.8-12.4-5.8-20.5-5.8h-17.5v55.5h17.5c8,0,14.9-2.1,20.5-6.1
c3-2.1,5.4-5.1,7.1-8.9c1.7-3.7,2.5-8.2,2.5-13.1c0-4.9-0.8-9.3-2.5-13C206.3,57.4,203.9,54.4,200.9,52.4z M173.1,56h5.5
c6.1,0,11.1,1.2,15,3.6c4.2,2.6,6.4,7.4,6.4,14.4c0,7.2-2.2,12.3-6.4,15.1h0c-3.7,2.4-8.7,3.6-14.9,3.6h-5.6V56z"/>
<path id="XMLID_277_" class="st0" d="M222.6,45.9c-1.7,0-3.1,0.6-4.3,1.8c-1.2,1.1-1.8,2.6-1.8,4.2c0,1.7,0.6,3.1,1.8,4.3
c1.2,1.2,2.6,1.8,4.3,1.8c1.7,0,3.1-0.6,4.3-1.8c1.2-1.2,1.8-2.6,1.8-4.3c0-1.7-0.6-3.1-1.8-4.2
C225.7,46.5,224.3,45.9,222.6,45.9z"/>
<rect id="XMLID_276_" x="217.6" y="63" class="st0" width="9.8" height="39.1"/>
<path id="XMLID_273_" class="st0" d="M263.2,66.3c-3-2.6-6.3-4.2-9.9-4.2c-5.4,0-9.9,1.9-13.4,5.6c-3.5,3.7-5.3,8.4-5.3,14.1
c0,5.5,1.8,10.2,5.2,14c3.5,3.7,8,5.5,13.5,5.5c3.8,0,7.1-1.1,9.7-3.1V99c0,3.2-0.9,5.8-2.6,7.5c-1.7,1.7-4.1,2.6-7.1,2.6
c-4.5,0-7.4-1.8-10.9-6.5l-6.7,6.4l0.2,0.3c1.4,2,3.7,4,6.6,5.9c2.9,1.9,6.6,2.8,10.9,2.8c5.8,0,10.6-1.8,14.1-5.4
c3.5-3.6,5.3-8.4,5.3-14.2V63h-9.7V66.3z M260.6,89.4c-1.7,2-3.9,2.9-6.8,2.9c-2.8,0-5-0.9-6.7-2.9c-1.7-1.9-2.5-4.5-2.5-7.7
c0-3.2,0.9-5.8,2.5-7.7c1.7-1.9,3.9-2.9,6.7-2.9c2.8,0,5,1,6.8,2.9c1.7,2,2.6,4.6,2.6,7.7C263.2,84.9,262.3,87.5,260.6,89.4z"/>
<rect id="XMLID_272_" x="281.3" y="63" class="st0" width="9.8" height="39.1"/>
<path id="XMLID_271_" class="st0" d="M286.3,45.9c-1.7,0-3.1,0.6-4.3,1.8c-1.2,1.1-1.8,2.6-1.8,4.2c0,1.7,0.6,3.1,1.8,4.3
c1.2,1.2,2.6,1.8,4.3,1.8c1.7,0,3.1-0.6,4.3-1.8c1.2-1.2,1.8-2.6,1.8-4.3c0-1.7-0.6-3.1-1.8-4.2C289.4,46.5,288,45.9,286.3,45.9
z"/>
<path id="XMLID_270_" class="st0" d="M312.7,52.5H303V63h-5.6v9h5.6v16.2c0,5.1,1,8.7,3,10.8c2,2.1,5.6,3.2,10.6,3.2
c1.6,0,3.2-0.1,4.8-0.2l0.4,0v-9l-3.4,0.2c-2.3,0-3.9-0.4-4.7-1.2c-0.8-0.8-1.1-2.6-1.1-5.2V72h9.2v-9h-9.2V52.5z"/>
<rect id="XMLID_269_" x="368" y="46.6" class="st0" width="9.8" height="55.5"/>
<path id="XMLID_268_" class="st0" d="M477.3,88.2c-1.8,2-3.6,3.7-4.9,4.6v0c-1.4,0.9-3.1,1.3-5.1,1.3c-2.9,0-5.2-1.1-7.1-3.2
c-1.9-2.2-2.8-4.9-2.8-8.3s0.9-6.1,2.8-8.2c1.9-2.2,4.2-3.2,7.1-3.2c3.2,0,6.5,2,9.4,5.4l6.5-6.2l0,0c-4.2-5.5-9.7-8.1-16.1-8.1
c-5.4,0-10.1,2-13.9,5.8c-3.8,3.9-5.7,8.8-5.7,14.6s1.9,10.7,5.7,14.6c3.8,3.9,8.5,5.9,13.9,5.9c7.1,0,12.9-3.1,16.8-8.7
L477.3,88.2z"/>
<path id="XMLID_265_" class="st0" d="M517.7,68.5c-1.4-1.9-3.3-3.5-5.7-4.7c-2.3-1.1-5.1-1.7-8.1-1.7c-5.5,0-10,2-13.4,6
c-3.3,4-4.9,8.9-4.9,14.7c0,5.9,1.8,10.8,5.4,14.6c3.6,3.7,8.4,5.6,14.2,5.6c6.6,0,12.1-2.7,16.2-8l0.2-0.3l-6.4-6.2l0,0
c-0.6,0.7-1.4,1.5-2.2,2.3c-1,0.9-1.9,1.6-2.9,2.1c-1.5,0.7-3.1,1.1-5,1.1c-2.7,0-5-0.8-6.7-2.4c-1.6-1.5-2.6-3.5-2.8-5.9h26.1
l0.1-3.6c0-2.5-0.3-5-1-7.3C520.1,72.6,519.1,70.4,517.7,68.5z M496.2,77.7c0.5-1.9,1.3-3.4,2.6-4.6c1.3-1.3,3.1-2,5.2-2
c2.4,0,4.2,0.7,5.5,2c1.2,1.2,1.8,2.8,2,4.6H496.2z"/>
<path id="XMLID_262_" class="st0" d="M555.5,66L555.5,66c-3-2.5-7.1-3.8-12.3-3.8c-3.3,0-6.3,0.7-9.1,2.1
c-2.6,1.3-5.1,3.5-6.7,6.3l0.1,0.1l6.3,6c2.6-4.1,5.5-5.6,9.3-5.6c2.1,0,3.8,0.6,5.1,1.6c1.3,1.1,1.9,2.5,1.9,4.2v1.9
c-2.4-0.7-4.9-1.1-7.2-1.1c-4.9,0-8.9,1.2-11.8,3.4c-3,2.3-4.5,5.6-4.5,9.8c0,3.7,1.3,6.7,3.8,8.9c2.6,2.1,5.8,3.2,9.5,3.2
c3.7,0,7.3-1.5,10.4-4.1v3.2h9.7V77C560,72.2,558.5,68.5,555.5,66z M538,87.2c1.1-0.8,2.7-1.2,4.7-1.2c2.4,0,4.9,0.5,7.5,1.4
v3.8c-2.1,2-5,3-8.5,3c-1.7,0-3-0.4-3.9-1.1c-0.9-0.7-1.3-1.7-1.3-2.8C536.4,89,536.9,88,538,87.2z"/>
<path id="XMLID_261_" class="st0" d="M597.9,66.7c-2.7-3.1-6.6-4.6-11.5-4.6c-3.9,0-7.1,1.1-9.4,3.3V63h-9.7v39.1h9.8V80.6
c0-3,0.7-5.3,2.1-7c1.4-1.7,3.3-2.5,5.8-2.5c2.2,0,3.9,0.7,5.2,2.2c1.3,1.5,1.9,3.6,1.9,6.2v22.7h9.8V79.5
C602,74.1,600.6,69.8,597.9,66.7z"/>
<path id="XMLID_258_" class="st0" d="M355.6,66L355.6,66c-3-2.5-7.1-3.8-12.3-3.8c-3.3,0-6.3,0.7-9.1,2.1
c-2.6,1.3-5.1,3.5-6.7,6.3l0.1,0.1l6.3,6c2.6-4.1,5.5-5.6,9.3-5.6c2.1,0,3.8,0.6,5.1,1.6c1.3,1.1,1.9,2.5,1.9,4.2v1.9
c-2.4-0.7-4.9-1.1-7.2-1.1c-4.9,0-8.9,1.2-11.8,3.4c-3,2.3-4.5,5.6-4.5,9.8c0,3.7,1.3,6.7,3.8,8.9c2.6,2.1,5.8,3.2,9.5,3.2
c3.7,0,7.3-1.5,10.4-4.1v3.2h9.7V77C360.2,72.2,358.7,68.5,355.6,66z M338.2,87.2c1.1-0.8,2.7-1.2,4.7-1.2
c2.4,0,4.9,0.5,7.5,1.4v3.8c-2.1,2-5,3-8.5,3c-1.7,0-3-0.4-3.9-1.1c-0.9-0.7-1.3-1.7-1.3-2.8C336.6,89,337.1,88,338.2,87.2z"/>
<path id="XMLID_255_" class="st0" d="M413.6,103c-15.8,0-28.6-12.8-28.6-28.6s12.8-28.6,28.6-28.6s28.6,12.8,28.6,28.6
S429.4,103,413.6,103z M413.6,55.8c-10.2,0-18.5,8.3-18.5,18.5s8.3,18.5,18.5,18.5s18.5-8.3,18.5-18.5S423.8,55.8,413.6,55.8z"
/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -0,0 +1,368 @@
{
"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": "እርግጠኛ ነዎት ይህንn ማጥፋት ይፈልጋሉ? ይህ የማይመለስ ተግባር ነው።",
"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": "አሳንስ",
"undo": "ቀልብስ",
"redo": "ድገም"
}
},
"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": "ወደ Reactive Resume ተመልሶ ሊመጣ የሚችል የስራ ልምድ ሰነድ የ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": "Reactive Resumeን መጠቀም ከወደዱ እባክዎን መተግበሪያው እንዲሰራ እና ያለ ማስታወቂያ ሁሌም በነፃ እንዲቀጥል በተቻለዎት መጠን ለመለገስ ያስቡበት።",
"button": "ቡና ይጋብዙኝ",
"heading": "ለ Reactive Resume ይለግሱ"
},
"github": "የምንጭ ኮድ",
"docs": "ሰነዶች",
"heading": "አገናኞች"
},
"settings": {
"global": {
"date": {
"primary": "ቀን",
"secondary": "በመላው መተግበሪያ ላይ የሚጠቀሙበት የቀን አይነት"
},
"heading": "ዓለም አቀፍ",
"language": {
"primary": "ቋንቋ",
"secondary": "በመላው መተግበሪያ ላይ የሚጠቀሙበት ቋንቋ"
},
"theme": {
"primary": "ገጽታ"
}
},
"heading": "ቅንብሮች",
"page": {
"format": {
"primary": "የወረቀት መጠን",
"secondary": "ከቆመበት ቀጥል ገጾችዎ ልኬቶችን ይወስናል"
},
"break-line": {
"primary": "መስመር መቁረጫ",
"secondary": "የA4 ገጽ ቁመትን ለመለየት በሁሉም ገጾች ላይ መስመር አሳይ"
},
"heading": "ገጽ",
"orientation": {
"disabled": "አንድ ገጽ ብቻ ሲኖር ምንም ተጽእኖ የለውም",
"primary": "አቅጣጫ",
"secondary": "ገጾችን በአግድም ሆነ በቋሚ ለማሳየት"
}
},
"resume": {
"heading": "የስራልምድ ሰነድ",
"reset": {
"primary": "ሁሉንም ነገር ዳግም አስጀምር",
"secondary": "በጣም ብዙ ስህተቶችን ሰርተዋል? ሁሉንም ለውጦች ዳግም ለማስጀመር እና ከባዶ ለመጀመር እዚህ ይንኩ። ይጠንቀቁ፤ ይህ እርምጃ ወደ ኋላ መመለስ አይቻልም።"
},
"sample": {
"primary": "የናሙና መረጃን ጫን",
"secondary": "የት መጀመር እንዳለብዎት እርግጠኛ አይደሉም? የተሟላ የስራ ልምድ ሰነድ እንዴት እንደሚመስል ለማየት አንዳንድ ናሙና መረጃ ለመጫን እዚህ ይንኩ።"
}
}
},
"sharing": {
"heading": "ማጋራት",
"short-url": {
"label": "አጭር ማስፈንጠሪያ ይመርጣሉ።"
},
"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>Amruth Pillai</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": "አዲስ የሥራ ታሪክ ፍጠር"
},
"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,42 @@
{
"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": "የምንጭ ኮድ",
"docs": "ሰነዶች",
"privacy": "የግላዊነት መመሪያ",
"service": "የአገልግሎት ውሎች"
}
},
"screenshots": {
"heading": "የገጽ እይታዎች"
},
"testimonials": {
"heading": "ምስክሮች",
"body": "ጥሩም ይሁን መጥፎ፣ ስለ Reactive Resume እና ለእርስዎ እንዴት እንደነበረ አስተያየትዎን መስማት እፈልጋለሁ።<br/>በአለም ዙሪያ በተጠቃሚዎች የተላኩ አንዳንድ መልዕክቶች እነዚሁና",
"contact": "በዚህ በኩል ልታገኙኝ <1>ኢሜል</1> ትችላላችሁ ወይም <3>በድረ-ገጽ</3> ላይ ባለው የእውቂያ ቅጽ ማግኘት ይችላሉ።"
},
"summary": {
"body": "Reactive Resume የእርስዎን የስራ ታሪክ የመፍጠር፣ የማዘመን እና የማጋራት መደበኛ ተግባራትን እንደ 1 2 3 ቀላል ለማድረግ የተሰራ ነፃ እና በነጻ የሚገኝ የስራ ልምድ ሰነድ መገንቢያ ነው። በዚህ መገልገያ የተለያዩ የስራ ልምድ ሰነዶችን በመስራት፣ ከቀጣሪዎች ወይም ከጓደኞች ጋር በማስፈንጠሪያ ማጋራት እና እንደ PDF ማተም ፣ ሁሉንም በነጻ ፣ ምንም ማስታወቂያ ሳይኖር ፣ ምንም ክትትል ሳይደረግ ፣ የመረጃዎን ትክክለኛነት እና ግላዊነት ተጠብቆ ማከናወን ይችላሉ።",
"heading": "ማጠቃለያ"
}
}

View File

@ -0,0 +1,135 @@
{
"auth": {
"forgot-password": {
"actions": {
"send-email": "የይለፍ ቃል ዳግም ማስጀመሪያ ኢሜይል ላክ"
},
"body": "መልሰው ማግኘት ከሚፈልጉት መለያ ጋር የተያያዘውን የኢሜይል አድራሻ ያስገቡ።",
"form": {
"email": {
"label": "የኢሜል አድራሻ"
}
},
"heading": "የይለፍ ቃልዎን ረሱ?",
"help-text": "መለያው ካለ የይለፍ ቃልዎን እንደገና ለማስጀመር የሚያስችል ኢሜል ይደርስዎታል።"
},
"login": {
"actions": {
"login": "ግባ"
},
"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 ሰነድ"
},
"linkedin": {
"actions": {
"upload-archive": "የ ZIP ማህደር ስቀል"
},
"body": "መረጃዎን ከ LinkedIn ወደ በመላክ እና Reactive Resume ላይ በራስ-ሙላ መስኮችን በመጠቀም ጊዜ መቆጠብ ይችላሉ። በ LinkedIn ላይ ወደ <1>የመረጃ ግላዊነት</1> ክፍል ይሂዱ እና የመረጃ ማህደርዎን ይጠይቁ። ከተገኘ በኋላ፣ ከታች በሚገኘው የ ZIP ፋይሉን ይስቀሉ።",
"heading": "ከ LinkedIn ስቀል"
},
"reactive-resume": {
"actions": {
"upload-json": "JSON ስቀል",
"upload-json-v2": "JSON v2 ይስቀሉ።"
},
"body": "አሁን ካለው Reactive Resume ስሪት ጋር ወደ ውጭ የተላከ JSON ካለዎት፣ እንደገና ሊስተካከል የሚችል ስሪት ለማግኘት ወደዚህ መልሰው ማስገባት ይችላሉ።",
"heading": "ከ Reactive Resume ስቀል"
}
},
"rename-resume": {
"actions": {
"rename-resume": "የስራ ታሪክ ሰነዱን ደግመው ይሰይሙ"
},
"form": {
"name": {
"label": "ስም"
},
"slug": {
"label": "ማስፈንጥሪያ"
}
},
"heading": "የስራ ታሪክ ሰነዱን ደግመው ይሰይሙ"
}
}
}

View File

@ -270,6 +270,7 @@
"heading": "تبرع الى Reactive Resume"
},
"github": "الشفرة المصدرية",
"docs": "توثيق",
"heading": "الروابط"
},
"settings": {
@ -289,6 +290,10 @@
},
"heading": "الإعدادات",
"page": {
"format": {
"primary": "حجم الورق",
"secondary": "تحدد أبعاد صفحات سيرتك الذاتية"
},
"break-line": {
"primary": "خط فاصل",
"secondary": "اعرض خط في كل الصفحات لتحديد ارتفاع صفحة A4"

View File

@ -22,6 +22,7 @@
"links": {
"donate": "تبرّع",
"github": "الشفرة المصدرية",
"docs": "توثيق",
"privacy": "سياسة الخصوصية",
"service": "شروط الإستخدام"
}

View File

@ -270,6 +270,7 @@
"heading": "Направи дарение и подкрепи Reactive Resume"
},
"github": "Програмен код",
"docs": "Документация",
"heading": "Връзки"
},
"settings": {
@ -289,6 +290,10 @@
},
"heading": "Настройки",
"page": {
"format": {
"primary": "Размер на хартията",
"secondary": "Определя размерите на вашите страници с автобиография"
},
"break-line": {
"primary": "Линия на прекъсване",
"secondary": "Показване на линия на всички страници за обозначаване на височината на страница A4"

View File

@ -22,6 +22,7 @@
"links": {
"donate": "Дарение",
"github": "Програмен код",
"docs": "Документация",
"privacy": "Политика за поверителност",
"service": "Условия на ползване"
}

View File

@ -270,6 +270,7 @@
"heading": "Reactive Resume -তে দান করুন"
},
"github": "সোর্স কোড",
"docs": "ডকুমেন্টেশন",
"heading": "লিঙ্ক"
},
"settings": {
@ -289,6 +290,10 @@
},
"heading": "সেটিংস",
"page": {
"format": {
"primary": "কাগজের আকার",
"secondary": "আপনার জীবনবৃত্তান্ত পৃষ্ঠাগুলির মাত্রা নির্ধারণ করে"
},
"break-line": {
"primary": "লাইন ভেঙ্গে ফেলুন",
"secondary": "একটি A4 পৃষ্ঠার উচ্চতা চিহ্নিত করতে সমস্ত পৃষ্ঠায় একটি লাইন দেখান৷"

View File

@ -22,6 +22,7 @@
"links": {
"donate": "দান করুন",
"github": "সোর্স কোড",
"docs": "ডকুমেন্টেশন",
"privacy": "গোপনীয়তা নীতি",
"service": "সেবা পাবার শর্ত"
}

View File

@ -270,6 +270,7 @@
"heading": "Dona a Reactive Curriculum vitae"
},
"github": "Codi font",
"docs": "Documentació",
"heading": "Enllaços"
},
"settings": {
@ -289,6 +290,10 @@
},
"heading": "Configuració",
"page": {
"format": {
"primary": "Mida del paper",
"secondary": "Determina les dimensions de les pàgines del vostre currículum"
},
"break-line": {
"primary": "Línia de trencament",
"secondary": "Mostra una línia a totes les pàgines per marcar l'alçada d'una pàgina A4"

View File

@ -22,6 +22,7 @@
"links": {
"donate": "Donar",
"github": "Codi font",
"docs": "Documentació",
"privacy": "Política de privacitat",
"service": "Termes del servei"
}

View File

@ -270,6 +270,7 @@
"heading": "Přispějte na Reactive Resume"
},
"github": "Zdrojový kód",
"docs": "Dokumentace",
"heading": "Odkazy"
},
"settings": {
@ -289,6 +290,10 @@
},
"heading": "Nastavení",
"page": {
"format": {
"primary": "Velikost papíru",
"secondary": "Určuje rozměry stránek vašeho životopisu"
},
"break-line": {
"primary": "Nový řádek",
"secondary": "Zobrazit čáru na všech stránkách pro označení výšky stránky A4"

View File

@ -22,6 +22,7 @@
"links": {
"donate": "Darovat",
"github": "Zdrojový kód",
"docs": "Dokumentace",
"privacy": "Zásady ochrany osobních údajů",
"service": "Podmínky služby"
}

View File

@ -3,6 +3,7 @@
"actions": {
"add": "Tilføj ny {{token}}",
"delete": "Slet {{token}}",
"duplicate": "Dublet afsnit",
"edit": "Rediger {{token}}"
},
"columns": {
@ -80,13 +81,13 @@
"center-artboard": "Centrer tegnebræt",
"copy-link": "Kopier link til CV",
"export-pdf": "Eksporter PDF",
"redo": "Redo",
"toggle-orientation": "Skift sideorientering",
"toggle-page-break-line": "Skift sideskiftlinje",
"toggle-sidebars": "Sidebjælke til/fra",
"zoom-in": "Zoom ind",
"zoom-out": "Zoom ud",
"undo": "Fortryd",
"redo": "Redo"
"zoom-in": "Zoom ind",
"zoom-out": "Zoom ud"
}
},
"header": {
@ -114,6 +115,9 @@
"actions": {
"photo-filters": "Fotofiltre"
},
"birthdate": {
"label": "Fødselsdato"
},
"heading": "Grundlæggende",
"headline": {
"label": "Overskrift"
@ -121,9 +125,6 @@
"name": {
"label": "Fulde navn"
},
"birthdate": {
"label": "Fødselsdato"
},
"photo-filters": {
"effects": {
"border": {
@ -264,13 +265,15 @@
"button": "GitHub-problemer",
"heading": "Fejl? Ønsker til en ny funktion?"
},
"docs": "Dokumentation",
"donate": {
"body": "Hvis du kunne lide at bruge Reactive Resume, bedes du overveje at donere så meget som muligt til formålet med at holde appen oppe og køre, uden annoncer og gratis for evigt.",
"button": "Købe mig en kop kaffe",
"heading": "Donér til Reactive Resume"
},
"github": "Kildekode",
"heading": "Links"
"heading": "Links",
"reddit": "Reddit"
},
"settings": {
"global": {
@ -293,6 +296,10 @@
"primary": "Brudlinje",
"secondary": "Vis en streg på alle sider for at markere højden på en A4-side"
},
"format": {
"primary": "Papirstørrelse",
"secondary": "Bestemmer dimensionerne på dine CV-sider"
},
"heading": "Side",
"orientation": {
"disabled": "Har ingen effekt, når der kun er én side",

View File

@ -8,34 +8,36 @@
"features": {
"heading": "Funktioner",
"list": {
"ads": "Ingen reklamer.",
"ads": "Ingen reklamer",
"export": "Eksporter dit CV til JSON- eller PDF-format",
"free": "Gratis for evigt",
"import": "Importer data fra LinkedIn, JSON CV",
"languages": "Tilgængelig på flere sprog",
"more": "Og meget flere spændende funktioner, <1>læs alt om det her</1>",
"more": "Og mange flere spændende funktioner, <1>læs alt om det her</1>",
"tracking": "Ingen brugersporing"
}
},
"links": {
"heading": "Links",
"links": {
"docs": "Dokumentation",
"donate": "Donér",
"github": "Kildekode",
"privacy": "Fortrolighedspolitik",
"reddit": "Reddit",
"service": "Servicevilkår"
}
},
"screenshots": {
"heading": "Skærmbilleder"
},
"testimonials": {
"heading": "Udtalelser",
"body": "Godt eller dårligt, jeg ville elske at høre din mening om Reactive Resume og hvordan oplevelsen har været for dig.<br/>Her er nogle af de beskeder, der er sendt af brugere over hele verden.",
"contact": "Du kan kontakte mig via <1>min e-mail</1> eller gennem kontaktformularen på <3>min hjemmeside</3> ."
},
"summary": {
"body": "Reactive Resume er en gratis og open source CV-bygger, der er bygget til at gøre de hverdagsagtige opgaver med at oprette, opdatere og dele dit CV så lette som 1, 2, 3. Med denne app kan du oprette flere CV'er, dele dem med rekrutterere eller venner gennem et unikt link og udskriv det som en PDF, helt gratis, ingen annoncer, ingen sporing, uden at miste integriteten og fortroligheden af dine data.",
"heading": "Opsummering"
},
"testimonials": {
"body": "Godt eller dårligt, jeg ville elske at høre din mening om Reactive Resume og hvordan oplevelsen har været for dig.<br/>Her er nogle af de beskeder, der er sendt af brugere over hele verden.",
"contact": "Du kan kontakte mig via <1>min e-mail</1> eller gennem kontaktformularen på <3>min hjemmeside</3> .",
"heading": "Udtalelser"
}
}

View File

@ -1,9 +1,10 @@
{
"common": {
"actions": {
"add": "Neue {{token}} hinzufügen",
"delete": "Löschen {{token}}",
"edit": "Bearbeiten {{token}}"
"add": "{{token}} hinzufügen",
"delete": "{{token}} löschen",
"duplicate": "Abschnitt duplizieren",
"edit": "{{token}} bearbeiten"
},
"columns": {
"heading": "Spalten",
@ -17,10 +18,10 @@
"label": "Beschreibung"
},
"email": {
"label": "E-Mail Adresse"
"label": "E-Mail-Adresse"
},
"end-date": {
"help-text": "Dieses Feld leer lassen, wenn noch vorhanden",
"help-text": "Dieses Feld leer lassen, wenn dieser Eintrag noch kein Enddatum hat.",
"label": "Enddatum"
},
"keywords": {
@ -69,7 +70,7 @@
"empty-text": "Diese Liste ist leer."
},
"tooltip": {
"delete-item": "Sind Sie sicher, dass Sie dieses Element löschen möchten? Dies ist eine unumkehrbare Aktion.",
"delete-item": "Sind Sie sicher, dass Sie dieses Element löschen möchten? Dies lässt sich nicht rückgängig machen.",
"delete-section": "Abschnitt löschen",
"rename-section": "Abschnitt umbenennen",
"toggle-visibility": "Sichtbarkeit umschalten"
@ -80,13 +81,13 @@
"center-artboard": "Artboard zentrieren",
"copy-link": "Link zum Lebenslauf kopieren",
"export-pdf": "PDF exportieren",
"redo": "Wiederholen",
"toggle-orientation": "Seitenausrichtung umschalten",
"toggle-page-break-line": "Pausenzeile umschalten",
"toggle-sidebars": "Seitenleisten umschalten",
"zoom-in": "Vergrößern",
"zoom-out": "Verkleinern",
"undo": "Rückgängig machen",
"redo": "Redo"
"zoom-in": "Vergrößern",
"zoom-out": "Verkleinern"
}
},
"header": {
@ -96,8 +97,8 @@
"rename": "Umbenennen",
"share-link": "Link teilen",
"tooltips": {
"delete": "Sind Sie sicher, dass Sie diesen Lebenslauf löschen möchten? Dies ist eine unumkehrbare Aktion.",
"share-link": "Du musst die Sichtbarkeit deines Lebenslaufs in die Öffentlichkeit ändern, um ihn für andere sichtbar zu machen."
"delete": "Sind Sie sicher, dass Sie diesen Lebenslauf löschen möchten? Dies lässt sich nicht rückgängig machen.",
"share-link": "Sie müssen die Sichtbarkeit Ihres Lebenslaufs in Öffentlich ändern, um ihn für andere sichtbar zu machen."
}
}
},
@ -106,7 +107,7 @@
"awards": {
"form": {
"awarder": {
"label": "Auszeichnung"
"label": "Auszeichner"
}
}
},
@ -114,20 +115,20 @@
"actions": {
"photo-filters": "Fotofilter"
},
"birthdate": {
"label": "Geburtsdatum"
},
"heading": "Grundlagen",
"headline": {
"label": "Überschrift"
},
"name": {
"label": "Voller Name"
},
"birthdate": {
"label": "Geburtsdatum"
"label": "Vollständiger Name"
},
"photo-filters": {
"effects": {
"border": {
"label": "Grenze"
"label": "Rahmen"
},
"grayscale": {
"label": "Graustufen"
@ -158,13 +159,13 @@
"education": {
"form": {
"area-study": {
"label": "Studienbereich"
"label": "Studienfach"
},
"courses": {
"label": "Kurse"
},
"degree": {
"label": "Grad"
"label": "Abschluss"
},
"grade": {
"label": "Note"
@ -176,7 +177,7 @@
},
"location": {
"address": {
"label": "Adresse"
"label": "Straße"
},
"city": {
"label": "Stadt"
@ -184,12 +185,12 @@
"country": {
"label": "Land"
},
"heading": "Standort",
"heading": "Anschrift",
"postal-code": {
"label": "Postleitzahl"
},
"region": {
"label": "Region"
"label": "Bundesland"
}
},
"profiles": {
@ -201,7 +202,7 @@
"label": "Benutzername"
}
},
"heading": "Profiles",
"heading": "Soziale Netzwerke",
"heading_one": "Profil"
},
"publications": {
@ -239,16 +240,16 @@
"heading": "Exportieren",
"json": {
"primary": "JSON",
"secondary": "Laden Sie eine JSON-Version Ihres Lebenslaufs herunter, die Sie wieder in Reaktives Lebenslauf importieren können."
"secondary": "Laden Sie eine JSON-Version Ihres Lebenslaufs herunter, die Sie wieder in Reactive Resume importieren können."
},
"pdf": {
"loading": {
"primary": "PDF wird erstellt",
"secondary": "Bitte warten Sie, wenn Ihr PDF generiert wird, dies kann bis zu 15 Sekunden dauern."
"secondary": "Bitte warten Sie, während Ihr PDF generiert wird. Dies kann bis zu 15 Sekunden dauern."
},
"normal": {
"primary": "PDF",
"secondary": "Laden Sie sich ein PDF Ihres Lebenslaufs herunter, das Sie ausdrucken und an Ihren Traumjob senden können. Diese Datei kann nicht zur weiteren Bearbeitung importiert werden."
"secondary": "Laden Sie sich ein PDF Ihres Lebenslaufs herunter, dass Sie ausdrucken oder an Ihren Traumarbeitgeber senden können. Diese Datei kann nicht zur weiteren Bearbeitung importiert werden."
}
}
},
@ -260,55 +261,61 @@
},
"links": {
"bugs-features": {
"body": "Hält Sie etwas davon ab, einen Lebenslauf zu erstellen? Oder haben Sie eine tolle Idee, die Sie hinzufügen möchten? Erhöhen Sie einen Eintrag auf GitHub, um loszulegen.",
"body": "Sind Sie bei der Erstellung Ihres Lebenslaufs auf ein Problem gestoßen? Oder haben Sie eine tolle Idee, die Sie hinzufügen möchten? Erstellen Sie ein Ticket auf GitHub.",
"button": "GitHub Themen",
"heading": "Fehler? Feature-Anfragen?"
"heading": "Fehler? Verbesserungsvorschläge?"
},
"docs": "Dokumentation",
"donate": {
"body": "Wenn Ihnen Reactive Resume gefallen hat, denken Sie bitte darüber nach, so viel wie möglich zu spenden, damit die App für immer kostenlos und werbefrei bleibt.",
"body": "Sollte Ihnen Reactive Resume gefallen, möchte ich Sie bitten, etwas zu spenden, damit die App für immer kostenlos und werbefrei bleibt.",
"button": "Kaufe mir einen Kaffee",
"heading": "Spenden an Reaktives Lebenslauf"
"heading": "Spenden Sie an Reactive Resume."
},
"github": "Quellcode",
"heading": "Links"
"heading": "Links",
"reddit": "Reddit"
},
"settings": {
"global": {
"date": {
"primary": "Datum",
"secondary": "Datumsformat für die gesamte App"
"secondary": "Datumsformat für die gesamte App."
},
"heading": "Globale",
"language": {
"primary": "Sprache",
"secondary": "Sprache anzeigen, die in der gesamten App verwendet wird"
"secondary": "Anzeigesprache, die in der gesamten App verwendet wird."
},
"theme": {
"primary": "Thema"
"primary": "App Design"
}
},
"heading": "Einstellungen",
"page": {
"break-line": {
"primary": "Linie anhalten",
"secondary": "Zeile auf allen Seiten anzeigen, um die Höhe einer A4-Seite zu markieren"
"primary": "Seitenumbruch anzeigen",
"secondary": "Zeigt den Seitenumbruch als Linie auf allen Seiten an."
},
"format": {
"primary": "Papiergröße",
"secondary": "Legt die Seitenabmessungen Ihres Lebenslaufs fest."
},
"heading": "Seite",
"orientation": {
"disabled": "Hat keine Auswirkung, wenn nur eine Seite vorhanden ist",
"disabled": "Hat keine Auswirkung, wenn nur eine Seite vorhanden ist.",
"primary": "Ausrichtung",
"secondary": "Ob Seiten horizontal oder vertikal angezeigt werden sollen"
"secondary": "Legt fest, ob Seiten horizontal oder vertikal angezeigt werden sollen."
}
},
"resume": {
"heading": "Lebenslauf",
"reset": {
"primary": "Alles zurücksetzen",
"secondary": "Zu viele Fehler gemacht? Klicken Sie hier, um alle Änderungen zurückzusetzen und bei Null zu beginnen. Sei vorsichtig, diese Aktion kann nicht rückgängig gemacht werden."
"secondary": "Zu viele Fehler gemacht? Klicken Sie hier, um alle Änderungen zurückzusetzen und von vorne zu beginnen. Vorsicht! Diese Aktion kann nicht rückgängig gemacht werden."
},
"sample": {
"primary": "Beispieldaten laden",
"secondary": "Nicht sicher, wo man anfangen soll? Klicken Sie hier, um ein paar Beispieldaten zu laden, um zu sehen, wie ein vollständiger Lebenslauf aussieht."
"secondary": "Sie sind nicht sicher, wo Sie anfangen sollen? Klicken Sie hier, um Beispieldaten zu laden. So können Sie sich ansehen, wie ein vollständiger Lebenslauf aussieht."
}
}
},
@ -318,8 +325,8 @@
"label": "Kurze URL bevorzugen"
},
"visibility": {
"subtitle": "Erlaube jemandem mit einem Link deinen Lebenslauf anzusehen",
"title": "Öffentlich"
"subtitle": "Erlaubt jedem, dem Sie diesen Link schicken, Ihren Lebenslauf anzusehen.",
"title": "Öffentlich zugänglich"
}
},
"templates": {
@ -328,16 +335,16 @@
"theme": {
"form": {
"background": {
"label": "Hintergrund"
"label": "Hintergrundfarbe"
},
"primary": {
"label": "Primär"
"label": "Primärfarbe"
},
"text": {
"label": "Text"
"label": "Textfarbe"
}
},
"heading": "Thema"
"heading": "Lebenslauf Design"
},
"typography": {
"form": {

View File

@ -13,14 +13,14 @@
"help-text": "Dieser Abschnitt unterstützt <1>Markdown</1> Formatierung."
},
"date": {
"present": "Gegenwärtig"
"present": "Heute"
},
"subtitle": "Ein freier und Open-Source-Lebenslauf-Builder.",
"title": "Reaktives Lebenslauf",
"subtitle": "Ein kostenloser Open Source Lebenslauf-Baukasten.",
"title": "Reactive Resume",
"toast": {
"error": {
"upload-file-size": "Bitte laden Sie nur Dateien unter 2 Megabytes hoch.",
"upload-photo-size": "Bitte laden Sie nur Fotos unter 2 Megabytes hoch, vorzugsweise quadratisch."
"upload-photo-size": "Bitte laden Sie nur Fotos unter 2 Megabytes hoch, am besten in einem quadratischen Format."
},
"success": {
"resume-link-copied": "Ein Link zu deinem Lebenslauf wurde in deine Zwischenablage kopiert."

View File

@ -1,25 +1,25 @@
{
"create-resume": {
"subtitle": "Bei Null anfangen",
"subtitle": "Mit einem leeren Lebenslauf starten",
"title": "Neuen Lebenslauf erstellen"
},
"import-external": {
"subtitle": "LinkedIn, JSON Resume, Reaktives Lebenslauf",
"title": "Aus externen Quellen importieren"
"subtitle": "LinkedIn, JSON Lebenslauf, Reactive Resume",
"title": "Aus externer Quelle importieren"
},
"resume": {
"menu": {
"delete": "Löschen",
"duplicate": "Duplikat",
"duplicate": "Duplizieren",
"open": "Öffnen",
"rename": "Umbenennen",
"share-link": "Einen Link teilen",
"share-link": "Link teilen",
"tooltips": {
"delete": "Möchten Sie diesen Lebenslauf wirklich löschen? Dies ist eine irreversible Aktion.",
"delete": "Möchten Sie diesen Lebenslauf wirklich löschen? Dies lässt sich nicht rückgängig machen.",
"share-link": "Sie müssen die Sichtbarkeit Ihres Lebenslaufs auf öffentlich ändern, um ihn für andere sichtbar zu machen."
}
},
"timestamp": "Zuletzt vor {{timestamp}} aktualisiert"
"timestamp": "Zuletzt vor {{timestamp}} geändert."
},
"title": "Dashboard"
}

View File

@ -1,6 +1,6 @@
{
"actions": {
"app": "Gehe zu App",
"app": "Gehe zur App",
"login": "Anmelden",
"logout": "Ausloggen",
"register": "Registrieren"
@ -9,33 +9,35 @@
"heading": "Eigenschaften",
"list": {
"ads": "Keine Werbung",
"export": "Exportieren Sie Ihren Lebenslauf in JSON oder PDF Format",
"free": "Frei, für immer",
"import": "Importiere Daten von LinkedIn, JSON Lebenslauf",
"languages": "In mehreren Sprachen zugänglich",
"more": "Und viel mehr aufregende Features, <1>lesen Sie alles hier</1>",
"tracking": "Keine Benutzerverfolgung"
"export": "Exportieren Sie Ihren Lebenslauf als JSON oder PDF Format",
"free": "Kostenlos, für immer",
"import": "Importieren Sie Ihre Daten von LinkedIn oder als JSON Lebenslauf",
"languages": "In mehreren Sprachen verfügbar",
"more": "Und viele weitere aufregende Features. <1>Hier gibt es mehr informationen (in englischer Sprache)</1>",
"tracking": "Kein Benutzertracking"
}
},
"links": {
"heading": "Verknüpfungen",
"links": {
"docs": "Dokumentation",
"donate": "Spenden",
"github": "Quellcode",
"privacy": "Datenschutzerklärung",
"reddit": "Reddit",
"service": "Nutzungsbedingungen"
}
},
"screenshots": {
"heading": "Screenshots"
},
"testimonials": {
"heading": "Referenzen",
"body": "Gut oder schlecht, ich würde gerne Ihre Meinung über Reactive Resume und wie die Erfahrung war für Sie.<br/>Hier sind einige der Nachrichten, die von Benutzern auf der ganzen Welt gesendet werden.",
"contact": "Du kannst mich über <1>meine E-Mail</1> oder über das Kontaktformular auf <3>meiner Website</3>erreichen."
},
"summary": {
"body": "Reaktives Lebenslauf ist ein freier und Open-Source-Lebenslauf-Builder, der gebaut wurde, um die weltlichen Aufgaben zu machen, zu erstellen, Aktualisieren und teilen Sie Ihren Lebenslauf so einfach wie 1, 2, 3. Mit dieser App kannst du mehrere Bewerbungen erstellen, sie mit Recruitern oder Freunden über einen einzigartigen Link teilen und sie als PDF ausdrucken. alle kostenlos, keine Werbung, keine Verfolgung, ohne die Integrität und Privatsphäre Ihrer Daten zu verlieren.",
"body": "Reactive Resume ist ein kostenloser Open Source Lebenslauf-Builder, der gebaut wurde, um die langweilige Aufgabe einen Lebenslauf zu erstellen, aktuell zu halten und zu teilen so einfach wie möglich zu machen. Mit dieser App können Sie mehrere Lebensläufe erstellen, sie mit Recruitern oder Freunden über einen einzigartigen Link teilen und als PDF exportieren. Kostenlos, ohne Werbung, kein Tracking, ohne die Integrität und Privatsphäre Ihrer Daten zu verlieren.",
"heading": "Zusammenfassung"
},
"testimonials": {
"body": "Egal ob gut oder schlecht - ich würde gerne Ihre Meinung über Reactive Resume hören und welche Erfahrungen Sie gemacht haben.<br/>Hier sind einige der Nachrichten, die mir von Benutzern auf der ganzen Welt zugesandt wurden.",
"contact": "Sie können mich über <1>meine E-Mail</1> oder über das Kontaktformular auf <3>meiner Website</3> erreichen.",
"heading": "Referenzen"
}
}

View File

@ -2,16 +2,16 @@
"auth": {
"forgot-password": {
"actions": {
"send-email": "Passwort zurücksetzen E-Mail senden"
"send-email": "Passwort zurücksetzen E-Mail senden."
},
"body": "Geben Sie einfach die E-Mail-Adresse ein, die mit dem Konto verknüpft ist, das Sie wiederherstellen möchten.",
"body": "Geben Sie die E-Mail-Adresse des Benutzerkontos ein, dass Sie wiederherstellen möchten.",
"form": {
"email": {
"label": "E-Mail-Addresse"
"label": "E-Mail-Adresse"
}
},
"heading": "Passwort vergessen?",
"help-text": "Wenn das Konto existiert, erhalten Sie eine E-Mail mit einem Link zum Zurücksetzen Ihres Passworts."
"help-text": "Sollte das Konto existieren, erhalten Sie eine E-Mail mit einem Link zum Zurücksetzen des Passworts."
},
"login": {
"actions": {
@ -24,12 +24,12 @@
},
"username": {
"help-text": "Sie können auch Ihre E-Mail-Adresse eingeben",
"label": "Nutzername"
"label": "Benutzername"
}
},
"heading": "Bei Ihrem Konto anmelden",
"recover-text": "Falls Sie Ihr Passwort vergessen haben, können Sie <1>Ihr Konto wiederherstellen</1> hier einrichten.",
"register-text": "Wenn Sie keinen haben, können Sie hier <1>ein Konto erstellen</1> anlegen."
"recover-text": "Falls Sie Ihr Passwort vergessen haben, können Sie es <1>hier zurücksetzen</1>.",
"register-text": "Sollten Sie kein Benutzerkonto haben, können Sie <1>hier ein Konto anlegen</1>."
},
"register": {
"actions": {
@ -42,7 +42,7 @@
"label": "Passwort bestätigen"
},
"email": {
"label": "E-Mail-Addresse"
"label": "E-Mail-Adresse"
},
"name": {
"label": "Vollständiger Name"
@ -71,6 +71,31 @@
}
},
"heading": "Passwort zurücksetzen"
},
"profile": {
"heading": "Ihr Benutzerkonto",
"form": {
"avatar": {
"help-text": "Sie können Ihr Profilbild auf <1>Gravatar</1> aktualisieren"
},
"name": {
"label": "Vollständiger Name"
},
"email": {
"label": "E-Mail-Adresse",
"help-text": "Im Moment ist es nicht möglich, Ihre E-Mail-Adresse zu aktualisieren. Bitte erstellen Sie stattdessen ein neues Konto."
}
},
"delete-account": {
"heading": "Konto und Daten löschen",
"body": "Um Ihr Konto, Ihre Daten und alle Ihre Lebensläufe zu löschen, geben Sie „{{keyword}}“ in das Textfeld ein und klicken Sie auf die Schaltfläche. Bitte beachten Sie, dass dies ein irreversibler Vorgang ist und Ihre Daten nicht wiederhergestellt werden können.",
"actions": {
"delete": "Account löschen"
}
},
"actions": {
"save": "Änderungen speichern"
}
}
},
"dashboard": {
@ -87,7 +112,7 @@
"label": "Ist öffentlich zugänglich?"
},
"slug": {
"label": "Slug"
"label": "URL-Segment"
}
},
"heading": "Neuen Lebenslauf erstellen"
@ -98,14 +123,14 @@
"actions": {
"upload-json": "JSON hochladen"
},
"body": "Wenn du einen <1>validierten JSON Resume</1> bereit hast, kannst du damit deine Entwicklung auf reaktiven Resume beschleunigen. Klicken Sie auf den Button unten und laden Sie eine gültige JSON-Datei hoch, um zu beginnen.",
"body": "Wenn du einen <1>validierten JSON Lebenslauf</1> bereit hast, kannst du damit deine Entwicklung auf Reactive Resume beschleunigen. Klicken Sie auf den Button unten und laden Sie eine gültige JSON-Datei hoch, um zu beginnen.",
"heading": "Import vom JSON-Lebenslauf"
},
"linkedin": {
"actions": {
"upload-archive": "ZIP-Archiv hochladen"
},
"body": "Sie können Zeit sparen, indem Sie Ihre Daten aus LinkedIn exportieren und sie zum automatischen Ausfüllen von Feldern auf Reaktives Lebenslauf verwenden. Gehen Sie zum Abschnitt <1>Datenschutz </1> auf LinkedIn und fordern Sie ein Archiv Ihrer Daten an. Sobald diese verfügbar sind, laden Sie die ZIP-Datei unten hoch.",
"body": "Sie können Zeit sparen, indem Sie Ihre Daten aus LinkedIn exportieren und sie zum automatischen Ausfüllen von Feldern auf Reactive Resume verwenden. Gehen Sie zum Abschnitt <1>Datenschutz </1> auf LinkedIn und fordern Sie ein Archiv Ihrer Daten an. Sobald diese verfügbar sind, laden Sie die ZIP-Datei unten hoch.",
"heading": "Aus LinkedIn importieren"
},
"reactive-resume": {
@ -114,7 +139,7 @@
"upload-json-v2": "Laden Sie JSON von v2 hoch"
},
"body": "Wenn Sie eine JSON haben, die mit der aktuellen Version von Reactive Resume exportiert wurde, können Sie sie hier wieder importieren, um wieder eine bearbeitbare Version zu erhalten.",
"heading": "Import vom Reaktives Lebenslauf"
"heading": "Import von Reactive Resume"
}
},
"rename-resume": {
@ -126,7 +151,7 @@
"label": "Name"
},
"slug": {
"label": "Slug"
"label": "URL-Segment"
}
},
"heading": "Lebenslauf umbenennen"

View File

@ -270,6 +270,7 @@
"heading": "Κάντε δωρεά στο Reactive βιογραφικό"
},
"github": "Πηγαίος κώδικας",
"docs": "Τεκμηρίωση",
"heading": "Σύνδεσμοι"
},
"settings": {
@ -289,6 +290,10 @@
},
"heading": "Ρυθμίσεις",
"page": {
"format": {
"primary": "Μέγεθος χαρτιού",
"secondary": "Καθορίζει τις διαστάσεις των σελίδων του βιογραφικού σας"
},
"break-line": {
"primary": "Γραμμή διακοπής",
"secondary": "Εμφάνιση μιας γραμμής σε όλες τις σελίδες για να επισημάνετε το ύψος μιας σελίδας Α4"

View File

@ -22,6 +22,7 @@
"links": {
"donate": "Δωρεά",
"github": "Πηγαίος Κώδικας",
"docs": "Τεκμηρίωση",
"privacy": "Πολιτική Απορρήτου",
"service": "Όρους παροχής υπηρεσιών"
}

View File

@ -3,6 +3,7 @@
"actions": {
"add": "Add New {{token}}",
"delete": "Delete {{token}}",
"duplicate": "Duplicate Section",
"edit": "Edit {{token}}"
},
"columns": {
@ -80,13 +81,13 @@
"center-artboard": "Center Artboard",
"copy-link": "Copy Link to Resume",
"export-pdf": "Export PDF",
"redo": "Redo",
"toggle-orientation": "Toggle Page Orientation",
"toggle-page-break-line": "Toggle Page Break Line",
"toggle-sidebars": "Toggle Sidebars",
"zoom-in": "Zoom In",
"zoom-out": "Zoom Out",
"undo": "Undo",
"redo": "Redo"
"zoom-in": "Zoom In",
"zoom-out": "Zoom Out"
}
},
"header": {
@ -114,6 +115,9 @@
"actions": {
"photo-filters": "Photo Filters"
},
"birthdate": {
"label": "Date of Birth"
},
"heading": "Basics",
"headline": {
"label": "Headline"
@ -121,9 +125,6 @@
"name": {
"label": "Full Name"
},
"birthdate": {
"label": "Date of Birth"
},
"photo-filters": {
"effects": {
"border": {
@ -244,7 +245,7 @@
"pdf": {
"loading": {
"primary": "Generating PDF",
"secondary": "Please wait as your PDF gets generated, this may take upto 15 seconds."
"secondary": "Please wait as your PDF gets generated, this may take up to 15 seconds."
},
"normal": {
"primary": "PDF",
@ -264,13 +265,15 @@
"button": "GitHub Issues",
"heading": "Bugs? Feature Requests?"
},
"docs": "Documentation",
"donate": {
"body": "If you liked using Reactive Resume, please consider donating as much as you can to the cause of keeping the app up and running, without ads and free forever.",
"button": "Buy me a coffee",
"heading": "Donate to Reactive Resume"
},
"github": "Source Code",
"heading": "Links"
"heading": "Links",
"reddit": "Reddit"
},
"settings": {
"global": {
@ -293,6 +296,10 @@
"primary": "Break Line",
"secondary": "Show a line on all pages to mark the height of an A4 page"
},
"format": {
"primary": "Paper Size",
"secondary": "Determines the dimensions of your resume pages"
},
"heading": "Page",
"orientation": {
"disabled": "Has no effect when there is only one page",

View File

@ -20,7 +20,7 @@
"toast": {
"error": {
"upload-file-size": "Please upload only files under 2 megabytes.",
"upload-photo-size": "Please upload only photos under 2 megabytes, preferrably square."
"upload-photo-size": "Please upload only photos under 2 megabytes, preferably square."
},
"success": {
"resume-link-copied": "A link to your resume has been copied to your clipboard."

View File

@ -20,22 +20,24 @@
"links": {
"heading": "Links",
"links": {
"docs": "Documentation",
"donate": "Donate",
"github": "Source Code",
"privacy": "Privacy Policy",
"reddit": "Reddit",
"service": "Terms of Service"
}
},
"screenshots": {
"heading": "Screenshots"
},
"testimonials": {
"heading": "Testimonials",
"body": "Good or bad, I would love to hear your opinion on Reactive Resume and how the experience has been for you.<br/>Here are some of the messages sent in by users across the world.",
"contact": "You can reach out to me through <1>my email</1> or through the contact form on <3>my website</3>."
},
"summary": {
"body": "Reactive Resume is a free and open source resume builder that's built to make the mundane tasks of creating, updating and sharing your resume as easy as 1, 2, 3. With this app, you can create multiple resumes, share them with recruiters or friends through a unique link and print it as a PDF, all for free, no ads, no tracking, without losing the integrity and privacy of your data.",
"heading": "Summary"
},
"testimonials": {
"body": "Good or bad, I would love to hear your opinion on Reactive Resume and how the experience has been for you.<br/>Here are some of the messages sent in by users across the world.",
"contact": "You can reach out to me through <1>my email</1> or through the contact form on <3>my website</3>.",
"heading": "Testimonials"
}
}

View File

@ -71,6 +71,31 @@
}
},
"heading": "Reset your password"
},
"profile": {
"heading": "Your Account",
"form": {
"avatar": {
"help-text": "You can update your profile picture on <1>Gravatar</1>"
},
"name": {
"label": "Full Name"
},
"email": {
"label": "Email Address",
"help-text": "It is not possible to update your email address at the moment, please create a new account instead."
}
},
"delete-account": {
"heading": "Delete Account and Data",
"body": "To delete your account, your data and all your resumes, type \"{{keyword}}\" into the textbox and click on the button. Please note that this is an irreversible action and your data cannot be retrieved again.",
"actions": {
"delete": "Delete Account"
}
},
"actions": {
"save": "Save Changes"
}
}
},
"dashboard": {

Some files were not shown because too many files have changed in this diff Show More