Compare commits

...

15 Commits

Author SHA1 Message Date
Henry
0f92ac0d9b fix: update pnpm lockfile 2025-08-23 17:22:12 +02:00
Ridham Khandar
eb0ca9c738 fix: delay clearing modal content until fade-out on public board (#151)
* fix: closing the modal on the public board page clears the content before the modal fade out animation finishes

* refactor: enhance CheckboxDropdown component to handle empty states and improve item rendering

* Update apps/web/src/views/public/board/CardModal.tsx

Co-authored-by: Henry <30578846+hjball@users.noreply.github.com>

---------

Co-authored-by: Henry <30578846+hjball@users.noreply.github.com>
2025-08-22 17:38:39 +02:00
Ridham Khandar
3233c35836 fix: board not found flicker on reloading public boards (#149)
* fix: board not found flicker on reloading public boards

* fix: using netx-theme's ThemeProvider

* chore: installing next-theme

* fix: theme issue on landing page

* fix: image theme hydration issue
2025-08-22 17:28:59 +02:00
Jyotirmoy Bandyopadhayaya
ba2fd7f695 feat: added oidc auth plugin for better auth (#147)
* feat: added oidc auth plugin for better auth

* chore: remove unused code

* chore: revert change to pnpm workspace file

* chore: remove unused code

* chore: remove unused code

* chore: remove unused code

* chore: added requested changes
2025-08-18 12:43:35 +01:00
Ridham Khandar
c7f7531b11 refactor: update modal implementation across multiple views (#150)
* fix: filter out null users from workspace members in board filters

* refactor: update modal implementation across multiple views
2025-08-18 12:41:44 +01:00
Vedant
4f57fc45a7 feat: add change password feature (#145)
* feat: add change password feature

* chore: update translations

---------

Co-authored-by: Henry <henry_ball@hotmail.co.uk>
2025-08-17 21:21:19 +01:00
Henry
ea92dcd2ed feat: add basic white labelling (#146) 2025-08-15 15:20:07 +01:00
Henry
d51600aba8 refactor: improve card layout and scrollbar styling (#143) 2025-08-14 22:10:45 +01:00
Henry
c3ed2e5e7f fix: missing translation for editor placeholder (#142) 2025-08-14 21:36:43 +01:00
Henry
13b10471ec feat: card checklists (#141)
* feat: setup checklist schema

* feat: scaffold checklist router

* feat: add create new checklist modal

* feat: create new checklist item

* feat: toggle checklist item completed state

* feat: update checklist name

* feat: delete checklist

* feat: show checklists progress on cards

* feat: tweak light mode styling

* feat: focus item form on creation of new checklist

* feat: tweak new checklist item form styling

* feat: add checklist activity

* feat: show checklist progress on public board page

* feat: display checklist items on public card modal

* chore: add translations
2025-08-14 19:59:36 +01:00
Cyber
80d1c5f805 fix: check if POSTGRES_URL env variable is set before starting the migration script (if external db) (#139) 2025-08-14 19:58:26 +01:00
Ridham Khandar
8079345546 feat: tagging members in description (#140)
* feat: tagging members in description

* chore: tiptap mention package

* feat: avatar before names in members dropdown
2025-08-14 19:57:35 +01:00
Ridham Khandar
4a67afdd3a fix: add new created label to selected label (#136) 2025-08-09 20:35:29 +01:00
Cyber
d555546782 feat: add pglite support (#138) 2025-08-09 20:32:13 +01:00
Henry
e53ec868a5 fix: only use cloud mailer client if creds exist 2025-08-04 11:29:17 +01:00
79 changed files with 9999 additions and 1286 deletions

View File

@@ -3,6 +3,8 @@
# Required environment variables # Required environment variables
NEXT_PUBLIC_BASE_URL= # e.g. https://kan.bn NEXT_PUBLIC_BASE_URL= # e.g. https://kan.bn
BETTER_AUTH_SECRET= # Random 32+ char string (can gen with: openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 32) BETTER_AUTH_SECRET= # Random 32+ char string (can gen with: openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 32)
# Fill if you want to use an external database
POSTGRES_URL= # e.g. postgresql://kan:your_password@your_host:5432/kan POSTGRES_URL= # e.g. postgresql://kan:your_password@your_host:5432/kan
# Only required if deploying from compose # Only required if deploying from compose

3
.gitignore vendored
View File

@@ -50,3 +50,6 @@ docker-compose.override.yml
# runtime env # runtime env
__ENV.js __ENV.js
i18n.cache i18n.cache
# pgdata
/apps/web/pgdata

View File

@@ -138,36 +138,40 @@ pnpm dev
## Environment Variables 🔐 ## Environment Variables 🔐
| Variable | Description | Required | Example | | Variable | Description | Required | Example |
| -------------------------------- | -------------------------------------------------------- | ------------------ | --------------------------------------------- | | ----------------------------------------- | -------------------------------------------------------- | ------------------------ | ----------------------------------------------------------- |
| `POSTGRES_URL` | PostgreSQL connection URL | Yes | `postgres://user:pass@localhost:5432/db` | | `POSTGRES_URL` | PostgreSQL connection URL | To use external database | `postgres://user:pass@localhost:5432/db` |
| `EMAIL_FROM` | Sender email address | For Email | `"Kan <hello@mail.kan.bn>"` | | `EMAIL_FROM` | Sender email address | For Email | `"Kan <hello@mail.kan.bn>"` |
| `SMTP_HOST` | SMTP server hostname | For Email | `smtp.resend.com` | | `SMTP_HOST` | SMTP server hostname | For Email | `smtp.resend.com` |
| `SMTP_PORT` | SMTP server port | For Email | `465` | | `SMTP_PORT` | SMTP server port | For Email | `465` |
| `SMTP_USER` | SMTP username/email | No | `resend` | | `SMTP_USER` | SMTP username/email | No | `resend` |
| `SMTP_PASSWORD` | SMTP password/token | No | `re_xxxx` | | `SMTP_PASSWORD` | SMTP password/token | No | `re_xxxx` |
| `SMTP_SECURE` | Use secure SMTP connection (defaults to true if not set) | For Email | `true` | | `SMTP_SECURE` | Use secure SMTP connection (defaults to true if not set) | For Email | `true` |
| `NEXT_PUBLIC_BASE_URL` | Base URL of your installation | Yes | `http://localhost:3000` | | `NEXT_PUBLIC_BASE_URL` | Base URL of your installation | Yes | `http://localhost:3000` |
| `BETTER_AUTH_SECRET` | Auth encryption secret | Yes | Random 32+ char string | | `BETTER_AUTH_SECRET` | Auth encryption secret | Yes | Random 32+ char string |
| `BETTER_AUTH_TRUSTED_ORIGINS` | Allowed callback origins | No | `http://localhost:3000,http://localhost:3001` | | `BETTER_AUTH_TRUSTED_ORIGINS` | Allowed callback origins | No | `http://localhost:3000,http://localhost:3001` |
| `GOOGLE_CLIENT_ID` | Google OAuth client ID | For Google login | `xxx.apps.googleusercontent.com` | | `GOOGLE_CLIENT_ID` | Google OAuth client ID | For Google login | `xxx.apps.googleusercontent.com` |
| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | For Google login | `xxx` | | `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | For Google login | `xxx` |
| `DISCORD_CLIENT_ID` | Discord OAuth client ID | For Discord login | `xxx` | | `DISCORD_CLIENT_ID` | Discord OAuth client ID | For Discord login | `xxx` |
| `DISCORD_CLIENT_SECRET` | Discord OAuth client secret | For Discord login | `xxx` | | `DISCORD_CLIENT_SECRET` | Discord OAuth client secret | For Discord login | `xxx` |
| `GITHUB_CLIENT_ID` | GitHub OAuth client ID | For GitHub login | `xxx` | | `GITHUB_CLIENT_ID` | GitHub OAuth client ID | For GitHub login | `xxx` |
| `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret | For GitHub login | `xxx` | | `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret | For GitHub login | `xxx` |
| `TRELLO_APP_API_KEY` | Trello app API key | For Trello import | `xxx` | | `OIDC_CLIENT_ID` | Generic OIDC client ID | For OIDC login | `xxx` |
| `TRELLO_APP_API_SECRET` | Trello app API secret | For Trello import | `xxx` | | `OIDC_CLIENT_SECRET` | Generic OIDC client secret | For OIDC login | `xxx` |
| `S3_REGION` | S3 storage region | For file uploads | `WEUR` | | `OIDC_DISCOVERY_URL` | OIDC discovery URL | For OIDC login | `https://auth.example.com/.well-known/openid-configuration` |
| `S3_ENDPOINT` | S3 endpoint URL | For file uploads | `https://xxx.r2.cloudflarestorage.com` | | `TRELLO_APP_API_KEY` | Trello app API key | For Trello import | `xxx` |
| `S3_ACCESS_KEY_ID` | S3 access key | For file uploads | `xxx` | | `TRELLO_APP_API_SECRET` | Trello app API secret | For Trello import | `xxx` |
| `S3_SECRET_ACCESS_KEY` | S3 secret key | For file uploads | `xxx` | | `S3_REGION` | S3 storage region | For file uploads | `WEUR` |
| `S3_FORCE_PATH_STYLE` | Use path-style URLs for S3 | For file uploads | `true` | | `S3_ENDPOINT` | S3 endpoint URL | For file uploads | `https://xxx.r2.cloudflarestorage.com` |
| `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` | | `S3_ACCESS_KEY_ID` | S3 access key | For file uploads | `xxx` |
| `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` | | `S3_SECRET_ACCESS_KEY` | S3 secret key | For file uploads | `xxx` |
| `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` | | `S3_FORCE_PATH_STYLE` | Use path-style URLs for S3 | For file uploads | `true` |
| `NEXT_PUBLIC_ALLOW_CREDENTIALS` | Allow email & password login | For authentication | `true` | | `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` |
| `NEXT_PUBLIC_DISABLE_SIGN_UP` | Disable sign up | For authentication | `false` | | `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` |
| `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` |
| `NEXT_PUBLIC_ALLOW_CREDENTIALS` | Allow email & password login | For authentication | `true` |
| `NEXT_PUBLIC_DISABLE_SIGN_UP` | Disable sign up | For authentication | `false` |
| `NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY` | Hide “Powered by kan.bn” on public boards (self-host) | For white labelling | `true` |
See `.env.example` for a complete list of supported environment variables. See `.env.example` for a complete list of supported environment variables.

View File

@@ -81,5 +81,4 @@ ARG PORT=3000
ENV PORT=${PORT} ENV PORT=${PORT}
EXPOSE ${PORT} EXPOSE ${PORT}
CMD ["sh", "-c", "cd /app && pnpm db:migrate && cd /app/apps/web && pnpm start"] CMD ["sh", "-c", "if [ -n \"$POSTGRES_URL\" ]; then cd /app && pnpm db:migrate && cd /app/apps/web; fi && pnpm start"]

View File

@@ -13,17 +13,25 @@ checksums:
Activity%20logs/singular: 8b1f0bb96a905646ecfad1cfdfa42168 Activity%20logs/singular: 8b1f0bb96a905646ecfad1cfdfa42168
Add%20a%20card/singular: 9d80becc4fe65a74e0004e4fd290735d Add%20a%20card/singular: 9d80becc4fe65a74e0004e4fd290735d
Add%20a%20comment.../singular: c28cfccc0cc69a2a2487e37eb9988028 Add%20a%20comment.../singular: c28cfccc0cc69a2a2487e37eb9988028
Add%20description...%20(type%20'%2F'%20to%20open%20commands)/singular: df99ea599521682e9ad0a90716955dc6 Add%20an%20item.../singular: f8e7993980420698700b07f56b3a38af
Add%20checklist/singular: 05d73200b56cfea75fb3a0f94c9bfb74
Add%20description...%20(type%20'%2F'%20to%20open%20commands%20or%20'%40'%20to%20mention)/singular: c6eb35a796dd7ac0e3dbc66244b71248
Add%20details.../singular: 2f42547fd5d199f173aa7a88c8a9b19a
Add%20label/singular: 0be732d46df263265935fda342097a08 Add%20label/singular: 0be732d46df263265935fda342097a08
Add%20member/singular: 11979625770516ca287e929381778e02 Add%20member/singular: 11979625770516ca287e929381778e02
added%20a%20checklist/singular: 44304f4a5ef3a46378eea243b5d2df79
added%20a%20checklist%20item/singular: 20bc0330dba5a9ec978e04bec174365a
added%20a%20label%20to%20the%20card/singular: 04c5e4ee9b7b7e77ef089d2ac473d235 added%20a%20label%20to%20the%20card/singular: 04c5e4ee9b7b7e77ef089d2ac473d235
added%20a%20member%20to%20the%20card/singular: 95495e770062e2fd590333d56e6308d2 added%20a%20member%20to%20the%20card/singular: 95495e770062e2fd590333d56e6308d2
added%20label%20%3C0%3E%7Blabel%7D%3C%2F0%3E/singular: 1caba6b6bca4c6fa1ab173d241059dc2 added%20checklist%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: fb6a852c50c1629f47c6f155fc93fdee
added%20checklist%20item%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: bdd202da20b1fffbec21792c5453f90c
added%20label%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: b32be052b3d57de0c9120fa7f9fc86ee
Admin%20roles/singular: 32a5d78073b9bb9a246773afba8831df Admin%20roles/singular: 32a5d78073b9bb9a246773afba8831df
All%20seats%20are%20free%20during%20the%20beta%20until%20Sept%201st!/singular: 015cec3899cf99e37c3cf231d432e31d All%20seats%20are%20free%20during%20the%20beta%20until%20Sept%201st!/singular: 015cec3899cf99e37c3cf231d432e31d
All%20systems%20operational/singular: ee943a4046b09e6334cceeea9fda2bfc All%20systems%20operational/singular: ee943a4046b09e6334cceeea9fda2bfc
Already%20have%20an%20account%3F%20%3C0%3E%3C1%3ESign%20in%3C%2F1%3E%3C%2F0%3E/singular: 2959fd276248208b65cb27ed46b20135 Already%20have%20an%20account%3F%20%3C0%3E%3C1%3ESign%20in%3C%2F1%3E%3C%2F0%3E/singular: 2959fd276248208b65cb27ed46b20135
An%20error%20occurred%20while%20disconnecting%20your%20Trello%20account./singular: 0aa3973b860c1faf8d9123aebf567e40 An%20error%20occurred%20while%20disconnecting%20your%20Trello%20account./singular: 0aa3973b860c1faf8d9123aebf567e40
An%20unexpected%20error%20occurred.%20Please%20try%20again%20later./singular: 1b5749b0cca6a62d75a577bee6804074
API%20keys/singular: 07f3620a30e08136f0b072c9af8d1eef API%20keys/singular: 07f3620a30e08136f0b072c9af8d1eef
API%20Reference/singular: 7dcc877064bfdf889ec55dbc9e06a242 API%20Reference/singular: 7dcc877064bfdf889ec55dbc9e06a242
Applicants/singular: 4babd8331a1441e91087f855f43e57f8 Applicants/singular: 4babd8331a1441e91087f855f43e57f8
@@ -31,10 +39,11 @@ checksums:
Are%20you%20sure%20want%20to%20remove%20%7BentityLabel%7D%3F/singular: f9b67026c5ef86ac4d5944380d571961 Are%20you%20sure%20want%20to%20remove%20%7BentityLabel%7D%3F/singular: f9b67026c5ef86ac4d5944380d571961
Are%20you%20sure%20you%20want%20to%20delete%20the%20workspace%20%7B0%7D%3F/singular: 27ba2854202dd77c51e78c64e5c93946 Are%20you%20sure%20you%20want%20to%20delete%20the%20workspace%20%7B0%7D%3F/singular: 27ba2854202dd77c51e78c64e5c93946
Are%20you%20sure%20you%20want%20to%20delete%20this%20card%3F/singular: 131a5a7cccca7be8b32c987d9fa0b0c0 Are%20you%20sure%20you%20want%20to%20delete%20this%20card%3F/singular: 131a5a7cccca7be8b32c987d9fa0b0c0
Are%20you%20sure%20you%20want%20to%20delete%20this%20checklist%3F/singular: 7c0f540603474b1a30462dda087fd2f0
Are%20you%20sure%20you%20want%20to%20delete%20this%20comment%3F/singular: 55fe6f1b52b71b91b2a079cfda3cc7fe Are%20you%20sure%20you%20want%20to%20delete%20this%20comment%3F/singular: 55fe6f1b52b71b91b2a079cfda3cc7fe
Are%20you%20sure%20you%20want%20to%20delete%20this%20label%3F/singular: 037fbaf1d04356937e6afb574714f51f Are%20you%20sure%20you%20want%20to%20delete%20this%20label%3F/singular: 037fbaf1d04356937e6afb574714f51f
Are%20you%20sure%20you%20want%20to%20delete%20your%20account%3F/singular: 428b74d781063224c3e63980e1094ec3 Are%20you%20sure%20you%20want%20to%20delete%20your%20account%3F/singular: 428b74d781063224c3e63980e1094ec3
assigned%20%3C0%3E%7BmemberName%7D%3C%2F0%3E%20to%20the%20card/singular: 4fb1c419a78a0f010a3e5790801551fc assigned%20%3C0%3E%7B0%7D%3C%2F0%3E%20to%20the%20card/singular: 9df6d89fa83706123dedd8cba2243d04
Awaiting%20Customer/singular: 122c108794f321c10e05a08f09b11457 Awaiting%20Customer/singular: 122c108794f321c10e05a08f09b11457
Backlog/singular: 35919fd5b10ad212839a75e72829fe4e Backlog/singular: 35919fd5b10ad212839a75e72829fe4e
Basic%20Kanban/singular: e46ebc406749486f3907436970d4d6c7 Basic%20Kanban/singular: e46ebc406749486f3907436970d4d6c7
@@ -59,8 +68,10 @@ checksums:
Cancel/singular: 2e2a849c2223911717de8caa2c71bade Cancel/singular: 2e2a849c2223911717de8caa2c71bade
Card%20not%20found/singular: 91509e2f92b0b3b11330b6983139fdbf Card%20not%20found/singular: 91509e2f92b0b3b11330b6983139fdbf
Card%20title/singular: 7c34f59f4005e6cb3a6ff546ea0b96e3 Card%20title/singular: 7c34f59f4005e6cb3a6ff546ea0b96e3
Change%20Password/singular: a552fc5c4189ebc3e2e6018edda7d18f
Change%20the%20language%20of%20the%20app./singular: fb20db145e28ed44aba89c146ded7bfc Change%20the%20language%20of%20the%20app./singular: fb20db145e28ed44aba89c146ded7bfc
Check%20your%20inbox/singular: e9a430fcd298def74212238df0f680d6 Check%20your%20inbox/singular: e9a430fcd298def74212238df0f680d6
Checklist%20name/singular: 5eb5de823f7ca5a4d97bb41e6a3f675a
Clear%20filters/singular: 8f40ab5af527e4b190da94e7b6221379 Clear%20filters/singular: 8f40ab5af527e4b190da94e7b6221379
Click%20on%20the%20link%20we've%20sent%20to%20%7BmagicLinkRecipient%7D%20to%20sign%20in./singular: 210b6ff8727f976182ec3f29ea3c7667 Click%20on%20the%20link%20we've%20sent%20to%20%7BmagicLinkRecipient%7D%20to%20sign%20in./singular: 210b6ff8727f976182ec3f29ea3c7667
Code%20Review/singular: a2da6c2339301e7c3ddf068c4ff9f7e8 Code%20Review/singular: a2da6c2339301e7c3ddf068c4ff9f7e8
@@ -70,7 +81,10 @@ checksums:
Company/singular: 9e36d11fa82d1bd4563eef2abc4fcfba Company/singular: 9e36d11fa82d1bd4563eef2abc4fcfba
Complete/singular: d3e36d723de0cfdea51c5b4171d30b4d Complete/singular: d3e36d723de0cfdea51c5b4171d30b4d
Complete%20control%20and%20ownership%3A/singular: 0d8b682ba873272217425ccfc96aa9cd Complete%20control%20and%20ownership%3A/singular: 0d8b682ba873272217425ccfc96aa9cd
completed%20a%20checklist%20item/singular: 757b04c6c80cc927e1c597c0ad4fda33
completed%20checklist%20item%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 71ec18acf051fc909a48a07ca3578673
Confirm%20URL%20change/singular: e14b4ce081d1ef6194b37e1814e97b39 Confirm%20URL%20change/singular: e14b4ce081d1ef6194b37e1814e97b39
Confirm%20your%20new%20password/singular: a0d2935d7b63f8dd19d7c0de47524416
Connect%20Trello/singular: 4440a0b9e387ef7136e3958e7a089213 Connect%20Trello/singular: 4440a0b9e387ef7136e3958e7a089213
Connect%20your%20favorite%20tools%20to%20streamline%20your%20workflow./singular: 033c5dcdb059ccb634aef7fe63f2f45d Connect%20your%20favorite%20tools%20to%20streamline%20your%20workflow./singular: 033c5dcdb059ccb634aef7fe63f2f45d
Connect%20your%20Trello%20account%20to%20import%20boards./singular: 84a510a7485f43e43f2191bd161171d7 Connect%20your%20Trello%20account%20to%20import%20boards./singular: 84a510a7485f43e43f2191bd161171d7
@@ -83,6 +97,7 @@ checksums:
Create%20another/singular: 2de8a82a416eb78c0462aa36278edc9a Create%20another/singular: 2de8a82a416eb78c0462aa36278edc9a
Create%20board/singular: 155b62818bfab0e34f0089e1b34a32f3 Create%20board/singular: 155b62818bfab0e34f0089e1b34a32f3
Create%20card/singular: 32792935dd5837a9433909b04021c22b Create%20card/singular: 32792935dd5837a9433909b04021c22b
Create%20checklist/singular: 5cbca15a7004558c4e6d381f83a34da2
Create%20label/singular: c64e8180fa956f005edc1fd9b8e65abb Create%20label/singular: c64e8180fa956f005edc1fd9b8e65abb
Create%20list/singular: 858c3d514aa95765ec82114393199144 Create%20list/singular: 858c3d514aa95765ec82114393199144
Create%20new%20board/singular: cbb87b1f4cc46b336ad9510c9f19407c Create%20new%20board/singular: cbb87b1f4cc46b336ad9510c9f19407c
@@ -92,6 +107,7 @@ checksums:
Create%20workspace/singular: 2e6718e79964ea5ce22d76c2189c77ca Create%20workspace/singular: 2e6718e79964ea5ce22d76c2189c77ca
created%20the%20card/singular: 605475f5aaeb4dbccbf7c4eb9107b43d created%20the%20card/singular: 605475f5aaeb4dbccbf7c4eb9107b43d
Critical/singular: eb327cd411b50aee954f8d1d215d003a Critical/singular: eb327cd411b50aee954f8d1d215d003a
Current%20password%20is%20required/singular: 72536bca9598680027f2be8ce80ac280
Custom%20domain/singular: b09e7a9c187b7163b4a6cfc78042fe42 Custom%20domain/singular: b09e7a9c187b7163b4a6cfc78042fe42
Custom%20URLs%20are%20a%20premium%20feature.%20You'll%20be%20directed%20to%20upgrade%20your%20account./singular: b52e4f6122cf739c9551d29beb89b25e Custom%20URLs%20are%20a%20premium%20feature.%20You'll%20be%20directed%20to%20upgrade%20your%20account./singular: b52e4f6122cf739c9551d29beb89b25e
Customer%20Support/singular: 50e3c77e22e41061ca85ea2f02625a2e Customer%20Support/singular: 50e3c77e22e41061ca85ea2f02625a2e
@@ -103,6 +119,10 @@ checksums:
Delete%20comment/singular: a3dae0c9ddbc73677aad9812e3dffd69 Delete%20comment/singular: a3dae0c9ddbc73677aad9812e3dffd69
Delete%20list/singular: b694f58e4c973d8797a78e746b550b1f Delete%20list/singular: b694f58e4c973d8797a78e746b550b1f
Delete%20workspace/singular: 9017c821209528d9b20d40a488854cdf Delete%20workspace/singular: 9017c821209528d9b20d40a488854cdf
deleted%20a%20checklist/singular: c54f922dc6c238c9141c700cb3180baf
deleted%20a%20checklist%20item/singular: 2b7a861600102ac5c271dd25c1df261a
deleted%20checklist%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 60f9107197e756487d3f95a1083846b5
deleted%20checklist%20item%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 8b7e270f612f9e91bda7f5cfb853d843
Design/singular: 991b75727b6784c1a063a7462b76186d Design/singular: 991b75727b6784c1a063a7462b76186d
Disconnect%20Trello/singular: a2dd737d133887d34504728c7e7f05e3 Disconnect%20Trello/singular: a2dd737d133887d34504728c7e7f05e3
Discuss%20and%20collaborate%20on%20cards./singular: f2e87816709f602130831ead50bba457 Discuss%20and%20collaborate%20on%20cards./singular: f2e87816709f602130831ead50bba457
@@ -124,9 +144,13 @@ checksums:
email/singular: f31eb214738e037d58e26149797739df email/singular: f31eb214738e037d58e26149797739df
Email/singular: e7f34943a0c2fb849db1839ff6ef5cb5 Email/singular: e7f34943a0c2fb849db1839ff6ef5cb5
Enhancement/singular: 785fe23c0eef0a5b60b5b2a88151de31 Enhancement/singular: 785fe23c0eef0a5b60b5b2a88151de31
Enter%20your%20current%20password/singular: bfceabde4c0b6f2cb439015b76549651
Enter%20your%20current%20password%20and%20choose%20a%20new%20secure%20password./singular: 9bb88155b18e98ea799c0e939d16af64
Enter%20your%20email%20address/singular: 9bc008365ebe3e404e241c8ca876f56e Enter%20your%20email%20address/singular: 9bc008365ebe3e404e241c8ca876f56e
Enter%20your%20name/singular: cd95fbdd0533f2c2e8edf9d9bd9aa8df Enter%20your%20name/singular: cd95fbdd0533f2c2e8edf9d9bd9aa8df
Enter%20your%20new%20password/singular: c67251e3002b68bc20a7cf5de23e43ac
Enter%20your%20password/singular: ea4fdd034522dead21bae0c0abb52eae Enter%20your%20password/singular: ea4fdd034522dead21bae0c0abb52eae
Error%20Changing%20Password/singular: ebecb5c1b72ba4b063117241f5ba4f2d
Error%20deleting%20account/singular: d42965a9bc9e5ec4ed57890268924643 Error%20deleting%20account/singular: d42965a9bc9e5ec4ed57890268924643
Error%20deleting%20label/singular: 94387e3a45ec768ae7715701ae00136e Error%20deleting%20label/singular: 94387e3a45ec768ae7715701ae00136e
Error%20deleting%20workspace/singular: 0aec9bd8170bc84f5ea5c9a47c52ed26 Error%20deleting%20workspace/singular: 0aec9bd8170bc84f5ea5c9a47c52ed26
@@ -211,20 +235,25 @@ checksums:
Long-term/singular: 51cb6f0b112250c5a091ca5f0866904b Long-term/singular: 51cb6f0b112250c5a091ca5f0866904b
Low%20Priority/singular: 509b5cb7c1e8a185e0aa6d38c64c90e8 Low%20Priority/singular: 509b5cb7c1e8a185e0aa6d38c64c90e8
magic%20link/singular: db9d17a5bd98bba8aa0d8068c68579f3 magic%20link/singular: db9d17a5bd98bba8aa0d8068c68579f3
marked%20a%20checklist%20item%20as%20incomplete/singular: 35d0822f65971b97774b962561b02649
marked%20checklist%20item%20%3C0%3E%7B0%7D%3C%2F0%3E%20as%20incomplete/singular: 4c38799ff25321ea25017bf4cd8e2e4f
Medium%20Priority/singular: 1f527cd6d1ed602930bcaa303f503b51 Medium%20Priority/singular: 1f527cd6d1ed602930bcaa303f503b51
Members/singular: 0932e80cba1e3e0a7f52bb67ff31da32 Members/singular: 0932e80cba1e3e0a7f52bb67ff31da32
Members%20%7C%20%7B0%7D/singular: a29e3e9f1076acd178c417d047584e88 Members%20%7C%20%7B0%7D/singular: a29e3e9f1076acd178c417d047584e88
Monthly/singular: 818f1192e32bb855597f930d3e78806e Monthly/singular: 818f1192e32bb855597f930d3e78806e
moved%20the%20card%20from%20%3C0%3E%7BfromList%7D%3C%2F0%3E%20to%3C1%3E%7BtoList%7D%3C%2F1%3E/singular: c2d0d72ad97510344b51154ef15060e0 moved%20the%20card%20from%20%3C0%3E%7B0%7D%3C%2F0%3E%20to%3C1%3E%7B1%7D%3C%2F1%3E/singular: 11edf0427766c26db541d46379dc3c16
moved%20the%20card%20to%20another%20list/singular: 2e8c41bfafb42fa299ce56e4300205ff moved%20the%20card%20to%20another%20list/singular: 2e8c41bfafb42fa299ce56e4300205ff
Name/singular: 9368b5a047572b6051f334af5aa76819 Name/singular: 9368b5a047572b6051f334af5aa76819
Need%20help%3F/singular: 04e7322f2d3ffb2d73ff2f64b71637c8 Need%20help%3F/singular: 04e7322f2d3ffb2d73ff2f64b71637c8
New/singular: 126d036fae5fb6b629728ecb97e6195b New/singular: 126d036fae5fb6b629728ecb97e6195b
New%20board/singular: 63f4e979e29a7fc2f5c09ff91fa75966 New%20board/singular: 63f4e979e29a7fc2f5c09ff91fa75966
New%20card/singular: a33f6219a756127f91c2523cfe845a19 New%20card/singular: a33f6219a756127f91c2523cfe845a19
New%20checklist/singular: 58252b71e9693ae0f4d2d0b72108a569
New%20import/singular: e8fddfe15dd170277df919e5d37efd47 New%20import/singular: e8fddfe15dd170277df919e5d37efd47
New%20label/singular: 890040da52a88c16c249a4ac78980f81 New%20label/singular: 890040da52a88c16c249a4ac78980f81
New%20list/singular: 146c2e642b11056a0b07ed65733e4178 New%20list/singular: 146c2e642b11056a0b07ed65733e4178
New%20password%20is%20required/singular: f88427a4cca058631199a4384cb5622e
New%20password%20must%20be%20different%20from%20current%20password/singular: db33013fcc6c40995cf8a37deb3d5667
New%20Ticket/singular: 665ff16ec736cba20e8a1b3beb3baa09 New%20Ticket/singular: 665ff16ec736cba20e8a1b3beb3baa09
New%20workspace/singular: 8eecf05b4ce29aa880adfed2e11476af New%20workspace/singular: 8eecf05b4ce29aa880adfed2e11476af
Newsletter/singular: dcfb9666301924431ac8ae88e5b6f9d7 Newsletter/singular: dcfb9666301924431ac8ae88e5b6f9d7
@@ -241,11 +270,15 @@ checksums:
Organize%20and%20find%20cards%20quickly%20with%20powerful%20filtering%20tools./singular: 1b9898c4b21e9dff413b4f76dc59db56 Organize%20and%20find%20cards%20quickly%20with%20powerful%20filtering%20tools./singular: 1b9898c4b21e9dff413b4f76dc59db56
Own%20your%20data/singular: cc2178dac4bdf6b07f030cfc2a7510e6 Own%20your%20data/singular: cc2178dac4bdf6b07f030cfc2a7510e6
Part-time/singular: 213d63da450f35dabb3ab0e35e29feed Part-time/singular: 213d63da450f35dabb3ab0e35e29feed
Password%20Changed/singular: 1fcebe9ddb46f722a57f195efddc695d
Password%20must%20be%20at%20least%208%20characters/singular: 4c30501d085eaccea47af34212bb26a7
Passwords%20do%20not%20match/singular: 37ca1f4e0afc9a0b8e9617f767103c92
Payment%20frequency/singular: 63ded0e4ffb462ca8bd33d38e4691d86 Payment%20frequency/singular: 63ded0e4ffb462ca8bd33d38e4691d86
Pending/singular: 030a6f3395d5d4efddd3cc67d6009039 Pending/singular: 030a6f3395d5d4efddd3cc67d6009039
per%20user%2Fmonth/singular: 72af182c1ba6df6732640f4d8a78d360 per%20user%2Fmonth/singular: 72af182c1ba6df6732640f4d8a78d360
Personal%20Project/singular: d7820b1bf4efecc61ed89234567aaa9c Personal%20Project/singular: d7820b1bf4efecc61ed89234567aaa9c
Planning/singular: 353f58c75248275fe091740607501610 Planning/singular: 353f58c75248275fe091740607501610
Please%20confirm%20your%20new%20password/singular: 43d0307b9307238cc6c199cfa66caff2
Please%20enter%20a%20valid%20email%20address/singular: 8de4bc8832b11b380bc4cbcedc16e48b Please%20enter%20a%20valid%20email%20address/singular: 8de4bc8832b11b380bc4cbcedc16e48b
Please%20enter%20a%20valid%20name/singular: f2d741f1b5cae722e35cb5206786f932 Please%20enter%20a%20valid%20name/singular: f2d741f1b5cae722e35cb5206786f932
Please%20enter%20a%20valid%20password/singular: 4b32c17e19b79bcbf0bb092c06ba310f Please%20enter%20a%20valid%20password/singular: 4b32c17e19b79bcbf0bb092c06ba310f
@@ -268,7 +301,10 @@ checksums:
Remove%20member/singular: 1d77c2ca3768e486fd1fb5df30cb60d9 Remove%20member/singular: 1d77c2ca3768e486fd1fb5df30cb60d9
removed%20a%20label%20from%20the%20card/singular: f83ec18850a2a8a3f8242a740a04df06 removed%20a%20label%20from%20the%20card/singular: f83ec18850a2a8a3f8242a740a04df06
removed%20a%20member%20from%20the%20card/singular: 0bd7561bb79358fde3d595c3e60a315a removed%20a%20member%20from%20the%20card/singular: 0bd7561bb79358fde3d595c3e60a315a
removed%20label%20%3C0%3E%7Blabel%7D%3C%2F0%3E/singular: 1e7ebc1866136352bdc3cd90afc083f0 removed%20label%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 7e0936b15831e65754588b8512f62fcb
renamed%20a%20checklist/singular: 4d208de1857740e63469007c5b8b491a
renamed%20checklist%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: e95d119ef65b0af6c0a96bef182be671
renamed%20checklist%20item%20to%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 50f55f71f9245890afee434d7adc2140
Research/singular: 3368e9638d1619babd6df9fad592274f Research/singular: 3368e9638d1619babd6df9fad592274f
Resolution/singular: 6d8bd9e1bd7dae5ae38c93061d32990e Resolution/singular: 6d8bd9e1bd7dae5ae38c93061d32990e
Resources/singular: ec7fb05ed963bb6781a35782b3475502 Resources/singular: ec7fb05ed963bb6781a35782b3475502
@@ -307,6 +343,7 @@ checksums:
Templates/singular: 8ed62f56c81fa96c0f3182acb331bf63 Templates/singular: 8ed62f56c81fa96c0f3182acb331bf63
Terms%20of%20service/singular: 0b8a8b23aff021a6cde79613fdb39c28 Terms%20of%20service/singular: 0b8a8b23aff021a6cde79613fdb39c28
Thank%20you%20for%20your%20feedback!/singular: 07edd8c50685a52c0969d711df26d768 Thank%20you%20for%20your%20feedback!/singular: 07edd8c50685a52c0969d711df26d768
The%20current%20password%20you%20entered%20is%20incorrect./singular: 67a76bf346ab4b48563269e9d941a64a
The%20main%20difference%20between%20Kan%20and%20Trello%20is%20that%20Kan%20is%20open%20source%2C%20allowing%20anyone%20to%20view%2C%20modify%2C%20and%20contribute%20to%20our%20code.%20Our%20cloud%20offering%20also%20offers%20no%20restrictions%20on%20features%20for%20individual%20use%2C%20whereas%20Trello%20locks%20basic%20features%20such%20as%20the%20number%20of%20boards%20you%20can%20create%20behind%20a%20paywall./singular: db6e22cc955c5fbe547feedeb48f8719 The%20main%20difference%20between%20Kan%20and%20Trello%20is%20that%20Kan%20is%20open%20source%2C%20allowing%20anyone%20to%20view%2C%20modify%2C%20and%20contribute%20to%20our%20code.%20Our%20cloud%20offering%20also%20offers%20no%20restrictions%20on%20features%20for%20individual%20use%2C%20whereas%20Trello%20locks%20basic%20features%20such%20as%20the%20number%20of%20boards%20you%20can%20create%20behind%20a%20paywall./singular: db6e22cc955c5fbe547feedeb48f8719
The%20open%20source%20%3C0%2F%3E%20alternative%20to%20Trello/singular: 692cb2e8a8e610953c996826beed45a2 The%20open%20source%20%3C0%2F%3E%20alternative%20to%20Trello/singular: 692cb2e8a8e610953c996826beed45a2
The%20visibility%20of%20your%20board%20has%20been%20set%20to%20%7B0%7D./singular: 970e17a115f7374e60e0a8ded425db8f The%20visibility%20of%20your%20board%20has%20been%20set%20to%20%7B0%7D./singular: 970e17a115f7374e60e0a8ded425db8f
@@ -324,22 +361,28 @@ checksums:
Trello%20disconnected/singular: 54b24a3e6c9a7eedd8c8d1060ab1175d Trello%20disconnected/singular: 54b24a3e6c9a7eedd8c8d1060ab1175d
Trello%20imports/singular: 6827eca403faa8f89891d17827e72af9 Trello%20imports/singular: 6827eca403faa8f89891d17827e72af9
Triaging/singular: 1d40799fcae53a8a27688fdae2a48dee Triaging/singular: 1d40799fcae53a8a27688fdae2a48dee
Unable%20to%20add%20checklist%20item/singular: 4c4c3eaaf10b348b39ae97eb5dc455df
Unable%20to%20add%20comment/singular: 49bb435880817434698f31a6069564d6 Unable%20to%20add%20comment/singular: 49bb435880817434698f31a6069564d6
Unable%20to%20create%20card/singular: 90112ea12ec6fa42097a6e022ae048a4 Unable%20to%20create%20card/singular: 90112ea12ec6fa42097a6e022ae048a4
Unable%20to%20create%20checklist/singular: 94eed122e42e0951cd08b9ec62f5eeb6
Unable%20to%20create%20list/singular: 7fbbf8314f8d08a4123c7daef09fed05 Unable%20to%20create%20list/singular: 7fbbf8314f8d08a4123c7daef09fed05
Unable%20to%20create%20workspace/singular: c1c949477e121d73ed6683eddf9cd874 Unable%20to%20create%20workspace/singular: c1c949477e121d73ed6683eddf9cd874
Unable%20to%20delete%20card/singular: 50ff06aa1265fe464f776aba33f1bef9 Unable%20to%20delete%20card/singular: 50ff06aa1265fe464f776aba33f1bef9
Unable%20to%20delete%20checklist/singular: d7067e2c009f4919f0cca77df3c228ee
Unable%20to%20delete%20checklist%20item/singular: a74144593b625e4d8d7ecf734462c60d
Unable%20to%20delete%20comment/singular: 550198b2c87f06726a843c79c1026ed9 Unable%20to%20delete%20comment/singular: 550198b2c87f06726a843c79c1026ed9
Unable%20to%20remove%20member/singular: 39025a0c53818438829603d213baef06 Unable%20to%20remove%20member/singular: 39025a0c53818438829603d213baef06
Unable%20to%20send%20feedback/singular: 656c93265d7e2bef1245b17d85f85ae5 Unable%20to%20send%20feedback/singular: 656c93265d7e2bef1245b17d85f85ae5
Unable%20to%20update%20board%20URL/singular: 080746884059142358b58d9a44ff7d93 Unable%20to%20update%20board%20URL/singular: 080746884059142358b58d9a44ff7d93
Unable%20to%20update%20board%20visibility/singular: a76a21d561b8943e9276e027a1e3f70d Unable%20to%20update%20board%20visibility/singular: a76a21d561b8943e9276e027a1e3f70d
Unable%20to%20update%20card/singular: eca6002e57af8ec97324eae64e3b5731 Unable%20to%20update%20card/singular: eca6002e57af8ec97324eae64e3b5731
Unable%20to%20update%20checklist/singular: 44c10f49f448909ceca481ed9b4b07e7
Unable%20to%20update%20checklist%20item/singular: 5c86b3523531c30d58856e3ecde0cb55
Unable%20to%20update%20comment/singular: 05e798ed6b0f3fee41f3e8832eb699ea Unable%20to%20update%20comment/singular: 05e798ed6b0f3fee41f3e8832eb699ea
Unable%20to%20update%20labels/singular: dca2bdc3dcf74bc9d95e05156039a291 Unable%20to%20update%20labels/singular: dca2bdc3dcf74bc9d95e05156039a291
Unable%20to%20update%20list/singular: 14aa802f91b9b4c05236c8c75afb33da Unable%20to%20update%20list/singular: 14aa802f91b9b4c05236c8c75afb33da
Unable%20to%20update%20members/singular: 9a851a6b0c75ee16d25cf2ff4b67b255 Unable%20to%20update%20members/singular: 9a851a6b0c75ee16d25cf2ff4b67b255
unassigned%20%3C0%3E%7BmemberName%7D%3C%2F0%3E%20from%20the%20card/singular: 105d4eeb32044126b8dde243bad11d56 unassigned%20%3C0%3E%7B0%7D%3C%2F0%3E%20from%20the%20card/singular: b683cc07092348c1e75dba40b1262b85
unassigned%20themselves%20from%20the%20card/singular: 27c6f293c562af6a44348d7f00036d30 unassigned%20themselves%20from%20the%20card/singular: 27c6f293c562af6a44348d7f00036d30
Unlimited%20activity%20log/singular: 8c993de94cda0deac19ba14ecafce6a5 Unlimited%20activity%20log/singular: 8c993de94cda0deac19ba14ecafce6a5
Unlimited%20boards/singular: cb4fd858137ce825c2f1904d142d8042 Unlimited%20boards/singular: cb4fd858137ce825c2f1904d142d8042
@@ -349,9 +392,10 @@ checksums:
Unlimited%20lists/singular: 5c418701b27b9acbc5dd199719007362 Unlimited%20lists/singular: 5c418701b27b9acbc5dd199719007362
Update/singular: 079fc039262fd31b10532929685c2d1b Update/singular: 079fc039262fd31b10532929685c2d1b
Update%20label/singular: 97880b503dfe956941c5f23025a1c102 Update%20label/singular: 97880b503dfe956941c5f23025a1c102
updated%20a%20checklist%20item/singular: 198e1d1d503f4b69b752dd84d0cc0e9d
updated%20the%20description/singular: 70fd604b6dc957a75be90ea77572d76d updated%20the%20description/singular: 70fd604b6dc957a75be90ea77572d76d
updated%20the%20title/singular: 98cf8f12923ec1a58e767e3a40863b21 updated%20the%20title/singular: 98cf8f12923ec1a58e767e3a40863b21
updated%20the%20title%20to%20%3C0%3E%7BtoTitle%7D%3C%2F0%3E/singular: 70cdf681ec2b6ef8e14397bc1f93f945 updated%20the%20title%20to%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: aca196d729401d8adc5c8ca9d558840e
Upgrade/singular: 63c3b52882e0d779859307d672c178c2 Upgrade/singular: 63c3b52882e0d779859307d672c178c2
Urgent/singular: e79afcd4398e52e10e7e8243a7eecabe Urgent/singular: e79afcd4398e52e10e7e8243a7eecabe
URL%20can%20only%20contain%20letters%2C%20numbers%2C%20and%20hyphens/singular: 875d37d2d920f98ef60a314eda8a5d9a URL%20can%20only%20contain%20letters%2C%20numbers%2C%20and%20hyphens/singular: 875d37d2d920f98ef60a314eda8a5d9a
@@ -391,6 +435,7 @@ checksums:
Writing/singular: 4f5f3ee3320c252921f80c42653c5d49 Writing/singular: 4f5f3ee3320c252921f80c42653c5d49
Yearly/singular: 87f43e016c19cb25860f456549a2f431 Yearly/singular: 87f43e016c19cb25860f456549a2f431
Yes%2C%20we%20offer%20an%20forever%20free%20plan%20for%20individual%20use.%20No%20restrictions%2C%20no%20paywalls%2C%20no%20limits./singular: 963cee303d0ff13c1719f4575e774fe3 Yes%2C%20we%20offer%20an%20forever%20free%20plan%20for%20individual%20use.%20No%20restrictions%2C%20no%20paywalls%2C%20no%20limits./singular: 963cee303d0ff13c1719f4575e774fe3
You%20are%20about%20to%20change%20your%20password./singular: df4783d593505766d78c5bc08d3d48ac
You%20can%20get%20a%20custom%20workspace%20URL%2C%20like%20%3C0%3Ekan.bn%2Fkan%3C%2F0%3E%2C%20by%20going%20into%20your%20%3C1%3Eworkspace%20settings%3C%2F1%3E%20and%20purchasing%20a%20pro%20workspace%20subscription.%20All%20subscriptions%20help%20fund%20the%20development%20of%20the%20project!/singular: 41dd145ef56f539e12dc064a9807c660 You%20can%20get%20a%20custom%20workspace%20URL%2C%20like%20%3C0%3Ekan.bn%2Fkan%3C%2F0%3E%2C%20by%20going%20into%20your%20%3C1%3Eworkspace%20settings%3C%2F1%3E%20and%20purchasing%20a%20pro%20workspace%20subscription.%20All%20subscriptions%20help%20fund%20the%20development%20of%20the%20project!/singular: 41dd145ef56f539e12dc064a9807c660
You%20can%20invite%20team%20members%20by%20clicking%20the%20%22Invite%22%20button%20in%20the%20top%20right%20corner%20of%20the%20%3C0%3Emembers%20page%3C%2F0%3E%20and%20entering%20their%20email%20address.%20They%20will%20receive%20an%20email%20with%20a%20link%20to%20join%20the%20workspace./singular: 47e125eb9b4c11cab5a2f4b3ab08e883 You%20can%20invite%20team%20members%20by%20clicking%20the%20%22Invite%22%20button%20in%20the%20top%20right%20corner%20of%20the%20%3C0%3Emembers%20page%3C%2F0%3E%20and%20entering%20their%20email%20address.%20They%20will%20receive%20an%20email%20with%20a%20link%20to%20join%20the%20workspace./singular: 47e125eb9b4c11cab5a2f4b3ab08e883
You%20can%20self-host%20by%20following%20the%20instructions%20in%20our%20%3C0%3Erepo%3C%2F0%3E./singular: a6152a41b2d8f64d5a657e5b8bc808a9 You%20can%20self-host%20by%20following%20the%20instructions%20in%20our%20%3C0%3Erepo%3C%2F0%3E./singular: a6152a41b2d8f64d5a657e5b8bc808a9
@@ -399,6 +444,7 @@ checksums:
Your%20account%20has%20been%20deleted./singular: 8c8d944e07388c5877effdb2c2803dcf Your%20account%20has%20been%20deleted./singular: 8c8d944e07388c5877effdb2c2803dcf
Your%20boards%20have%20been%20imported./singular: 403972e7a25afc2415762c1c2b1ec868 Your%20boards%20have%20been%20imported./singular: 403972e7a25afc2415762c1c2b1ec868
Your%20display%20name%20has%20been%20updated./singular: 15e5fff36c554c16ec5214427fae1bf4 Your%20display%20name%20has%20been%20updated./singular: 15e5fff36c554c16ec5214427fae1bf4
Your%20password%20has%20been%20changed./singular: 8f730f68d52b7efa727aa0784282ebcb
Your%20profile%20image%20has%20been%20updated./singular: 099e1780348cd7bf617721344371a430 Your%20profile%20image%20has%20been%20updated./singular: 099e1780348cd7bf617721344371a430
Your%20Trello%20account%20has%20been%20disconnected./singular: 126aeeb73f7e4cad338056e4c933f39b Your%20Trello%20account%20has%20been%20disconnected./singular: 126aeeb73f7e4cad338056e4c933f39b
Your%20Trello%20account%20is%20connected./singular: 0499d193001fce2fbec445ae034ce512 Your%20Trello%20account%20is%20connected./singular: 0499d193001fce2fbec445ae034ce512

View File

@@ -31,12 +31,12 @@ const config = {
images: { images: {
remotePatterns: [ remotePatterns: [
{ {
protocol: "https", protocol: "https",
hostname: process.env.S3_FORCE_PATH_STYLE === "true" hostname:
? `${env("NEXT_PUBLIC_STORAGE_DOMAIN")}` env("S3_FORCE_PATH_STYLE") === "true"
: `*.${env("NEXT_PUBLIC_STORAGE_DOMAIN")}`, ? `${env("NEXT_PUBLIC_STORAGE_DOMAIN")}`
: `*.${env("NEXT_PUBLIC_STORAGE_DOMAIN")}`,
}, },
{ {
protocol: "http", protocol: "http",
@@ -54,4 +54,16 @@ const config = {
}, },
}; };
// Only allow external images when OIDC is configured (for OIDC provider avatars)
if (
env("OIDC_CLIENT_ID") &&
env("OIDC_CLIENT_SECRET") &&
env("OIDC_DISCOVERY_URL")
) {
config.images?.remotePatterns?.push({
protocol: "https",
hostname: "**",
});
}
export default config; export default config;

View File

@@ -33,6 +33,7 @@
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@tanstack/react-query": "catalog:", "@tanstack/react-query": "catalog:",
"@tiptap/extension-link": "^2.22.2", "@tiptap/extension-link": "^2.22.2",
"@tiptap/extension-mention": "^3.0.9",
"@tiptap/extension-placeholder": "^2.14.0", "@tiptap/extension-placeholder": "^2.14.0",
"@tiptap/pm": "^2.14.0", "@tiptap/pm": "^2.14.0",
"@tiptap/react": "^2.14.0", "@tiptap/react": "^2.14.0",
@@ -48,6 +49,7 @@
"next": "^15.3.4", "next": "^15.3.4",
"next-logger": "^5.0.1", "next-logger": "^5.0.1",
"next-runtime-env": "^1.7.2", "next-runtime-env": "^1.7.2",
"next-themes": "^0.4.6",
"nextjs-cors": "^2.2.0", "nextjs-cors": "^2.2.0",
"pino": "^9.6.0", "pino": "^9.6.0",
"posthog-js": "^1.254.0", "posthog-js": "^1.254.0",

View File

@@ -4,7 +4,7 @@ import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro"; import { Trans } from "@lingui/react/macro";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { env } from "next-runtime-env"; import { env } from "next-runtime-env";
import { useState } from "react"; import { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { import {
FaApple, FaApple,
@@ -16,6 +16,7 @@ import {
FaGoogle, FaGoogle,
FaLinkedin, FaLinkedin,
FaMicrosoft, FaMicrosoft,
FaOpenid,
FaReddit, FaReddit,
FaSpotify, FaSpotify,
FaTiktok, FaTiktok,
@@ -33,6 +34,8 @@ import Button from "~/components/Button";
import Input from "~/components/Input"; import Input from "~/components/Input";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
type AuthProvider = SocialProvider | "oidc";
interface FormValues { interface FormValues {
name?: string; name?: string;
email: string; email: string;
@@ -141,16 +144,28 @@ const availableSocialProviders = {
name: "Zoom", name: "Zoom",
icon: SiZoom, icon: SiZoom,
}, },
oidc: {
id: "oidc",
name: "OIDC",
icon: FaOpenid,
},
}; };
export function Auth({ setIsMagicLinkSent, isSignUp }: AuthProps) { export function Auth({ setIsMagicLinkSent, isSignUp }: AuthProps) {
const [isLoginWithProviderPending, setIsLoginWithProviderPending] = const [isLoginWithProviderPending, setIsLoginWithProviderPending] =
useState<null | SocialProvider>(null); useState<null | AuthProvider>(null);
const isCredentialsEnabled = const [isCredentialsEnabled, setIsCredentialsEnabled] = useState(false);
env("NEXT_PUBLIC_ALLOW_CREDENTIALS")?.toLowerCase() === "true";
const [isLoginWithEmailPending, setIsLoginWithEmailPending] = useState(false); const [isLoginWithEmailPending, setIsLoginWithEmailPending] = useState(false);
const [loginError, setLoginError] = useState<string | null>(null); const [loginError, setLoginError] = useState<string | null>(null);
const { showPopup } = usePopup(); const { showPopup } = usePopup();
const oidcProviderName = "OIDC";
// Safely get environment variables on client side to avoid hydration mismatch
useEffect(() => {
const credentialsAllowed =
env("NEXT_PUBLIC_ALLOW_CREDENTIALS")?.toLowerCase() === "true";
setIsCredentialsEnabled(credentialsAllowed);
}, []);
const { const {
register, register,
@@ -226,13 +241,26 @@ export function Auth({ setIsMagicLinkSent, isSignUp }: AuthProps) {
setIsLoginWithEmailPending(false); setIsLoginWithEmailPending(false);
}; };
const handleLoginWithProvider = async (provider: SocialProvider) => { const handleLoginWithProvider = async (provider: AuthProvider) => {
setIsLoginWithProviderPending(provider); setIsLoginWithProviderPending(provider);
setLoginError(null); setLoginError(null);
const { error } = await authClient.signIn.social({
provider, let error;
callbackURL: "/boards", if (provider === "oidc") {
}); // Use oauth2 signin for OIDC provider
const result = await authClient.signIn.oauth2({
providerId: "oidc",
callbackURL: "/boards",
});
error = result.error;
} else {
// Use social signin for traditional social providers
const result = await authClient.signIn.social({
provider,
callbackURL: "/boards",
});
error = result.error;
}
setIsLoginWithProviderPending(null); setIsLoginWithProviderPending(null);
@@ -260,13 +288,16 @@ export function Auth({ setIsMagicLinkSent, isSignUp }: AuthProps) {
return ( return (
<Button <Button
key={key} key={key}
onClick={() => handleLoginWithProvider(key as SocialProvider)} onClick={() => handleLoginWithProvider(key as AuthProvider)}
isLoading={isLoginWithProviderPending === key} isLoading={isLoginWithProviderPending === key}
iconLeft={<provider.icon />} iconLeft={<provider.icon />}
fullWidth fullWidth
size="lg" size="lg"
> >
<Trans>Continue with {provider.name}</Trans> <Trans>
Continue with{" "}
{key === "oidc" ? oidcProviderName : provider.name}
</Trans>
</Button> </Button>
); );
})} })}

View File

@@ -5,7 +5,7 @@ import LoadingSpinner from "./LoadingSpinner";
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "primary" | "secondary" | "danger" | "ghost"; variant?: "primary" | "secondary" | "danger" | "ghost";
size?: "sm" | "md" | "lg"; size?: "xs" | "sm" | "md" | "lg";
isLoading?: boolean; isLoading?: boolean;
iconLeft?: React.ReactNode; iconLeft?: React.ReactNode;
iconRight?: React.ReactNode; iconRight?: React.ReactNode;
@@ -28,6 +28,7 @@ const Button = ({
}: ButtonProps) => { }: ButtonProps) => {
const classes = twMerge( const classes = twMerge(
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-2 text-sm font-semibold text-light-50 shadow-sm focus-visible:outline-none", "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-2 text-sm font-semibold text-light-50 shadow-sm focus-visible:outline-none",
size === "xs" && "text-xs px-2 py-1",
size === "sm" && "text-xs", size === "sm" && "text-xs",
size === "lg" && "py-[0.65rem]", size === "lg" && "py-[0.65rem]",
fullWidth && "w-full", fullWidth && "w-full",

View File

@@ -55,51 +55,59 @@ export default function CheckboxDropdown({
const renderMenuItems = (items: Item[], groupKey: string | null) => ( const renderMenuItems = (items: Item[], groupKey: string | null) => (
<> <>
{items.map((item) => ( {items.length > 0 ? (
<Menu.Item key={item.key}> items.map((item) => (
<div <Menu.Item key={item.key}>
className="group flex items-center rounded-[5px] p-2 hover:bg-light-200 dark:hover:bg-dark-300" <div
onClick={(e) => { className="group flex items-center rounded-[5px] p-2 hover:bg-light-200 dark:hover:bg-dark-300"
e.preventDefault(); onClick={(e) => {
handleSelect(groupKey, { key: item.key, value: item.value }); e.preventDefault();
}} handleSelect(groupKey, { key: item.key, value: item.value });
> }}
<input
id={item.key}
name={item.key}
type="checkbox"
className="h-[14px] w-[14px] rounded bg-transparent"
onClick={(event) => event.stopPropagation()}
onChange={() =>
handleSelect(groupKey, { key: item.key, value: item.value })
}
checked={item.selected}
/>
{item.leftIcon && (
<span className="ml-3 flex items-center">{item.leftIcon}</span>
)}
<label
htmlFor={item.key}
className="ml-3 text-[12px] text-dark-900"
> >
{item.value} <input
</label> id={item.key}
{handleEdit && ( name={item.key}
<button type="checkbox"
type="button" className="h-[14px] w-[14px] rounded bg-transparent"
className="invisible ml-auto group-hover:visible" onClick={(event) => event.stopPropagation()}
onClick={(event) => { onChange={() =>
event.preventDefault(); handleSelect(groupKey, { key: item.key, value: item.value })
event.stopPropagation(); }
handleEdit(item.key); checked={item.selected}
}} />
{item.leftIcon && (
<span className="ml-3 flex items-center">{item.leftIcon}</span>
)}
<label
htmlFor={item.key}
className="ml-3 text-[12px] text-dark-900"
> >
<HiEllipsisHorizontal size={20} className="text-dark-900" /> {item.value}
</button> </label>
)} {handleEdit && (
<button
type="button"
className="invisible ml-auto group-hover:visible"
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
handleEdit(item.key);
}}
>
<HiEllipsisHorizontal size={20} className="text-dark-900" />
</button>
)}
</div>
</Menu.Item>
))
) : (
!handleCreate && (
<div className="flex items-center p-2 text-[12px] text-dark-900">
No items
</div> </div>
</Menu.Item> )
))} )}
{handleCreate && ( {handleCreate && (
<button <button
type="button" type="button"

View File

@@ -0,0 +1,58 @@
import { twMerge } from "tailwind-merge";
interface CircularProgressProps {
progress: number; // 0-100
size?: "sm" | "md" | "lg";
className?: string;
}
const CircularProgress = ({
progress,
size = "md",
className,
}: CircularProgressProps) => {
const radius = 40;
const circumference = 2 * Math.PI * radius;
const strokeDashoffset = circumference - (progress / 100) * circumference;
return (
<div className={twMerge("relative", className)}>
<svg
className={twMerge(
"-rotate-90 transform",
size === "sm" && "h-4 w-4",
size === "md" && "h-5 w-5",
size === "lg" && "h-8 w-8",
)}
viewBox="0 0 100 100"
>
<circle
cx="50"
cy="50"
r={radius}
fill="none"
stroke="currentColor"
strokeWidth="14"
className="text-light-300 dark:text-dark-400"
/>
<circle
cx="50"
cy="50"
r={radius}
fill="none"
stroke="currentColor"
strokeWidth="14"
strokeDasharray={circumference}
strokeDashoffset={strokeDashoffset}
strokeLinecap="round"
className={twMerge(
"transition-all duration-300 ease-in-out",
progress === 100 ? "text-green-500" : "text-blue-500",
)}
/>
</svg>
</div>
);
};
export default CircularProgress;

View File

@@ -10,7 +10,7 @@ import { authClient } from "@kan/auth/client";
import { useClickOutside } from "~/hooks/useClickOutside"; import { useClickOutside } from "~/hooks/useClickOutside";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { useTheme } from "~/providers/theme"; import { useTheme } from "next-themes";
import { WorkspaceProvider } from "~/providers/workspace"; import { WorkspaceProvider } from "~/providers/workspace";
import FeedbackModal from "./FeedbackModal"; import FeedbackModal from "./FeedbackModal";
import Modal from "./modal"; import Modal from "./modal";
@@ -41,7 +41,7 @@ export default function Dashboard({
rightPanel, rightPanel,
hasRightPanel = false, hasRightPanel = false,
}: DashboardProps) { }: DashboardProps) {
const theme = useTheme(); const { theme } = useTheme();
const { modalContentType } = useModal(); const { modalContentType } = useModal();
const { data: session, isPending: sessionLoading } = authClient.useSession(); const { data: session, isPending: sessionLoading } = authClient.useSession();
@@ -90,7 +90,7 @@ export default function Dashboard({
} }
}); });
const isDarkMode = theme.activeTheme === "dark"; const isDarkMode = theme === "dark";
return ( return (
<> <>

View File

@@ -12,11 +12,14 @@ export function DeleteLabelConfirmation({
labelPublicId: string; labelPublicId: string;
refetch: () => void; refetch: () => void;
}) { }) {
const { closeModal } = useModal(); const { closeModal, closeModals } = useModal();
const { showPopup } = usePopup(); const { showPopup } = usePopup();
const deleteLabelMutation = api.label.delete.useMutation({ const deleteLabelMutation = api.label.delete.useMutation({
onSuccess: () => refetch(), onSuccess: () => {
refetch();
closeModals(2);
},
onError: () => onError: () =>
showPopup({ showPopup({
header: t`Error deleting label`, header: t`Error deleting label`,
@@ -26,7 +29,6 @@ export function DeleteLabelConfirmation({
}); });
const handleDeleteLabel = () => { const handleDeleteLabel = () => {
closeModal();
deleteLabelMutation.mutate({ deleteLabelMutation.mutate({
labelPublicId, labelPublicId,
}); });

View File

@@ -15,10 +15,15 @@ import {
ReactRenderer, ReactRenderer,
useEditor, useEditor,
} from "@tiptap/react"; } from "@tiptap/react";
import { useEffect } from "react";
import StarterKit from "@tiptap/starter-kit"; import StarterKit from "@tiptap/starter-kit";
import Suggestion from "@tiptap/suggestion"; import Suggestion from "@tiptap/suggestion";
import { forwardRef, useImperativeHandle, useRef, useState } from "react"; import {
forwardRef,
useEffect,
useImperativeHandle,
useRef,
useState,
} from "react";
import { import {
HiH1, HiH1,
HiH2, HiH2,
@@ -34,6 +39,9 @@ import {
} from "react-icons/hi2"; } from "react-icons/hi2";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
import tippy from "tippy.js"; import tippy from "tippy.js";
import Mention from "@tiptap/extension-mention";
import Avatar from "./Avatar";
import { getAvatarUrl } from "~/utils/helpers";
declare module "@tiptap/core" { declare module "@tiptap/core" {
interface Commands<ReturnType> { interface Commands<ReturnType> {
@@ -69,6 +77,16 @@ export interface RenderSuggestionsProps {
command: (item: SlashCommandItem) => void; command: (item: SlashCommandItem) => void;
} }
export type WorkspaceMember = {
publicId: string;
user: {
id: string;
name: string | null;
image: string | null;
} | null;
email: string;
};
const CommandsList = forwardRef< const CommandsList = forwardRef<
{ onKeyDown: (props: SuggestionKeyDownProps) => boolean }, { onKeyDown: (props: SuggestionKeyDownProps) => boolean },
{ {
@@ -182,6 +200,125 @@ const RenderSuggestions = () => {
}; };
}; };
type MentionItem = { id: string; label: string; image: string | null };
const MentionList = forwardRef<
{ onKeyDown: (props: SuggestionKeyDownProps) => boolean },
{
items: MentionItem[];
command: (item: MentionItem) => void;
}
>(({ items, command }, ref) => {
const [selectedIndex, setSelectedIndex] = useState(0);
useImperativeHandle(ref, () => ({
onKeyDown: ({ event }: SuggestionKeyDownProps) => {
if (event.key === "ArrowUp") {
setSelectedIndex((selectedIndex + items.length - 1) % items.length);
return true;
}
if (event.key === "ArrowDown") {
setSelectedIndex((selectedIndex + 1) % items.length);
return true;
}
if (event.key === "Enter") {
const item = items[selectedIndex];
if (item) {
command(item);
}
return true;
}
return false;
},
}));
return (
<div className="w-56 rounded-md border-[1px] border-light-200 bg-light-50 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-500 dark:bg-dark-200">
<div className="max-h-[350px] overflow-y-auto p-1 scrollbar-thin scrollbar-thumb-light-200 dark:scrollbar-thumb-dark-300">
{items.length > 0 ? items.map((item, index) => (
<button
key={item.id}
onClick={() => command(item)}
className={twMerge(
"group flex w-full items-center rounded-[5px] p-2 hover:bg-light-200 dark:hover:bg-dark-300",
index === selectedIndex && "bg-light-200 dark:bg-dark-300",
)}
>
<Avatar
size="xs"
name={item.label}
imageUrl={
item.image ? getAvatarUrl(item.image) : undefined
}
email={item.label}
/>
<span className="ml-3 text-[12px] font-medium text-dark-900 dark:text-dark-1000">
{item.label}
</span>
</button>
)) : (
<div className="flex items-center justify-start p-2">
<span className="text-dark-900 text-[12px] dark:text-dark-1000">No results</span>
</div>
)}
</div>
</div>
);
});
MentionList.displayName = "MentionList";
const renderMentionSuggestions = () => {
let reactRenderer: ReactRenderer;
let popup: TippyInstance[];
return {
onStart: (props: any) => {
reactRenderer = new ReactRenderer(MentionList, {
props,
editor: props.editor,
});
if (!props.clientRect) return;
popup = tippy("body", {
getReferenceClientRect: props.clientRect,
appendTo: () => document.body,
content: reactRenderer.element,
showOnCreate: true,
interactive: true,
trigger: "manual",
placement: "bottom-start",
});
},
onUpdate(props: any) {
reactRenderer.updateProps(props);
if (!props.clientRect) return;
popup[0]?.setProps({ getReferenceClientRect: props.clientRect });
},
onKeyDown(props: SuggestionKeyDownProps) {
if (props.event.key === "Escape") {
popup[0]?.hide();
return true;
}
return (
(
reactRenderer.ref as {
onKeyDown?: (props: SuggestionKeyDownProps) => boolean;
}
).onKeyDown?.(props) ?? false
);
},
onExit() {
popup[0]?.destroy();
reactRenderer.destroy();
},
};
};
const SlashCommands = Extension.create<SlashCommandsOptions>({ const SlashCommands = Extension.create<SlashCommandsOptions>({
name: "slash-commands", name: "slash-commands",
addOptions() { addOptions() {
@@ -285,11 +422,13 @@ export default function Editor({
onChange, onChange,
onBlur, onBlur,
readOnly = false, readOnly = false,
workspaceMembers,
}: { }: {
content: string | null; content: string | null;
onChange?: (value: string) => void; onChange?: (value: string) => void;
onBlur?: () => void; onBlur?: () => void;
readOnly?: boolean; readOnly?: boolean;
workspaceMembers: WorkspaceMember[];
}) { }) {
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
@@ -300,7 +439,7 @@ export default function Editor({
Placeholder.configure({ Placeholder.configure({
placeholder: readOnly placeholder: readOnly
? "" ? ""
: t`Add description... (type '/' to open commands)`, : t`Add description... (type '/' to open commands or '@' to mention)`,
}), }),
Link.configure({ Link.configure({
openOnClick: true, openOnClick: true,
@@ -321,6 +460,38 @@ export default function Editor({
char: "/", char: "/",
}, },
}), }),
Mention.configure({
HTMLAttributes: {
class: 'mention',
},
suggestion: {
char: "@",
items: ({ query }: { query: string }) => {
const all: MentionItem[] = workspaceMembers.map((member: WorkspaceMember) => ({
id: member.publicId,
label: member?.user?.name ?? member.email,
image: member?.user?.image ?? null,
}));
const q = query.toLowerCase();
return all.filter((u) => u.label.toLowerCase().includes(q));
},
command: ({ editor, range, props }: any) => {
const mentionHTML = `<span data-type="mention" data-id="${props.id}" data-label="${props.label}">@${props.label}</span>&nbsp;`;
editor
.chain()
.focus()
.deleteRange(range)
.insertContent(mentionHTML)
.focus()
.run();
},
render: renderMentionSuggestions,
},
renderText({ options, node }) {
return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`;
},
}),
], ],
content, content,
onUpdate: ({ editor }) => onChange?.(editor.getHTML()), onUpdate: ({ editor }) => onChange?.(editor.getHTML()),
@@ -369,11 +540,19 @@ export default function Editor({
.tiptap p { .tiptap p {
margin: 0 0 1rem 0 !important; margin: 0 0 1rem 0 !important;
} }
.tiptap .mention {
background-color: rgba(59, 130, 246, 0.1);
border-radius: 0.25rem;
padding: 0.125rem 0.25rem;
color: rgb(59, 130, 246);
text-decoration: none;
font-weight: 500;
}
`}</style> `}</style>
{!readOnly && editor && <EditorBubbleMenu editor={editor} />} {!readOnly && editor && <EditorBubbleMenu editor={editor} />}
<EditorContent <EditorContent
editor={editor} editor={editor}
className="prose dark:prose-invert prose-sm max-w-none overflow-y-auto [&_blockquote]:!text-xs [&_h1]:!text-lg [&_h2]:!text-base [&_h3]:!text-sm [&_ol]:!text-xs [&_p.is-empty::before]:text-light-900 [&_p.is-empty::before]:dark:text-dark-800 [&_p]:!text-sm [&_p]:text-black [&_p]:dark:text-white [&_ul]:!text-xs" className="prose dark:prose-invert prose-sm max-w-none overflow-y-auto [&_blockquote]:!text-xs [&_h1]:!text-lg [&_h2]:!text-base [&_h3]:!text-sm [&_ol]:!text-xs [&_p.is-empty::before]:text-light-900 [&_p.is-empty::before]:dark:text-dark-800 [&_p]:!text-sm [&_p]:text-light-950 [&_p]:dark:text-dark-950 [&_ul]:!text-xs"
/> />
</div> </div>
); );

View File

@@ -32,7 +32,7 @@ export function LabelForm({
refetch: () => void; refetch: () => void;
isEdit?: boolean; isEdit?: boolean;
}) { }) {
const { closeModal, entityId, openModal } = useModal(); const { closeModal, entityId, openModal, setModalState } = useModal();
const label = api.label.byPublicId.useQuery( const label = api.label.byPublicId.useQuery(
{ {
@@ -57,12 +57,13 @@ export function LabelForm({
const isCreateAnotherEnabled = watch("isCreateAnotherEnabled"); const isCreateAnotherEnabled = watch("isCreateAnotherEnabled");
const createLabel = api.label.create.useMutation({ const createLabel = api.label.create.useMutation({
onSuccess: () => { onSuccess: (newLabel) => {
const currentColourIndex = colours.findIndex( const currentColourIndex = colours.findIndex(
(c) => c.code === watch("colour").code, (c) => c.code === watch("colour").code,
); );
try { try {
refetch(); refetch();
setModalState("NEW_LABEL_CREATED", newLabel.publicId);
if (!isCreateAnotherEnabled) { if (!isCreateAnotherEnabled) {
closeModal(); closeModal();
} else { } else {
@@ -220,6 +221,7 @@ export function LabelForm({
<div className="space-x-2"> <div className="space-x-2">
{isEdit && ( {isEdit && (
<Button <Button
type="button"
variant="secondary" variant="secondary"
onClick={() => openModal("DELETE_LABEL", entityId)} onClick={() => openModal("DELETE_LABEL", entityId)}
> >

View File

@@ -31,6 +31,7 @@ export function NewWorkspaceForm() {
description: values.description, description: values.description,
slug: values.slug, slug: values.slug,
plan: values.plan, plan: values.plan,
role: "admin",
}); });
closeModal(); closeModal();
} }

View File

@@ -18,7 +18,7 @@ import settingsIconLight from "~/assets/settings-light.json";
import ReactiveButton from "~/components/ReactiveButton"; import ReactiveButton from "~/components/ReactiveButton";
import UserMenu from "~/components/UserMenu"; import UserMenu from "~/components/UserMenu";
import WorkspaceMenu from "~/components/WorkspaceMenu"; import WorkspaceMenu from "~/components/WorkspaceMenu";
import { useTheme } from "~/providers/theme"; import { useTheme } from "next-themes";
interface SideNavigationProps { interface SideNavigationProps {
user: UserType; user: UserType;
@@ -59,9 +59,9 @@ export default function SideNavigation({
const { pathname } = router; const { pathname } = router;
const { activeTheme } = useTheme(); const { theme, resolvedTheme } = useTheme();
const isDarkMode = activeTheme === "dark"; const isDarkMode = resolvedTheme === "dark";
const navigation = [ const navigation = [
{ {

View File

@@ -1,23 +1,22 @@
import { CgDarkMode } from "react-icons/cg"; import { CgDarkMode } from "react-icons/cg";
import { useTheme } from "next-themes";
import { useTheme } from "~/providers/theme";
const ThemeToggle = () => { const ThemeToggle = () => {
const { themePreference, switchTheme } = useTheme(); const { theme, setTheme } = useTheme();
const toggleTheme = () => { const toggleTheme = () => {
switchTheme(themePreference === "light" ? "dark" : "light"); setTheme(theme === "light" ? "dark" : "light");
}; };
return ( return (
<button <button
onClick={toggleTheme} onClick={toggleTheme}
className="rounded p-1.5 transition-all hover:bg-light-200 dark:hover:bg-dark-100" className="rounded p-1.5 transition-all hover:bg-light-200 dark:hover:bg-dark-100"
aria-label={`Switch to ${themePreference === "light" ? "dark" : "light"} theme`} aria-label={`Switch to ${theme === "light" ? "dark" : "light"} theme`}
> >
<CgDarkMode <CgDarkMode
className={`h-4 w-4 text-light-900 transition-transform duration-200 dark:text-dark-900 ${ className={`h-4 w-4 text-light-900 transition-transform duration-200 dark:text-dark-900 ${
themePreference === "dark" ? "rotate-180" : "rotate-0" theme === "dark" ? "rotate-180" : "rotate-0"
}`} }`}
/> />
</button> </button>

View File

@@ -10,7 +10,7 @@ import { authClient } from "@kan/auth/client";
import { useIsMobile } from "~/hooks/useMediaQuery"; import { useIsMobile } from "~/hooks/useMediaQuery";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { useTheme } from "~/providers/theme"; import { useTheme } from "next-themes";
import { getAvatarUrl } from "~/utils/helpers"; import { getAvatarUrl } from "~/utils/helpers";
interface UserMenuProps { interface UserMenuProps {
@@ -29,7 +29,7 @@ export default function UserMenu({
onCloseSideNav, onCloseSideNav,
}: UserMenuProps) { }: UserMenuProps) {
const router = useRouter(); const router = useRouter();
const { themePreference, switchTheme } = useTheme(); const { theme, setTheme } = useTheme();
const { openModal } = useModal(); const { openModal } = useModal();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
@@ -127,12 +127,12 @@ export default function UserMenu({
</div> </div>
<Menu.Item> <Menu.Item>
<button <button
onClick={() => switchTheme("system")} onClick={() => setTheme("system")}
className="flex w-full items-center rounded-[5px] px-3 py-2 text-left text-xs hover:bg-light-200 dark:hover:bg-dark-400" className="flex w-full items-center rounded-[5px] px-3 py-2 text-left text-xs hover:bg-light-200 dark:hover:bg-dark-400"
> >
<span <span
className={twMerge( className={twMerge(
themePreference === "system" ? "visible" : "invisible", theme === "system" ? "visible" : "invisible",
"mr-4 h-[6px] w-[6px] rounded-full bg-light-900 dark:bg-dark-900", "mr-4 h-[6px] w-[6px] rounded-full bg-light-900 dark:bg-dark-900",
)} )}
/> />
@@ -141,12 +141,12 @@ export default function UserMenu({
</Menu.Item> </Menu.Item>
<Menu.Item> <Menu.Item>
<button <button
onClick={() => switchTheme("dark")} onClick={() => setTheme("dark")}
className="flex w-full items-center rounded-[5px] px-3 py-2 text-left text-xs hover:bg-light-200 dark:hover:bg-dark-400" className="flex w-full items-center rounded-[5px] px-3 py-2 text-left text-xs hover:bg-light-200 dark:hover:bg-dark-400"
> >
<span <span
className={twMerge( className={twMerge(
themePreference === "dark" ? "visible" : "invisible", theme === "dark" ? "visible" : "invisible",
"mr-4 h-[6px] w-[6px] rounded-full bg-light-900 dark:bg-dark-900", "mr-4 h-[6px] w-[6px] rounded-full bg-light-900 dark:bg-dark-900",
)} )}
/> />
@@ -155,12 +155,12 @@ export default function UserMenu({
</Menu.Item> </Menu.Item>
<Menu.Item> <Menu.Item>
<button <button
onClick={() => switchTheme("light")} onClick={() => setTheme("light")}
className="flex w-full items-center rounded-[5px] px-3 py-2 text-left text-xs hover:bg-light-200 dark:hover:bg-dark-400" className="flex w-full items-center rounded-[5px] px-3 py-2 text-left text-xs hover:bg-light-200 dark:hover:bg-dark-400"
> >
<span <span
className={twMerge( className={twMerge(
themePreference === "light" ? "visible" : "invisible", theme === "light" ? "visible" : "invisible",
"mr-4 h-[6px] w-[6px] rounded-full bg-light-900 dark:bg-dark-900", "mr-4 h-[6px] w-[6px] rounded-full bg-light-900 dark:bg-dark-900",
)} )}
/> />

View File

@@ -24,7 +24,7 @@ export const env = createEnv({
s.split(",").every((l) => z.string().url().safeParse(l).success), s.split(",").every((l) => z.string().url().safeParse(l).success),
) )
.optional(), .optional(),
POSTGRES_URL: z.string().url(), POSTGRES_URL: z.string().url().optional().or(z.literal("")),
TRELLO_APP_API_KEY: z.string().optional(), TRELLO_APP_API_KEY: z.string().optional(),
TRELLO_APP_SECRET: z.string().optional(), TRELLO_APP_SECRET: z.string().optional(),
STRIPE_SECRET_KEY: z.string().optional(), STRIPE_SECRET_KEY: z.string().optional(),
@@ -51,6 +51,10 @@ export const env = createEnv({
VK_CLIENT_SECRET: z.string().optional(), VK_CLIENT_SECRET: z.string().optional(),
LINKEDIN_CLIENT_ID: z.string().optional(), LINKEDIN_CLIENT_ID: z.string().optional(),
LINKEDIN_CLIENT_SECRET: z.string().optional(), LINKEDIN_CLIENT_SECRET: z.string().optional(),
// Generic OIDC Provider
OIDC_CLIENT_ID: z.string().optional(),
OIDC_CLIENT_SECRET: z.string().optional(),
OIDC_DISCOVERY_URL: z.string().optional(),
REDDIT_CLIENT_ID: z.string().optional(), REDDIT_CLIENT_ID: z.string().optional(),
REDDIT_CLIENT_SECRET: z.string().optional(), REDDIT_CLIENT_SECRET: z.string().optional(),
ROBLOX_CLIENT_ID: z.string().optional(), ROBLOX_CLIENT_ID: z.string().optional(),
@@ -101,6 +105,13 @@ export const env = createEnv({
(s) => !s || s.toLowerCase() === "true" || s.toLowerCase() === "false", (s) => !s || s.toLowerCase() === "true" || s.toLowerCase() === "false",
) )
.optional(), .optional(),
NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY: z
.string()
.transform((s) => (s === "" ? undefined : s))
.refine(
(s) => !s || s.toLowerCase() === "true" || s.toLowerCase() === "false",
)
.optional(),
}, },
/** /**
* Destructure all variables from `process.env` to make sure they aren't tree-shaken away. * Destructure all variables from `process.env` to make sure they aren't tree-shaken away.
@@ -119,6 +130,8 @@ export const env = createEnv({
NEXT_PUBLIC_DISABLE_SIGN_UP: process.env.NEXT_PUBLIC_DISABLE_SIGN_UP, NEXT_PUBLIC_DISABLE_SIGN_UP: process.env.NEXT_PUBLIC_DISABLE_SIGN_UP,
NEXT_PUBLIC_USE_STANDALONE_OUTPUT: NEXT_PUBLIC_USE_STANDALONE_OUTPUT:
process.env.NEXT_PUBLIC_USE_STANDALONE_OUTPUT, process.env.NEXT_PUBLIC_USE_STANDALONE_OUTPUT,
NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY:
process.env.NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY,
}, },
skipValidation: skipValidation:
!!process.env.CI || process.env.npm_lifecycle_event === "lint", !!process.env.CI || process.env.npm_lifecycle_event === "lint",

View File

@@ -23,12 +23,12 @@ msgstr ", oder besuche unsere"
#. placeholder {0}: card?.title ?? "Card" #. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board" #. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:189 #: src/views/card/index.tsx:213
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:392 #: src/views/board/components/NewCardForm.tsx:432
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} Labels" msgstr "{0} Labels"
@@ -48,8 +48,8 @@ msgstr "Eine leistungsstarke, flexible Kanban-App, die dir hilft, Arbeit zu orga
msgid "Account deleted" msgid "Account deleted"
msgstr "Konto gelöscht" msgstr "Konto gelöscht"
#: src/views/public/board/CardModal.tsx:128 #: src/views/public/board/CardModal.tsx:140
#: src/views/card/index.tsx:256 #: src/views/card/index.tsx:288
msgid "Activity" msgid "Activity"
msgstr "Aktivität" msgstr "Aktivität"
@@ -66,9 +66,21 @@ msgstr "Karte hinzufügen"
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Kommentar hinzufügen..." msgstr "Kommentar hinzufügen..."
#: src/components/Editor.tsx:303 #: src/views/card/components/NewChecklistItemForm.tsx:140
msgid "Add description... (type '/' to open commands)" msgid "Add an item..."
msgstr "Beschreibung hinzufügen... (tippe '/' um Befehle zu öffnen)" msgstr "Element hinzufügen..."
#: src/views/card/components/Dropdown.tsx:18
msgid "Add checklist"
msgstr "Checkliste hinzufügen"
#: src/components/Editor.tsx:442
msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Beschreibung hinzufügen... (tippe '/' um Befehle zu öffnen oder '@' um jemanden zu erwähnen)"
#: src/views/card/components/ChecklistItemRow.tsx:172
msgid "Add details..."
msgstr "Details hinzufügen..."
#: src/views/card/components/LabelSelector.tsx:110 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:118 #: src/views/card/components/LabelSelector.tsx:118
@@ -80,17 +92,36 @@ msgstr "Label hinzufügen"
msgid "Add member" msgid "Add member"
msgstr "Mitglied hinzufügen" msgstr "Mitglied hinzufügen"
#: src/views/card/components/ActivityList.tsx:56 #: src/views/card/components/ActivityList.tsx:69
msgid "added a checklist"
msgstr "hat eine Checkliste hinzugefügt"
#: src/views/card/components/ActivityList.tsx:72
msgid "added a checklist item"
msgstr "hat ein Checklistenelement hinzugefügt"
#: src/views/card/components/ActivityList.tsx:65
msgid "added a label to the card" msgid "added a label to the card"
msgstr "hat ein Label zur Karte hinzugefügt" msgstr "hat ein Label zur Karte hinzugefügt"
#: src/views/card/components/ActivityList.tsx:58 #: src/views/card/components/ActivityList.tsx:67
msgid "added a member to the card" msgid "added a member to the card"
msgstr "hat ein Mitglied zur Karte hinzugefügt" msgstr "hat ein Mitglied zur Karte hinzugefügt"
#: src/views/card/components/ActivityList.tsx:110 #. placeholder {0}: truncate(toTitle)
msgid "added label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:146
msgstr "hat Label <0>{label}</0> hinzugefügt" msgid "added checklist <0>{0}</0>"
msgstr "hat Checkliste <0>{0}</0> hinzugefügt"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170
msgid "added checklist item <0>{0}</0>"
msgstr "hat Checklistenelement <0>{0}</0> hinzugefügt"
#. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130
msgid "added label <0>{0}</0>"
msgstr "hat Label <0>{0}</0> hinzugefügt"
#: src/views/home/components/Pricing.tsx:55 #: src/views/home/components/Pricing.tsx:55
msgid "Admin roles" msgid "Admin roles"
@@ -108,11 +139,15 @@ msgstr "Alle Systeme funktionieren"
msgid "Already have an account? <0><1>Sign in</1></0>" msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "Du hast bereits ein Konto? <0><1>Anmelden</1></0>" msgstr "Du hast bereits ein Konto? <0><1>Anmelden</1></0>"
#: src/views/settings/index.tsx:100 #: src/views/settings/index.tsx:102
msgid "An error occurred while disconnecting your Trello account." msgid "An error occurred while disconnecting your Trello account."
msgstr "Beim Trennen deines Trello-Kontos ist ein Fehler aufgetreten." msgstr "Beim Trennen deines Trello-Kontos ist ein Fehler aufgetreten."
#: src/views/settings/index.tsx:257 #: src/views/settings/components/ChangePasswordConfirmation.tsx:90
msgid "An unexpected error occurred. Please try again later."
msgstr "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es später erneut."
#: src/views/settings/index.tsx:259
msgid "API keys" msgid "API keys"
msgstr "API-Schlüssel" msgstr "API-Schlüssel"
@@ -141,11 +176,15 @@ msgstr "Bist du sicher, dass du den Workspace {0} löschen möchtest?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Bist du sicher, dass du diese Karte löschen möchtest?" msgstr "Bist du sicher, dass du diese Karte löschen möchtest?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55
msgid "Are you sure you want to delete this checklist?"
msgstr "Sind Sie sicher, dass Sie diese Checkliste löschen möchten?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:65
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Bist du sicher, dass du diesen Kommentar löschen möchtest?" msgstr "Bist du sicher, dass du diesen Kommentar löschen möchtest?"
#: src/components/DeleteLabelConfirmation.tsx:39 #: src/components/DeleteLabelConfirmation.tsx:41
msgid "Are you sure you want to delete this label?" msgid "Are you sure you want to delete this label?"
msgstr "Sind Sie sicher, dass Sie dieses Label löschen möchten?" msgstr "Sind Sie sicher, dass Sie dieses Label löschen möchten?"
@@ -153,9 +192,10 @@ msgstr "Sind Sie sicher, dass Sie dieses Label löschen möchten?"
msgid "Are you sure you want to delete your account?" msgid "Are you sure you want to delete your account?"
msgstr "Bist du sicher, dass du dein Konto löschen möchtest?" msgstr "Bist du sicher, dass du dein Konto löschen möchtest?"
#: src/views/card/components/ActivityList.tsx:92 #. placeholder {0}: truncate(memberName)
msgid "assigned <0>{memberName}</0> to the card" #: src/views/card/components/ActivityList.tsx:110
msgstr "hat <0>{memberName}</0> der Karte zugewiesen" msgid "assigned <0>{0}</0> to the card"
msgstr "hat <0>{0}</0> der Karte zugewiesen"
#: src/views/boards/components/TemplateBoards.tsx:46 #: src/views/boards/components/TemplateBoards.tsx:46
msgid "Awaiting Customer" msgid "Awaiting Customer"
@@ -169,12 +209,12 @@ msgstr "Backlog"
msgid "Basic Kanban" msgid "Basic Kanban"
msgstr "Einfaches Kanban" msgstr "Einfaches Kanban"
#: src/views/settings/index.tsx:196 #: src/views/settings/index.tsx:198
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing" msgid "Billing"
msgstr "Abrechnung" msgstr "Abrechnung"
#: src/views/settings/index.tsx:206 #: src/views/settings/index.tsx:208
msgid "Billing portal" msgid "Billing portal"
msgstr "Abrechnungsportal" msgstr "Abrechnungsportal"
@@ -182,7 +222,7 @@ msgstr "Abrechnungsportal"
msgid "Blog Post" msgid "Blog Post"
msgstr "Blogbeitrag" msgstr "Blogbeitrag"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Board" msgid "Board"
msgstr "Board" msgstr "Board"
@@ -195,7 +235,7 @@ msgid "Board name is required"
msgstr "Boardname ist erforderlich" msgstr "Boardname ist erforderlich"
#: src/views/public/board/index.tsx:143 #: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358 #: src/views/board/index.tsx:357
msgid "Board not found" msgid "Board not found"
msgstr "Board nicht gefunden" msgstr "Board nicht gefunden"
@@ -248,23 +288,32 @@ msgstr "Fehlerbericht"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98
#: src/views/settings/components/DeleteAccountConfirmation.tsx:88 #: src/views/settings/components/DeleteAccountConfirmation.tsx:88
#: src/views/settings/components/CustomURLConfirmation.tsx:50 #: src/views/settings/components/CustomURLConfirmation.tsx:50
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47 #: src/components/DeleteLabelConfirmation.tsx:49
msgid "Cancel" msgid "Cancel"
msgstr "Abbrechen" msgstr "Abbrechen"
#: src/views/card/index.tsx:234 #: src/views/card/index.tsx:259
msgid "Card not found" msgid "Card not found"
msgstr "Karte nicht gefunden" msgstr "Karte nicht gefunden"
#: src/views/board/components/NewCardForm.tsx:278 #: src/views/board/components/NewCardForm.tsx:307
msgid "Card title" msgid "Card title"
msgstr "Kartentitel" msgstr "Kartentitel"
#: src/views/settings/index.tsx:188 #: src/views/settings/index.tsx:291
#: src/views/settings/index.tsx:301
#: src/views/settings/components/ChangePasswordConfirmation.tsx:109
#: src/views/settings/components/ChangePasswordConfirmation.tsx:178
msgid "Change Password"
msgstr "Passwort ändern"
#: src/views/settings/index.tsx:190
msgid "Change the language of the app." msgid "Change the language of the app."
msgstr "Ändere die Sprache der App." msgstr "Ändere die Sprache der App."
@@ -273,6 +322,10 @@ msgstr "Ändere die Sprache der App."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Überprüfe deinen Posteingang" msgstr "Überprüfe deinen Posteingang"
#: src/views/card/components/NewChecklistForm.tsx:118
msgid "Checklist name"
msgstr "Checklistenname"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:155
msgid "Clear filters" msgid "Clear filters"
msgstr "Filter löschen" msgstr "Filter löschen"
@@ -310,11 +363,24 @@ msgstr "Abgeschlossen"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Vollständige Kontrolle und Eigentum:" msgstr "Vollständige Kontrolle und Eigentum:"
#: src/views/card/components/ActivityList.tsx:74
msgid "completed a checklist item"
msgstr "hat ein Checklistenelement abgeschlossen"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187
msgid "completed checklist item <0>{0}</0>"
msgstr "hat Checklistenelement <0>{0}</0> abgeschlossen"
#: src/views/settings/components/CustomURLConfirmation.tsx:42 #: src/views/settings/components/CustomURLConfirmation.tsx:42
msgid "Confirm URL change" msgid "Confirm URL change"
msgstr "URL-Änderung bestätigen" msgstr "URL-Änderung bestätigen"
#: src/views/settings/index.tsx:233 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password"
msgstr "Bestätigen Sie Ihr neues Passwort"
#: src/views/settings/index.tsx:235
#: src/views/boards/components/ImportBoardsForm.tsx:157 #: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello" msgid "Connect Trello"
msgstr "Trello verbinden" msgstr "Trello verbinden"
@@ -323,7 +389,7 @@ msgstr "Trello verbinden"
msgid "Connect your favorite tools to streamline your workflow." msgid "Connect your favorite tools to streamline your workflow."
msgstr "Verbinde deine Lieblingstools, um deinen Arbeitsablauf zu optimieren." msgstr "Verbinde deine Lieblingstools, um deinen Arbeitsablauf zu optimieren."
#: src/views/settings/index.tsx:220 #: src/views/settings/index.tsx:222
msgid "Connect your Trello account to import boards." msgid "Connect your Trello account to import boards."
msgstr "Verbinde dein Trello-Konto, um Boards zu importieren." msgstr "Verbinde dein Trello-Konto, um Boards zu importieren."
@@ -353,8 +419,8 @@ msgid "Control who can view and edit your boards."
msgstr "Kontrolliere, wer deine Boards ansehen und bearbeiten kann." msgstr "Kontrolliere, wer deine Boards ansehen und bearbeiten kann."
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:418 #: src/views/board/components/NewCardForm.tsx:458
#: src/components/LabelForm.tsx:212 #: src/components/LabelForm.tsx:213
msgid "Create another" msgid "Create another"
msgstr "Weitere erstellen" msgstr "Weitere erstellen"
@@ -362,11 +428,15 @@ msgstr "Weitere erstellen"
msgid "Create board" msgid "Create board"
msgstr "Board erstellen" msgstr "Board erstellen"
#: src/views/board/components/NewCardForm.tsx:428 #: src/views/board/components/NewCardForm.tsx:468
msgid "Create card" msgid "Create card"
msgstr "Karte erstellen" msgstr "Karte erstellen"
#: src/components/LabelForm.tsx:236 #: src/views/card/components/NewChecklistForm.tsx:134
msgid "Create checklist"
msgstr "Checkliste erstellen"
#: src/components/LabelForm.tsx:238
msgid "Create label" msgid "Create label"
msgstr "Label erstellen" msgstr "Label erstellen"
@@ -383,11 +453,11 @@ msgid "Create new key"
msgstr "Neuen Schlüssel erstellen" msgstr "Neuen Schlüssel erstellen"
#: src/views/card/components/LabelSelector.tsx:98 #: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:354 #: src/views/board/components/NewCardForm.tsx:394
msgid "Create new label" msgid "Create new label"
msgstr "Neues Label erstellen" msgstr "Neues Label erstellen"
#: src/views/board/index.tsx:426 #: src/views/board/index.tsx:425
msgid "Create new list" msgid "Create new list"
msgstr "Neue Liste erstellen" msgstr "Neue Liste erstellen"
@@ -396,7 +466,7 @@ msgstr "Neue Liste erstellen"
msgid "Create workspace" msgid "Create workspace"
msgstr "Arbeitsbereich erstellen" msgstr "Arbeitsbereich erstellen"
#: src/views/card/components/ActivityList.tsx:52 #: src/views/card/components/ActivityList.tsx:61
msgid "created the card" msgid "created the card"
msgstr "hat die Karte erstellt" msgstr "hat die Karte erstellt"
@@ -404,6 +474,10 @@ msgstr "hat die Karte erstellt"
msgid "Critical" msgid "Critical"
msgstr "Kritisch" msgstr "Kritisch"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:19
msgid "Current password is required"
msgstr "Aktuelles Passwort ist erforderlich"
#: src/views/home/components/Pricing.tsx:74 #: src/views/home/components/Pricing.tsx:74
msgid "Custom domain" msgid "Custom domain"
msgstr "Benutzerdefinierte Domain" msgstr "Benutzerdefinierte Domain"
@@ -421,14 +495,15 @@ msgid "Dark"
msgstr "Dunkel" msgstr "Dunkel"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226 #: src/components/LabelForm.tsx:228
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:51
msgid "Delete" msgid "Delete"
msgstr "Löschen" msgstr "Löschen"
#: src/views/settings/index.tsx:288 #: src/views/settings/index.tsx:309
#: src/views/settings/index.tsx:298 #: src/views/settings/index.tsx:319
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96 #: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account" msgid "Delete account"
msgstr "Konto löschen" msgstr "Konto löschen"
@@ -437,7 +512,7 @@ msgstr "Konto löschen"
msgid "Delete board" msgid "Delete board"
msgstr "Board löschen" msgstr "Board löschen"
#: src/views/card/components/Dropdown.tsx:14 #: src/views/card/components/Dropdown.tsx:25
msgid "Delete card" msgid "Delete card"
msgstr "Karte löschen" msgstr "Karte löschen"
@@ -449,17 +524,35 @@ msgstr "Kommentar löschen"
msgid "Delete list" msgid "Delete list"
msgstr "Liste löschen" msgstr "Liste löschen"
#: src/views/settings/index.tsx:270 #: src/views/settings/index.tsx:272
#: src/views/settings/index.tsx:281 #: src/views/settings/index.tsx:283
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Workspace löschen" msgstr "Workspace löschen"
#: src/views/card/components/ActivityList.tsx:71
msgid "deleted a checklist"
msgstr "hat eine Checkliste gelöscht"
#: src/views/card/components/ActivityList.tsx:76
msgid "deleted a checklist item"
msgstr "hat ein Checklistenelement gelöscht"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162
msgid "deleted checklist <0>{0}</0>"
msgstr "hat Checkliste <0>{0}</0> gelöscht"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205
msgid "deleted checklist item <0>{0}</0>"
msgstr "hat Checklistenelement <0>{0}</0> gelöscht"
#: src/views/boards/components/TemplateBoards.tsx:32 #: src/views/boards/components/TemplateBoards.tsx:32
msgid "Design" msgid "Design"
msgstr "Design" msgstr "Design"
#: src/views/settings/index.tsx:248 #: src/views/settings/index.tsx:250
msgid "Disconnect Trello" msgid "Disconnect Trello"
msgstr "Trello trennen" msgstr "Trello trennen"
@@ -467,7 +560,7 @@ msgstr "Trello trennen"
msgid "Discuss and collaborate on cards." msgid "Discuss and collaborate on cards."
msgstr "Diskutiere und arbeite gemeinsam an Karten." msgstr "Diskutiere und arbeite gemeinsam an Karten."
#: src/views/settings/index.tsx:149 #: src/views/settings/index.tsx:151
msgid "Display name" msgid "Display name"
msgstr "Anzeigename" msgstr "Anzeigename"
@@ -521,7 +614,7 @@ msgstr "Board-URL bearbeiten"
msgid "Edit comment" msgid "Edit comment"
msgstr "Kommentar bearbeiten" msgstr "Kommentar bearbeiten"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "Edit label" msgid "Edit label"
msgstr "Label bearbeiten" msgstr "Label bearbeiten"
@@ -545,6 +638,14 @@ msgstr "E-Mail"
msgid "Enhancement" msgid "Enhancement"
msgstr "Verbesserung" msgstr "Verbesserung"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:122
msgid "Enter your current password"
msgstr "Geben Sie Ihr aktuelles Passwort ein"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:111
msgid "Enter your current password and choose a new secure password."
msgstr "Geben Sie Ihr aktuelles Passwort ein und wählen Sie ein neues sicheres Passwort."
#: src/components/AuthForm.tsx:302 #: src/components/AuthForm.tsx:302
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Gib deine E-Mail-Adresse ein" msgstr "Gib deine E-Mail-Adresse ein"
@@ -553,15 +654,23 @@ msgstr "Gib deine E-Mail-Adresse ein"
msgid "Enter your name" msgid "Enter your name"
msgstr "Gib deinen Namen ein" msgstr "Gib deinen Namen ein"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:136
msgid "Enter your new password"
msgstr "Geben Sie Ihr neues Passwort ein"
#: src/components/AuthForm.tsx:315 #: src/components/AuthForm.tsx:315
msgid "Enter your password" msgid "Enter your password"
msgstr "Gib dein Passwort ein" msgstr "Gib dein Passwort ein"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:89
msgid "Error Changing Password"
msgstr "Fehler beim Ändern des Passworts"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:39 #: src/views/settings/components/DeleteAccountConfirmation.tsx:39
msgid "Error deleting account" msgid "Error deleting account"
msgstr "Fehler beim Löschen des Kontos" msgstr "Fehler beim Löschen des Kontos"
#: src/components/DeleteLabelConfirmation.tsx:22 #: src/components/DeleteLabelConfirmation.tsx:25
msgid "Error deleting label" msgid "Error deleting label"
msgstr "Fehler beim Löschen des Labels" msgstr "Fehler beim Löschen des Labels"
@@ -569,7 +678,7 @@ msgstr "Fehler beim Löschen des Labels"
msgid "Error deleting workspace" msgid "Error deleting workspace"
msgstr "Fehler beim Löschen des Arbeitsbereichs" msgstr "Fehler beim Löschen des Arbeitsbereichs"
#: src/views/settings/index.tsx:99 #: src/views/settings/index.tsx:101
msgid "Error disconnecting Trello" msgid "Error disconnecting Trello"
msgstr "Fehler beim Trennen von Trello" msgstr "Fehler beim Trennen von Trello"
@@ -692,7 +801,7 @@ msgstr "Loslegen"
msgid "Get started by creating a new board" msgid "Get started by creating a new board"
msgstr "Beginne, indem du ein neues Board erstellst" msgstr "Beginne, indem du ein neues Board erstellst"
#: src/views/board/index.tsx:418 #: src/views/board/index.tsx:417
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Beginne mit dem Erstellen einer neuen Liste" msgstr "Beginne mit dem Erstellen einer neuen Liste"
@@ -849,8 +958,8 @@ msgstr "Kanban neu gedacht"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Beachten Sie, dass diese Aktion nicht rückgängig gemacht werden kann." msgstr "Beachten Sie, dass diese Aktion nicht rückgängig gemacht werden kann."
#: src/views/card/index.tsx:113 #: src/views/card/index.tsx:117
#: src/views/board/components/NewCardForm.tsx:358 #: src/views/board/components/NewCardForm.tsx:398
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:101
msgid "Labels" msgid "Labels"
msgstr "Labels" msgstr "Labels"
@@ -859,7 +968,7 @@ msgstr "Labels"
msgid "Labels & Filters" msgid "Labels & Filters"
msgstr "Labels & Filter" msgstr "Labels & Filter"
#: src/views/settings/index.tsx:185 #: src/views/settings/index.tsx:187
msgid "Language" msgid "Language"
msgstr "Sprache" msgstr "Sprache"
@@ -883,7 +992,7 @@ msgstr "Hell"
msgid "Link copied" msgid "Link copied"
msgstr "Link kopiert" msgstr "Link kopiert"
#: src/views/card/index.tsx:105 #: src/views/card/index.tsx:109
msgid "List" msgid "List"
msgstr "Liste" msgstr "Liste"
@@ -911,13 +1020,22 @@ msgstr "Niedrige Priorität"
msgid "magic link" msgid "magic link"
msgstr "Magic Link" msgstr "Magic Link"
#: src/views/card/components/ActivityList.tsx:75
msgid "marked a checklist item as incomplete"
msgstr "hat ein Checklistenelement als unvollständig markiert"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196
msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "hat Checklistenelement <0>{0}</0> als unvollständig markiert"
#: src/views/boards/components/TemplateBoards.tsx:17 #: src/views/boards/components/TemplateBoards.tsx:17
msgid "Medium Priority" msgid "Medium Priority"
msgstr "Mittlere Priorität" msgstr "Mittlere Priorität"
#: src/views/members/index.tsx:161 #: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121 #: src/views/card/index.tsx:125
#: src/views/board/components/NewCardForm.tsx:317 #: src/views/board/components/NewCardForm.tsx:357
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:73 #: src/components/SideNavigation.tsx:73
msgid "Members" msgid "Members"
@@ -932,16 +1050,18 @@ msgstr "Mitglieder | {0}"
msgid "Monthly" msgid "Monthly"
msgstr "Monatlich" msgstr "Monatlich"
#: src/views/card/components/ActivityList.tsx:81 #. placeholder {0}: truncate(fromList)
msgid "moved the card from <0>{fromList}</0> to<1>{toList}</1>" #. placeholder {1}: truncate(toList)
msgstr "hat die Karte von <0>{fromList}</0> nach <1>{toList}</1> verschoben" #: src/views/card/components/ActivityList.tsx:98
msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "hat die Karte von <0>{0}</0> nach <1>{1}</1> verschoben"
#: src/views/card/components/ActivityList.tsx:55 #: src/views/card/components/ActivityList.tsx:64
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "hat die Karte in eine andere Liste verschoben" msgstr "hat die Karte in eine andere Liste verschoben"
#: src/views/boards/components/NewBoardForm.tsx:99 #: src/views/boards/components/NewBoardForm.tsx:99
#: src/components/LabelForm.tsx:134 #: src/components/LabelForm.tsx:135
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
@@ -957,23 +1077,35 @@ msgstr "Neu"
msgid "New board" msgid "New board"
msgstr "Neues Board" msgstr "Neues Board"
#: src/views/board/components/NewCardForm.tsx:261 #: src/views/board/components/NewCardForm.tsx:290
msgid "New card" msgid "New card"
msgstr "Neue Karte" msgstr "Neue Karte"
#: src/views/card/components/NewChecklistForm.tsx:102
msgid "New checklist"
msgstr "Neue Checkliste"
#: src/views/boards/components/ImportBoardsForm.tsx:322 #: src/views/boards/components/ImportBoardsForm.tsx:322
msgid "New import" msgid "New import"
msgstr "Neuer Import" msgstr "Neuer Import"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "New label" msgid "New label"
msgstr "Neues Label" msgstr "Neues Label"
#: src/views/board/index.tsx:395 #: src/views/board/index.tsx:394
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:112
msgid "New list" msgid "New list"
msgstr "Neue Liste" msgstr "Neue Liste"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:23
msgid "New password is required"
msgstr "Neues Passwort ist erforderlich"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:31
msgid "New password must be different from current password"
msgstr "Neues Passwort muss sich vom aktuellen Passwort unterscheiden"
#: src/views/boards/components/TemplateBoards.tsx:43 #: src/views/boards/components/TemplateBoards.tsx:43
msgid "New Ticket" msgid "New Ticket"
msgstr "Neues Ticket" msgstr "Neues Ticket"
@@ -1002,7 +1134,7 @@ msgstr "Keine Boards gefunden"
msgid "No credit card required" msgid "No credit card required"
msgstr "Keine Kreditkarte erforderlich" msgstr "Keine Kreditkarte erforderlich"
#: src/views/board/index.tsx:415 #: src/views/board/index.tsx:414
msgid "No lists" msgid "No lists"
msgstr "Keine Listen" msgstr "Keine Listen"
@@ -1014,11 +1146,11 @@ msgstr "Angebot"
msgid "Onboarding" msgid "Onboarding"
msgstr "Einarbeitung" msgstr "Einarbeitung"
#: src/views/settings/index.tsx:291 #: src/views/settings/index.tsx:312
msgid "Once you delete your account, there is no going back. This action cannot be undone." msgid "Once you delete your account, there is no going back. This action cannot be undone."
msgstr "Sobald Sie Ihr Konto löschen, gibt es kein Zurück mehr. Diese Aktion kann nicht rückgängig gemacht werden." msgstr "Sobald Sie Ihr Konto löschen, gibt es kein Zurück mehr. Diese Aktion kann nicht rückgängig gemacht werden."
#: src/views/settings/index.tsx:273 #: src/views/settings/index.tsx:275
msgid "Once you delete your workspace, there is no going back. This action cannot be undone." msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
msgstr "Sobald Sie Ihren Arbeitsbereich löschen, gibt es kein Zurück mehr. Diese Aktion kann nicht rückgängig gemacht werden." msgstr "Sobald Sie Ihren Arbeitsbereich löschen, gibt es kein Zurück mehr. Diese Aktion kann nicht rückgängig gemacht werden."
@@ -1038,6 +1170,18 @@ msgstr "Besitze deine Daten"
msgid "Part-time" msgid "Part-time"
msgstr "Teilzeit" msgstr "Teilzeit"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:69
msgid "Password Changed"
msgstr "Passwort geändert"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:22
msgid "Password must be at least 8 characters"
msgstr "Passwort muss mindestens 8 Zeichen lang sein"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:27
msgid "Passwords do not match"
msgstr "Passwörter stimmen nicht überein"
#: src/views/home/components/Pricing.tsx:101 #: src/views/home/components/Pricing.tsx:101
msgid "Payment frequency" msgid "Payment frequency"
msgstr "Zahlungshäufigkeit" msgstr "Zahlungshäufigkeit"
@@ -1059,6 +1203,10 @@ msgstr "Persönliches Projekt"
msgid "Planning" msgid "Planning"
msgstr "Planung" msgstr "Planung"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:24
msgid "Please confirm your new password"
msgstr "Bitte bestätigen Sie Ihr neues Passwort"
#: src/components/AuthForm.tsx:306 #: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Bitte gib eine gültige E-Mail-Adresse ein" msgstr "Bitte gib eine gültige E-Mail-Adresse ein"
@@ -1085,24 +1233,30 @@ msgstr "Bitte wähle eine Datei zum Hochladen aus."
#: src/views/settings/components/Avatar.tsx:98 #: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64 #: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:159 #: src/views/card/index.tsx:172
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/MemberSelector.tsx:80 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Comment.tsx:64
#: src/views/card/components/ChecklistNameInput.tsx:46
#: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:135 #: src/views/board/index.tsx:134
#: src/views/board/index.tsx:191 #: src/views/board/index.tsx:190
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78 #: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:145 #: src/views/board/components/NewCardForm.tsx:174
#: src/components/NewWorkspaceForm.tsx:41 #: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23 #: src/components/DeleteLabelConfirmation.tsx:26
msgid "Please try again later, or contact customer support." msgid "Please try again later, or contact customer support."
msgstr "Bitte versuche es später noch einmal oder kontaktiere den Kundensupport." msgstr "Bitte versuche es später noch einmal oder kontaktiere den Kundensupport."
@@ -1128,7 +1282,7 @@ msgstr "Privat"
msgid "Profile image updated" msgid "Profile image updated"
msgstr "Profilbild aktualisiert" msgstr "Profilbild aktualisiert"
#: src/views/settings/index.tsx:144 #: src/views/settings/index.tsx:146
msgid "Profile picture" msgid "Profile picture"
msgstr "Profilbild" msgstr "Profilbild"
@@ -1168,17 +1322,32 @@ msgstr "Entfernen"
msgid "Remove member" msgid "Remove member"
msgstr "Mitglied entfernen" msgstr "Mitglied entfernen"
#: src/views/card/components/ActivityList.tsx:57 #: src/views/card/components/ActivityList.tsx:66
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "hat ein Label von der Karte entfernt" msgstr "hat ein Label von der Karte entfernt"
#: src/views/card/components/ActivityList.tsx:59 #: src/views/card/components/ActivityList.tsx:68
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "hat ein Mitglied von der Karte entfernt" msgstr "hat ein Mitglied von der Karte entfernt"
#: src/views/card/components/ActivityList.tsx:118 #. placeholder {0}: truncate(label)
msgid "removed label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:138
msgstr "hat Label <0>{label}</0> entfernt" msgid "removed label <0>{0}</0>"
msgstr "hat Label <0>{0}</0> entfernt"
#: src/views/card/components/ActivityList.tsx:70
msgid "renamed a checklist"
msgstr "hat eine Checkliste umbenannt"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154
msgid "renamed checklist <0>{0}</0>"
msgstr "hat Checkliste <0>{0}</0> umbenannt"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178
msgid "renamed checklist item to <0>{0}</0>"
msgstr "hat Checklistenelement in <0>{0}</0> umbenannt"
#: src/views/boards/components/TemplateBoards.tsx:76 #: src/views/boards/components/TemplateBoards.tsx:76
msgid "Research" msgid "Research"
@@ -1241,7 +1410,7 @@ msgstr "Selbst hosten"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Selbst hosten mit Github" msgstr "Selbst hosten mit Github"
#: src/views/card/components/ActivityList.tsx:89 #: src/views/card/components/ActivityList.tsx:107
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "hat sich selbst die Karte zugewiesen" msgstr "hat sich selbst die Karte zugewiesen"
@@ -1253,13 +1422,13 @@ msgstr "Feedback senden"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/settings/index.tsx:138 #: src/views/settings/index.tsx:140
#: src/components/SideNavigation.tsx:78 #: src/components/SideNavigation.tsx:78
msgid "Settings" msgid "Settings"
msgstr "Einstellungen" msgstr "Einstellungen"
#. placeholder {0}: workspace.name ?? "Workspace" #. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:134 #: src/views/settings/index.tsx:136
msgid "Settings | {0}" msgid "Settings | {0}"
msgstr "Einstellungen | {0}" msgstr "Einstellungen | {0}"
@@ -1338,6 +1507,10 @@ msgstr "Nutzungsbedingungen"
msgid "Thank you for your feedback!" msgid "Thank you for your feedback!"
msgstr "Vielen Dank für dein Feedback!" msgstr "Vielen Dank für dein Feedback!"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:84
msgid "The current password you entered is incorrect."
msgstr "Das eingegebene aktuelle Passwort ist falsch."
#: src/views/home/components/Faqs.tsx:33 #: src/views/home/components/Faqs.tsx:33
msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall." msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
msgstr "Der hauptunterschied zwischen Kan und Trello ist, dass Kan open source ist und jedem ermöglicht, unseren code einzusehen, zu ändern und dazu beizutragen. Unser cloud-angebot bietet außerdem keine einschränkungen bei funktionen für die individuelle nutzung, während Trello grundlegende funktionen wie die anzahl der boards, die du erstellen kannst, hinter einer paywall versteckt." msgstr "Der hauptunterschied zwischen Kan und Trello ist, dass Kan open source ist und jedem ermöglicht, unseren code einzusehen, zu ändern und dazu beizutragen. Unser cloud-angebot bietet außerdem keine einschränkungen bei funktionen für die individuelle nutzung, während Trello grundlegende funktionen wie die anzahl der boards, die du erstellen kannst, hinter einer paywall versteckt."
@@ -1360,8 +1533,9 @@ msgid "They won't be able to access this workspace."
msgstr "Sie werden keinen Zugriff mehr auf diesen Workspace haben." msgstr "Sie werden keinen Zugriff mehr auf diesen Workspace haben."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42 #: src/components/DeleteLabelConfirmation.tsx:44
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Diese Aktion kann nicht rückgängig gemacht werden." msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
@@ -1398,7 +1572,7 @@ msgstr "Menü umschalten"
msgid "Track all card changes with detailed activity history." msgid "Track all card changes with detailed activity history."
msgstr "Verfolge alle kartenänderungen mit detaillierter aktivitätshistorie." msgstr "Verfolge alle kartenänderungen mit detaillierter aktivitätshistorie."
#: src/views/settings/index.tsx:92 #: src/views/settings/index.tsx:94
msgid "Trello disconnected" msgid "Trello disconnected"
msgstr "Trello getrennt" msgstr "Trello getrennt"
@@ -1410,14 +1584,22 @@ msgstr "Trello-importe"
msgid "Triaging" msgid "Triaging"
msgstr "Priorisierung" msgstr "Priorisierung"
#: src/views/card/components/NewChecklistItemForm.tsx:88
msgid "Unable to add checklist item"
msgstr "Checklistenelement kann nicht hinzugefügt werden"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:30
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Kommentar konnte nicht hinzugefügt werden" msgstr "Kommentar konnte nicht hinzugefügt werden"
#: src/views/board/components/NewCardForm.tsx:142 #: src/views/board/components/NewCardForm.tsx:171
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Karte konnte nicht erstellt werden" msgstr "Karte konnte nicht erstellt werden"
#: src/views/card/components/NewChecklistForm.tsx:69
msgid "Unable to create checklist"
msgstr "Checkliste kann nicht erstellt werden"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:77
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Liste konnte nicht erstellt werden" msgstr "Liste konnte nicht erstellt werden"
@@ -1430,6 +1612,14 @@ msgstr "Workspace konnte nicht erstellt werden"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Karte konnte nicht gelöscht werden" msgstr "Karte konnte nicht gelöscht werden"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36
msgid "Unable to delete checklist"
msgstr "Checkliste kann nicht gelöscht werden"
#: src/views/card/components/ChecklistItemRow.tsx:87
msgid "Unable to delete checklist item"
msgstr "Checklistenelement kann nicht gelöscht werden"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:44
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Kommentar konnte nicht gelöscht werden" msgstr "Kommentar konnte nicht gelöscht werden"
@@ -1450,11 +1640,19 @@ msgstr "Board-URL kann nicht aktualisiert werden"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Board-Sichtbarkeit konnte nicht aktualisiert werden" msgstr "Board-Sichtbarkeit konnte nicht aktualisiert werden"
#: src/views/card/index.tsx:158 #: src/views/card/index.tsx:171
#: src/views/board/index.tsx:190 #: src/views/board/index.tsx:189
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Karte konnte nicht aktualisiert werden" msgstr "Karte konnte nicht aktualisiert werden"
#: src/views/card/components/ChecklistNameInput.tsx:45
msgid "Unable to update checklist"
msgstr "Checkliste kann nicht aktualisiert werden"
#: src/views/card/components/ChecklistItemRow.tsx:59
msgid "Unable to update checklist item"
msgstr "Checklistenelement kann nicht aktualisiert werden"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Kommentar konnte nicht aktualisiert werden" msgstr "Kommentar konnte nicht aktualisiert werden"
@@ -1464,7 +1662,7 @@ msgid "Unable to update labels"
msgstr "Labels konnten nicht aktualisiert werden" msgstr "Labels konnten nicht aktualisiert werden"
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:134 #: src/views/board/index.tsx:133
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Liste konnte nicht aktualisiert werden" msgstr "Liste konnte nicht aktualisiert werden"
@@ -1472,11 +1670,12 @@ msgstr "Liste konnte nicht aktualisiert werden"
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Mitglieder konnten nicht aktualisiert werden" msgstr "Mitglieder konnten nicht aktualisiert werden"
#: src/views/card/components/ActivityList.tsx:102 #. placeholder {0}: truncate(memberName)
msgid "unassigned <0>{memberName}</0> from the card" #: src/views/card/components/ActivityList.tsx:121
msgstr "<0>{memberName}</0> von der Karte entfernt" msgid "unassigned <0>{0}</0> from the card"
msgstr "hat <0>{0}</0> von der Karte entfernt"
#: src/views/card/components/ActivityList.tsx:99 #: src/views/card/components/ActivityList.tsx:118
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "hat sich selbst von der Karte entfernt" msgstr "hat sich selbst von der Karte entfernt"
@@ -1512,21 +1711,26 @@ msgstr "Unbegrenzte listen"
msgid "Update" msgid "Update"
msgstr "Aktualisieren" msgstr "Aktualisieren"
#: src/components/LabelForm.tsx:236 #: src/components/LabelForm.tsx:238
msgid "Update label" msgid "Update label"
msgstr "Label aktualisieren" msgstr "Label aktualisieren"
#: src/views/card/components/ActivityList.tsx:54 #: src/views/card/components/ActivityList.tsx:73
msgid "updated a checklist item"
msgstr "hat ein Checklistenelement aktualisiert"
#: src/views/card/components/ActivityList.tsx:63
msgid "updated the description" msgid "updated the description"
msgstr "hat die Beschreibung aktualisiert" msgstr "hat die Beschreibung aktualisiert"
#: src/views/card/components/ActivityList.tsx:53 #: src/views/card/components/ActivityList.tsx:62
msgid "updated the title" msgid "updated the title"
msgstr "hat den Titel aktualisiert" msgstr "hat den Titel aktualisiert"
#: src/views/card/components/ActivityList.tsx:73 #. placeholder {0}: truncate(toTitle)
msgid "updated the title to <0>{toTitle}</0>" #: src/views/card/components/ActivityList.tsx:90
msgstr "hat den Titel zu <0>{toTitle}</0> aktualisiert" msgid "updated the title to <0>{0}</0>"
msgstr "hat den Titel in <0>{0}</0> geändert"
#: src/views/settings/components/CustomURLConfirmation.tsx:52 #: src/views/settings/components/CustomURLConfirmation.tsx:52
msgid "Upgrade" msgid "Upgrade"
@@ -1565,11 +1769,11 @@ msgstr "Benutzer ist bereits Mitglied dieses Arbeitsbereichs"
msgid "Video" msgid "Video"
msgstr "Video" msgstr "Video"
#: src/views/settings/index.tsx:260 #: src/views/settings/index.tsx:262
msgid "View and manage your API keys." msgid "View and manage your API keys."
msgstr "API-Schlüssel anzeigen und verwalten." msgstr "API-Schlüssel anzeigen und verwalten."
#: src/views/settings/index.tsx:199 #: src/views/settings/index.tsx:201
msgid "View and manage your billing and subscription." msgid "View and manage your billing and subscription."
msgstr "Verwalte deine Abrechnung und dein Abonnement." msgstr "Verwalte deine Abrechnung und dein Abonnement."
@@ -1621,7 +1825,7 @@ msgstr "Als Trello 2011 auf den markt kam, beeindruckte es alle mit seiner sorgf
msgid "Why make an open source Trello?" msgid "Why make an open source Trello?"
msgstr "Warum ein open source Trello entwickeln?" msgstr "Warum ein open source Trello entwickeln?"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Workspace" msgid "Workspace"
msgstr "Arbeitsbereich" msgstr "Arbeitsbereich"
@@ -1629,7 +1833,7 @@ msgstr "Arbeitsbereich"
msgid "Workspace deleted" msgid "Workspace deleted"
msgstr "Workspace gelöscht" msgstr "Workspace gelöscht"
#: src/views/settings/index.tsx:175 #: src/views/settings/index.tsx:177
msgid "Workspace description" msgid "Workspace description"
msgstr "Workspace-Beschreibung" msgstr "Workspace-Beschreibung"
@@ -1650,7 +1854,7 @@ msgstr "Workspace-Beschreibung aktualisiert"
msgid "Workspace members" msgid "Workspace members"
msgstr "Workspace-mitglieder" msgstr "Workspace-mitglieder"
#: src/views/settings/index.tsx:156 #: src/views/settings/index.tsx:158
#: src/components/NewWorkspaceForm.tsx:80 #: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name" msgid "Workspace name"
msgstr "Name des Workspaces" msgstr "Name des Workspaces"
@@ -1671,7 +1875,7 @@ msgstr "Workspace-Name aktualisiert"
msgid "Workspace slug updated" msgid "Workspace slug updated"
msgstr "Workspace-Slug aktualisiert" msgstr "Workspace-Slug aktualisiert"
#: src/views/settings/index.tsx:165 #: src/views/settings/index.tsx:167
msgid "Workspace URL" msgid "Workspace URL"
msgstr "Workspace-URL" msgstr "Workspace-URL"
@@ -1687,6 +1891,10 @@ msgstr "Jährlich"
msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits." msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
msgstr "Ja, wir bieten einen dauerhaft kostenlosen plan für die individuelle nutzung an. Keine einschränkungen, keine paywalls, keine limits." msgstr "Ja, wir bieten einen dauerhaft kostenlosen plan für die individuelle nutzung an. Keine einschränkungen, keine paywalls, keine limits."
#: src/views/settings/index.tsx:294
msgid "You are about to change your password."
msgstr "Sie sind dabei, Ihr Passwort zu ändern."
#: src/views/home/components/Faqs.tsx:67 #: src/views/home/components/Faqs.tsx:67
msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!" msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
msgstr "Du kannst eine benutzerdefinierte workspace-URL, wie <0>kan.bn/kan</0>, erhalten, indem du in deine <1>workspace-einstellungen</1> gehst und ein pro-workspace-abonnement kaufst. Alle abonnements helfen, die entwicklung des projekts zu finanzieren!" msgstr "Du kannst eine benutzerdefinierte workspace-URL, wie <0>kan.bn/kan</0>, erhalten, indem du in deine <1>workspace-einstellungen</1> gehst und ein pro-workspace-abonnement kaufst. Alle abonnements helfen, die entwicklung des projekts zu finanzieren!"
@@ -1719,15 +1927,19 @@ msgstr "Deine Boards wurden importiert."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Dein Anzeigename wurde aktualisiert." msgstr "Dein Anzeigename wurde aktualisiert."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed."
msgstr "Ihr Passwort wurde geändert."
#: src/views/settings/components/Avatar.tsx:27 #: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated." msgid "Your profile image has been updated."
msgstr "Dein Profilbild wurde aktualisiert." msgstr "Dein Profilbild wurde aktualisiert."
#: src/views/settings/index.tsx:93 #: src/views/settings/index.tsx:95
msgid "Your Trello account has been disconnected." msgid "Your Trello account has been disconnected."
msgstr "Dein Trello-Konto wurde getrennt." msgstr "Dein Trello-Konto wurde getrennt."
#: src/views/settings/index.tsx:242 #: src/views/settings/index.tsx:244
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Dein Trello-Konto ist verbunden." msgstr "Dein Trello-Konto ist verbunden."

File diff suppressed because one or more lines are too long

View File

@@ -23,12 +23,12 @@ msgstr ", or see our"
#. placeholder {0}: card?.title ?? "Card" #. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board" #. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:189 #: src/views/card/index.tsx:213
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:392 #: src/views/board/components/NewCardForm.tsx:432
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} labels" msgstr "{0} labels"
@@ -60,8 +60,8 @@ msgstr "A powerful, flexible kanban app that helps you organise work, track prog
msgid "Account deleted" msgid "Account deleted"
msgstr "Account deleted" msgstr "Account deleted"
#: src/views/public/board/CardModal.tsx:128 #: src/views/public/board/CardModal.tsx:140
#: src/views/card/index.tsx:256 #: src/views/card/index.tsx:288
msgid "Activity" msgid "Activity"
msgstr "Activity" msgstr "Activity"
@@ -78,9 +78,25 @@ msgstr "Add a card"
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Add a comment..." msgstr "Add a comment..."
#: src/components/Editor.tsx:303 #: src/views/card/components/NewChecklistItemForm.tsx:140
msgid "Add description... (type '/' to open commands)" msgid "Add an item..."
msgstr "Add description... (type '/' to open commands)" msgstr "Add an item..."
#: src/views/card/components/Dropdown.tsx:18
msgid "Add checklist"
msgstr "Add checklist"
#: src/components/Editor.tsx:442
msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Add description... (type '/' to open commands or '@' to mention)"
#: src/components/Editor.tsx:308
#~ msgid "Add description... (type '/' to open commands)"
#~ msgstr "Add description... (type '/' to open commands)"
#: src/views/card/components/ChecklistItemRow.tsx:172
msgid "Add details..."
msgstr "Add details..."
#: src/views/card/components/LabelSelector.tsx:110 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:118 #: src/views/card/components/LabelSelector.tsx:118
@@ -92,17 +108,40 @@ msgstr "Add label"
msgid "Add member" msgid "Add member"
msgstr "Add member" msgstr "Add member"
#: src/views/card/components/ActivityList.tsx:56 #: src/views/card/components/ActivityList.tsx:69
msgid "added a checklist"
msgstr "added a checklist"
#: src/views/card/components/ActivityList.tsx:72
msgid "added a checklist item"
msgstr "added a checklist item"
#: src/views/card/components/ActivityList.tsx:65
msgid "added a label to the card" msgid "added a label to the card"
msgstr "added a label to the card" msgstr "added a label to the card"
#: src/views/card/components/ActivityList.tsx:58 #: src/views/card/components/ActivityList.tsx:67
msgid "added a member to the card" msgid "added a member to the card"
msgstr "added a member to the card" msgstr "added a member to the card"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:146
msgid "added checklist <0>{0}</0>"
msgstr "added checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170
msgid "added checklist item <0>{0}</0>"
msgstr "added checklist item <0>{0}</0>"
#. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130
msgid "added label <0>{0}</0>"
msgstr "added label <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:110 #: src/views/card/components/ActivityList.tsx:110
msgid "added label <0>{label}</0>" #~ msgid "added label <0>{label}</0>"
msgstr "added label <0>{label}</0>" #~ msgstr "added label <0>{label}</0>"
#: src/views/home/components/Pricing.tsx:55 #: src/views/home/components/Pricing.tsx:55
msgid "Admin roles" msgid "Admin roles"
@@ -120,11 +159,15 @@ msgstr "All systems operational"
msgid "Already have an account? <0><1>Sign in</1></0>" msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "Already have an account? <0><1>Sign in</1></0>" msgstr "Already have an account? <0><1>Sign in</1></0>"
#: src/views/settings/index.tsx:100 #: src/views/settings/index.tsx:102
msgid "An error occurred while disconnecting your Trello account." msgid "An error occurred while disconnecting your Trello account."
msgstr "An error occurred while disconnecting your Trello account." msgstr "An error occurred while disconnecting your Trello account."
#: src/views/settings/index.tsx:257 #: src/views/settings/components/ChangePasswordConfirmation.tsx:90
msgid "An unexpected error occurred. Please try again later."
msgstr "An unexpected error occurred. Please try again later."
#: src/views/settings/index.tsx:259
msgid "API keys" msgid "API keys"
msgstr "API keys" msgstr "API keys"
@@ -157,11 +200,15 @@ msgstr "Are you sure you want to delete the workspace {0}?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Are you sure you want to delete this card?" msgstr "Are you sure you want to delete this card?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55
msgid "Are you sure you want to delete this checklist?"
msgstr "Are you sure you want to delete this checklist?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:65
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Are you sure you want to delete this comment?" msgstr "Are you sure you want to delete this comment?"
#: src/components/DeleteLabelConfirmation.tsx:39 #: src/components/DeleteLabelConfirmation.tsx:41
msgid "Are you sure you want to delete this label?" msgid "Are you sure you want to delete this label?"
msgstr "Are you sure you want to delete this label?" msgstr "Are you sure you want to delete this label?"
@@ -169,9 +216,14 @@ msgstr "Are you sure you want to delete this label?"
msgid "Are you sure you want to delete your account?" msgid "Are you sure you want to delete your account?"
msgstr "Are you sure you want to delete your account?" msgstr "Are you sure you want to delete your account?"
#. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:110
msgid "assigned <0>{0}</0> to the card"
msgstr "assigned <0>{0}</0> to the card"
#: src/views/card/components/ActivityList.tsx:92 #: src/views/card/components/ActivityList.tsx:92
msgid "assigned <0>{memberName}</0> to the card" #~ msgid "assigned <0>{memberName}</0> to the card"
msgstr "assigned <0>{memberName}</0> to the card" #~ msgstr "assigned <0>{memberName}</0> to the card"
#: src/views/boards/components/TemplateBoards.tsx:46 #: src/views/boards/components/TemplateBoards.tsx:46
msgid "Awaiting Customer" msgid "Awaiting Customer"
@@ -189,12 +241,12 @@ msgstr "Backlog"
msgid "Basic Kanban" msgid "Basic Kanban"
msgstr "Basic Kanban" msgstr "Basic Kanban"
#: src/views/settings/index.tsx:196 #: src/views/settings/index.tsx:198
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing" msgid "Billing"
msgstr "Billing" msgstr "Billing"
#: src/views/settings/index.tsx:206 #: src/views/settings/index.tsx:208
msgid "Billing portal" msgid "Billing portal"
msgstr "Billing portal" msgstr "Billing portal"
@@ -202,7 +254,7 @@ msgstr "Billing portal"
msgid "Blog Post" msgid "Blog Post"
msgstr "Blog Post" msgstr "Blog Post"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Board" msgid "Board"
msgstr "Board" msgstr "Board"
@@ -219,7 +271,7 @@ msgid "Board name is required"
msgstr "Board name is required" msgstr "Board name is required"
#: src/views/public/board/index.tsx:143 #: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358 #: src/views/board/index.tsx:357
msgid "Board not found" msgid "Board not found"
msgstr "Board not found" msgstr "Board not found"
@@ -276,23 +328,32 @@ msgstr "Bug Report"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98
#: src/views/settings/components/DeleteAccountConfirmation.tsx:88 #: src/views/settings/components/DeleteAccountConfirmation.tsx:88
#: src/views/settings/components/CustomURLConfirmation.tsx:50 #: src/views/settings/components/CustomURLConfirmation.tsx:50
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47 #: src/components/DeleteLabelConfirmation.tsx:49
msgid "Cancel" msgid "Cancel"
msgstr "Cancel" msgstr "Cancel"
#: src/views/card/index.tsx:234 #: src/views/card/index.tsx:259
msgid "Card not found" msgid "Card not found"
msgstr "Card not found" msgstr "Card not found"
#: src/views/board/components/NewCardForm.tsx:278 #: src/views/board/components/NewCardForm.tsx:307
msgid "Card title" msgid "Card title"
msgstr "Card title" msgstr "Card title"
#: src/views/settings/index.tsx:188 #: src/views/settings/index.tsx:291
#: src/views/settings/index.tsx:301
#: src/views/settings/components/ChangePasswordConfirmation.tsx:109
#: src/views/settings/components/ChangePasswordConfirmation.tsx:178
msgid "Change Password"
msgstr "Change Password"
#: src/views/settings/index.tsx:190
msgid "Change the language of the app." msgid "Change the language of the app."
msgstr "Change the language of the app." msgstr "Change the language of the app."
@@ -301,6 +362,10 @@ msgstr "Change the language of the app."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Check your inbox" msgstr "Check your inbox"
#: src/views/card/components/NewChecklistForm.tsx:118
msgid "Checklist name"
msgstr "Checklist name"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:155
msgid "Clear filters" msgid "Clear filters"
msgstr "Clear filters" msgstr "Clear filters"
@@ -338,11 +403,24 @@ msgstr "Complete"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Complete control and ownership:" msgstr "Complete control and ownership:"
#: src/views/card/components/ActivityList.tsx:74
msgid "completed a checklist item"
msgstr "completed a checklist item"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187
msgid "completed checklist item <0>{0}</0>"
msgstr "completed checklist item <0>{0}</0>"
#: src/views/settings/components/CustomURLConfirmation.tsx:42 #: src/views/settings/components/CustomURLConfirmation.tsx:42
msgid "Confirm URL change" msgid "Confirm URL change"
msgstr "Confirm URL change" msgstr "Confirm URL change"
#: src/views/settings/index.tsx:233 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password"
msgstr "Confirm your new password"
#: src/views/settings/index.tsx:235
#: src/views/boards/components/ImportBoardsForm.tsx:157 #: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello" msgid "Connect Trello"
msgstr "Connect Trello" msgstr "Connect Trello"
@@ -351,7 +429,7 @@ msgstr "Connect Trello"
msgid "Connect your favorite tools to streamline your workflow." msgid "Connect your favorite tools to streamline your workflow."
msgstr "Connect your favorite tools to streamline your workflow." msgstr "Connect your favorite tools to streamline your workflow."
#: src/views/settings/index.tsx:220 #: src/views/settings/index.tsx:222
msgid "Connect your Trello account to import boards." msgid "Connect your Trello account to import boards."
msgstr "Connect your Trello account to import boards." msgstr "Connect your Trello account to import boards."
@@ -381,8 +459,8 @@ msgid "Control who can view and edit your boards."
msgstr "Control who can view and edit your boards." msgstr "Control who can view and edit your boards."
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:418 #: src/views/board/components/NewCardForm.tsx:458
#: src/components/LabelForm.tsx:212 #: src/components/LabelForm.tsx:213
msgid "Create another" msgid "Create another"
msgstr "Create another" msgstr "Create another"
@@ -398,11 +476,15 @@ msgstr "Create another"
msgid "Create board" msgid "Create board"
msgstr "Create board" msgstr "Create board"
#: src/views/board/components/NewCardForm.tsx:428 #: src/views/board/components/NewCardForm.tsx:468
msgid "Create card" msgid "Create card"
msgstr "Create card" msgstr "Create card"
#: src/components/LabelForm.tsx:236 #: src/views/card/components/NewChecklistForm.tsx:134
msgid "Create checklist"
msgstr "Create checklist"
#: src/components/LabelForm.tsx:238
msgid "Create label" msgid "Create label"
msgstr "Create label" msgstr "Create label"
@@ -419,11 +501,11 @@ msgid "Create new key"
msgstr "Create new key" msgstr "Create new key"
#: src/views/card/components/LabelSelector.tsx:98 #: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:354 #: src/views/board/components/NewCardForm.tsx:394
msgid "Create new label" msgid "Create new label"
msgstr "Create new label" msgstr "Create new label"
#: src/views/board/index.tsx:426 #: src/views/board/index.tsx:425
msgid "Create new list" msgid "Create new list"
msgstr "Create new list" msgstr "Create new list"
@@ -432,7 +514,7 @@ msgstr "Create new list"
msgid "Create workspace" msgid "Create workspace"
msgstr "Create workspace" msgstr "Create workspace"
#: src/views/card/components/ActivityList.tsx:52 #: src/views/card/components/ActivityList.tsx:61
msgid "created the card" msgid "created the card"
msgstr "created the card" msgstr "created the card"
@@ -440,6 +522,10 @@ msgstr "created the card"
msgid "Critical" msgid "Critical"
msgstr "Critical" msgstr "Critical"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:19
msgid "Current password is required"
msgstr "Current password is required"
#: src/views/home/components/Pricing.tsx:74 #: src/views/home/components/Pricing.tsx:74
msgid "Custom domain" msgid "Custom domain"
msgstr "Custom domain" msgstr "Custom domain"
@@ -457,14 +543,15 @@ msgid "Dark"
msgstr "Dark" msgstr "Dark"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226 #: src/components/LabelForm.tsx:228
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:51
msgid "Delete" msgid "Delete"
msgstr "Delete" msgstr "Delete"
#: src/views/settings/index.tsx:288 #: src/views/settings/index.tsx:309
#: src/views/settings/index.tsx:298 #: src/views/settings/index.tsx:319
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96 #: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account" msgid "Delete account"
msgstr "Delete account" msgstr "Delete account"
@@ -473,7 +560,7 @@ msgstr "Delete account"
msgid "Delete board" msgid "Delete board"
msgstr "Delete board" msgstr "Delete board"
#: src/views/card/components/Dropdown.tsx:14 #: src/views/card/components/Dropdown.tsx:25
msgid "Delete card" msgid "Delete card"
msgstr "Delete card" msgstr "Delete card"
@@ -485,17 +572,35 @@ msgstr "Delete comment"
msgid "Delete list" msgid "Delete list"
msgstr "Delete list" msgstr "Delete list"
#: src/views/settings/index.tsx:270 #: src/views/settings/index.tsx:272
#: src/views/settings/index.tsx:281 #: src/views/settings/index.tsx:283
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Delete workspace" msgstr "Delete workspace"
#: src/views/card/components/ActivityList.tsx:71
msgid "deleted a checklist"
msgstr "deleted a checklist"
#: src/views/card/components/ActivityList.tsx:76
msgid "deleted a checklist item"
msgstr "deleted a checklist item"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162
msgid "deleted checklist <0>{0}</0>"
msgstr "deleted checklist <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205
msgid "deleted checklist item <0>{0}</0>"
msgstr "deleted checklist item <0>{0}</0>"
#: src/views/boards/components/TemplateBoards.tsx:32 #: src/views/boards/components/TemplateBoards.tsx:32
msgid "Design" msgid "Design"
msgstr "Design" msgstr "Design"
#: src/views/settings/index.tsx:248 #: src/views/settings/index.tsx:250
msgid "Disconnect Trello" msgid "Disconnect Trello"
msgstr "Disconnect Trello" msgstr "Disconnect Trello"
@@ -503,7 +608,7 @@ msgstr "Disconnect Trello"
msgid "Discuss and collaborate on cards." msgid "Discuss and collaborate on cards."
msgstr "Discuss and collaborate on cards." msgstr "Discuss and collaborate on cards."
#: src/views/settings/index.tsx:149 #: src/views/settings/index.tsx:151
msgid "Display name" msgid "Display name"
msgstr "Display name" msgstr "Display name"
@@ -557,7 +662,7 @@ msgstr "Edit board URL"
msgid "Edit comment" msgid "Edit comment"
msgstr "Edit comment" msgstr "Edit comment"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "Edit label" msgid "Edit label"
msgstr "Edit label" msgstr "Edit label"
@@ -581,6 +686,14 @@ msgstr "Email"
msgid "Enhancement" msgid "Enhancement"
msgstr "Enhancement" msgstr "Enhancement"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:122
msgid "Enter your current password"
msgstr "Enter your current password"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:111
msgid "Enter your current password and choose a new secure password."
msgstr "Enter your current password and choose a new secure password."
#: src/components/AuthForm.tsx:302 #: src/components/AuthForm.tsx:302
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Enter your email address" msgstr "Enter your email address"
@@ -589,15 +702,23 @@ msgstr "Enter your email address"
msgid "Enter your name" msgid "Enter your name"
msgstr "Enter your name" msgstr "Enter your name"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:136
msgid "Enter your new password"
msgstr "Enter your new password"
#: src/components/AuthForm.tsx:315 #: src/components/AuthForm.tsx:315
msgid "Enter your password" msgid "Enter your password"
msgstr "Enter your password" msgstr "Enter your password"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:89
msgid "Error Changing Password"
msgstr "Error Changing Password"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:39 #: src/views/settings/components/DeleteAccountConfirmation.tsx:39
msgid "Error deleting account" msgid "Error deleting account"
msgstr "Error deleting account" msgstr "Error deleting account"
#: src/components/DeleteLabelConfirmation.tsx:22 #: src/components/DeleteLabelConfirmation.tsx:25
msgid "Error deleting label" msgid "Error deleting label"
msgstr "Error deleting label" msgstr "Error deleting label"
@@ -605,7 +726,7 @@ msgstr "Error deleting label"
msgid "Error deleting workspace" msgid "Error deleting workspace"
msgstr "Error deleting workspace" msgstr "Error deleting workspace"
#: src/views/settings/index.tsx:99 #: src/views/settings/index.tsx:101
msgid "Error disconnecting Trello" msgid "Error disconnecting Trello"
msgstr "Error disconnecting Trello" msgstr "Error disconnecting Trello"
@@ -729,7 +850,7 @@ msgstr "Get Started"
msgid "Get started by creating a new board" msgid "Get started by creating a new board"
msgstr "Get started by creating a new board" msgstr "Get started by creating a new board"
#: src/views/board/index.tsx:418 #: src/views/board/index.tsx:417
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Get started by creating a new list" msgstr "Get started by creating a new list"
@@ -890,8 +1011,8 @@ msgstr "Kanban reimagined"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Keep in mind that this action is irreversible." msgstr "Keep in mind that this action is irreversible."
#: src/views/card/index.tsx:113 #: src/views/card/index.tsx:117
#: src/views/board/components/NewCardForm.tsx:358 #: src/views/board/components/NewCardForm.tsx:398
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:101
msgid "Labels" msgid "Labels"
msgstr "Labels" msgstr "Labels"
@@ -900,7 +1021,7 @@ msgstr "Labels"
msgid "Labels & Filters" msgid "Labels & Filters"
msgstr "Labels & Filters" msgstr "Labels & Filters"
#: src/views/settings/index.tsx:185 #: src/views/settings/index.tsx:187
msgid "Language" msgid "Language"
msgstr "Language" msgstr "Language"
@@ -924,7 +1045,7 @@ msgstr "Light"
msgid "Link copied" msgid "Link copied"
msgstr "Link copied" msgstr "Link copied"
#: src/views/card/index.tsx:105 #: src/views/card/index.tsx:109
msgid "List" msgid "List"
msgstr "List" msgstr "List"
@@ -952,13 +1073,22 @@ msgstr "Low Priority"
msgid "magic link" msgid "magic link"
msgstr "magic link" msgstr "magic link"
#: src/views/card/components/ActivityList.tsx:75
msgid "marked a checklist item as incomplete"
msgstr "marked a checklist item as incomplete"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196
msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "marked checklist item <0>{0}</0> as incomplete"
#: src/views/boards/components/TemplateBoards.tsx:17 #: src/views/boards/components/TemplateBoards.tsx:17
msgid "Medium Priority" msgid "Medium Priority"
msgstr "Medium Priority" msgstr "Medium Priority"
#: src/views/members/index.tsx:161 #: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121 #: src/views/card/index.tsx:125
#: src/views/board/components/NewCardForm.tsx:317 #: src/views/board/components/NewCardForm.tsx:357
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:73 #: src/components/SideNavigation.tsx:73
msgid "Members" msgid "Members"
@@ -973,16 +1103,22 @@ msgstr "Members | {0}"
msgid "Monthly" msgid "Monthly"
msgstr "Monthly" msgstr "Monthly"
#: src/views/card/components/ActivityList.tsx:81 #. placeholder {0}: truncate(fromList)
msgid "moved the card from <0>{fromList}</0> to<1>{toList}</1>" #. placeholder {1}: truncate(toList)
msgstr "moved the card from <0>{fromList}</0> to<1>{toList}</1>" #: src/views/card/components/ActivityList.tsx:98
msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "moved the card from <0>{0}</0> to<1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:55 #: src/views/card/components/ActivityList.tsx:81
#~ msgid "moved the card from <0>{fromList}</0> to<1>{toList}</1>"
#~ msgstr "moved the card from <0>{fromList}</0> to<1>{toList}</1>"
#: src/views/card/components/ActivityList.tsx:64
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "moved the card to another list" msgstr "moved the card to another list"
#: src/views/boards/components/NewBoardForm.tsx:99 #: src/views/boards/components/NewBoardForm.tsx:99
#: src/components/LabelForm.tsx:134 #: src/components/LabelForm.tsx:135
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
@@ -998,23 +1134,35 @@ msgstr "New"
msgid "New board" msgid "New board"
msgstr "New board" msgstr "New board"
#: src/views/board/components/NewCardForm.tsx:261 #: src/views/board/components/NewCardForm.tsx:290
msgid "New card" msgid "New card"
msgstr "New card" msgstr "New card"
#: src/views/card/components/NewChecklistForm.tsx:102
msgid "New checklist"
msgstr "New checklist"
#: src/views/boards/components/ImportBoardsForm.tsx:322 #: src/views/boards/components/ImportBoardsForm.tsx:322
msgid "New import" msgid "New import"
msgstr "New import" msgstr "New import"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "New label" msgid "New label"
msgstr "New label" msgstr "New label"
#: src/views/board/index.tsx:395 #: src/views/board/index.tsx:394
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:112
msgid "New list" msgid "New list"
msgstr "New list" msgstr "New list"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:23
msgid "New password is required"
msgstr "New password is required"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:31
msgid "New password must be different from current password"
msgstr "New password must be different from current password"
#: src/views/boards/components/TemplateBoards.tsx:43 #: src/views/boards/components/TemplateBoards.tsx:43
msgid "New Ticket" msgid "New Ticket"
msgstr "New Ticket" msgstr "New Ticket"
@@ -1047,7 +1195,7 @@ msgstr "No boards found"
msgid "No credit card required" msgid "No credit card required"
msgstr "No credit card required" msgstr "No credit card required"
#: src/views/board/index.tsx:415 #: src/views/board/index.tsx:414
msgid "No lists" msgid "No lists"
msgstr "No lists" msgstr "No lists"
@@ -1059,11 +1207,11 @@ msgstr "Offer"
msgid "Onboarding" msgid "Onboarding"
msgstr "Onboarding" msgstr "Onboarding"
#: src/views/settings/index.tsx:291 #: src/views/settings/index.tsx:312
msgid "Once you delete your account, there is no going back. This action cannot be undone." msgid "Once you delete your account, there is no going back. This action cannot be undone."
msgstr "Once you delete your account, there is no going back. This action cannot be undone." msgstr "Once you delete your account, there is no going back. This action cannot be undone."
#: src/views/settings/index.tsx:273 #: src/views/settings/index.tsx:275
msgid "Once you delete your workspace, there is no going back. This action cannot be undone." msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
msgstr "Once you delete your workspace, there is no going back. This action cannot be undone." msgstr "Once you delete your workspace, there is no going back. This action cannot be undone."
@@ -1083,6 +1231,18 @@ msgstr "Own your data"
msgid "Part-time" msgid "Part-time"
msgstr "Part-time" msgstr "Part-time"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:69
msgid "Password Changed"
msgstr "Password Changed"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:22
msgid "Password must be at least 8 characters"
msgstr "Password must be at least 8 characters"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:27
msgid "Passwords do not match"
msgstr "Passwords do not match"
#: src/views/home/components/Pricing.tsx:101 #: src/views/home/components/Pricing.tsx:101
msgid "Payment frequency" msgid "Payment frequency"
msgstr "Payment frequency" msgstr "Payment frequency"
@@ -1104,6 +1264,10 @@ msgstr "Personal Project"
msgid "Planning" msgid "Planning"
msgstr "Planning" msgstr "Planning"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:24
msgid "Please confirm your new password"
msgstr "Please confirm your new password"
#: src/components/AuthForm.tsx:306 #: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Please enter a valid email address" msgstr "Please enter a valid email address"
@@ -1130,24 +1294,30 @@ msgstr "Please select a file to upload."
#: src/views/settings/components/Avatar.tsx:98 #: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64 #: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:159 #: src/views/card/index.tsx:172
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/MemberSelector.tsx:80 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Comment.tsx:64
#: src/views/card/components/ChecklistNameInput.tsx:46
#: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:135 #: src/views/board/index.tsx:134
#: src/views/board/index.tsx:191 #: src/views/board/index.tsx:190
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78 #: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:145 #: src/views/board/components/NewCardForm.tsx:174
#: src/components/NewWorkspaceForm.tsx:41 #: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23 #: src/components/DeleteLabelConfirmation.tsx:26
msgid "Please try again later, or contact customer support." msgid "Please try again later, or contact customer support."
msgstr "Please try again later, or contact customer support." msgstr "Please try again later, or contact customer support."
@@ -1173,7 +1343,7 @@ msgstr "Private"
msgid "Profile image updated" msgid "Profile image updated"
msgstr "Profile image updated" msgstr "Profile image updated"
#: src/views/settings/index.tsx:144 #: src/views/settings/index.tsx:146
msgid "Profile picture" msgid "Profile picture"
msgstr "Profile picture" msgstr "Profile picture"
@@ -1213,17 +1383,36 @@ msgstr "Remove"
msgid "Remove member" msgid "Remove member"
msgstr "Remove member" msgstr "Remove member"
#: src/views/card/components/ActivityList.tsx:57 #: src/views/card/components/ActivityList.tsx:66
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "removed a label from the card" msgstr "removed a label from the card"
#: src/views/card/components/ActivityList.tsx:59 #: src/views/card/components/ActivityList.tsx:68
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "removed a member from the card" msgstr "removed a member from the card"
#. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:138
msgid "removed label <0>{0}</0>"
msgstr "removed label <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:118 #: src/views/card/components/ActivityList.tsx:118
msgid "removed label <0>{label}</0>" #~ msgid "removed label <0>{label}</0>"
msgstr "removed label <0>{label}</0>" #~ msgstr "removed label <0>{label}</0>"
#: src/views/card/components/ActivityList.tsx:70
msgid "renamed a checklist"
msgstr "renamed a checklist"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154
msgid "renamed checklist <0>{0}</0>"
msgstr "renamed checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178
msgid "renamed checklist item to <0>{0}</0>"
msgstr "renamed checklist item to <0>{0}</0>"
#: src/views/boards/components/TemplateBoards.tsx:76 #: src/views/boards/components/TemplateBoards.tsx:76
msgid "Research" msgid "Research"
@@ -1286,7 +1475,7 @@ msgstr "Self Host"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Self host with Github" msgstr "Self host with Github"
#: src/views/card/components/ActivityList.tsx:89 #: src/views/card/components/ActivityList.tsx:107
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "self-assigned the card" msgstr "self-assigned the card"
@@ -1302,13 +1491,13 @@ msgstr "Send feedback"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/settings/index.tsx:138 #: src/views/settings/index.tsx:140
#: src/components/SideNavigation.tsx:78 #: src/components/SideNavigation.tsx:78
msgid "Settings" msgid "Settings"
msgstr "Settings" msgstr "Settings"
#. placeholder {0}: workspace.name ?? "Workspace" #. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:134 #: src/views/settings/index.tsx:136
msgid "Settings | {0}" msgid "Settings | {0}"
msgstr "Settings | {0}" msgstr "Settings | {0}"
@@ -1387,6 +1576,10 @@ msgstr "Terms of service"
msgid "Thank you for your feedback!" msgid "Thank you for your feedback!"
msgstr "Thank you for your feedback!" msgstr "Thank you for your feedback!"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:84
msgid "The current password you entered is incorrect."
msgstr "The current password you entered is incorrect."
#: src/views/home/components/Faqs.tsx:33 #: src/views/home/components/Faqs.tsx:33
msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall." msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
msgstr "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall." msgstr "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
@@ -1409,8 +1602,9 @@ msgid "They won't be able to access this workspace."
msgstr "They won't be able to access this workspace." msgstr "They won't be able to access this workspace."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42 #: src/components/DeleteLabelConfirmation.tsx:44
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "This action can't be undone." msgstr "This action can't be undone."
@@ -1451,7 +1645,7 @@ msgstr "Toggle menu"
msgid "Track all card changes with detailed activity history." msgid "Track all card changes with detailed activity history."
msgstr "Track all card changes with detailed activity history." msgstr "Track all card changes with detailed activity history."
#: src/views/settings/index.tsx:92 #: src/views/settings/index.tsx:94
msgid "Trello disconnected" msgid "Trello disconnected"
msgstr "Trello disconnected" msgstr "Trello disconnected"
@@ -1463,14 +1657,22 @@ msgstr "Trello imports"
msgid "Triaging" msgid "Triaging"
msgstr "Triaging" msgstr "Triaging"
#: src/views/card/components/NewChecklistItemForm.tsx:88
msgid "Unable to add checklist item"
msgstr "Unable to add checklist item"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:30
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Unable to add comment" msgstr "Unable to add comment"
#: src/views/board/components/NewCardForm.tsx:142 #: src/views/board/components/NewCardForm.tsx:171
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Unable to create card" msgstr "Unable to create card"
#: src/views/card/components/NewChecklistForm.tsx:69
msgid "Unable to create checklist"
msgstr "Unable to create checklist"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:77
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Unable to create list" msgstr "Unable to create list"
@@ -1483,6 +1685,14 @@ msgstr "Unable to create workspace"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Unable to delete card" msgstr "Unable to delete card"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36
msgid "Unable to delete checklist"
msgstr "Unable to delete checklist"
#: src/views/card/components/ChecklistItemRow.tsx:87
msgid "Unable to delete checklist item"
msgstr "Unable to delete checklist item"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:44
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Unable to delete comment" msgstr "Unable to delete comment"
@@ -1503,11 +1713,19 @@ msgstr "Unable to update board URL"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Unable to update board visibility" msgstr "Unable to update board visibility"
#: src/views/card/index.tsx:158 #: src/views/card/index.tsx:171
#: src/views/board/index.tsx:190 #: src/views/board/index.tsx:189
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Unable to update card" msgstr "Unable to update card"
#: src/views/card/components/ChecklistNameInput.tsx:45
msgid "Unable to update checklist"
msgstr "Unable to update checklist"
#: src/views/card/components/ChecklistItemRow.tsx:59
msgid "Unable to update checklist item"
msgstr "Unable to update checklist item"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Unable to update comment" msgstr "Unable to update comment"
@@ -1517,7 +1735,7 @@ msgid "Unable to update labels"
msgstr "Unable to update labels" msgstr "Unable to update labels"
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:134 #: src/views/board/index.tsx:133
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Unable to update list" msgstr "Unable to update list"
@@ -1525,11 +1743,16 @@ msgstr "Unable to update list"
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Unable to update members" msgstr "Unable to update members"
#: src/views/card/components/ActivityList.tsx:102 #. placeholder {0}: truncate(memberName)
msgid "unassigned <0>{memberName}</0> from the card" #: src/views/card/components/ActivityList.tsx:121
msgstr "unassigned <0>{memberName}</0> from the card" msgid "unassigned <0>{0}</0> from the card"
msgstr "unassigned <0>{0}</0> from the card"
#: src/views/card/components/ActivityList.tsx:99 #: src/views/card/components/ActivityList.tsx:102
#~ msgid "unassigned <0>{memberName}</0> from the card"
#~ msgstr "unassigned <0>{memberName}</0> from the card"
#: src/views/card/components/ActivityList.tsx:118
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "unassigned themselves from the card" msgstr "unassigned themselves from the card"
@@ -1565,21 +1788,30 @@ msgstr "Unlimited lists"
msgid "Update" msgid "Update"
msgstr "Update" msgstr "Update"
#: src/components/LabelForm.tsx:236 #: src/components/LabelForm.tsx:238
msgid "Update label" msgid "Update label"
msgstr "Update label" msgstr "Update label"
#: src/views/card/components/ActivityList.tsx:54 #: src/views/card/components/ActivityList.tsx:73
msgid "updated a checklist item"
msgstr "updated a checklist item"
#: src/views/card/components/ActivityList.tsx:63
msgid "updated the description" msgid "updated the description"
msgstr "updated the description" msgstr "updated the description"
#: src/views/card/components/ActivityList.tsx:53 #: src/views/card/components/ActivityList.tsx:62
msgid "updated the title" msgid "updated the title"
msgstr "updated the title" msgstr "updated the title"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:90
msgid "updated the title to <0>{0}</0>"
msgstr "updated the title to <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:73 #: src/views/card/components/ActivityList.tsx:73
msgid "updated the title to <0>{toTitle}</0>" #~ msgid "updated the title to <0>{toTitle}</0>"
msgstr "updated the title to <0>{toTitle}</0>" #~ msgstr "updated the title to <0>{toTitle}</0>"
#: src/views/settings/components/CustomURLConfirmation.tsx:52 #: src/views/settings/components/CustomURLConfirmation.tsx:52
msgid "Upgrade" msgid "Upgrade"
@@ -1618,11 +1850,11 @@ msgstr "User is already a member of this workspace"
msgid "Video" msgid "Video"
msgstr "Video" msgstr "Video"
#: src/views/settings/index.tsx:260 #: src/views/settings/index.tsx:262
msgid "View and manage your API keys." msgid "View and manage your API keys."
msgstr "View and manage your API keys." msgstr "View and manage your API keys."
#: src/views/settings/index.tsx:199 #: src/views/settings/index.tsx:201
msgid "View and manage your billing and subscription." msgid "View and manage your billing and subscription."
msgstr "View and manage your billing and subscription." msgstr "View and manage your billing and subscription."
@@ -1678,7 +1910,7 @@ msgstr "When Trello launched in 2011, it blew everyone away with its carefully d
msgid "Why make an open source Trello?" msgid "Why make an open source Trello?"
msgstr "Why make an open source Trello?" msgstr "Why make an open source Trello?"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Workspace" msgid "Workspace"
msgstr "Workspace" msgstr "Workspace"
@@ -1686,7 +1918,7 @@ msgstr "Workspace"
msgid "Workspace deleted" msgid "Workspace deleted"
msgstr "Workspace deleted" msgstr "Workspace deleted"
#: src/views/settings/index.tsx:175 #: src/views/settings/index.tsx:177
msgid "Workspace description" msgid "Workspace description"
msgstr "Workspace description" msgstr "Workspace description"
@@ -1707,7 +1939,7 @@ msgstr "Workspace description updated"
msgid "Workspace members" msgid "Workspace members"
msgstr "Workspace members" msgstr "Workspace members"
#: src/views/settings/index.tsx:156 #: src/views/settings/index.tsx:158
#: src/components/NewWorkspaceForm.tsx:80 #: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name" msgid "Workspace name"
msgstr "Workspace name" msgstr "Workspace name"
@@ -1728,7 +1960,7 @@ msgstr "Workspace name updated"
msgid "Workspace slug updated" msgid "Workspace slug updated"
msgstr "Workspace slug updated" msgstr "Workspace slug updated"
#: src/views/settings/index.tsx:165 #: src/views/settings/index.tsx:167
msgid "Workspace URL" msgid "Workspace URL"
msgstr "Workspace URL" msgstr "Workspace URL"
@@ -1744,6 +1976,10 @@ msgstr "Yearly"
msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits." msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
msgstr "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits." msgstr "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
#: src/views/settings/index.tsx:294
msgid "You are about to change your password."
msgstr "You are about to change your password."
#: src/views/home/components/Faqs.tsx:67 #: src/views/home/components/Faqs.tsx:67
msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!" msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
msgstr "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!" msgstr "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
@@ -1776,15 +2012,19 @@ msgstr "Your boards have been imported."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Your display name has been updated." msgstr "Your display name has been updated."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed."
msgstr "Your password has been changed."
#: src/views/settings/components/Avatar.tsx:27 #: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated." msgid "Your profile image has been updated."
msgstr "Your profile image has been updated." msgstr "Your profile image has been updated."
#: src/views/settings/index.tsx:93 #: src/views/settings/index.tsx:95
msgid "Your Trello account has been disconnected." msgid "Your Trello account has been disconnected."
msgstr "Your Trello account has been disconnected." msgstr "Your Trello account has been disconnected."
#: src/views/settings/index.tsx:242 #: src/views/settings/index.tsx:244
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Your Trello account is connected." msgstr "Your Trello account is connected."

File diff suppressed because one or more lines are too long

View File

@@ -23,12 +23,12 @@ msgstr ", o consulta nuestra"
#. placeholder {0}: card?.title ?? "Card" #. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board" #. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:189 #: src/views/card/index.tsx:213
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:392 #: src/views/board/components/NewCardForm.tsx:432
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} etiquetas" msgstr "{0} etiquetas"
@@ -48,8 +48,8 @@ msgstr "Una aplicación kanban potente y flexible que te ayuda a organizar el tr
msgid "Account deleted" msgid "Account deleted"
msgstr "Cuenta eliminada" msgstr "Cuenta eliminada"
#: src/views/public/board/CardModal.tsx:128 #: src/views/public/board/CardModal.tsx:140
#: src/views/card/index.tsx:256 #: src/views/card/index.tsx:288
msgid "Activity" msgid "Activity"
msgstr "Actividad" msgstr "Actividad"
@@ -66,9 +66,21 @@ msgstr "Añadir una tarjeta"
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Añadir un comentario..." msgstr "Añadir un comentario..."
#: src/components/Editor.tsx:303 #: src/views/card/components/NewChecklistItemForm.tsx:140
msgid "Add description... (type '/' to open commands)" msgid "Add an item..."
msgstr "Añadir descripción... (escribe '/' para abrir comandos)" msgstr "Añadir un elemento..."
#: src/views/card/components/Dropdown.tsx:18
msgid "Add checklist"
msgstr "Añadir lista de verificación"
#: src/components/Editor.tsx:442
msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Añadir descripción... (escribe '/' para abrir comandos o '@' para mencionar)"
#: src/views/card/components/ChecklistItemRow.tsx:172
msgid "Add details..."
msgstr "Añadir detalles..."
#: src/views/card/components/LabelSelector.tsx:110 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:118 #: src/views/card/components/LabelSelector.tsx:118
@@ -80,17 +92,36 @@ msgstr "Añadir etiqueta"
msgid "Add member" msgid "Add member"
msgstr "Añadir miembro" msgstr "Añadir miembro"
#: src/views/card/components/ActivityList.tsx:56 #: src/views/card/components/ActivityList.tsx:69
msgid "added a checklist"
msgstr "añadió una lista de verificación"
#: src/views/card/components/ActivityList.tsx:72
msgid "added a checklist item"
msgstr "añadió un elemento a la lista de verificación"
#: src/views/card/components/ActivityList.tsx:65
msgid "added a label to the card" msgid "added a label to the card"
msgstr "añadió una etiqueta a la tarjeta" msgstr "añadió una etiqueta a la tarjeta"
#: src/views/card/components/ActivityList.tsx:58 #: src/views/card/components/ActivityList.tsx:67
msgid "added a member to the card" msgid "added a member to the card"
msgstr "añadió un miembro a la tarjeta" msgstr "añadió un miembro a la tarjeta"
#: src/views/card/components/ActivityList.tsx:110 #. placeholder {0}: truncate(toTitle)
msgid "added label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:146
msgstr "añadió la etiqueta <0>{label}</0>" msgid "added checklist <0>{0}</0>"
msgstr "añadió la lista de verificación <0>{0}</0>"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170
msgid "added checklist item <0>{0}</0>"
msgstr "añadió el elemento <0>{0}</0> a la lista de verificación"
#. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130
msgid "added label <0>{0}</0>"
msgstr "añadió la etiqueta <0>{0}</0>"
#: src/views/home/components/Pricing.tsx:55 #: src/views/home/components/Pricing.tsx:55
msgid "Admin roles" msgid "Admin roles"
@@ -108,11 +139,15 @@ msgstr "Todos los sistemas operativos"
msgid "Already have an account? <0><1>Sign in</1></0>" msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "¿Ya tienes una cuenta? <0><1>Iniciar sesión</1></0>" msgstr "¿Ya tienes una cuenta? <0><1>Iniciar sesión</1></0>"
#: src/views/settings/index.tsx:100 #: src/views/settings/index.tsx:102
msgid "An error occurred while disconnecting your Trello account." msgid "An error occurred while disconnecting your Trello account."
msgstr "Ocurrió un error al desconectar tu cuenta de Trello." msgstr "Ocurrió un error al desconectar tu cuenta de Trello."
#: src/views/settings/index.tsx:257 #: src/views/settings/components/ChangePasswordConfirmation.tsx:90
msgid "An unexpected error occurred. Please try again later."
msgstr "Ha ocurrido un error inesperado. Por favor, inténtalo de nuevo más tarde."
#: src/views/settings/index.tsx:259
msgid "API keys" msgid "API keys"
msgstr "Claves API" msgstr "Claves API"
@@ -141,11 +176,15 @@ msgstr "¿Estás seguro de que quieres eliminar el espacio de trabajo {0}?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "¿Estás seguro de que quieres eliminar esta tarjeta?" msgstr "¿Estás seguro de que quieres eliminar esta tarjeta?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55
msgid "Are you sure you want to delete this checklist?"
msgstr "¿Estás seguro de que quieres eliminar esta lista de verificación?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:65
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "¿Estás seguro de que quieres eliminar este comentario?" msgstr "¿Estás seguro de que quieres eliminar este comentario?"
#: src/components/DeleteLabelConfirmation.tsx:39 #: src/components/DeleteLabelConfirmation.tsx:41
msgid "Are you sure you want to delete this label?" msgid "Are you sure you want to delete this label?"
msgstr "¿Estás seguro de que quieres eliminar esta etiqueta?" msgstr "¿Estás seguro de que quieres eliminar esta etiqueta?"
@@ -153,9 +192,10 @@ msgstr "¿Estás seguro de que quieres eliminar esta etiqueta?"
msgid "Are you sure you want to delete your account?" msgid "Are you sure you want to delete your account?"
msgstr "¿Estás seguro de que quieres eliminar tu cuenta?" msgstr "¿Estás seguro de que quieres eliminar tu cuenta?"
#: src/views/card/components/ActivityList.tsx:92 #. placeholder {0}: truncate(memberName)
msgid "assigned <0>{memberName}</0> to the card" #: src/views/card/components/ActivityList.tsx:110
msgstr "asignó a <0>{memberName}</0> a la tarjeta" msgid "assigned <0>{0}</0> to the card"
msgstr "asignó <0>{0}</0> a la tarjeta"
#: src/views/boards/components/TemplateBoards.tsx:46 #: src/views/boards/components/TemplateBoards.tsx:46
msgid "Awaiting Customer" msgid "Awaiting Customer"
@@ -169,12 +209,12 @@ msgstr "Pendientes"
msgid "Basic Kanban" msgid "Basic Kanban"
msgstr "Kanban básico" msgstr "Kanban básico"
#: src/views/settings/index.tsx:196 #: src/views/settings/index.tsx:198
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing" msgid "Billing"
msgstr "Facturación" msgstr "Facturación"
#: src/views/settings/index.tsx:206 #: src/views/settings/index.tsx:208
msgid "Billing portal" msgid "Billing portal"
msgstr "Portal de facturación" msgstr "Portal de facturación"
@@ -182,7 +222,7 @@ msgstr "Portal de facturación"
msgid "Blog Post" msgid "Blog Post"
msgstr "Entrada de blog" msgstr "Entrada de blog"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Board" msgid "Board"
msgstr "Tablero" msgstr "Tablero"
@@ -195,7 +235,7 @@ msgid "Board name is required"
msgstr "El nombre del tablero es obligatorio" msgstr "El nombre del tablero es obligatorio"
#: src/views/public/board/index.tsx:143 #: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358 #: src/views/board/index.tsx:357
msgid "Board not found" msgid "Board not found"
msgstr "Tablero no encontrado" msgstr "Tablero no encontrado"
@@ -248,23 +288,32 @@ msgstr "Informe de error"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98
#: src/views/settings/components/DeleteAccountConfirmation.tsx:88 #: src/views/settings/components/DeleteAccountConfirmation.tsx:88
#: src/views/settings/components/CustomURLConfirmation.tsx:50 #: src/views/settings/components/CustomURLConfirmation.tsx:50
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47 #: src/components/DeleteLabelConfirmation.tsx:49
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
#: src/views/card/index.tsx:234 #: src/views/card/index.tsx:259
msgid "Card not found" msgid "Card not found"
msgstr "Tarjeta no encontrada" msgstr "Tarjeta no encontrada"
#: src/views/board/components/NewCardForm.tsx:278 #: src/views/board/components/NewCardForm.tsx:307
msgid "Card title" msgid "Card title"
msgstr "Título de la tarjeta" msgstr "Título de la tarjeta"
#: src/views/settings/index.tsx:188 #: src/views/settings/index.tsx:291
#: src/views/settings/index.tsx:301
#: src/views/settings/components/ChangePasswordConfirmation.tsx:109
#: src/views/settings/components/ChangePasswordConfirmation.tsx:178
msgid "Change Password"
msgstr "Cambiar contraseña"
#: src/views/settings/index.tsx:190
msgid "Change the language of the app." msgid "Change the language of the app."
msgstr "Cambiar el idioma de la aplicación." msgstr "Cambiar el idioma de la aplicación."
@@ -273,6 +322,10 @@ msgstr "Cambiar el idioma de la aplicación."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Revisa tu bandeja de entrada" msgstr "Revisa tu bandeja de entrada"
#: src/views/card/components/NewChecklistForm.tsx:118
msgid "Checklist name"
msgstr "Nombre de la lista de verificación"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:155
msgid "Clear filters" msgid "Clear filters"
msgstr "Borrar filtros" msgstr "Borrar filtros"
@@ -310,11 +363,24 @@ msgstr "Completado"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Control y propiedad completos:" msgstr "Control y propiedad completos:"
#: src/views/card/components/ActivityList.tsx:74
msgid "completed a checklist item"
msgstr "completó un elemento de la lista de verificación"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187
msgid "completed checklist item <0>{0}</0>"
msgstr "completó el elemento <0>{0}</0> de la lista de verificación"
#: src/views/settings/components/CustomURLConfirmation.tsx:42 #: src/views/settings/components/CustomURLConfirmation.tsx:42
msgid "Confirm URL change" msgid "Confirm URL change"
msgstr "Confirmar cambio de URL" msgstr "Confirmar cambio de URL"
#: src/views/settings/index.tsx:233 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password"
msgstr "Confirma tu nueva contraseña"
#: src/views/settings/index.tsx:235
#: src/views/boards/components/ImportBoardsForm.tsx:157 #: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello" msgid "Connect Trello"
msgstr "Conectar Trello" msgstr "Conectar Trello"
@@ -323,7 +389,7 @@ msgstr "Conectar Trello"
msgid "Connect your favorite tools to streamline your workflow." msgid "Connect your favorite tools to streamline your workflow."
msgstr "Conecta tus herramientas favoritas para agilizar tu flujo de trabajo." msgstr "Conecta tus herramientas favoritas para agilizar tu flujo de trabajo."
#: src/views/settings/index.tsx:220 #: src/views/settings/index.tsx:222
msgid "Connect your Trello account to import boards." msgid "Connect your Trello account to import boards."
msgstr "Conecta tu cuenta de Trello para importar tableros." msgstr "Conecta tu cuenta de Trello para importar tableros."
@@ -353,8 +419,8 @@ msgid "Control who can view and edit your boards."
msgstr "Controla quién puede ver y editar tus tableros." msgstr "Controla quién puede ver y editar tus tableros."
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:418 #: src/views/board/components/NewCardForm.tsx:458
#: src/components/LabelForm.tsx:212 #: src/components/LabelForm.tsx:213
msgid "Create another" msgid "Create another"
msgstr "Crear otro" msgstr "Crear otro"
@@ -362,11 +428,15 @@ msgstr "Crear otro"
msgid "Create board" msgid "Create board"
msgstr "Crear tablero" msgstr "Crear tablero"
#: src/views/board/components/NewCardForm.tsx:428 #: src/views/board/components/NewCardForm.tsx:468
msgid "Create card" msgid "Create card"
msgstr "Crear tarjeta" msgstr "Crear tarjeta"
#: src/components/LabelForm.tsx:236 #: src/views/card/components/NewChecklistForm.tsx:134
msgid "Create checklist"
msgstr "Crear lista de verificación"
#: src/components/LabelForm.tsx:238
msgid "Create label" msgid "Create label"
msgstr "Crear etiqueta" msgstr "Crear etiqueta"
@@ -383,11 +453,11 @@ msgid "Create new key"
msgstr "Crear nueva clave" msgstr "Crear nueva clave"
#: src/views/card/components/LabelSelector.tsx:98 #: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:354 #: src/views/board/components/NewCardForm.tsx:394
msgid "Create new label" msgid "Create new label"
msgstr "Crear nueva etiqueta" msgstr "Crear nueva etiqueta"
#: src/views/board/index.tsx:426 #: src/views/board/index.tsx:425
msgid "Create new list" msgid "Create new list"
msgstr "Crear nueva lista" msgstr "Crear nueva lista"
@@ -396,7 +466,7 @@ msgstr "Crear nueva lista"
msgid "Create workspace" msgid "Create workspace"
msgstr "Crear espacio de trabajo" msgstr "Crear espacio de trabajo"
#: src/views/card/components/ActivityList.tsx:52 #: src/views/card/components/ActivityList.tsx:61
msgid "created the card" msgid "created the card"
msgstr "creó la tarjeta" msgstr "creó la tarjeta"
@@ -404,6 +474,10 @@ msgstr "creó la tarjeta"
msgid "Critical" msgid "Critical"
msgstr "Crítico" msgstr "Crítico"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:19
msgid "Current password is required"
msgstr "Se requiere la contraseña actual"
#: src/views/home/components/Pricing.tsx:74 #: src/views/home/components/Pricing.tsx:74
msgid "Custom domain" msgid "Custom domain"
msgstr "Dominio personalizado" msgstr "Dominio personalizado"
@@ -421,14 +495,15 @@ msgid "Dark"
msgstr "Oscuro" msgstr "Oscuro"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226 #: src/components/LabelForm.tsx:228
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:51
msgid "Delete" msgid "Delete"
msgstr "Eliminar" msgstr "Eliminar"
#: src/views/settings/index.tsx:288 #: src/views/settings/index.tsx:309
#: src/views/settings/index.tsx:298 #: src/views/settings/index.tsx:319
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96 #: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account" msgid "Delete account"
msgstr "Eliminar cuenta" msgstr "Eliminar cuenta"
@@ -437,7 +512,7 @@ msgstr "Eliminar cuenta"
msgid "Delete board" msgid "Delete board"
msgstr "Eliminar tablero" msgstr "Eliminar tablero"
#: src/views/card/components/Dropdown.tsx:14 #: src/views/card/components/Dropdown.tsx:25
msgid "Delete card" msgid "Delete card"
msgstr "Eliminar tarjeta" msgstr "Eliminar tarjeta"
@@ -449,17 +524,35 @@ msgstr "Eliminar comentario"
msgid "Delete list" msgid "Delete list"
msgstr "Eliminar lista" msgstr "Eliminar lista"
#: src/views/settings/index.tsx:270 #: src/views/settings/index.tsx:272
#: src/views/settings/index.tsx:281 #: src/views/settings/index.tsx:283
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Eliminar espacio de trabajo" msgstr "Eliminar espacio de trabajo"
#: src/views/card/components/ActivityList.tsx:71
msgid "deleted a checklist"
msgstr "eliminó una lista de verificación"
#: src/views/card/components/ActivityList.tsx:76
msgid "deleted a checklist item"
msgstr "eliminó un elemento de la lista de verificación"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162
msgid "deleted checklist <0>{0}</0>"
msgstr "eliminó la lista de verificación <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205
msgid "deleted checklist item <0>{0}</0>"
msgstr "eliminó el elemento <0>{0}</0> de la lista de verificación"
#: src/views/boards/components/TemplateBoards.tsx:32 #: src/views/boards/components/TemplateBoards.tsx:32
msgid "Design" msgid "Design"
msgstr "Diseño" msgstr "Diseño"
#: src/views/settings/index.tsx:248 #: src/views/settings/index.tsx:250
msgid "Disconnect Trello" msgid "Disconnect Trello"
msgstr "Desconectar Trello" msgstr "Desconectar Trello"
@@ -467,7 +560,7 @@ msgstr "Desconectar Trello"
msgid "Discuss and collaborate on cards." msgid "Discuss and collaborate on cards."
msgstr "Discute y colabora en las tarjetas." msgstr "Discute y colabora en las tarjetas."
#: src/views/settings/index.tsx:149 #: src/views/settings/index.tsx:151
msgid "Display name" msgid "Display name"
msgstr "Nombre visible" msgstr "Nombre visible"
@@ -521,7 +614,7 @@ msgstr "Editar URL del tablero"
msgid "Edit comment" msgid "Edit comment"
msgstr "Editar comentario" msgstr "Editar comentario"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "Edit label" msgid "Edit label"
msgstr "Editar etiqueta" msgstr "Editar etiqueta"
@@ -545,6 +638,14 @@ msgstr "Correo electrónico"
msgid "Enhancement" msgid "Enhancement"
msgstr "Mejora" msgstr "Mejora"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:122
msgid "Enter your current password"
msgstr "Introduce tu contraseña actual"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:111
msgid "Enter your current password and choose a new secure password."
msgstr "Introduce tu contraseña actual y elige una nueva contraseña segura."
#: src/components/AuthForm.tsx:302 #: src/components/AuthForm.tsx:302
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Introduce tu dirección de correo electrónico" msgstr "Introduce tu dirección de correo electrónico"
@@ -553,15 +654,23 @@ msgstr "Introduce tu dirección de correo electrónico"
msgid "Enter your name" msgid "Enter your name"
msgstr "Introduce tu nombre" msgstr "Introduce tu nombre"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:136
msgid "Enter your new password"
msgstr "Introduce tu nueva contraseña"
#: src/components/AuthForm.tsx:315 #: src/components/AuthForm.tsx:315
msgid "Enter your password" msgid "Enter your password"
msgstr "Introduce tu contraseña" msgstr "Introduce tu contraseña"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:89
msgid "Error Changing Password"
msgstr "Error al cambiar la contraseña"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:39 #: src/views/settings/components/DeleteAccountConfirmation.tsx:39
msgid "Error deleting account" msgid "Error deleting account"
msgstr "Error al eliminar la cuenta" msgstr "Error al eliminar la cuenta"
#: src/components/DeleteLabelConfirmation.tsx:22 #: src/components/DeleteLabelConfirmation.tsx:25
msgid "Error deleting label" msgid "Error deleting label"
msgstr "Error al eliminar la etiqueta" msgstr "Error al eliminar la etiqueta"
@@ -569,7 +678,7 @@ msgstr "Error al eliminar la etiqueta"
msgid "Error deleting workspace" msgid "Error deleting workspace"
msgstr "Error al eliminar el espacio de trabajo" msgstr "Error al eliminar el espacio de trabajo"
#: src/views/settings/index.tsx:99 #: src/views/settings/index.tsx:101
msgid "Error disconnecting Trello" msgid "Error disconnecting Trello"
msgstr "Error al desconectar Trello" msgstr "Error al desconectar Trello"
@@ -692,7 +801,7 @@ msgstr "Comenzar"
msgid "Get started by creating a new board" msgid "Get started by creating a new board"
msgstr "Comienza creando un nuevo tablero" msgstr "Comienza creando un nuevo tablero"
#: src/views/board/index.tsx:418 #: src/views/board/index.tsx:417
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Comienza creando una nueva lista" msgstr "Comienza creando una nueva lista"
@@ -849,8 +958,8 @@ msgstr "Kanban reinventado"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Ten en cuenta que esta acción es irreversible." msgstr "Ten en cuenta que esta acción es irreversible."
#: src/views/card/index.tsx:113 #: src/views/card/index.tsx:117
#: src/views/board/components/NewCardForm.tsx:358 #: src/views/board/components/NewCardForm.tsx:398
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:101
msgid "Labels" msgid "Labels"
msgstr "Etiquetas" msgstr "Etiquetas"
@@ -859,7 +968,7 @@ msgstr "Etiquetas"
msgid "Labels & Filters" msgid "Labels & Filters"
msgstr "Etiquetas y filtros" msgstr "Etiquetas y filtros"
#: src/views/settings/index.tsx:185 #: src/views/settings/index.tsx:187
msgid "Language" msgid "Language"
msgstr "Idioma" msgstr "Idioma"
@@ -883,7 +992,7 @@ msgstr "Claro"
msgid "Link copied" msgid "Link copied"
msgstr "Enlace copiado" msgstr "Enlace copiado"
#: src/views/card/index.tsx:105 #: src/views/card/index.tsx:109
msgid "List" msgid "List"
msgstr "Lista" msgstr "Lista"
@@ -911,13 +1020,22 @@ msgstr "Prioridad baja"
msgid "magic link" msgid "magic link"
msgstr "enlace mágico" msgstr "enlace mágico"
#: src/views/card/components/ActivityList.tsx:75
msgid "marked a checklist item as incomplete"
msgstr "marcó un elemento de la lista de verificación como incompleto"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196
msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "marcó el elemento <0>{0}</0> de la lista de verificación como incompleto"
#: src/views/boards/components/TemplateBoards.tsx:17 #: src/views/boards/components/TemplateBoards.tsx:17
msgid "Medium Priority" msgid "Medium Priority"
msgstr "Prioridad media" msgstr "Prioridad media"
#: src/views/members/index.tsx:161 #: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121 #: src/views/card/index.tsx:125
#: src/views/board/components/NewCardForm.tsx:317 #: src/views/board/components/NewCardForm.tsx:357
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:73 #: src/components/SideNavigation.tsx:73
msgid "Members" msgid "Members"
@@ -932,16 +1050,18 @@ msgstr "Miembros | {0}"
msgid "Monthly" msgid "Monthly"
msgstr "Mensual" msgstr "Mensual"
#: src/views/card/components/ActivityList.tsx:81 #. placeholder {0}: truncate(fromList)
msgid "moved the card from <0>{fromList}</0> to<1>{toList}</1>" #. placeholder {1}: truncate(toList)
msgstr "movió la tarjeta de <0>{fromList}</0> a<1>{toList}</1>" #: src/views/card/components/ActivityList.tsx:98
msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "movió la tarjeta de <0>{0}</0> a<1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:55 #: src/views/card/components/ActivityList.tsx:64
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "movió la tarjeta a otra lista" msgstr "movió la tarjeta a otra lista"
#: src/views/boards/components/NewBoardForm.tsx:99 #: src/views/boards/components/NewBoardForm.tsx:99
#: src/components/LabelForm.tsx:134 #: src/components/LabelForm.tsx:135
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
@@ -957,23 +1077,35 @@ msgstr "Nuevo"
msgid "New board" msgid "New board"
msgstr "Nuevo tablero" msgstr "Nuevo tablero"
#: src/views/board/components/NewCardForm.tsx:261 #: src/views/board/components/NewCardForm.tsx:290
msgid "New card" msgid "New card"
msgstr "Nueva tarjeta" msgstr "Nueva tarjeta"
#: src/views/card/components/NewChecklistForm.tsx:102
msgid "New checklist"
msgstr "Nueva lista de verificación"
#: src/views/boards/components/ImportBoardsForm.tsx:322 #: src/views/boards/components/ImportBoardsForm.tsx:322
msgid "New import" msgid "New import"
msgstr "Nueva importación" msgstr "Nueva importación"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "New label" msgid "New label"
msgstr "Nueva etiqueta" msgstr "Nueva etiqueta"
#: src/views/board/index.tsx:395 #: src/views/board/index.tsx:394
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:112
msgid "New list" msgid "New list"
msgstr "Nueva lista" msgstr "Nueva lista"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:23
msgid "New password is required"
msgstr "Se requiere una nueva contraseña"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:31
msgid "New password must be different from current password"
msgstr "La nueva contraseña debe ser diferente de la contraseña actual"
#: src/views/boards/components/TemplateBoards.tsx:43 #: src/views/boards/components/TemplateBoards.tsx:43
msgid "New Ticket" msgid "New Ticket"
msgstr "Nuevo ticket" msgstr "Nuevo ticket"
@@ -1002,7 +1134,7 @@ msgstr "No se encontraron tableros"
msgid "No credit card required" msgid "No credit card required"
msgstr "No se requiere tarjeta de crédito" msgstr "No se requiere tarjeta de crédito"
#: src/views/board/index.tsx:415 #: src/views/board/index.tsx:414
msgid "No lists" msgid "No lists"
msgstr "Sin listas" msgstr "Sin listas"
@@ -1014,11 +1146,11 @@ msgstr "Oferta"
msgid "Onboarding" msgid "Onboarding"
msgstr "Incorporación" msgstr "Incorporación"
#: src/views/settings/index.tsx:291 #: src/views/settings/index.tsx:312
msgid "Once you delete your account, there is no going back. This action cannot be undone." msgid "Once you delete your account, there is no going back. This action cannot be undone."
msgstr "Una vez que elimines tu cuenta, no hay vuelta atrás. Esta acción no se puede deshacer." msgstr "Una vez que elimines tu cuenta, no hay vuelta atrás. Esta acción no se puede deshacer."
#: src/views/settings/index.tsx:273 #: src/views/settings/index.tsx:275
msgid "Once you delete your workspace, there is no going back. This action cannot be undone." msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
msgstr "Una vez que elimines tu espacio de trabajo, no hay vuelta atrás. Esta acción no se puede deshacer." msgstr "Una vez que elimines tu espacio de trabajo, no hay vuelta atrás. Esta acción no se puede deshacer."
@@ -1038,6 +1170,18 @@ msgstr "Sé dueño de tus datos"
msgid "Part-time" msgid "Part-time"
msgstr "Tiempo parcial" msgstr "Tiempo parcial"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:69
msgid "Password Changed"
msgstr "Contraseña cambiada"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:22
msgid "Password must be at least 8 characters"
msgstr "La contraseña debe tener al menos 8 caracteres"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:27
msgid "Passwords do not match"
msgstr "Las contraseñas no coinciden"
#: src/views/home/components/Pricing.tsx:101 #: src/views/home/components/Pricing.tsx:101
msgid "Payment frequency" msgid "Payment frequency"
msgstr "Frecuencia de pago" msgstr "Frecuencia de pago"
@@ -1059,6 +1203,10 @@ msgstr "Proyecto personal"
msgid "Planning" msgid "Planning"
msgstr "Planificación" msgstr "Planificación"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:24
msgid "Please confirm your new password"
msgstr "Por favor, confirma tu nueva contraseña"
#: src/components/AuthForm.tsx:306 #: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Por favor, introduce una dirección de correo electrónico válida" msgstr "Por favor, introduce una dirección de correo electrónico válida"
@@ -1085,24 +1233,30 @@ msgstr "Por favor selecciona un archivo para subir."
#: src/views/settings/components/Avatar.tsx:98 #: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64 #: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:159 #: src/views/card/index.tsx:172
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/MemberSelector.tsx:80 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Comment.tsx:64
#: src/views/card/components/ChecklistNameInput.tsx:46
#: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:135 #: src/views/board/index.tsx:134
#: src/views/board/index.tsx:191 #: src/views/board/index.tsx:190
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78 #: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:145 #: src/views/board/components/NewCardForm.tsx:174
#: src/components/NewWorkspaceForm.tsx:41 #: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23 #: src/components/DeleteLabelConfirmation.tsx:26
msgid "Please try again later, or contact customer support." msgid "Please try again later, or contact customer support."
msgstr "Por favor, inténtalo de nuevo más tarde o contacta con atención al cliente." msgstr "Por favor, inténtalo de nuevo más tarde o contacta con atención al cliente."
@@ -1128,7 +1282,7 @@ msgstr "Privado"
msgid "Profile image updated" msgid "Profile image updated"
msgstr "Imagen de perfil actualizada" msgstr "Imagen de perfil actualizada"
#: src/views/settings/index.tsx:144 #: src/views/settings/index.tsx:146
msgid "Profile picture" msgid "Profile picture"
msgstr "Foto de perfil" msgstr "Foto de perfil"
@@ -1168,17 +1322,32 @@ msgstr "Eliminar"
msgid "Remove member" msgid "Remove member"
msgstr "Eliminar miembro" msgstr "Eliminar miembro"
#: src/views/card/components/ActivityList.tsx:57 #: src/views/card/components/ActivityList.tsx:66
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "eliminó una etiqueta de la tarjeta" msgstr "eliminó una etiqueta de la tarjeta"
#: src/views/card/components/ActivityList.tsx:59 #: src/views/card/components/ActivityList.tsx:68
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "eliminó un miembro de la tarjeta" msgstr "eliminó un miembro de la tarjeta"
#: src/views/card/components/ActivityList.tsx:118 #. placeholder {0}: truncate(label)
msgid "removed label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:138
msgstr "eliminó la etiqueta <0>{label}</0>" msgid "removed label <0>{0}</0>"
msgstr "eliminó la etiqueta <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:70
msgid "renamed a checklist"
msgstr "renombró una lista de verificación"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154
msgid "renamed checklist <0>{0}</0>"
msgstr "renombró la lista de verificación <0>{0}</0>"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178
msgid "renamed checklist item to <0>{0}</0>"
msgstr "renombró el elemento de la lista de verificación a <0>{0}</0>"
#: src/views/boards/components/TemplateBoards.tsx:76 #: src/views/boards/components/TemplateBoards.tsx:76
msgid "Research" msgid "Research"
@@ -1241,7 +1410,7 @@ msgstr "Autoalojamiento"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Autoalojamiento con Github" msgstr "Autoalojamiento con Github"
#: src/views/card/components/ActivityList.tsx:89 #: src/views/card/components/ActivityList.tsx:107
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "se autoasignó la tarjeta" msgstr "se autoasignó la tarjeta"
@@ -1253,13 +1422,13 @@ msgstr "Enviar comentarios"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/settings/index.tsx:138 #: src/views/settings/index.tsx:140
#: src/components/SideNavigation.tsx:78 #: src/components/SideNavigation.tsx:78
msgid "Settings" msgid "Settings"
msgstr "Configuración" msgstr "Configuración"
#. placeholder {0}: workspace.name ?? "Workspace" #. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:134 #: src/views/settings/index.tsx:136
msgid "Settings | {0}" msgid "Settings | {0}"
msgstr "Configuración | {0}" msgstr "Configuración | {0}"
@@ -1338,6 +1507,10 @@ msgstr "Términos de servicio"
msgid "Thank you for your feedback!" msgid "Thank you for your feedback!"
msgstr "¡Gracias por tus comentarios!" msgstr "¡Gracias por tus comentarios!"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:84
msgid "The current password you entered is incorrect."
msgstr "La contraseña actual que has introducido es incorrecta."
#: src/views/home/components/Faqs.tsx:33 #: src/views/home/components/Faqs.tsx:33
msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall." msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
msgstr "La principal diferencia entre Kan y Trello es que Kan es de código abierto, permitiendo a cualquiera ver, modificar y contribuir a nuestro código. Nuestra oferta en la nube también ofrece funciones sin restricciones para uso individual, mientras que Trello bloquea características básicas como el número de tableros que puedes crear detrás de un muro de pago." msgstr "La principal diferencia entre Kan y Trello es que Kan es de código abierto, permitiendo a cualquiera ver, modificar y contribuir a nuestro código. Nuestra oferta en la nube también ofrece funciones sin restricciones para uso individual, mientras que Trello bloquea características básicas como el número de tableros que puedes crear detrás de un muro de pago."
@@ -1360,8 +1533,9 @@ msgid "They won't be able to access this workspace."
msgstr "No podrán acceder a este espacio de trabajo." msgstr "No podrán acceder a este espacio de trabajo."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42 #: src/components/DeleteLabelConfirmation.tsx:44
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Esta acción no se puede deshacer." msgstr "Esta acción no se puede deshacer."
@@ -1398,7 +1572,7 @@ msgstr "Alternar menú"
msgid "Track all card changes with detailed activity history." msgid "Track all card changes with detailed activity history."
msgstr "Rastrea todos los cambios en las tarjetas con un historial de actividad detallado." msgstr "Rastrea todos los cambios en las tarjetas con un historial de actividad detallado."
#: src/views/settings/index.tsx:92 #: src/views/settings/index.tsx:94
msgid "Trello disconnected" msgid "Trello disconnected"
msgstr "Trello desconectado" msgstr "Trello desconectado"
@@ -1410,14 +1584,22 @@ msgstr "Importaciones de Trello"
msgid "Triaging" msgid "Triaging"
msgstr "Clasificación" msgstr "Clasificación"
#: src/views/card/components/NewChecklistItemForm.tsx:88
msgid "Unable to add checklist item"
msgstr "No se puede añadir el elemento a la lista de verificación"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:30
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "No se puede añadir el comentario" msgstr "No se puede añadir el comentario"
#: src/views/board/components/NewCardForm.tsx:142 #: src/views/board/components/NewCardForm.tsx:171
msgid "Unable to create card" msgid "Unable to create card"
msgstr "No se puede crear la tarjeta" msgstr "No se puede crear la tarjeta"
#: src/views/card/components/NewChecklistForm.tsx:69
msgid "Unable to create checklist"
msgstr "No se puede crear la lista de verificación"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:77
msgid "Unable to create list" msgid "Unable to create list"
msgstr "No se puede crear la lista" msgstr "No se puede crear la lista"
@@ -1430,6 +1612,14 @@ msgstr "No se puede crear el espacio de trabajo"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "No se puede eliminar la tarjeta" msgstr "No se puede eliminar la tarjeta"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36
msgid "Unable to delete checklist"
msgstr "No se puede eliminar la lista de verificación"
#: src/views/card/components/ChecklistItemRow.tsx:87
msgid "Unable to delete checklist item"
msgstr "No se puede eliminar el elemento de la lista de verificación"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:44
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "No se puede eliminar el comentario" msgstr "No se puede eliminar el comentario"
@@ -1450,11 +1640,19 @@ msgstr "No se puede actualizar la URL del tablero"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "No se puede actualizar la visibilidad del tablero" msgstr "No se puede actualizar la visibilidad del tablero"
#: src/views/card/index.tsx:158 #: src/views/card/index.tsx:171
#: src/views/board/index.tsx:190 #: src/views/board/index.tsx:189
msgid "Unable to update card" msgid "Unable to update card"
msgstr "No se puede actualizar la tarjeta" msgstr "No se puede actualizar la tarjeta"
#: src/views/card/components/ChecklistNameInput.tsx:45
msgid "Unable to update checklist"
msgstr "No se puede actualizar la lista de verificación"
#: src/views/card/components/ChecklistItemRow.tsx:59
msgid "Unable to update checklist item"
msgstr "No se puede actualizar el elemento de la lista de verificación"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "No se puede actualizar el comentario" msgstr "No se puede actualizar el comentario"
@@ -1464,7 +1662,7 @@ msgid "Unable to update labels"
msgstr "No se pueden actualizar las etiquetas" msgstr "No se pueden actualizar las etiquetas"
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:134 #: src/views/board/index.tsx:133
msgid "Unable to update list" msgid "Unable to update list"
msgstr "No se puede actualizar la lista" msgstr "No se puede actualizar la lista"
@@ -1472,11 +1670,12 @@ msgstr "No se puede actualizar la lista"
msgid "Unable to update members" msgid "Unable to update members"
msgstr "No se pueden actualizar los miembros" msgstr "No se pueden actualizar los miembros"
#: src/views/card/components/ActivityList.tsx:102 #. placeholder {0}: truncate(memberName)
msgid "unassigned <0>{memberName}</0> from the card" #: src/views/card/components/ActivityList.tsx:121
msgstr "desasignó a <0>{memberName}</0> de la tarjeta" msgid "unassigned <0>{0}</0> from the card"
msgstr "desasignó <0>{0}</0> de la tarjeta"
#: src/views/card/components/ActivityList.tsx:99 #: src/views/card/components/ActivityList.tsx:118
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "se desasignó de la tarjeta" msgstr "se desasignó de la tarjeta"
@@ -1512,21 +1711,26 @@ msgstr "Listas ilimitadas"
msgid "Update" msgid "Update"
msgstr "Actualizar" msgstr "Actualizar"
#: src/components/LabelForm.tsx:236 #: src/components/LabelForm.tsx:238
msgid "Update label" msgid "Update label"
msgstr "Actualizar etiqueta" msgstr "Actualizar etiqueta"
#: src/views/card/components/ActivityList.tsx:54 #: src/views/card/components/ActivityList.tsx:73
msgid "updated a checklist item"
msgstr "actualizó un elemento de la lista de verificación"
#: src/views/card/components/ActivityList.tsx:63
msgid "updated the description" msgid "updated the description"
msgstr "actualizó la descripción" msgstr "actualizó la descripción"
#: src/views/card/components/ActivityList.tsx:53 #: src/views/card/components/ActivityList.tsx:62
msgid "updated the title" msgid "updated the title"
msgstr "actualizó el título" msgstr "actualizó el título"
#: src/views/card/components/ActivityList.tsx:73 #. placeholder {0}: truncate(toTitle)
msgid "updated the title to <0>{toTitle}</0>" #: src/views/card/components/ActivityList.tsx:90
msgstr "actualizó el título a <0>{toTitle}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "actualizó el título a <0>{0}</0>"
#: src/views/settings/components/CustomURLConfirmation.tsx:52 #: src/views/settings/components/CustomURLConfirmation.tsx:52
msgid "Upgrade" msgid "Upgrade"
@@ -1565,11 +1769,11 @@ msgstr "El usuario ya es miembro de este espacio de trabajo"
msgid "Video" msgid "Video"
msgstr "Video" msgstr "Video"
#: src/views/settings/index.tsx:260 #: src/views/settings/index.tsx:262
msgid "View and manage your API keys." msgid "View and manage your API keys."
msgstr "Ver y gestionar tus claves API." msgstr "Ver y gestionar tus claves API."
#: src/views/settings/index.tsx:199 #: src/views/settings/index.tsx:201
msgid "View and manage your billing and subscription." msgid "View and manage your billing and subscription."
msgstr "Ver y gestionar tu facturación y suscripción." msgstr "Ver y gestionar tu facturación y suscripción."
@@ -1621,7 +1825,7 @@ msgstr "Cuando Trello se lanzó en 2011, impresionó a todos con su simplicidad
msgid "Why make an open source Trello?" msgid "Why make an open source Trello?"
msgstr "¿Por qué crear un Trello de código abierto?" msgstr "¿Por qué crear un Trello de código abierto?"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Workspace" msgid "Workspace"
msgstr "Espacio de trabajo" msgstr "Espacio de trabajo"
@@ -1629,7 +1833,7 @@ msgstr "Espacio de trabajo"
msgid "Workspace deleted" msgid "Workspace deleted"
msgstr "Espacio de trabajo eliminado" msgstr "Espacio de trabajo eliminado"
#: src/views/settings/index.tsx:175 #: src/views/settings/index.tsx:177
msgid "Workspace description" msgid "Workspace description"
msgstr "Descripción del espacio de trabajo" msgstr "Descripción del espacio de trabajo"
@@ -1650,7 +1854,7 @@ msgstr "Descripción del espacio de trabajo actualizada"
msgid "Workspace members" msgid "Workspace members"
msgstr "Miembros del espacio de trabajo" msgstr "Miembros del espacio de trabajo"
#: src/views/settings/index.tsx:156 #: src/views/settings/index.tsx:158
#: src/components/NewWorkspaceForm.tsx:80 #: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name" msgid "Workspace name"
msgstr "Nombre del espacio de trabajo" msgstr "Nombre del espacio de trabajo"
@@ -1671,7 +1875,7 @@ msgstr "Nombre del espacio de trabajo actualizado"
msgid "Workspace slug updated" msgid "Workspace slug updated"
msgstr "Slug del espacio de trabajo actualizado" msgstr "Slug del espacio de trabajo actualizado"
#: src/views/settings/index.tsx:165 #: src/views/settings/index.tsx:167
msgid "Workspace URL" msgid "Workspace URL"
msgstr "URL del espacio de trabajo" msgstr "URL del espacio de trabajo"
@@ -1687,6 +1891,10 @@ msgstr "Anual"
msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits." msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
msgstr "Sí, ofrecemos un plan gratuito para siempre para uso individual. Sin restricciones, sin muros de pago, sin límites." msgstr "Sí, ofrecemos un plan gratuito para siempre para uso individual. Sin restricciones, sin muros de pago, sin límites."
#: src/views/settings/index.tsx:294
msgid "You are about to change your password."
msgstr "Estás a punto de cambiar tu contraseña."
#: src/views/home/components/Faqs.tsx:67 #: src/views/home/components/Faqs.tsx:67
msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!" msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
msgstr "Puedes obtener una URL personalizada para tu espacio de trabajo, como <0>kan.bn/kan</0>, yendo a la <1>configuración de tu espacio de trabajo</1> y comprando una suscripción pro. ¡Todas las suscripciones ayudan a financiar el desarrollo del proyecto!" msgstr "Puedes obtener una URL personalizada para tu espacio de trabajo, como <0>kan.bn/kan</0>, yendo a la <1>configuración de tu espacio de trabajo</1> y comprando una suscripción pro. ¡Todas las suscripciones ayudan a financiar el desarrollo del proyecto!"
@@ -1719,15 +1927,19 @@ msgstr "Tus tableros han sido importados."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Tu nombre de visualización ha sido actualizado." msgstr "Tu nombre de visualización ha sido actualizado."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed."
msgstr "Tu contraseña ha sido cambiada."
#: src/views/settings/components/Avatar.tsx:27 #: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated." msgid "Your profile image has been updated."
msgstr "Tu imagen de perfil ha sido actualizada." msgstr "Tu imagen de perfil ha sido actualizada."
#: src/views/settings/index.tsx:93 #: src/views/settings/index.tsx:95
msgid "Your Trello account has been disconnected." msgid "Your Trello account has been disconnected."
msgstr "Tu cuenta de Trello ha sido desconectada." msgstr "Tu cuenta de Trello ha sido desconectada."
#: src/views/settings/index.tsx:242 #: src/views/settings/index.tsx:244
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Tu cuenta de Trello está conectada." msgstr "Tu cuenta de Trello está conectada."

File diff suppressed because one or more lines are too long

View File

@@ -23,12 +23,12 @@ msgstr ", ou consultez notre"
#. placeholder {0}: card?.title ?? "Card" #. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board" #. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:189 #: src/views/card/index.tsx:213
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:392 #: src/views/board/components/NewCardForm.tsx:432
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} étiquettes" msgstr "{0} étiquettes"
@@ -48,8 +48,8 @@ msgstr "Une application kanban puissante et flexible qui vous aide à organiser
msgid "Account deleted" msgid "Account deleted"
msgstr "Compte supprimé" msgstr "Compte supprimé"
#: src/views/public/board/CardModal.tsx:128 #: src/views/public/board/CardModal.tsx:140
#: src/views/card/index.tsx:256 #: src/views/card/index.tsx:288
msgid "Activity" msgid "Activity"
msgstr "Activité" msgstr "Activité"
@@ -66,9 +66,21 @@ msgstr "Ajouter une carte"
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Ajouter un commentaire..." msgstr "Ajouter un commentaire..."
#: src/components/Editor.tsx:303 #: src/views/card/components/NewChecklistItemForm.tsx:140
msgid "Add description... (type '/' to open commands)" msgid "Add an item..."
msgstr "Ajouter une description... (tapez '/' pour ouvrir les commandes)" msgstr "Ajouter un élément..."
#: src/views/card/components/Dropdown.tsx:18
msgid "Add checklist"
msgstr "Ajouter une checklist"
#: src/components/Editor.tsx:442
msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Ajouter une description... (tapez '/' pour ouvrir les commandes ou '@' pour mentionner)"
#: src/views/card/components/ChecklistItemRow.tsx:172
msgid "Add details..."
msgstr "Ajouter des détails..."
#: src/views/card/components/LabelSelector.tsx:110 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:118 #: src/views/card/components/LabelSelector.tsx:118
@@ -80,17 +92,36 @@ msgstr "Ajouter une étiquette"
msgid "Add member" msgid "Add member"
msgstr "Ajouter un membre" msgstr "Ajouter un membre"
#: src/views/card/components/ActivityList.tsx:56 #: src/views/card/components/ActivityList.tsx:69
msgid "added a checklist"
msgstr "a ajouté une checklist"
#: src/views/card/components/ActivityList.tsx:72
msgid "added a checklist item"
msgstr "a ajouté un élément à la checklist"
#: src/views/card/components/ActivityList.tsx:65
msgid "added a label to the card" msgid "added a label to the card"
msgstr "a ajouté une étiquette à la carte" msgstr "a ajouté une étiquette à la carte"
#: src/views/card/components/ActivityList.tsx:58 #: src/views/card/components/ActivityList.tsx:67
msgid "added a member to the card" msgid "added a member to the card"
msgstr "a ajouté un membre à la carte" msgstr "a ajouté un membre à la carte"
#: src/views/card/components/ActivityList.tsx:110 #. placeholder {0}: truncate(toTitle)
msgid "added label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:146
msgstr "a ajouté l'étiquette <0>{label}</0>" msgid "added checklist <0>{0}</0>"
msgstr "a ajouté la checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170
msgid "added checklist item <0>{0}</0>"
msgstr "a ajouté l'élément <0>{0}</0> à la checklist"
#. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130
msgid "added label <0>{0}</0>"
msgstr "a ajouté l'étiquette <0>{0}</0>"
#: src/views/home/components/Pricing.tsx:55 #: src/views/home/components/Pricing.tsx:55
msgid "Admin roles" msgid "Admin roles"
@@ -108,11 +139,15 @@ msgstr "Tous les systèmes opérationnels"
msgid "Already have an account? <0><1>Sign in</1></0>" msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "Vous avez déjà un compte ? <0><1>Connectez-vous</1></0>" msgstr "Vous avez déjà un compte ? <0><1>Connectez-vous</1></0>"
#: src/views/settings/index.tsx:100 #: src/views/settings/index.tsx:102
msgid "An error occurred while disconnecting your Trello account." msgid "An error occurred while disconnecting your Trello account."
msgstr "Une erreur s'est produite lors de la déconnexion de votre compte Trello." msgstr "Une erreur s'est produite lors de la déconnexion de votre compte Trello."
#: src/views/settings/index.tsx:257 #: src/views/settings/components/ChangePasswordConfirmation.tsx:90
msgid "An unexpected error occurred. Please try again later."
msgstr "Une erreur inattendue s'est produite. Veuillez réessayer plus tard."
#: src/views/settings/index.tsx:259
msgid "API keys" msgid "API keys"
msgstr "Clés API" msgstr "Clés API"
@@ -141,11 +176,15 @@ msgstr "Êtes-vous sûr de vouloir supprimer l'espace de travail {0} ?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Êtes-vous sûr de vouloir supprimer cette carte ?" msgstr "Êtes-vous sûr de vouloir supprimer cette carte ?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55
msgid "Are you sure you want to delete this checklist?"
msgstr "Êtes-vous sûr de vouloir supprimer cette checklist ?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:65
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Êtes-vous sûr de vouloir supprimer ce commentaire ?" msgstr "Êtes-vous sûr de vouloir supprimer ce commentaire ?"
#: src/components/DeleteLabelConfirmation.tsx:39 #: src/components/DeleteLabelConfirmation.tsx:41
msgid "Are you sure you want to delete this label?" msgid "Are you sure you want to delete this label?"
msgstr "Êtes-vous sûr de vouloir supprimer cette étiquette ?" msgstr "Êtes-vous sûr de vouloir supprimer cette étiquette ?"
@@ -153,9 +192,10 @@ msgstr "Êtes-vous sûr de vouloir supprimer cette étiquette ?"
msgid "Are you sure you want to delete your account?" msgid "Are you sure you want to delete your account?"
msgstr "Êtes-vous sûr de vouloir supprimer votre compte ?" msgstr "Êtes-vous sûr de vouloir supprimer votre compte ?"
#: src/views/card/components/ActivityList.tsx:92 #. placeholder {0}: truncate(memberName)
msgid "assigned <0>{memberName}</0> to the card" #: src/views/card/components/ActivityList.tsx:110
msgstr "a assigné <0>{memberName}</0> à la carte" msgid "assigned <0>{0}</0> to the card"
msgstr "a assigné <0>{0}</0> à la carte"
#: src/views/boards/components/TemplateBoards.tsx:46 #: src/views/boards/components/TemplateBoards.tsx:46
msgid "Awaiting Customer" msgid "Awaiting Customer"
@@ -169,12 +209,12 @@ msgstr "Backlog"
msgid "Basic Kanban" msgid "Basic Kanban"
msgstr "Kanban basique" msgstr "Kanban basique"
#: src/views/settings/index.tsx:196 #: src/views/settings/index.tsx:198
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing" msgid "Billing"
msgstr "Facturation" msgstr "Facturation"
#: src/views/settings/index.tsx:206 #: src/views/settings/index.tsx:208
msgid "Billing portal" msgid "Billing portal"
msgstr "Portail de facturation" msgstr "Portail de facturation"
@@ -182,7 +222,7 @@ msgstr "Portail de facturation"
msgid "Blog Post" msgid "Blog Post"
msgstr "Article de blog" msgstr "Article de blog"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Board" msgid "Board"
msgstr "Tableau" msgstr "Tableau"
@@ -195,7 +235,7 @@ msgid "Board name is required"
msgstr "Le nom du tableau est requis" msgstr "Le nom du tableau est requis"
#: src/views/public/board/index.tsx:143 #: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358 #: src/views/board/index.tsx:357
msgid "Board not found" msgid "Board not found"
msgstr "Tableau introuvable" msgstr "Tableau introuvable"
@@ -248,23 +288,32 @@ msgstr "Rapport de bug"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98
#: src/views/settings/components/DeleteAccountConfirmation.tsx:88 #: src/views/settings/components/DeleteAccountConfirmation.tsx:88
#: src/views/settings/components/CustomURLConfirmation.tsx:50 #: src/views/settings/components/CustomURLConfirmation.tsx:50
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47 #: src/components/DeleteLabelConfirmation.tsx:49
msgid "Cancel" msgid "Cancel"
msgstr "Annuler" msgstr "Annuler"
#: src/views/card/index.tsx:234 #: src/views/card/index.tsx:259
msgid "Card not found" msgid "Card not found"
msgstr "Carte introuvable" msgstr "Carte introuvable"
#: src/views/board/components/NewCardForm.tsx:278 #: src/views/board/components/NewCardForm.tsx:307
msgid "Card title" msgid "Card title"
msgstr "Titre de la carte" msgstr "Titre de la carte"
#: src/views/settings/index.tsx:188 #: src/views/settings/index.tsx:291
#: src/views/settings/index.tsx:301
#: src/views/settings/components/ChangePasswordConfirmation.tsx:109
#: src/views/settings/components/ChangePasswordConfirmation.tsx:178
msgid "Change Password"
msgstr "Modifier le mot de passe"
#: src/views/settings/index.tsx:190
msgid "Change the language of the app." msgid "Change the language of the app."
msgstr "Changer la langue de l'application." msgstr "Changer la langue de l'application."
@@ -273,6 +322,10 @@ msgstr "Changer la langue de l'application."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Vérifiez votre boîte de réception" msgstr "Vérifiez votre boîte de réception"
#: src/views/card/components/NewChecklistForm.tsx:118
msgid "Checklist name"
msgstr "Nom de la checklist"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:155
msgid "Clear filters" msgid "Clear filters"
msgstr "Effacer les filtres" msgstr "Effacer les filtres"
@@ -310,11 +363,24 @@ msgstr "Terminé"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Contrôle et propriété complets :" msgstr "Contrôle et propriété complets :"
#: src/views/card/components/ActivityList.tsx:74
msgid "completed a checklist item"
msgstr "a terminé un élément de la checklist"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187
msgid "completed checklist item <0>{0}</0>"
msgstr "a terminé l'élément <0>{0}</0> de la checklist"
#: src/views/settings/components/CustomURLConfirmation.tsx:42 #: src/views/settings/components/CustomURLConfirmation.tsx:42
msgid "Confirm URL change" msgid "Confirm URL change"
msgstr "Confirmer le changement d'URL" msgstr "Confirmer le changement d'URL"
#: src/views/settings/index.tsx:233 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password"
msgstr "Confirmez votre nouveau mot de passe"
#: src/views/settings/index.tsx:235
#: src/views/boards/components/ImportBoardsForm.tsx:157 #: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello" msgid "Connect Trello"
msgstr "Connecter Trello" msgstr "Connecter Trello"
@@ -323,7 +389,7 @@ msgstr "Connecter Trello"
msgid "Connect your favorite tools to streamline your workflow." msgid "Connect your favorite tools to streamline your workflow."
msgstr "Connectez vos outils favoris pour simplifier votre flux de travail." msgstr "Connectez vos outils favoris pour simplifier votre flux de travail."
#: src/views/settings/index.tsx:220 #: src/views/settings/index.tsx:222
msgid "Connect your Trello account to import boards." msgid "Connect your Trello account to import boards."
msgstr "Connectez votre compte Trello pour importer des tableaux." msgstr "Connectez votre compte Trello pour importer des tableaux."
@@ -353,8 +419,8 @@ msgid "Control who can view and edit your boards."
msgstr "Contrôlez qui peut voir et modifier vos tableaux." msgstr "Contrôlez qui peut voir et modifier vos tableaux."
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:418 #: src/views/board/components/NewCardForm.tsx:458
#: src/components/LabelForm.tsx:212 #: src/components/LabelForm.tsx:213
msgid "Create another" msgid "Create another"
msgstr "Créer un autre" msgstr "Créer un autre"
@@ -362,11 +428,15 @@ msgstr "Créer un autre"
msgid "Create board" msgid "Create board"
msgstr "Créer un tableau" msgstr "Créer un tableau"
#: src/views/board/components/NewCardForm.tsx:428 #: src/views/board/components/NewCardForm.tsx:468
msgid "Create card" msgid "Create card"
msgstr "Créer une carte" msgstr "Créer une carte"
#: src/components/LabelForm.tsx:236 #: src/views/card/components/NewChecklistForm.tsx:134
msgid "Create checklist"
msgstr "Créer une checklist"
#: src/components/LabelForm.tsx:238
msgid "Create label" msgid "Create label"
msgstr "Créer une étiquette" msgstr "Créer une étiquette"
@@ -383,11 +453,11 @@ msgid "Create new key"
msgstr "Créer une nouvelle clé" msgstr "Créer une nouvelle clé"
#: src/views/card/components/LabelSelector.tsx:98 #: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:354 #: src/views/board/components/NewCardForm.tsx:394
msgid "Create new label" msgid "Create new label"
msgstr "Créer une nouvelle étiquette" msgstr "Créer une nouvelle étiquette"
#: src/views/board/index.tsx:426 #: src/views/board/index.tsx:425
msgid "Create new list" msgid "Create new list"
msgstr "Créer une nouvelle liste" msgstr "Créer une nouvelle liste"
@@ -396,7 +466,7 @@ msgstr "Créer une nouvelle liste"
msgid "Create workspace" msgid "Create workspace"
msgstr "Créer un espace de travail" msgstr "Créer un espace de travail"
#: src/views/card/components/ActivityList.tsx:52 #: src/views/card/components/ActivityList.tsx:61
msgid "created the card" msgid "created the card"
msgstr "a créé la carte" msgstr "a créé la carte"
@@ -404,6 +474,10 @@ msgstr "a créé la carte"
msgid "Critical" msgid "Critical"
msgstr "Critique" msgstr "Critique"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:19
msgid "Current password is required"
msgstr "Le mot de passe actuel est requis"
#: src/views/home/components/Pricing.tsx:74 #: src/views/home/components/Pricing.tsx:74
msgid "Custom domain" msgid "Custom domain"
msgstr "Domaine personnalisé" msgstr "Domaine personnalisé"
@@ -421,14 +495,15 @@ msgid "Dark"
msgstr "Sombre" msgstr "Sombre"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226 #: src/components/LabelForm.tsx:228
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:51
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
#: src/views/settings/index.tsx:288 #: src/views/settings/index.tsx:309
#: src/views/settings/index.tsx:298 #: src/views/settings/index.tsx:319
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96 #: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account" msgid "Delete account"
msgstr "Supprimer le compte" msgstr "Supprimer le compte"
@@ -437,7 +512,7 @@ msgstr "Supprimer le compte"
msgid "Delete board" msgid "Delete board"
msgstr "Supprimer le tableau" msgstr "Supprimer le tableau"
#: src/views/card/components/Dropdown.tsx:14 #: src/views/card/components/Dropdown.tsx:25
msgid "Delete card" msgid "Delete card"
msgstr "Supprimer la carte" msgstr "Supprimer la carte"
@@ -449,17 +524,35 @@ msgstr "Supprimer le commentaire"
msgid "Delete list" msgid "Delete list"
msgstr "Supprimer la liste" msgstr "Supprimer la liste"
#: src/views/settings/index.tsx:270 #: src/views/settings/index.tsx:272
#: src/views/settings/index.tsx:281 #: src/views/settings/index.tsx:283
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Supprimer l'espace de travail" msgstr "Supprimer l'espace de travail"
#: src/views/card/components/ActivityList.tsx:71
msgid "deleted a checklist"
msgstr "a supprimé une checklist"
#: src/views/card/components/ActivityList.tsx:76
msgid "deleted a checklist item"
msgstr "a supprimé un élément de la checklist"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162
msgid "deleted checklist <0>{0}</0>"
msgstr "a supprimé la checklist <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205
msgid "deleted checklist item <0>{0}</0>"
msgstr "a supprimé l'élément <0>{0}</0> de la checklist"
#: src/views/boards/components/TemplateBoards.tsx:32 #: src/views/boards/components/TemplateBoards.tsx:32
msgid "Design" msgid "Design"
msgstr "Design" msgstr "Design"
#: src/views/settings/index.tsx:248 #: src/views/settings/index.tsx:250
msgid "Disconnect Trello" msgid "Disconnect Trello"
msgstr "Déconnecter Trello" msgstr "Déconnecter Trello"
@@ -467,7 +560,7 @@ msgstr "Déconnecter Trello"
msgid "Discuss and collaborate on cards." msgid "Discuss and collaborate on cards."
msgstr "Discutez et collaborez sur les cartes." msgstr "Discutez et collaborez sur les cartes."
#: src/views/settings/index.tsx:149 #: src/views/settings/index.tsx:151
msgid "Display name" msgid "Display name"
msgstr "Nom d'affichage" msgstr "Nom d'affichage"
@@ -521,7 +614,7 @@ msgstr "Modifier l'URL du tableau"
msgid "Edit comment" msgid "Edit comment"
msgstr "Modifier le commentaire" msgstr "Modifier le commentaire"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "Edit label" msgid "Edit label"
msgstr "Modifier l'étiquette" msgstr "Modifier l'étiquette"
@@ -545,6 +638,14 @@ msgstr "E-mail"
msgid "Enhancement" msgid "Enhancement"
msgstr "Amélioration" msgstr "Amélioration"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:122
msgid "Enter your current password"
msgstr "Saisissez votre mot de passe actuel"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:111
msgid "Enter your current password and choose a new secure password."
msgstr "Saisissez votre mot de passe actuel et choisissez un nouveau mot de passe sécurisé."
#: src/components/AuthForm.tsx:302 #: src/components/AuthForm.tsx:302
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Saisissez votre adresse e-mail" msgstr "Saisissez votre adresse e-mail"
@@ -553,15 +654,23 @@ msgstr "Saisissez votre adresse e-mail"
msgid "Enter your name" msgid "Enter your name"
msgstr "Saisissez votre nom" msgstr "Saisissez votre nom"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:136
msgid "Enter your new password"
msgstr "Saisissez votre nouveau mot de passe"
#: src/components/AuthForm.tsx:315 #: src/components/AuthForm.tsx:315
msgid "Enter your password" msgid "Enter your password"
msgstr "Saisissez votre mot de passe" msgstr "Saisissez votre mot de passe"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:89
msgid "Error Changing Password"
msgstr "Erreur lors du changement de mot de passe"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:39 #: src/views/settings/components/DeleteAccountConfirmation.tsx:39
msgid "Error deleting account" msgid "Error deleting account"
msgstr "Erreur lors de la suppression du compte" msgstr "Erreur lors de la suppression du compte"
#: src/components/DeleteLabelConfirmation.tsx:22 #: src/components/DeleteLabelConfirmation.tsx:25
msgid "Error deleting label" msgid "Error deleting label"
msgstr "Erreur lors de la suppression de l'étiquette" msgstr "Erreur lors de la suppression de l'étiquette"
@@ -569,7 +678,7 @@ msgstr "Erreur lors de la suppression de l'étiquette"
msgid "Error deleting workspace" msgid "Error deleting workspace"
msgstr "Erreur lors de la suppression de l'espace de travail" msgstr "Erreur lors de la suppression de l'espace de travail"
#: src/views/settings/index.tsx:99 #: src/views/settings/index.tsx:101
msgid "Error disconnecting Trello" msgid "Error disconnecting Trello"
msgstr "Erreur lors de la déconnexion de Trello" msgstr "Erreur lors de la déconnexion de Trello"
@@ -692,7 +801,7 @@ msgstr "Commencer"
msgid "Get started by creating a new board" msgid "Get started by creating a new board"
msgstr "Commencez par créer un nouveau tableau" msgstr "Commencez par créer un nouveau tableau"
#: src/views/board/index.tsx:418 #: src/views/board/index.tsx:417
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Commencez par créer une nouvelle liste" msgstr "Commencez par créer une nouvelle liste"
@@ -849,8 +958,8 @@ msgstr "Kanban réinventé"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Gardez à l'esprit que cette action est irréversible." msgstr "Gardez à l'esprit que cette action est irréversible."
#: src/views/card/index.tsx:113 #: src/views/card/index.tsx:117
#: src/views/board/components/NewCardForm.tsx:358 #: src/views/board/components/NewCardForm.tsx:398
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:101
msgid "Labels" msgid "Labels"
msgstr "Étiquettes" msgstr "Étiquettes"
@@ -859,7 +968,7 @@ msgstr "Étiquettes"
msgid "Labels & Filters" msgid "Labels & Filters"
msgstr "Étiquettes & filtres" msgstr "Étiquettes & filtres"
#: src/views/settings/index.tsx:185 #: src/views/settings/index.tsx:187
msgid "Language" msgid "Language"
msgstr "Langue" msgstr "Langue"
@@ -883,7 +992,7 @@ msgstr "Clair"
msgid "Link copied" msgid "Link copied"
msgstr "Lien copié" msgstr "Lien copié"
#: src/views/card/index.tsx:105 #: src/views/card/index.tsx:109
msgid "List" msgid "List"
msgstr "Liste" msgstr "Liste"
@@ -911,13 +1020,22 @@ msgstr "Priorité basse"
msgid "magic link" msgid "magic link"
msgstr "lien magique" msgstr "lien magique"
#: src/views/card/components/ActivityList.tsx:75
msgid "marked a checklist item as incomplete"
msgstr "a marqué un élément de la checklist comme incomplet"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196
msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "a marqué l'élément <0>{0}</0> de la checklist comme incomplet"
#: src/views/boards/components/TemplateBoards.tsx:17 #: src/views/boards/components/TemplateBoards.tsx:17
msgid "Medium Priority" msgid "Medium Priority"
msgstr "Priorité moyenne" msgstr "Priorité moyenne"
#: src/views/members/index.tsx:161 #: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121 #: src/views/card/index.tsx:125
#: src/views/board/components/NewCardForm.tsx:317 #: src/views/board/components/NewCardForm.tsx:357
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:73 #: src/components/SideNavigation.tsx:73
msgid "Members" msgid "Members"
@@ -932,16 +1050,18 @@ msgstr "Membres | {0}"
msgid "Monthly" msgid "Monthly"
msgstr "Mensuel" msgstr "Mensuel"
#: src/views/card/components/ActivityList.tsx:81 #. placeholder {0}: truncate(fromList)
msgid "moved the card from <0>{fromList}</0> to<1>{toList}</1>" #. placeholder {1}: truncate(toList)
msgstr "a déplacé la carte de <0>{fromList}</0> vers<1>{toList}</1>" #: src/views/card/components/ActivityList.tsx:98
msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "a déplacé la carte de <0>{0}</0> vers <1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:55 #: src/views/card/components/ActivityList.tsx:64
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "a déplacé la carte vers une autre liste" msgstr "a déplacé la carte vers une autre liste"
#: src/views/boards/components/NewBoardForm.tsx:99 #: src/views/boards/components/NewBoardForm.tsx:99
#: src/components/LabelForm.tsx:134 #: src/components/LabelForm.tsx:135
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
@@ -957,23 +1077,35 @@ msgstr "Nouveau"
msgid "New board" msgid "New board"
msgstr "Nouveau tableau" msgstr "Nouveau tableau"
#: src/views/board/components/NewCardForm.tsx:261 #: src/views/board/components/NewCardForm.tsx:290
msgid "New card" msgid "New card"
msgstr "Nouvelle carte" msgstr "Nouvelle carte"
#: src/views/card/components/NewChecklistForm.tsx:102
msgid "New checklist"
msgstr "Nouvelle checklist"
#: src/views/boards/components/ImportBoardsForm.tsx:322 #: src/views/boards/components/ImportBoardsForm.tsx:322
msgid "New import" msgid "New import"
msgstr "Nouvel import" msgstr "Nouvel import"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "New label" msgid "New label"
msgstr "Nouvelle étiquette" msgstr "Nouvelle étiquette"
#: src/views/board/index.tsx:395 #: src/views/board/index.tsx:394
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:112
msgid "New list" msgid "New list"
msgstr "Nouvelle liste" msgstr "Nouvelle liste"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:23
msgid "New password is required"
msgstr "Le nouveau mot de passe est requis"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:31
msgid "New password must be different from current password"
msgstr "Le nouveau mot de passe doit être différent du mot de passe actuel"
#: src/views/boards/components/TemplateBoards.tsx:43 #: src/views/boards/components/TemplateBoards.tsx:43
msgid "New Ticket" msgid "New Ticket"
msgstr "Nouveau ticket" msgstr "Nouveau ticket"
@@ -1002,7 +1134,7 @@ msgstr "Aucun tableau trouvé"
msgid "No credit card required" msgid "No credit card required"
msgstr "Aucune carte de crédit requise" msgstr "Aucune carte de crédit requise"
#: src/views/board/index.tsx:415 #: src/views/board/index.tsx:414
msgid "No lists" msgid "No lists"
msgstr "Aucune liste" msgstr "Aucune liste"
@@ -1014,11 +1146,11 @@ msgstr "Offre"
msgid "Onboarding" msgid "Onboarding"
msgstr "Intégration" msgstr "Intégration"
#: src/views/settings/index.tsx:291 #: src/views/settings/index.tsx:312
msgid "Once you delete your account, there is no going back. This action cannot be undone." msgid "Once you delete your account, there is no going back. This action cannot be undone."
msgstr "Une fois que vous supprimez votre compte, il n'y a pas de retour possible. Cette action ne peut pas être annulée." msgstr "Une fois que vous supprimez votre compte, il n'y a pas de retour possible. Cette action ne peut pas être annulée."
#: src/views/settings/index.tsx:273 #: src/views/settings/index.tsx:275
msgid "Once you delete your workspace, there is no going back. This action cannot be undone." msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
msgstr "Une fois que vous supprimez votre espace de travail, il n'y a pas de retour possible. Cette action ne peut pas être annulée." msgstr "Une fois que vous supprimez votre espace de travail, il n'y a pas de retour possible. Cette action ne peut pas être annulée."
@@ -1038,6 +1170,18 @@ msgstr "Maîtrisez vos données"
msgid "Part-time" msgid "Part-time"
msgstr "Temps partiel" msgstr "Temps partiel"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:69
msgid "Password Changed"
msgstr "Mot de passe modifié"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:22
msgid "Password must be at least 8 characters"
msgstr "Le mot de passe doit comporter au moins 8 caractères"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:27
msgid "Passwords do not match"
msgstr "Les mots de passe ne correspondent pas"
#: src/views/home/components/Pricing.tsx:101 #: src/views/home/components/Pricing.tsx:101
msgid "Payment frequency" msgid "Payment frequency"
msgstr "Fréquence de paiement" msgstr "Fréquence de paiement"
@@ -1059,6 +1203,10 @@ msgstr "Projet personnel"
msgid "Planning" msgid "Planning"
msgstr "Planification" msgstr "Planification"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:24
msgid "Please confirm your new password"
msgstr "Veuillez confirmer votre nouveau mot de passe"
#: src/components/AuthForm.tsx:306 #: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Veuillez saisir une adresse e-mail valide" msgstr "Veuillez saisir une adresse e-mail valide"
@@ -1085,24 +1233,30 @@ msgstr "Veuillez sélectionner un fichier à télécharger."
#: src/views/settings/components/Avatar.tsx:98 #: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64 #: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:159 #: src/views/card/index.tsx:172
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/MemberSelector.tsx:80 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Comment.tsx:64
#: src/views/card/components/ChecklistNameInput.tsx:46
#: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:135 #: src/views/board/index.tsx:134
#: src/views/board/index.tsx:191 #: src/views/board/index.tsx:190
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78 #: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:145 #: src/views/board/components/NewCardForm.tsx:174
#: src/components/NewWorkspaceForm.tsx:41 #: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23 #: src/components/DeleteLabelConfirmation.tsx:26
msgid "Please try again later, or contact customer support." msgid "Please try again later, or contact customer support."
msgstr "Veuillez réessayer plus tard ou contacter le service client." msgstr "Veuillez réessayer plus tard ou contacter le service client."
@@ -1128,7 +1282,7 @@ msgstr "Privé"
msgid "Profile image updated" msgid "Profile image updated"
msgstr "Image de profil mise à jour" msgstr "Image de profil mise à jour"
#: src/views/settings/index.tsx:144 #: src/views/settings/index.tsx:146
msgid "Profile picture" msgid "Profile picture"
msgstr "Photo de profil" msgstr "Photo de profil"
@@ -1168,17 +1322,32 @@ msgstr "Supprimer"
msgid "Remove member" msgid "Remove member"
msgstr "Supprimer le membre" msgstr "Supprimer le membre"
#: src/views/card/components/ActivityList.tsx:57 #: src/views/card/components/ActivityList.tsx:66
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "a supprimé une étiquette de la carte" msgstr "a supprimé une étiquette de la carte"
#: src/views/card/components/ActivityList.tsx:59 #: src/views/card/components/ActivityList.tsx:68
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "a retiré un membre de la carte" msgstr "a retiré un membre de la carte"
#: src/views/card/components/ActivityList.tsx:118 #. placeholder {0}: truncate(label)
msgid "removed label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:138
msgstr "a supprimé l'étiquette <0>{label}</0>" msgid "removed label <0>{0}</0>"
msgstr "a supprimé l'étiquette <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:70
msgid "renamed a checklist"
msgstr "a renommé une checklist"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154
msgid "renamed checklist <0>{0}</0>"
msgstr "a renommé la checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178
msgid "renamed checklist item to <0>{0}</0>"
msgstr "a renommé l'élément de la liste de contrôle en <0>{0}</0>"
#: src/views/boards/components/TemplateBoards.tsx:76 #: src/views/boards/components/TemplateBoards.tsx:76
msgid "Research" msgid "Research"
@@ -1241,7 +1410,7 @@ msgstr "Auto-hébergement"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Auto-hébergement avec Github" msgstr "Auto-hébergement avec Github"
#: src/views/card/components/ActivityList.tsx:89 #: src/views/card/components/ActivityList.tsx:107
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "s'est auto-assigné la carte" msgstr "s'est auto-assigné la carte"
@@ -1253,13 +1422,13 @@ msgstr "Envoyer des commentaires"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/settings/index.tsx:138 #: src/views/settings/index.tsx:140
#: src/components/SideNavigation.tsx:78 #: src/components/SideNavigation.tsx:78
msgid "Settings" msgid "Settings"
msgstr "Paramètres" msgstr "Paramètres"
#. placeholder {0}: workspace.name ?? "Workspace" #. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:134 #: src/views/settings/index.tsx:136
msgid "Settings | {0}" msgid "Settings | {0}"
msgstr "Paramètres | {0}" msgstr "Paramètres | {0}"
@@ -1338,6 +1507,10 @@ msgstr "Conditions d'utilisation"
msgid "Thank you for your feedback!" msgid "Thank you for your feedback!"
msgstr "Merci pour vos commentaires !" msgstr "Merci pour vos commentaires !"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:84
msgid "The current password you entered is incorrect."
msgstr "Le mot de passe actuel que vous avez saisi est incorrect."
#: src/views/home/components/Faqs.tsx:33 #: src/views/home/components/Faqs.tsx:33
msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall." msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
msgstr "La principale différence entre Kan et Trello est que Kan est open source, permettant à chacun de consulter, modifier et contribuer à notre code. Notre offre cloud ne comporte également aucune restriction sur les fonctionnalités pour un usage individuel, alors que Trello verrouille des fonctionnalités de base comme le nombre de tableaux que vous pouvez créer derrière un paywall." msgstr "La principale différence entre Kan et Trello est que Kan est open source, permettant à chacun de consulter, modifier et contribuer à notre code. Notre offre cloud ne comporte également aucune restriction sur les fonctionnalités pour un usage individuel, alors que Trello verrouille des fonctionnalités de base comme le nombre de tableaux que vous pouvez créer derrière un paywall."
@@ -1360,8 +1533,9 @@ msgid "They won't be able to access this workspace."
msgstr "Ils ne pourront plus accéder à cet espace de travail." msgstr "Ils ne pourront plus accéder à cet espace de travail."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42 #: src/components/DeleteLabelConfirmation.tsx:44
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Cette action ne peut pas être annulée." msgstr "Cette action ne peut pas être annulée."
@@ -1398,7 +1572,7 @@ msgstr "Basculer le menu"
msgid "Track all card changes with detailed activity history." msgid "Track all card changes with detailed activity history."
msgstr "Suivez tous les changements de cartes avec un historique d'activité détaillé." msgstr "Suivez tous les changements de cartes avec un historique d'activité détaillé."
#: src/views/settings/index.tsx:92 #: src/views/settings/index.tsx:94
msgid "Trello disconnected" msgid "Trello disconnected"
msgstr "Trello déconnecté" msgstr "Trello déconnecté"
@@ -1410,14 +1584,22 @@ msgstr "Importations Trello"
msgid "Triaging" msgid "Triaging"
msgstr "Triage" msgstr "Triage"
#: src/views/card/components/NewChecklistItemForm.tsx:88
msgid "Unable to add checklist item"
msgstr "Impossible d'ajouter l'élément à la liste de contrôle"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:30
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Impossible d'ajouter un commentaire" msgstr "Impossible d'ajouter un commentaire"
#: src/views/board/components/NewCardForm.tsx:142 #: src/views/board/components/NewCardForm.tsx:171
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Impossible de créer la carte" msgstr "Impossible de créer la carte"
#: src/views/card/components/NewChecklistForm.tsx:69
msgid "Unable to create checklist"
msgstr "Impossible de créer la liste de contrôle"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:77
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Impossible de créer une liste" msgstr "Impossible de créer une liste"
@@ -1430,6 +1612,14 @@ msgstr "Impossible de créer l'espace de travail"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Impossible de supprimer la carte" msgstr "Impossible de supprimer la carte"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36
msgid "Unable to delete checklist"
msgstr "Impossible de supprimer la liste de contrôle"
#: src/views/card/components/ChecklistItemRow.tsx:87
msgid "Unable to delete checklist item"
msgstr "Impossible de supprimer l'élément de la liste de contrôle"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:44
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Impossible de supprimer le commentaire" msgstr "Impossible de supprimer le commentaire"
@@ -1450,11 +1640,19 @@ msgstr "Impossible de mettre à jour l'URL du tableau"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Impossible de mettre à jour la visibilité du tableau" msgstr "Impossible de mettre à jour la visibilité du tableau"
#: src/views/card/index.tsx:158 #: src/views/card/index.tsx:171
#: src/views/board/index.tsx:190 #: src/views/board/index.tsx:189
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Impossible de mettre à jour la carte" msgstr "Impossible de mettre à jour la carte"
#: src/views/card/components/ChecklistNameInput.tsx:45
msgid "Unable to update checklist"
msgstr "Impossible de mettre à jour la liste de contrôle"
#: src/views/card/components/ChecklistItemRow.tsx:59
msgid "Unable to update checklist item"
msgstr "Impossible de mettre à jour l'élément de la liste de contrôle"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Impossible de mettre à jour le commentaire" msgstr "Impossible de mettre à jour le commentaire"
@@ -1464,7 +1662,7 @@ msgid "Unable to update labels"
msgstr "Impossible de mettre à jour les étiquettes" msgstr "Impossible de mettre à jour les étiquettes"
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:134 #: src/views/board/index.tsx:133
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Impossible de mettre à jour la liste" msgstr "Impossible de mettre à jour la liste"
@@ -1472,11 +1670,12 @@ msgstr "Impossible de mettre à jour la liste"
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Impossible de mettre à jour les membres" msgstr "Impossible de mettre à jour les membres"
#: src/views/card/components/ActivityList.tsx:102 #. placeholder {0}: truncate(memberName)
msgid "unassigned <0>{memberName}</0> from the card" #: src/views/card/components/ActivityList.tsx:121
msgstr "a retiré <0>{memberName}</0> de la carte" msgid "unassigned <0>{0}</0> from the card"
msgstr "a désassigné <0>{0}</0> de la carte"
#: src/views/card/components/ActivityList.tsx:99 #: src/views/card/components/ActivityList.tsx:118
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "s'est retiré de la carte" msgstr "s'est retiré de la carte"
@@ -1512,21 +1711,26 @@ msgstr "Listes illimitées"
msgid "Update" msgid "Update"
msgstr "Mettre à jour" msgstr "Mettre à jour"
#: src/components/LabelForm.tsx:236 #: src/components/LabelForm.tsx:238
msgid "Update label" msgid "Update label"
msgstr "Mettre à jour l'étiquette" msgstr "Mettre à jour l'étiquette"
#: src/views/card/components/ActivityList.tsx:54 #: src/views/card/components/ActivityList.tsx:73
msgid "updated a checklist item"
msgstr "a mis à jour un élément de la liste de contrôle"
#: src/views/card/components/ActivityList.tsx:63
msgid "updated the description" msgid "updated the description"
msgstr "a mis à jour la description" msgstr "a mis à jour la description"
#: src/views/card/components/ActivityList.tsx:53 #: src/views/card/components/ActivityList.tsx:62
msgid "updated the title" msgid "updated the title"
msgstr "a mis à jour le titre" msgstr "a mis à jour le titre"
#: src/views/card/components/ActivityList.tsx:73 #. placeholder {0}: truncate(toTitle)
msgid "updated the title to <0>{toTitle}</0>" #: src/views/card/components/ActivityList.tsx:90
msgstr "a mis à jour le titre en <0>{toTitle}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "a mis à jour le titre en <0>{0}</0>"
#: src/views/settings/components/CustomURLConfirmation.tsx:52 #: src/views/settings/components/CustomURLConfirmation.tsx:52
msgid "Upgrade" msgid "Upgrade"
@@ -1565,11 +1769,11 @@ msgstr "L'utilisateur est déjà membre de cet espace de travail"
msgid "Video" msgid "Video"
msgstr "Vidéo" msgstr "Vidéo"
#: src/views/settings/index.tsx:260 #: src/views/settings/index.tsx:262
msgid "View and manage your API keys." msgid "View and manage your API keys."
msgstr "Consultez et gérez vos clés API." msgstr "Consultez et gérez vos clés API."
#: src/views/settings/index.tsx:199 #: src/views/settings/index.tsx:201
msgid "View and manage your billing and subscription." msgid "View and manage your billing and subscription."
msgstr "Consultez et gérez votre facturation et votre abonnement." msgstr "Consultez et gérez votre facturation et votre abonnement."
@@ -1621,7 +1825,7 @@ msgstr "Quand Trello a été lancé en 2011, il a impressionné tout le monde pa
msgid "Why make an open source Trello?" msgid "Why make an open source Trello?"
msgstr "Pourquoi créer un Trello open source ?" msgstr "Pourquoi créer un Trello open source ?"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Workspace" msgid "Workspace"
msgstr "Espace de travail" msgstr "Espace de travail"
@@ -1629,7 +1833,7 @@ msgstr "Espace de travail"
msgid "Workspace deleted" msgid "Workspace deleted"
msgstr "Espace de travail supprimé" msgstr "Espace de travail supprimé"
#: src/views/settings/index.tsx:175 #: src/views/settings/index.tsx:177
msgid "Workspace description" msgid "Workspace description"
msgstr "Description de l'espace de travail" msgstr "Description de l'espace de travail"
@@ -1650,7 +1854,7 @@ msgstr "Description de l'espace de travail mise à jour"
msgid "Workspace members" msgid "Workspace members"
msgstr "Membres de l'espace de travail" msgstr "Membres de l'espace de travail"
#: src/views/settings/index.tsx:156 #: src/views/settings/index.tsx:158
#: src/components/NewWorkspaceForm.tsx:80 #: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name" msgid "Workspace name"
msgstr "Nom de l'espace de travail" msgstr "Nom de l'espace de travail"
@@ -1671,7 +1875,7 @@ msgstr "Nom de l'espace de travail mis à jour"
msgid "Workspace slug updated" msgid "Workspace slug updated"
msgstr "Slug de l'espace de travail mis à jour" msgstr "Slug de l'espace de travail mis à jour"
#: src/views/settings/index.tsx:165 #: src/views/settings/index.tsx:167
msgid "Workspace URL" msgid "Workspace URL"
msgstr "URL de l'espace de travail" msgstr "URL de l'espace de travail"
@@ -1687,6 +1891,10 @@ msgstr "Annuel"
msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits." msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
msgstr "Oui, nous proposons un plan gratuit à vie pour un usage individuel. Aucune restriction, aucun paywall, aucune limite." msgstr "Oui, nous proposons un plan gratuit à vie pour un usage individuel. Aucune restriction, aucun paywall, aucune limite."
#: src/views/settings/index.tsx:294
msgid "You are about to change your password."
msgstr "Vous êtes sur le point de modifier votre mot de passe."
#: src/views/home/components/Faqs.tsx:67 #: src/views/home/components/Faqs.tsx:67
msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!" msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
msgstr "Vous pouvez obtenir une URL d'espace de travail personnalisée, comme <0>kan.bn/kan</0>, en accédant à vos <1>paramètres d'espace de travail</1> et en souscrivant à un abonnement pro. Tous les abonnements contribuent à financer le développement du projet !" msgstr "Vous pouvez obtenir une URL d'espace de travail personnalisée, comme <0>kan.bn/kan</0>, en accédant à vos <1>paramètres d'espace de travail</1> et en souscrivant à un abonnement pro. Tous les abonnements contribuent à financer le développement du projet !"
@@ -1719,15 +1927,19 @@ msgstr "Vos tableaux ont été importés."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Votre nom d'affichage a été mis à jour." msgstr "Votre nom d'affichage a été mis à jour."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed."
msgstr "Votre mot de passe a été modifié."
#: src/views/settings/components/Avatar.tsx:27 #: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated." msgid "Your profile image has been updated."
msgstr "Votre image de profil a été mise à jour." msgstr "Votre image de profil a été mise à jour."
#: src/views/settings/index.tsx:93 #: src/views/settings/index.tsx:95
msgid "Your Trello account has been disconnected." msgid "Your Trello account has been disconnected."
msgstr "Votre compte Trello a été déconnecté." msgstr "Votre compte Trello a été déconnecté."
#: src/views/settings/index.tsx:242 #: src/views/settings/index.tsx:244
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Votre compte Trello est connecté." msgstr "Votre compte Trello est connecté."

File diff suppressed because one or more lines are too long

View File

@@ -23,12 +23,12 @@ msgstr ", o consulta i nostri"
#. placeholder {0}: card?.title ?? "Card" #. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board" #. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:189 #: src/views/card/index.tsx:213
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:392 #: src/views/board/components/NewCardForm.tsx:432
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} etichette" msgstr "{0} etichette"
@@ -48,8 +48,8 @@ msgstr "Un'app kanban potente e flessibile che ti aiuta a organizzare il lavoro,
msgid "Account deleted" msgid "Account deleted"
msgstr "Account eliminato" msgstr "Account eliminato"
#: src/views/public/board/CardModal.tsx:128 #: src/views/public/board/CardModal.tsx:140
#: src/views/card/index.tsx:256 #: src/views/card/index.tsx:288
msgid "Activity" msgid "Activity"
msgstr "Attività" msgstr "Attività"
@@ -66,9 +66,21 @@ msgstr "Aggiungi una carta"
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Aggiungi un commento..." msgstr "Aggiungi un commento..."
#: src/components/Editor.tsx:303 #: src/views/card/components/NewChecklistItemForm.tsx:140
msgid "Add description... (type '/' to open commands)" msgid "Add an item..."
msgstr "Aggiungi descrizione... (digita '/' per aprire i comandi)" msgstr "Aggiungi un elemento..."
#: src/views/card/components/Dropdown.tsx:18
msgid "Add checklist"
msgstr "Aggiungi checklist"
#: src/components/Editor.tsx:442
msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Aggiungi descrizione... (digita '/' per aprire i comandi o '@' per menzionare)"
#: src/views/card/components/ChecklistItemRow.tsx:172
msgid "Add details..."
msgstr "Aggiungi dettagli..."
#: src/views/card/components/LabelSelector.tsx:110 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:118 #: src/views/card/components/LabelSelector.tsx:118
@@ -80,17 +92,36 @@ msgstr "Aggiungi etichetta"
msgid "Add member" msgid "Add member"
msgstr "Aggiungi membro" msgstr "Aggiungi membro"
#: src/views/card/components/ActivityList.tsx:56 #: src/views/card/components/ActivityList.tsx:69
msgid "added a checklist"
msgstr "ha aggiunto una checklist"
#: src/views/card/components/ActivityList.tsx:72
msgid "added a checklist item"
msgstr "ha aggiunto un elemento alla checklist"
#: src/views/card/components/ActivityList.tsx:65
msgid "added a label to the card" msgid "added a label to the card"
msgstr "ha aggiunto un'etichetta alla carta" msgstr "ha aggiunto un'etichetta alla carta"
#: src/views/card/components/ActivityList.tsx:58 #: src/views/card/components/ActivityList.tsx:67
msgid "added a member to the card" msgid "added a member to the card"
msgstr "ha aggiunto un membro alla carta" msgstr "ha aggiunto un membro alla carta"
#: src/views/card/components/ActivityList.tsx:110 #. placeholder {0}: truncate(toTitle)
msgid "added label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:146
msgstr "ha aggiunto l'etichetta <0>{label}</0>" msgid "added checklist <0>{0}</0>"
msgstr "ha aggiunto la checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170
msgid "added checklist item <0>{0}</0>"
msgstr "ha aggiunto l'elemento <0>{0}</0> alla checklist"
#. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130
msgid "added label <0>{0}</0>"
msgstr "ha aggiunto l'etichetta <0>{0}</0>"
#: src/views/home/components/Pricing.tsx:55 #: src/views/home/components/Pricing.tsx:55
msgid "Admin roles" msgid "Admin roles"
@@ -108,11 +139,15 @@ msgstr "Tutti i sistemi operativi"
msgid "Already have an account? <0><1>Sign in</1></0>" msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "Hai già un account? <0><1>Accedi</1></0>" msgstr "Hai già un account? <0><1>Accedi</1></0>"
#: src/views/settings/index.tsx:100 #: src/views/settings/index.tsx:102
msgid "An error occurred while disconnecting your Trello account." msgid "An error occurred while disconnecting your Trello account."
msgstr "Si è verificato un errore durante la disconnessione del tuo account Trello." msgstr "Si è verificato un errore durante la disconnessione del tuo account Trello."
#: src/views/settings/index.tsx:257 #: src/views/settings/components/ChangePasswordConfirmation.tsx:90
msgid "An unexpected error occurred. Please try again later."
msgstr "Si è verificato un errore imprevisto. Riprova più tardi."
#: src/views/settings/index.tsx:259
msgid "API keys" msgid "API keys"
msgstr "Chiavi API" msgstr "Chiavi API"
@@ -141,11 +176,15 @@ msgstr "Sei sicuro di voler eliminare lo spazio di lavoro {0}?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Sei sicuro di voler eliminare questa carta?" msgstr "Sei sicuro di voler eliminare questa carta?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55
msgid "Are you sure you want to delete this checklist?"
msgstr "Sei sicuro di voler eliminare questa checklist?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:65
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Sei sicuro di voler eliminare questo commento?" msgstr "Sei sicuro di voler eliminare questo commento?"
#: src/components/DeleteLabelConfirmation.tsx:39 #: src/components/DeleteLabelConfirmation.tsx:41
msgid "Are you sure you want to delete this label?" msgid "Are you sure you want to delete this label?"
msgstr "Sei sicuro di voler eliminare questa etichetta?" msgstr "Sei sicuro di voler eliminare questa etichetta?"
@@ -153,9 +192,10 @@ msgstr "Sei sicuro di voler eliminare questa etichetta?"
msgid "Are you sure you want to delete your account?" msgid "Are you sure you want to delete your account?"
msgstr "Sei sicuro di voler eliminare il tuo account?" msgstr "Sei sicuro di voler eliminare il tuo account?"
#: src/views/card/components/ActivityList.tsx:92 #. placeholder {0}: truncate(memberName)
msgid "assigned <0>{memberName}</0> to the card" #: src/views/card/components/ActivityList.tsx:110
msgstr "ha assegnato <0>{memberName}</0> alla carta" msgid "assigned <0>{0}</0> to the card"
msgstr "ha assegnato <0>{0}</0> alla scheda"
#: src/views/boards/components/TemplateBoards.tsx:46 #: src/views/boards/components/TemplateBoards.tsx:46
msgid "Awaiting Customer" msgid "Awaiting Customer"
@@ -169,12 +209,12 @@ msgstr "Backlog"
msgid "Basic Kanban" msgid "Basic Kanban"
msgstr "Kanban base" msgstr "Kanban base"
#: src/views/settings/index.tsx:196 #: src/views/settings/index.tsx:198
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing" msgid "Billing"
msgstr "Fatturazione" msgstr "Fatturazione"
#: src/views/settings/index.tsx:206 #: src/views/settings/index.tsx:208
msgid "Billing portal" msgid "Billing portal"
msgstr "Portale di fatturazione" msgstr "Portale di fatturazione"
@@ -182,7 +222,7 @@ msgstr "Portale di fatturazione"
msgid "Blog Post" msgid "Blog Post"
msgstr "Post del blog" msgstr "Post del blog"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Board" msgid "Board"
msgstr "Bacheca" msgstr "Bacheca"
@@ -195,7 +235,7 @@ msgid "Board name is required"
msgstr "Il nome della bacheca è obbligatorio" msgstr "Il nome della bacheca è obbligatorio"
#: src/views/public/board/index.tsx:143 #: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358 #: src/views/board/index.tsx:357
msgid "Board not found" msgid "Board not found"
msgstr "Bacheca non trovata" msgstr "Bacheca non trovata"
@@ -248,23 +288,32 @@ msgstr "Segnalazione bug"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98
#: src/views/settings/components/DeleteAccountConfirmation.tsx:88 #: src/views/settings/components/DeleteAccountConfirmation.tsx:88
#: src/views/settings/components/CustomURLConfirmation.tsx:50 #: src/views/settings/components/CustomURLConfirmation.tsx:50
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47 #: src/components/DeleteLabelConfirmation.tsx:49
msgid "Cancel" msgid "Cancel"
msgstr "Annulla" msgstr "Annulla"
#: src/views/card/index.tsx:234 #: src/views/card/index.tsx:259
msgid "Card not found" msgid "Card not found"
msgstr "Carta non trovata" msgstr "Carta non trovata"
#: src/views/board/components/NewCardForm.tsx:278 #: src/views/board/components/NewCardForm.tsx:307
msgid "Card title" msgid "Card title"
msgstr "Titolo della carta" msgstr "Titolo della carta"
#: src/views/settings/index.tsx:188 #: src/views/settings/index.tsx:291
#: src/views/settings/index.tsx:301
#: src/views/settings/components/ChangePasswordConfirmation.tsx:109
#: src/views/settings/components/ChangePasswordConfirmation.tsx:178
msgid "Change Password"
msgstr "Cambia password"
#: src/views/settings/index.tsx:190
msgid "Change the language of the app." msgid "Change the language of the app."
msgstr "Cambia la lingua dell'app." msgstr "Cambia la lingua dell'app."
@@ -273,6 +322,10 @@ msgstr "Cambia la lingua dell'app."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Controlla la tua casella di posta" msgstr "Controlla la tua casella di posta"
#: src/views/card/components/NewChecklistForm.tsx:118
msgid "Checklist name"
msgstr "Nome della checklist"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:155
msgid "Clear filters" msgid "Clear filters"
msgstr "Cancella filtri" msgstr "Cancella filtri"
@@ -310,11 +363,24 @@ msgstr "Completato"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Controllo e proprietà completi:" msgstr "Controllo e proprietà completi:"
#: src/views/card/components/ActivityList.tsx:74
msgid "completed a checklist item"
msgstr "ha completato un elemento della checklist"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187
msgid "completed checklist item <0>{0}</0>"
msgstr "ha completato l'elemento <0>{0}</0> della checklist"
#: src/views/settings/components/CustomURLConfirmation.tsx:42 #: src/views/settings/components/CustomURLConfirmation.tsx:42
msgid "Confirm URL change" msgid "Confirm URL change"
msgstr "Conferma modifica URL" msgstr "Conferma modifica URL"
#: src/views/settings/index.tsx:233 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password"
msgstr "Conferma la tua nuova password"
#: src/views/settings/index.tsx:235
#: src/views/boards/components/ImportBoardsForm.tsx:157 #: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello" msgid "Connect Trello"
msgstr "Connetti Trello" msgstr "Connetti Trello"
@@ -323,7 +389,7 @@ msgstr "Connetti Trello"
msgid "Connect your favorite tools to streamline your workflow." msgid "Connect your favorite tools to streamline your workflow."
msgstr "Connetti i tuoi strumenti preferiti per semplificare il tuo flusso di lavoro." msgstr "Connetti i tuoi strumenti preferiti per semplificare il tuo flusso di lavoro."
#: src/views/settings/index.tsx:220 #: src/views/settings/index.tsx:222
msgid "Connect your Trello account to import boards." msgid "Connect your Trello account to import boards."
msgstr "Connetti il tuo account Trello per importare le bacheche." msgstr "Connetti il tuo account Trello per importare le bacheche."
@@ -353,8 +419,8 @@ msgid "Control who can view and edit your boards."
msgstr "Controlla chi può visualizzare e modificare le tue bacheche." msgstr "Controlla chi può visualizzare e modificare le tue bacheche."
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:418 #: src/views/board/components/NewCardForm.tsx:458
#: src/components/LabelForm.tsx:212 #: src/components/LabelForm.tsx:213
msgid "Create another" msgid "Create another"
msgstr "Crea un altro" msgstr "Crea un altro"
@@ -362,11 +428,15 @@ msgstr "Crea un altro"
msgid "Create board" msgid "Create board"
msgstr "Crea bacheca" msgstr "Crea bacheca"
#: src/views/board/components/NewCardForm.tsx:428 #: src/views/board/components/NewCardForm.tsx:468
msgid "Create card" msgid "Create card"
msgstr "Crea carta" msgstr "Crea carta"
#: src/components/LabelForm.tsx:236 #: src/views/card/components/NewChecklistForm.tsx:134
msgid "Create checklist"
msgstr "Crea checklist"
#: src/components/LabelForm.tsx:238
msgid "Create label" msgid "Create label"
msgstr "Crea etichetta" msgstr "Crea etichetta"
@@ -383,11 +453,11 @@ msgid "Create new key"
msgstr "Crea nuova chiave" msgstr "Crea nuova chiave"
#: src/views/card/components/LabelSelector.tsx:98 #: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:354 #: src/views/board/components/NewCardForm.tsx:394
msgid "Create new label" msgid "Create new label"
msgstr "Crea nuova etichetta" msgstr "Crea nuova etichetta"
#: src/views/board/index.tsx:426 #: src/views/board/index.tsx:425
msgid "Create new list" msgid "Create new list"
msgstr "Crea nuova lista" msgstr "Crea nuova lista"
@@ -396,7 +466,7 @@ msgstr "Crea nuova lista"
msgid "Create workspace" msgid "Create workspace"
msgstr "Crea spazio di lavoro" msgstr "Crea spazio di lavoro"
#: src/views/card/components/ActivityList.tsx:52 #: src/views/card/components/ActivityList.tsx:61
msgid "created the card" msgid "created the card"
msgstr "ha creato la carta" msgstr "ha creato la carta"
@@ -404,6 +474,10 @@ msgstr "ha creato la carta"
msgid "Critical" msgid "Critical"
msgstr "Critico" msgstr "Critico"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:19
msgid "Current password is required"
msgstr "La password attuale è obbligatoria"
#: src/views/home/components/Pricing.tsx:74 #: src/views/home/components/Pricing.tsx:74
msgid "Custom domain" msgid "Custom domain"
msgstr "Dominio personalizzato" msgstr "Dominio personalizzato"
@@ -421,14 +495,15 @@ msgid "Dark"
msgstr "Scuro" msgstr "Scuro"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226 #: src/components/LabelForm.tsx:228
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:51
msgid "Delete" msgid "Delete"
msgstr "Elimina" msgstr "Elimina"
#: src/views/settings/index.tsx:288 #: src/views/settings/index.tsx:309
#: src/views/settings/index.tsx:298 #: src/views/settings/index.tsx:319
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96 #: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account" msgid "Delete account"
msgstr "Elimina account" msgstr "Elimina account"
@@ -437,7 +512,7 @@ msgstr "Elimina account"
msgid "Delete board" msgid "Delete board"
msgstr "Elimina bacheca" msgstr "Elimina bacheca"
#: src/views/card/components/Dropdown.tsx:14 #: src/views/card/components/Dropdown.tsx:25
msgid "Delete card" msgid "Delete card"
msgstr "Elimina carta" msgstr "Elimina carta"
@@ -449,17 +524,35 @@ msgstr "Elimina commento"
msgid "Delete list" msgid "Delete list"
msgstr "Elimina lista" msgstr "Elimina lista"
#: src/views/settings/index.tsx:270 #: src/views/settings/index.tsx:272
#: src/views/settings/index.tsx:281 #: src/views/settings/index.tsx:283
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Elimina spazio di lavoro" msgstr "Elimina spazio di lavoro"
#: src/views/card/components/ActivityList.tsx:71
msgid "deleted a checklist"
msgstr "ha eliminato una checklist"
#: src/views/card/components/ActivityList.tsx:76
msgid "deleted a checklist item"
msgstr "ha eliminato un elemento della checklist"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162
msgid "deleted checklist <0>{0}</0>"
msgstr "ha eliminato la checklist <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205
msgid "deleted checklist item <0>{0}</0>"
msgstr "ha eliminato l'elemento <0>{0}</0> della checklist"
#: src/views/boards/components/TemplateBoards.tsx:32 #: src/views/boards/components/TemplateBoards.tsx:32
msgid "Design" msgid "Design"
msgstr "Design" msgstr "Design"
#: src/views/settings/index.tsx:248 #: src/views/settings/index.tsx:250
msgid "Disconnect Trello" msgid "Disconnect Trello"
msgstr "Disconnetti Trello" msgstr "Disconnetti Trello"
@@ -467,7 +560,7 @@ msgstr "Disconnetti Trello"
msgid "Discuss and collaborate on cards." msgid "Discuss and collaborate on cards."
msgstr "Discuti e collabora sulle schede." msgstr "Discuti e collabora sulle schede."
#: src/views/settings/index.tsx:149 #: src/views/settings/index.tsx:151
msgid "Display name" msgid "Display name"
msgstr "Nome visualizzato" msgstr "Nome visualizzato"
@@ -521,7 +614,7 @@ msgstr "Modifica URL della bacheca"
msgid "Edit comment" msgid "Edit comment"
msgstr "Modifica commento" msgstr "Modifica commento"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "Edit label" msgid "Edit label"
msgstr "Modifica etichetta" msgstr "Modifica etichetta"
@@ -545,6 +638,14 @@ msgstr "Email"
msgid "Enhancement" msgid "Enhancement"
msgstr "Miglioramento" msgstr "Miglioramento"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:122
msgid "Enter your current password"
msgstr "Inserisci la tua password attuale"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:111
msgid "Enter your current password and choose a new secure password."
msgstr "Inserisci la tua password attuale e scegli una nuova password sicura."
#: src/components/AuthForm.tsx:302 #: src/components/AuthForm.tsx:302
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Inserisci il tuo indirizzo email" msgstr "Inserisci il tuo indirizzo email"
@@ -553,15 +654,23 @@ msgstr "Inserisci il tuo indirizzo email"
msgid "Enter your name" msgid "Enter your name"
msgstr "Inserisci il tuo nome" msgstr "Inserisci il tuo nome"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:136
msgid "Enter your new password"
msgstr "Inserisci la tua nuova password"
#: src/components/AuthForm.tsx:315 #: src/components/AuthForm.tsx:315
msgid "Enter your password" msgid "Enter your password"
msgstr "Inserisci la tua password" msgstr "Inserisci la tua password"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:89
msgid "Error Changing Password"
msgstr "Errore durante il cambio della password"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:39 #: src/views/settings/components/DeleteAccountConfirmation.tsx:39
msgid "Error deleting account" msgid "Error deleting account"
msgstr "Errore durante l'eliminazione dell'account" msgstr "Errore durante l'eliminazione dell'account"
#: src/components/DeleteLabelConfirmation.tsx:22 #: src/components/DeleteLabelConfirmation.tsx:25
msgid "Error deleting label" msgid "Error deleting label"
msgstr "Errore durante l'eliminazione dell'etichetta" msgstr "Errore durante l'eliminazione dell'etichetta"
@@ -569,7 +678,7 @@ msgstr "Errore durante l'eliminazione dell'etichetta"
msgid "Error deleting workspace" msgid "Error deleting workspace"
msgstr "Errore durante l'eliminazione dell'area di lavoro" msgstr "Errore durante l'eliminazione dell'area di lavoro"
#: src/views/settings/index.tsx:99 #: src/views/settings/index.tsx:101
msgid "Error disconnecting Trello" msgid "Error disconnecting Trello"
msgstr "Errore durante la disconnessione da Trello" msgstr "Errore durante la disconnessione da Trello"
@@ -692,7 +801,7 @@ msgstr "Inizia ora"
msgid "Get started by creating a new board" msgid "Get started by creating a new board"
msgstr "Inizia creando una nuova bacheca" msgstr "Inizia creando una nuova bacheca"
#: src/views/board/index.tsx:418 #: src/views/board/index.tsx:417
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Inizia creando una nuova lista" msgstr "Inizia creando una nuova lista"
@@ -849,8 +958,8 @@ msgstr "Kanban reinventato"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Tieni presente che questa azione è irreversibile." msgstr "Tieni presente che questa azione è irreversibile."
#: src/views/card/index.tsx:113 #: src/views/card/index.tsx:117
#: src/views/board/components/NewCardForm.tsx:358 #: src/views/board/components/NewCardForm.tsx:398
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:101
msgid "Labels" msgid "Labels"
msgstr "Etichette" msgstr "Etichette"
@@ -859,7 +968,7 @@ msgstr "Etichette"
msgid "Labels & Filters" msgid "Labels & Filters"
msgstr "Etichette & Filtri" msgstr "Etichette & Filtri"
#: src/views/settings/index.tsx:185 #: src/views/settings/index.tsx:187
msgid "Language" msgid "Language"
msgstr "Lingua" msgstr "Lingua"
@@ -883,7 +992,7 @@ msgstr "Chiaro"
msgid "Link copied" msgid "Link copied"
msgstr "Link copiato" msgstr "Link copiato"
#: src/views/card/index.tsx:105 #: src/views/card/index.tsx:109
msgid "List" msgid "List"
msgstr "Lista" msgstr "Lista"
@@ -911,13 +1020,22 @@ msgstr "Bassa priorità"
msgid "magic link" msgid "magic link"
msgstr "link magico" msgstr "link magico"
#: src/views/card/components/ActivityList.tsx:75
msgid "marked a checklist item as incomplete"
msgstr "ha segnato un elemento della checklist come incompleto"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196
msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "ha segnato l'elemento <0>{0}</0> della checklist come incompleto"
#: src/views/boards/components/TemplateBoards.tsx:17 #: src/views/boards/components/TemplateBoards.tsx:17
msgid "Medium Priority" msgid "Medium Priority"
msgstr "Media priorità" msgstr "Media priorità"
#: src/views/members/index.tsx:161 #: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121 #: src/views/card/index.tsx:125
#: src/views/board/components/NewCardForm.tsx:317 #: src/views/board/components/NewCardForm.tsx:357
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:73 #: src/components/SideNavigation.tsx:73
msgid "Members" msgid "Members"
@@ -932,16 +1050,18 @@ msgstr "Membri | {0}"
msgid "Monthly" msgid "Monthly"
msgstr "Mensile" msgstr "Mensile"
#: src/views/card/components/ActivityList.tsx:81 #. placeholder {0}: truncate(fromList)
msgid "moved the card from <0>{fromList}</0> to<1>{toList}</1>" #. placeholder {1}: truncate(toList)
msgstr "ha spostato la scheda da <0>{fromList}</0> a<1>{toList}</1>" #: src/views/card/components/ActivityList.tsx:98
msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "ha spostato la scheda da <0>{0}</0> a<1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:55 #: src/views/card/components/ActivityList.tsx:64
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "ha spostato la scheda in un'altra lista" msgstr "ha spostato la scheda in un'altra lista"
#: src/views/boards/components/NewBoardForm.tsx:99 #: src/views/boards/components/NewBoardForm.tsx:99
#: src/components/LabelForm.tsx:134 #: src/components/LabelForm.tsx:135
msgid "Name" msgid "Name"
msgstr "Nome" msgstr "Nome"
@@ -957,23 +1077,35 @@ msgstr "Nuovo"
msgid "New board" msgid "New board"
msgstr "Nuova bacheca" msgstr "Nuova bacheca"
#: src/views/board/components/NewCardForm.tsx:261 #: src/views/board/components/NewCardForm.tsx:290
msgid "New card" msgid "New card"
msgstr "Nuova carta" msgstr "Nuova carta"
#: src/views/card/components/NewChecklistForm.tsx:102
msgid "New checklist"
msgstr "Nuova checklist"
#: src/views/boards/components/ImportBoardsForm.tsx:322 #: src/views/boards/components/ImportBoardsForm.tsx:322
msgid "New import" msgid "New import"
msgstr "Nuova importazione" msgstr "Nuova importazione"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "New label" msgid "New label"
msgstr "Nuova etichetta" msgstr "Nuova etichetta"
#: src/views/board/index.tsx:395 #: src/views/board/index.tsx:394
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:112
msgid "New list" msgid "New list"
msgstr "Nuova lista" msgstr "Nuova lista"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:23
msgid "New password is required"
msgstr "La nuova password è obbligatoria"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:31
msgid "New password must be different from current password"
msgstr "La nuova password deve essere diversa dalla password attuale"
#: src/views/boards/components/TemplateBoards.tsx:43 #: src/views/boards/components/TemplateBoards.tsx:43
msgid "New Ticket" msgid "New Ticket"
msgstr "Nuovo ticket" msgstr "Nuovo ticket"
@@ -1002,7 +1134,7 @@ msgstr "Nessuna bacheca trovata"
msgid "No credit card required" msgid "No credit card required"
msgstr "Nessuna carta di credito richiesta" msgstr "Nessuna carta di credito richiesta"
#: src/views/board/index.tsx:415 #: src/views/board/index.tsx:414
msgid "No lists" msgid "No lists"
msgstr "Nessuna lista" msgstr "Nessuna lista"
@@ -1014,11 +1146,11 @@ msgstr "Offerta"
msgid "Onboarding" msgid "Onboarding"
msgstr "Inserimento" msgstr "Inserimento"
#: src/views/settings/index.tsx:291 #: src/views/settings/index.tsx:312
msgid "Once you delete your account, there is no going back. This action cannot be undone." msgid "Once you delete your account, there is no going back. This action cannot be undone."
msgstr "Una volta eliminato il tuo account, non si può tornare indietro. Questa azione non può essere annullata." msgstr "Una volta eliminato il tuo account, non si può tornare indietro. Questa azione non può essere annullata."
#: src/views/settings/index.tsx:273 #: src/views/settings/index.tsx:275
msgid "Once you delete your workspace, there is no going back. This action cannot be undone." msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
msgstr "Una volta eliminata l'area di lavoro, non si può tornare indietro. Questa azione non può essere annullata." msgstr "Una volta eliminata l'area di lavoro, non si può tornare indietro. Questa azione non può essere annullata."
@@ -1038,6 +1170,18 @@ msgstr "Possiedi i tuoi dati"
msgid "Part-time" msgid "Part-time"
msgstr "Part-time" msgstr "Part-time"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:69
msgid "Password Changed"
msgstr "Password modificata"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:22
msgid "Password must be at least 8 characters"
msgstr "La password deve contenere almeno 8 caratteri"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:27
msgid "Passwords do not match"
msgstr "Le password non corrispondono"
#: src/views/home/components/Pricing.tsx:101 #: src/views/home/components/Pricing.tsx:101
msgid "Payment frequency" msgid "Payment frequency"
msgstr "Frequenza di pagamento" msgstr "Frequenza di pagamento"
@@ -1059,6 +1203,10 @@ msgstr "Progetto personale"
msgid "Planning" msgid "Planning"
msgstr "Pianificazione" msgstr "Pianificazione"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:24
msgid "Please confirm your new password"
msgstr "Conferma la tua nuova password"
#: src/components/AuthForm.tsx:306 #: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Inserisci un indirizzo email valido" msgstr "Inserisci un indirizzo email valido"
@@ -1085,24 +1233,30 @@ msgstr "Seleziona un file da caricare."
#: src/views/settings/components/Avatar.tsx:98 #: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64 #: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:159 #: src/views/card/index.tsx:172
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/MemberSelector.tsx:80 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Comment.tsx:64
#: src/views/card/components/ChecklistNameInput.tsx:46
#: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:135 #: src/views/board/index.tsx:134
#: src/views/board/index.tsx:191 #: src/views/board/index.tsx:190
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78 #: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:145 #: src/views/board/components/NewCardForm.tsx:174
#: src/components/NewWorkspaceForm.tsx:41 #: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23 #: src/components/DeleteLabelConfirmation.tsx:26
msgid "Please try again later, or contact customer support." msgid "Please try again later, or contact customer support."
msgstr "Riprova più tardi o contatta l'assistenza clienti." msgstr "Riprova più tardi o contatta l'assistenza clienti."
@@ -1128,7 +1282,7 @@ msgstr "Privato"
msgid "Profile image updated" msgid "Profile image updated"
msgstr "Immagine del profilo aggiornata" msgstr "Immagine del profilo aggiornata"
#: src/views/settings/index.tsx:144 #: src/views/settings/index.tsx:146
msgid "Profile picture" msgid "Profile picture"
msgstr "Immagine del profilo" msgstr "Immagine del profilo"
@@ -1168,17 +1322,32 @@ msgstr "Rimuovi"
msgid "Remove member" msgid "Remove member"
msgstr "Rimuovi membro" msgstr "Rimuovi membro"
#: src/views/card/components/ActivityList.tsx:57 #: src/views/card/components/ActivityList.tsx:66
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "ha rimosso un'etichetta dalla scheda" msgstr "ha rimosso un'etichetta dalla scheda"
#: src/views/card/components/ActivityList.tsx:59 #: src/views/card/components/ActivityList.tsx:68
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "ha rimosso un membro dalla scheda" msgstr "ha rimosso un membro dalla scheda"
#: src/views/card/components/ActivityList.tsx:118 #. placeholder {0}: truncate(label)
msgid "removed label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:138
msgstr "ha rimosso l'etichetta <0>{label}</0>" msgid "removed label <0>{0}</0>"
msgstr "ha rimosso l'etichetta <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:70
msgid "renamed a checklist"
msgstr "ha rinominato una checklist"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154
msgid "renamed checklist <0>{0}</0>"
msgstr "ha rinominato la checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178
msgid "renamed checklist item to <0>{0}</0>"
msgstr "ha rinominato l'elemento della checklist in <0>{0}</0>"
#: src/views/boards/components/TemplateBoards.tsx:76 #: src/views/boards/components/TemplateBoards.tsx:76
msgid "Research" msgid "Research"
@@ -1241,7 +1410,7 @@ msgstr "Self Host"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Self host con Github" msgstr "Self host con Github"
#: src/views/card/components/ActivityList.tsx:89 #: src/views/card/components/ActivityList.tsx:107
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "si è auto-assegnato la scheda" msgstr "si è auto-assegnato la scheda"
@@ -1253,13 +1422,13 @@ msgstr "Invia feedback"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/settings/index.tsx:138 #: src/views/settings/index.tsx:140
#: src/components/SideNavigation.tsx:78 #: src/components/SideNavigation.tsx:78
msgid "Settings" msgid "Settings"
msgstr "Impostazioni" msgstr "Impostazioni"
#. placeholder {0}: workspace.name ?? "Workspace" #. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:134 #: src/views/settings/index.tsx:136
msgid "Settings | {0}" msgid "Settings | {0}"
msgstr "Impostazioni | {0}" msgstr "Impostazioni | {0}"
@@ -1338,6 +1507,10 @@ msgstr "Termini di servizio"
msgid "Thank you for your feedback!" msgid "Thank you for your feedback!"
msgstr "Grazie per il tuo feedback!" msgstr "Grazie per il tuo feedback!"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:84
msgid "The current password you entered is incorrect."
msgstr "La password attuale inserita non è corretta."
#: src/views/home/components/Faqs.tsx:33 #: src/views/home/components/Faqs.tsx:33
msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall." msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
msgstr "La principale differenza tra Kan e Trello è che Kan è open source, permettendo a chiunque di visualizzare, modificare e contribuire al nostro codice. La nostra offerta cloud non impone inoltre alcuna restrizione sulle funzionalità per uso individuale, mentre Trello blocca funzionalità di base come il numero di bacheche che puoi creare dietro un paywall." msgstr "La principale differenza tra Kan e Trello è che Kan è open source, permettendo a chiunque di visualizzare, modificare e contribuire al nostro codice. La nostra offerta cloud non impone inoltre alcuna restrizione sulle funzionalità per uso individuale, mentre Trello blocca funzionalità di base come il numero di bacheche che puoi creare dietro un paywall."
@@ -1360,8 +1533,9 @@ msgid "They won't be able to access this workspace."
msgstr "Non potranno accedere a questo spazio di lavoro." msgstr "Non potranno accedere a questo spazio di lavoro."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42 #: src/components/DeleteLabelConfirmation.tsx:44
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Questa azione non può essere annullata." msgstr "Questa azione non può essere annullata."
@@ -1398,7 +1572,7 @@ msgstr "Attiva/disattiva menu"
msgid "Track all card changes with detailed activity history." msgid "Track all card changes with detailed activity history."
msgstr "Tieni traccia di tutte le modifiche alle schede con una cronologia dettagliata delle attività." msgstr "Tieni traccia di tutte le modifiche alle schede con una cronologia dettagliata delle attività."
#: src/views/settings/index.tsx:92 #: src/views/settings/index.tsx:94
msgid "Trello disconnected" msgid "Trello disconnected"
msgstr "Trello disconnesso" msgstr "Trello disconnesso"
@@ -1410,14 +1584,22 @@ msgstr "Importazioni da Trello"
msgid "Triaging" msgid "Triaging"
msgstr "Smistamento" msgstr "Smistamento"
#: src/views/card/components/NewChecklistItemForm.tsx:88
msgid "Unable to add checklist item"
msgstr "Impossibile aggiungere l'elemento della checklist"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:30
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Impossibile aggiungere il commento" msgstr "Impossibile aggiungere il commento"
#: src/views/board/components/NewCardForm.tsx:142 #: src/views/board/components/NewCardForm.tsx:171
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Impossibile creare la scheda" msgstr "Impossibile creare la scheda"
#: src/views/card/components/NewChecklistForm.tsx:69
msgid "Unable to create checklist"
msgstr "Impossibile creare la checklist"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:77
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Impossibile creare la lista" msgstr "Impossibile creare la lista"
@@ -1430,6 +1612,14 @@ msgstr "Impossibile creare lo spazio di lavoro"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Impossibile eliminare la scheda" msgstr "Impossibile eliminare la scheda"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36
msgid "Unable to delete checklist"
msgstr "Impossibile eliminare la checklist"
#: src/views/card/components/ChecklistItemRow.tsx:87
msgid "Unable to delete checklist item"
msgstr "Impossibile eliminare l'elemento della checklist"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:44
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Impossibile eliminare il commento" msgstr "Impossibile eliminare il commento"
@@ -1450,11 +1640,19 @@ msgstr "Impossibile aggiornare l'URL della bacheca"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Impossibile aggiornare la visibilità della bacheca" msgstr "Impossibile aggiornare la visibilità della bacheca"
#: src/views/card/index.tsx:158 #: src/views/card/index.tsx:171
#: src/views/board/index.tsx:190 #: src/views/board/index.tsx:189
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Impossibile aggiornare la scheda" msgstr "Impossibile aggiornare la scheda"
#: src/views/card/components/ChecklistNameInput.tsx:45
msgid "Unable to update checklist"
msgstr "Impossibile aggiornare la checklist"
#: src/views/card/components/ChecklistItemRow.tsx:59
msgid "Unable to update checklist item"
msgstr "Impossibile aggiornare l'elemento della checklist"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Impossibile aggiornare il commento" msgstr "Impossibile aggiornare il commento"
@@ -1464,7 +1662,7 @@ msgid "Unable to update labels"
msgstr "Impossibile aggiornare le etichette" msgstr "Impossibile aggiornare le etichette"
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:134 #: src/views/board/index.tsx:133
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Impossibile aggiornare la lista" msgstr "Impossibile aggiornare la lista"
@@ -1472,11 +1670,12 @@ msgstr "Impossibile aggiornare la lista"
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Impossibile aggiornare i membri" msgstr "Impossibile aggiornare i membri"
#: src/views/card/components/ActivityList.tsx:102 #. placeholder {0}: truncate(memberName)
msgid "unassigned <0>{memberName}</0> from the card" #: src/views/card/components/ActivityList.tsx:121
msgstr "ha rimosso l'assegnazione di <0>{memberName}</0> dalla scheda" msgid "unassigned <0>{0}</0> from the card"
msgstr "ha rimosso l'assegnazione di <0>{0}</0> dalla scheda"
#: src/views/card/components/ActivityList.tsx:99 #: src/views/card/components/ActivityList.tsx:118
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "si è rimosso dall'assegnazione della scheda" msgstr "si è rimosso dall'assegnazione della scheda"
@@ -1512,21 +1711,26 @@ msgstr "Liste illimitate"
msgid "Update" msgid "Update"
msgstr "Aggiorna" msgstr "Aggiorna"
#: src/components/LabelForm.tsx:236 #: src/components/LabelForm.tsx:238
msgid "Update label" msgid "Update label"
msgstr "Aggiorna etichetta" msgstr "Aggiorna etichetta"
#: src/views/card/components/ActivityList.tsx:54 #: src/views/card/components/ActivityList.tsx:73
msgid "updated a checklist item"
msgstr "ha aggiornato un elemento della checklist"
#: src/views/card/components/ActivityList.tsx:63
msgid "updated the description" msgid "updated the description"
msgstr "ha aggiornato la descrizione" msgstr "ha aggiornato la descrizione"
#: src/views/card/components/ActivityList.tsx:53 #: src/views/card/components/ActivityList.tsx:62
msgid "updated the title" msgid "updated the title"
msgstr "ha aggiornato il titolo" msgstr "ha aggiornato il titolo"
#: src/views/card/components/ActivityList.tsx:73 #. placeholder {0}: truncate(toTitle)
msgid "updated the title to <0>{toTitle}</0>" #: src/views/card/components/ActivityList.tsx:90
msgstr "ha aggiornato il titolo in <0>{toTitle}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "ha aggiornato il titolo in <0>{0}</0>"
#: src/views/settings/components/CustomURLConfirmation.tsx:52 #: src/views/settings/components/CustomURLConfirmation.tsx:52
msgid "Upgrade" msgid "Upgrade"
@@ -1565,11 +1769,11 @@ msgstr "L'utente è già membro di questo spazio di lavoro"
msgid "Video" msgid "Video"
msgstr "Video" msgstr "Video"
#: src/views/settings/index.tsx:260 #: src/views/settings/index.tsx:262
msgid "View and manage your API keys." msgid "View and manage your API keys."
msgstr "Visualizza e gestisci le tue chiavi API." msgstr "Visualizza e gestisci le tue chiavi API."
#: src/views/settings/index.tsx:199 #: src/views/settings/index.tsx:201
msgid "View and manage your billing and subscription." msgid "View and manage your billing and subscription."
msgstr "Visualizza e gestisci la tua fatturazione e abbonamento." msgstr "Visualizza e gestisci la tua fatturazione e abbonamento."
@@ -1621,7 +1825,7 @@ msgstr "Quando Trello fu lanciato nel 2011, stupì tutti con la sua semplicità
msgid "Why make an open source Trello?" msgid "Why make an open source Trello?"
msgstr "Perché creare un Trello open source?" msgstr "Perché creare un Trello open source?"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Workspace" msgid "Workspace"
msgstr "Spazio di lavoro" msgstr "Spazio di lavoro"
@@ -1629,7 +1833,7 @@ msgstr "Spazio di lavoro"
msgid "Workspace deleted" msgid "Workspace deleted"
msgstr "Spazio di lavoro eliminato" msgstr "Spazio di lavoro eliminato"
#: src/views/settings/index.tsx:175 #: src/views/settings/index.tsx:177
msgid "Workspace description" msgid "Workspace description"
msgstr "Descrizione dello spazio di lavoro" msgstr "Descrizione dello spazio di lavoro"
@@ -1650,7 +1854,7 @@ msgstr "Descrizione dell'area di lavoro aggiornata"
msgid "Workspace members" msgid "Workspace members"
msgstr "Membri del workspace" msgstr "Membri del workspace"
#: src/views/settings/index.tsx:156 #: src/views/settings/index.tsx:158
#: src/components/NewWorkspaceForm.tsx:80 #: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name" msgid "Workspace name"
msgstr "Nome dello spazio di lavoro" msgstr "Nome dello spazio di lavoro"
@@ -1671,7 +1875,7 @@ msgstr "Nome dello spazio di lavoro aggiornato"
msgid "Workspace slug updated" msgid "Workspace slug updated"
msgstr "Slug dell'area di lavoro aggiornato" msgstr "Slug dell'area di lavoro aggiornato"
#: src/views/settings/index.tsx:165 #: src/views/settings/index.tsx:167
msgid "Workspace URL" msgid "Workspace URL"
msgstr "URL dello spazio di lavoro" msgstr "URL dello spazio di lavoro"
@@ -1687,6 +1891,10 @@ msgstr "Annuale"
msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits." msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
msgstr "Sì, offriamo un piano gratuito per sempre per uso individuale. Nessuna restrizione, nessun paywall, nessun limite." msgstr "Sì, offriamo un piano gratuito per sempre per uso individuale. Nessuna restrizione, nessun paywall, nessun limite."
#: src/views/settings/index.tsx:294
msgid "You are about to change your password."
msgstr "Stai per cambiare la tua password."
#: src/views/home/components/Faqs.tsx:67 #: src/views/home/components/Faqs.tsx:67
msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!" msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
msgstr "Puoi ottenere un URL personalizzato per il tuo workspace, come <0>kan.bn/kan</0>, accedendo alle tue <1>impostazioni del workspace</1> e acquistando un abbonamento pro. Tutti gli abbonamenti contribuiscono a finanziare lo sviluppo del progetto!" msgstr "Puoi ottenere un URL personalizzato per il tuo workspace, come <0>kan.bn/kan</0>, accedendo alle tue <1>impostazioni del workspace</1> e acquistando un abbonamento pro. Tutti gli abbonamenti contribuiscono a finanziare lo sviluppo del progetto!"
@@ -1719,15 +1927,19 @@ msgstr "Le tue bacheche sono state importate."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Il tuo nome visualizzato è stato aggiornato." msgstr "Il tuo nome visualizzato è stato aggiornato."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed."
msgstr "La tua password è stata modificata."
#: src/views/settings/components/Avatar.tsx:27 #: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated." msgid "Your profile image has been updated."
msgstr "La tua immagine del profilo è stata aggiornata." msgstr "La tua immagine del profilo è stata aggiornata."
#: src/views/settings/index.tsx:93 #: src/views/settings/index.tsx:95
msgid "Your Trello account has been disconnected." msgid "Your Trello account has been disconnected."
msgstr "Il tuo account Trello è stato disconnesso." msgstr "Il tuo account Trello è stato disconnesso."
#: src/views/settings/index.tsx:242 #: src/views/settings/index.tsx:244
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Il tuo account Trello è connesso." msgstr "Il tuo account Trello è connesso."

File diff suppressed because one or more lines are too long

View File

@@ -23,12 +23,12 @@ msgstr ", of bekijk onze"
#. placeholder {0}: card?.title ?? "Card" #. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board" #. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:189 #: src/views/card/index.tsx:213
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:392 #: src/views/board/components/NewCardForm.tsx:432
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} labels" msgstr "{0} labels"
@@ -48,8 +48,8 @@ msgstr "Een krachtige, flexibele kanban-app die je helpt werk te organiseren, vo
msgid "Account deleted" msgid "Account deleted"
msgstr "Account verwijderd" msgstr "Account verwijderd"
#: src/views/public/board/CardModal.tsx:128 #: src/views/public/board/CardModal.tsx:140
#: src/views/card/index.tsx:256 #: src/views/card/index.tsx:288
msgid "Activity" msgid "Activity"
msgstr "Activiteit" msgstr "Activiteit"
@@ -66,9 +66,21 @@ msgstr "Voeg een kaart toe"
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Voeg een reactie toe..." msgstr "Voeg een reactie toe..."
#: src/components/Editor.tsx:303 #: src/views/card/components/NewChecklistItemForm.tsx:140
msgid "Add description... (type '/' to open commands)" msgid "Add an item..."
msgstr "Voeg beschrijving toe... (typ '/' om commando's te openen)" msgstr "Voeg een item toe..."
#: src/views/card/components/Dropdown.tsx:18
msgid "Add checklist"
msgstr "Checklist toevoegen"
#: src/components/Editor.tsx:442
msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Beschrijving toevoegen... (typ '/' om commando's te openen of '@' om te vermelden)"
#: src/views/card/components/ChecklistItemRow.tsx:172
msgid "Add details..."
msgstr "Details toevoegen..."
#: src/views/card/components/LabelSelector.tsx:110 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:118 #: src/views/card/components/LabelSelector.tsx:118
@@ -80,17 +92,36 @@ msgstr "Label toevoegen"
msgid "Add member" msgid "Add member"
msgstr "Lid toevoegen" msgstr "Lid toevoegen"
#: src/views/card/components/ActivityList.tsx:56 #: src/views/card/components/ActivityList.tsx:69
msgid "added a checklist"
msgstr "heeft een checklist toegevoegd"
#: src/views/card/components/ActivityList.tsx:72
msgid "added a checklist item"
msgstr "heeft een checklistitem toegevoegd"
#: src/views/card/components/ActivityList.tsx:65
msgid "added a label to the card" msgid "added a label to the card"
msgstr "heeft een label aan de kaart toegevoegd" msgstr "heeft een label aan de kaart toegevoegd"
#: src/views/card/components/ActivityList.tsx:58 #: src/views/card/components/ActivityList.tsx:67
msgid "added a member to the card" msgid "added a member to the card"
msgstr "heeft een lid aan de kaart toegevoegd" msgstr "heeft een lid aan de kaart toegevoegd"
#: src/views/card/components/ActivityList.tsx:110 #. placeholder {0}: truncate(toTitle)
msgid "added label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:146
msgstr "heeft label <0>{label}</0> toegevoegd" msgid "added checklist <0>{0}</0>"
msgstr "heeft checklist <0>{0}</0> toegevoegd"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170
msgid "added checklist item <0>{0}</0>"
msgstr "heeft checklistitem <0>{0}</0> toegevoegd"
#. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130
msgid "added label <0>{0}</0>"
msgstr "heeft label <0>{0}</0> toegevoegd"
#: src/views/home/components/Pricing.tsx:55 #: src/views/home/components/Pricing.tsx:55
msgid "Admin roles" msgid "Admin roles"
@@ -108,11 +139,15 @@ msgstr "Alle systemen operationeel"
msgid "Already have an account? <0><1>Sign in</1></0>" msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "Heb je al een account? <0><1>Log in</1></0>" msgstr "Heb je al een account? <0><1>Log in</1></0>"
#: src/views/settings/index.tsx:100 #: src/views/settings/index.tsx:102
msgid "An error occurred while disconnecting your Trello account." msgid "An error occurred while disconnecting your Trello account."
msgstr "Er is een fout opgetreden bij het verbreken van de verbinding met je Trello-account." msgstr "Er is een fout opgetreden bij het verbreken van de verbinding met je Trello-account."
#: src/views/settings/index.tsx:257 #: src/views/settings/components/ChangePasswordConfirmation.tsx:90
msgid "An unexpected error occurred. Please try again later."
msgstr "Er is een onverwachte fout opgetreden. Probeer het later opnieuw."
#: src/views/settings/index.tsx:259
msgid "API keys" msgid "API keys"
msgstr "API-sleutels" msgstr "API-sleutels"
@@ -141,11 +176,15 @@ msgstr "Weet je zeker dat je de werkruimte {0} wilt verwijderen?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Weet je zeker dat je deze kaart wilt verwijderen?" msgstr "Weet je zeker dat je deze kaart wilt verwijderen?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55
msgid "Are you sure you want to delete this checklist?"
msgstr "Weet je zeker dat je deze checklist wilt verwijderen?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:65
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Weet je zeker dat je deze opmerking wilt verwijderen?" msgstr "Weet je zeker dat je deze opmerking wilt verwijderen?"
#: src/components/DeleteLabelConfirmation.tsx:39 #: src/components/DeleteLabelConfirmation.tsx:41
msgid "Are you sure you want to delete this label?" msgid "Are you sure you want to delete this label?"
msgstr "Weet je zeker dat je dit label wilt verwijderen?" msgstr "Weet je zeker dat je dit label wilt verwijderen?"
@@ -153,9 +192,10 @@ msgstr "Weet je zeker dat je dit label wilt verwijderen?"
msgid "Are you sure you want to delete your account?" msgid "Are you sure you want to delete your account?"
msgstr "Weet je zeker dat je je account wilt verwijderen?" msgstr "Weet je zeker dat je je account wilt verwijderen?"
#: src/views/card/components/ActivityList.tsx:92 #. placeholder {0}: truncate(memberName)
msgid "assigned <0>{memberName}</0> to the card" #: src/views/card/components/ActivityList.tsx:110
msgstr "heeft <0>{memberName}</0> aan de kaart toegewezen" msgid "assigned <0>{0}</0> to the card"
msgstr "heeft <0>{0}</0> aan de kaart toegewezen"
#: src/views/boards/components/TemplateBoards.tsx:46 #: src/views/boards/components/TemplateBoards.tsx:46
msgid "Awaiting Customer" msgid "Awaiting Customer"
@@ -169,12 +209,12 @@ msgstr "Backlog"
msgid "Basic Kanban" msgid "Basic Kanban"
msgstr "Basis kanban" msgstr "Basis kanban"
#: src/views/settings/index.tsx:196 #: src/views/settings/index.tsx:198
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing" msgid "Billing"
msgstr "Facturering" msgstr "Facturering"
#: src/views/settings/index.tsx:206 #: src/views/settings/index.tsx:208
msgid "Billing portal" msgid "Billing portal"
msgstr "Factureringsportaal" msgstr "Factureringsportaal"
@@ -182,7 +222,7 @@ msgstr "Factureringsportaal"
msgid "Blog Post" msgid "Blog Post"
msgstr "Blogbericht" msgstr "Blogbericht"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Board" msgid "Board"
msgstr "Bord" msgstr "Bord"
@@ -195,7 +235,7 @@ msgid "Board name is required"
msgstr "Bordnaam is verplicht" msgstr "Bordnaam is verplicht"
#: src/views/public/board/index.tsx:143 #: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358 #: src/views/board/index.tsx:357
msgid "Board not found" msgid "Board not found"
msgstr "Bord niet gevonden" msgstr "Bord niet gevonden"
@@ -248,23 +288,32 @@ msgstr "Bugrapport"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:98
#: src/views/settings/components/DeleteAccountConfirmation.tsx:88 #: src/views/settings/components/DeleteAccountConfirmation.tsx:88
#: src/views/settings/components/CustomURLConfirmation.tsx:50 #: src/views/settings/components/CustomURLConfirmation.tsx:50
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47 #: src/components/DeleteLabelConfirmation.tsx:49
msgid "Cancel" msgid "Cancel"
msgstr "Annuleren" msgstr "Annuleren"
#: src/views/card/index.tsx:234 #: src/views/card/index.tsx:259
msgid "Card not found" msgid "Card not found"
msgstr "Kaart niet gevonden" msgstr "Kaart niet gevonden"
#: src/views/board/components/NewCardForm.tsx:278 #: src/views/board/components/NewCardForm.tsx:307
msgid "Card title" msgid "Card title"
msgstr "Kaarttitel" msgstr "Kaarttitel"
#: src/views/settings/index.tsx:188 #: src/views/settings/index.tsx:291
#: src/views/settings/index.tsx:301
#: src/views/settings/components/ChangePasswordConfirmation.tsx:109
#: src/views/settings/components/ChangePasswordConfirmation.tsx:178
msgid "Change Password"
msgstr "Wachtwoord wijzigen"
#: src/views/settings/index.tsx:190
msgid "Change the language of the app." msgid "Change the language of the app."
msgstr "Wijzig de taal van de app." msgstr "Wijzig de taal van de app."
@@ -273,6 +322,10 @@ msgstr "Wijzig de taal van de app."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Controleer je inbox" msgstr "Controleer je inbox"
#: src/views/card/components/NewChecklistForm.tsx:118
msgid "Checklist name"
msgstr "Naam checklist"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:155
msgid "Clear filters" msgid "Clear filters"
msgstr "Filters wissen" msgstr "Filters wissen"
@@ -310,11 +363,24 @@ msgstr "Voltooid"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Volledige controle en eigendom:" msgstr "Volledige controle en eigendom:"
#: src/views/card/components/ActivityList.tsx:74
msgid "completed a checklist item"
msgstr "heeft een checklistitem voltooid"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187
msgid "completed checklist item <0>{0}</0>"
msgstr "heeft checklistitem <0>{0}</0> voltooid"
#: src/views/settings/components/CustomURLConfirmation.tsx:42 #: src/views/settings/components/CustomURLConfirmation.tsx:42
msgid "Confirm URL change" msgid "Confirm URL change"
msgstr "URL-wijziging bevestigen" msgstr "URL-wijziging bevestigen"
#: src/views/settings/index.tsx:233 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password"
msgstr "Bevestig je nieuwe wachtwoord"
#: src/views/settings/index.tsx:235
#: src/views/boards/components/ImportBoardsForm.tsx:157 #: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello" msgid "Connect Trello"
msgstr "Verbind Trello" msgstr "Verbind Trello"
@@ -323,7 +389,7 @@ msgstr "Verbind Trello"
msgid "Connect your favorite tools to streamline your workflow." msgid "Connect your favorite tools to streamline your workflow."
msgstr "Verbind je favoriete tools om je werkstroom te stroomlijnen." msgstr "Verbind je favoriete tools om je werkstroom te stroomlijnen."
#: src/views/settings/index.tsx:220 #: src/views/settings/index.tsx:222
msgid "Connect your Trello account to import boards." msgid "Connect your Trello account to import boards."
msgstr "Verbind je Trello-account om borden te importeren." msgstr "Verbind je Trello-account om borden te importeren."
@@ -353,8 +419,8 @@ msgid "Control who can view and edit your boards."
msgstr "Bepaal wie je borden kan bekijken en bewerken." msgstr "Bepaal wie je borden kan bekijken en bewerken."
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:418 #: src/views/board/components/NewCardForm.tsx:458
#: src/components/LabelForm.tsx:212 #: src/components/LabelForm.tsx:213
msgid "Create another" msgid "Create another"
msgstr "Maak nog een" msgstr "Maak nog een"
@@ -362,11 +428,15 @@ msgstr "Maak nog een"
msgid "Create board" msgid "Create board"
msgstr "Maak bord" msgstr "Maak bord"
#: src/views/board/components/NewCardForm.tsx:428 #: src/views/board/components/NewCardForm.tsx:468
msgid "Create card" msgid "Create card"
msgstr "Maak kaart" msgstr "Maak kaart"
#: src/components/LabelForm.tsx:236 #: src/views/card/components/NewChecklistForm.tsx:134
msgid "Create checklist"
msgstr "Checklist maken"
#: src/components/LabelForm.tsx:238
msgid "Create label" msgid "Create label"
msgstr "Maak label" msgstr "Maak label"
@@ -383,11 +453,11 @@ msgid "Create new key"
msgstr "Nieuwe sleutel aanmaken" msgstr "Nieuwe sleutel aanmaken"
#: src/views/card/components/LabelSelector.tsx:98 #: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:354 #: src/views/board/components/NewCardForm.tsx:394
msgid "Create new label" msgid "Create new label"
msgstr "Maak nieuw label" msgstr "Maak nieuw label"
#: src/views/board/index.tsx:426 #: src/views/board/index.tsx:425
msgid "Create new list" msgid "Create new list"
msgstr "Maak nieuwe lijst" msgstr "Maak nieuwe lijst"
@@ -396,7 +466,7 @@ msgstr "Maak nieuwe lijst"
msgid "Create workspace" msgid "Create workspace"
msgstr "Werkruimte maken" msgstr "Werkruimte maken"
#: src/views/card/components/ActivityList.tsx:52 #: src/views/card/components/ActivityList.tsx:61
msgid "created the card" msgid "created the card"
msgstr "heeft de kaart aangemaakt" msgstr "heeft de kaart aangemaakt"
@@ -404,6 +474,10 @@ msgstr "heeft de kaart aangemaakt"
msgid "Critical" msgid "Critical"
msgstr "Kritiek" msgstr "Kritiek"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:19
msgid "Current password is required"
msgstr "Huidig wachtwoord is vereist"
#: src/views/home/components/Pricing.tsx:74 #: src/views/home/components/Pricing.tsx:74
msgid "Custom domain" msgid "Custom domain"
msgstr "Aangepast domein" msgstr "Aangepast domein"
@@ -421,14 +495,15 @@ msgid "Dark"
msgstr "Donker" msgstr "Donker"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226 #: src/components/LabelForm.tsx:228
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:51
msgid "Delete" msgid "Delete"
msgstr "Verwijderen" msgstr "Verwijderen"
#: src/views/settings/index.tsx:288 #: src/views/settings/index.tsx:309
#: src/views/settings/index.tsx:298 #: src/views/settings/index.tsx:319
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96 #: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account" msgid "Delete account"
msgstr "Account verwijderen" msgstr "Account verwijderen"
@@ -437,7 +512,7 @@ msgstr "Account verwijderen"
msgid "Delete board" msgid "Delete board"
msgstr "Board verwijderen" msgstr "Board verwijderen"
#: src/views/card/components/Dropdown.tsx:14 #: src/views/card/components/Dropdown.tsx:25
msgid "Delete card" msgid "Delete card"
msgstr "Kaart verwijderen" msgstr "Kaart verwijderen"
@@ -449,17 +524,35 @@ msgstr "Reactie verwijderen"
msgid "Delete list" msgid "Delete list"
msgstr "Lijst verwijderen" msgstr "Lijst verwijderen"
#: src/views/settings/index.tsx:270 #: src/views/settings/index.tsx:272
#: src/views/settings/index.tsx:281 #: src/views/settings/index.tsx:283
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106 #: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Werkruimte verwijderen" msgstr "Werkruimte verwijderen"
#: src/views/card/components/ActivityList.tsx:71
msgid "deleted a checklist"
msgstr "heeft een checklist verwijderd"
#: src/views/card/components/ActivityList.tsx:76
msgid "deleted a checklist item"
msgstr "heeft een checklistitem verwijderd"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162
msgid "deleted checklist <0>{0}</0>"
msgstr "heeft checklist <0>{0}</0> verwijderd"
#. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205
msgid "deleted checklist item <0>{0}</0>"
msgstr "heeft checklistitem <0>{0}</0> verwijderd"
#: src/views/boards/components/TemplateBoards.tsx:32 #: src/views/boards/components/TemplateBoards.tsx:32
msgid "Design" msgid "Design"
msgstr "Ontwerp" msgstr "Ontwerp"
#: src/views/settings/index.tsx:248 #: src/views/settings/index.tsx:250
msgid "Disconnect Trello" msgid "Disconnect Trello"
msgstr "Trello ontkoppelen" msgstr "Trello ontkoppelen"
@@ -467,7 +560,7 @@ msgstr "Trello ontkoppelen"
msgid "Discuss and collaborate on cards." msgid "Discuss and collaborate on cards."
msgstr "Bespreek en werk samen aan kaarten." msgstr "Bespreek en werk samen aan kaarten."
#: src/views/settings/index.tsx:149 #: src/views/settings/index.tsx:151
msgid "Display name" msgid "Display name"
msgstr "Weergavenaam" msgstr "Weergavenaam"
@@ -521,7 +614,7 @@ msgstr "Board URL bewerken"
msgid "Edit comment" msgid "Edit comment"
msgstr "Reactie bewerken" msgstr "Reactie bewerken"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "Edit label" msgid "Edit label"
msgstr "Label bewerken" msgstr "Label bewerken"
@@ -545,6 +638,14 @@ msgstr "E-mail"
msgid "Enhancement" msgid "Enhancement"
msgstr "Verbetering" msgstr "Verbetering"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:122
msgid "Enter your current password"
msgstr "Voer je huidige wachtwoord in"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:111
msgid "Enter your current password and choose a new secure password."
msgstr "Voer je huidige wachtwoord in en kies een nieuw veilig wachtwoord."
#: src/components/AuthForm.tsx:302 #: src/components/AuthForm.tsx:302
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Voer je e-mailadres in" msgstr "Voer je e-mailadres in"
@@ -553,15 +654,23 @@ msgstr "Voer je e-mailadres in"
msgid "Enter your name" msgid "Enter your name"
msgstr "Voer je naam in" msgstr "Voer je naam in"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:136
msgid "Enter your new password"
msgstr "Voer je nieuwe wachtwoord in"
#: src/components/AuthForm.tsx:315 #: src/components/AuthForm.tsx:315
msgid "Enter your password" msgid "Enter your password"
msgstr "Voer je wachtwoord in" msgstr "Voer je wachtwoord in"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:89
msgid "Error Changing Password"
msgstr "Fout bij wijzigen wachtwoord"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:39 #: src/views/settings/components/DeleteAccountConfirmation.tsx:39
msgid "Error deleting account" msgid "Error deleting account"
msgstr "Fout bij verwijderen account" msgstr "Fout bij verwijderen account"
#: src/components/DeleteLabelConfirmation.tsx:22 #: src/components/DeleteLabelConfirmation.tsx:25
msgid "Error deleting label" msgid "Error deleting label"
msgstr "Fout bij het verwijderen van label" msgstr "Fout bij het verwijderen van label"
@@ -569,7 +678,7 @@ msgstr "Fout bij het verwijderen van label"
msgid "Error deleting workspace" msgid "Error deleting workspace"
msgstr "Fout bij verwijderen werkruimte" msgstr "Fout bij verwijderen werkruimte"
#: src/views/settings/index.tsx:99 #: src/views/settings/index.tsx:101
msgid "Error disconnecting Trello" msgid "Error disconnecting Trello"
msgstr "Fout bij ontkoppelen van Trello" msgstr "Fout bij ontkoppelen van Trello"
@@ -692,7 +801,7 @@ msgstr "Aan de slag"
msgid "Get started by creating a new board" msgid "Get started by creating a new board"
msgstr "Begin door een nieuw bord te maken" msgstr "Begin door een nieuw bord te maken"
#: src/views/board/index.tsx:418 #: src/views/board/index.tsx:417
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Begin door een nieuwe lijst te maken" msgstr "Begin door een nieuwe lijst te maken"
@@ -849,8 +958,8 @@ msgstr "Kanban opnieuw uitgevonden"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Houd er rekening mee dat deze actie onomkeerbaar is." msgstr "Houd er rekening mee dat deze actie onomkeerbaar is."
#: src/views/card/index.tsx:113 #: src/views/card/index.tsx:117
#: src/views/board/components/NewCardForm.tsx:358 #: src/views/board/components/NewCardForm.tsx:398
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:101
msgid "Labels" msgid "Labels"
msgstr "Labels" msgstr "Labels"
@@ -859,7 +968,7 @@ msgstr "Labels"
msgid "Labels & Filters" msgid "Labels & Filters"
msgstr "Labels & filters" msgstr "Labels & filters"
#: src/views/settings/index.tsx:185 #: src/views/settings/index.tsx:187
msgid "Language" msgid "Language"
msgstr "Taal" msgstr "Taal"
@@ -883,7 +992,7 @@ msgstr "Licht"
msgid "Link copied" msgid "Link copied"
msgstr "Link gekopieerd" msgstr "Link gekopieerd"
#: src/views/card/index.tsx:105 #: src/views/card/index.tsx:109
msgid "List" msgid "List"
msgstr "Lijst" msgstr "Lijst"
@@ -911,13 +1020,22 @@ msgstr "Lage prioriteit"
msgid "magic link" msgid "magic link"
msgstr "magische link" msgstr "magische link"
#: src/views/card/components/ActivityList.tsx:75
msgid "marked a checklist item as incomplete"
msgstr "heeft een checklistitem als onvoltooid gemarkeerd"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196
msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "heeft checklistitem <0>{0}</0> als onvoltooid gemarkeerd"
#: src/views/boards/components/TemplateBoards.tsx:17 #: src/views/boards/components/TemplateBoards.tsx:17
msgid "Medium Priority" msgid "Medium Priority"
msgstr "Gemiddelde prioriteit" msgstr "Gemiddelde prioriteit"
#: src/views/members/index.tsx:161 #: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121 #: src/views/card/index.tsx:125
#: src/views/board/components/NewCardForm.tsx:317 #: src/views/board/components/NewCardForm.tsx:357
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:73 #: src/components/SideNavigation.tsx:73
msgid "Members" msgid "Members"
@@ -932,16 +1050,18 @@ msgstr "Leden | {0}"
msgid "Monthly" msgid "Monthly"
msgstr "Maandelijks" msgstr "Maandelijks"
#: src/views/card/components/ActivityList.tsx:81 #. placeholder {0}: truncate(fromList)
msgid "moved the card from <0>{fromList}</0> to<1>{toList}</1>" #. placeholder {1}: truncate(toList)
msgstr "heeft de kaart verplaatst van <0>{fromList}</0> naar<1>{toList}</1>" #: src/views/card/components/ActivityList.tsx:98
msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "heeft de kaart verplaatst van <0>{0}</0> naar<1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:55 #: src/views/card/components/ActivityList.tsx:64
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "heeft de kaart naar een andere lijst verplaatst" msgstr "heeft de kaart naar een andere lijst verplaatst"
#: src/views/boards/components/NewBoardForm.tsx:99 #: src/views/boards/components/NewBoardForm.tsx:99
#: src/components/LabelForm.tsx:134 #: src/components/LabelForm.tsx:135
msgid "Name" msgid "Name"
msgstr "Naam" msgstr "Naam"
@@ -957,23 +1077,35 @@ msgstr "Nieuw"
msgid "New board" msgid "New board"
msgstr "Nieuw bord" msgstr "Nieuw bord"
#: src/views/board/components/NewCardForm.tsx:261 #: src/views/board/components/NewCardForm.tsx:290
msgid "New card" msgid "New card"
msgstr "Nieuwe kaart" msgstr "Nieuwe kaart"
#: src/views/card/components/NewChecklistForm.tsx:102
msgid "New checklist"
msgstr "Nieuwe checklist"
#: src/views/boards/components/ImportBoardsForm.tsx:322 #: src/views/boards/components/ImportBoardsForm.tsx:322
msgid "New import" msgid "New import"
msgstr "Nieuwe import" msgstr "Nieuwe import"
#: src/components/LabelForm.tsx:118 #: src/components/LabelForm.tsx:119
msgid "New label" msgid "New label"
msgstr "Nieuw label" msgstr "Nieuw label"
#: src/views/board/index.tsx:395 #: src/views/board/index.tsx:394
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:112
msgid "New list" msgid "New list"
msgstr "Nieuwe lijst" msgstr "Nieuwe lijst"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:23
msgid "New password is required"
msgstr "Nieuw wachtwoord is vereist"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:31
msgid "New password must be different from current password"
msgstr "Nieuw wachtwoord moet verschillen van het huidige wachtwoord"
#: src/views/boards/components/TemplateBoards.tsx:43 #: src/views/boards/components/TemplateBoards.tsx:43
msgid "New Ticket" msgid "New Ticket"
msgstr "Nieuw ticket" msgstr "Nieuw ticket"
@@ -1002,7 +1134,7 @@ msgstr "Geen borden gevonden"
msgid "No credit card required" msgid "No credit card required"
msgstr "Geen creditcard vereist" msgstr "Geen creditcard vereist"
#: src/views/board/index.tsx:415 #: src/views/board/index.tsx:414
msgid "No lists" msgid "No lists"
msgstr "Geen lijsten" msgstr "Geen lijsten"
@@ -1014,11 +1146,11 @@ msgstr "Aanbod"
msgid "Onboarding" msgid "Onboarding"
msgstr "Inwerktraject" msgstr "Inwerktraject"
#: src/views/settings/index.tsx:291 #: src/views/settings/index.tsx:312
msgid "Once you delete your account, there is no going back. This action cannot be undone." msgid "Once you delete your account, there is no going back. This action cannot be undone."
msgstr "Zodra je je account verwijdert, is er geen weg terug. Deze actie kan niet ongedaan worden gemaakt." msgstr "Zodra je je account verwijdert, is er geen weg terug. Deze actie kan niet ongedaan worden gemaakt."
#: src/views/settings/index.tsx:273 #: src/views/settings/index.tsx:275
msgid "Once you delete your workspace, there is no going back. This action cannot be undone." msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
msgstr "Zodra je je werkruimte verwijdert, is er geen weg terug. Deze actie kan niet ongedaan worden gemaakt." msgstr "Zodra je je werkruimte verwijdert, is er geen weg terug. Deze actie kan niet ongedaan worden gemaakt."
@@ -1038,6 +1170,18 @@ msgstr "Bezit je eigen data"
msgid "Part-time" msgid "Part-time"
msgstr "Deeltijd" msgstr "Deeltijd"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:69
msgid "Password Changed"
msgstr "Wachtwoord gewijzigd"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:22
msgid "Password must be at least 8 characters"
msgstr "Wachtwoord moet minimaal 8 tekens bevatten"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:27
msgid "Passwords do not match"
msgstr "Wachtwoorden komen niet overeen"
#: src/views/home/components/Pricing.tsx:101 #: src/views/home/components/Pricing.tsx:101
msgid "Payment frequency" msgid "Payment frequency"
msgstr "Betalingsfrequentie" msgstr "Betalingsfrequentie"
@@ -1059,6 +1203,10 @@ msgstr "Persoonlijk project"
msgid "Planning" msgid "Planning"
msgstr "Planning" msgstr "Planning"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:24
msgid "Please confirm your new password"
msgstr "Bevestig je nieuwe wachtwoord"
#: src/components/AuthForm.tsx:306 #: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Voer een geldig e-mailadres in" msgstr "Voer een geldig e-mailadres in"
@@ -1085,24 +1233,30 @@ msgstr "Selecteer een bestand om te uploaden."
#: src/views/settings/components/Avatar.tsx:98 #: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64 #: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:159 #: src/views/card/index.tsx:172
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/MemberSelector.tsx:80 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Comment.tsx:64
#: src/views/card/components/ChecklistNameInput.tsx:46
#: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:135 #: src/views/board/index.tsx:134
#: src/views/board/index.tsx:191 #: src/views/board/index.tsx:190
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78 #: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:145 #: src/views/board/components/NewCardForm.tsx:174
#: src/components/NewWorkspaceForm.tsx:41 #: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23 #: src/components/DeleteLabelConfirmation.tsx:26
msgid "Please try again later, or contact customer support." msgid "Please try again later, or contact customer support."
msgstr "Probeer het later opnieuw of neem contact op met de klantenservice." msgstr "Probeer het later opnieuw of neem contact op met de klantenservice."
@@ -1128,7 +1282,7 @@ msgstr "Privé"
msgid "Profile image updated" msgid "Profile image updated"
msgstr "Profielafbeelding bijgewerkt" msgstr "Profielafbeelding bijgewerkt"
#: src/views/settings/index.tsx:144 #: src/views/settings/index.tsx:146
msgid "Profile picture" msgid "Profile picture"
msgstr "Profielfoto" msgstr "Profielfoto"
@@ -1168,17 +1322,32 @@ msgstr "Verwijderen"
msgid "Remove member" msgid "Remove member"
msgstr "Lid verwijderen" msgstr "Lid verwijderen"
#: src/views/card/components/ActivityList.tsx:57 #: src/views/card/components/ActivityList.tsx:66
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "heeft een label van de kaart verwijderd" msgstr "heeft een label van de kaart verwijderd"
#: src/views/card/components/ActivityList.tsx:59 #: src/views/card/components/ActivityList.tsx:68
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "heeft een lid van de kaart verwijderd" msgstr "heeft een lid van de kaart verwijderd"
#: src/views/card/components/ActivityList.tsx:118 #. placeholder {0}: truncate(label)
msgid "removed label <0>{label}</0>" #: src/views/card/components/ActivityList.tsx:138
msgstr "heeft label <0>{label}</0> verwijderd" msgid "removed label <0>{0}</0>"
msgstr "heeft label <0>{0}</0> verwijderd"
#: src/views/card/components/ActivityList.tsx:70
msgid "renamed a checklist"
msgstr "heeft een checklist hernoemd"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154
msgid "renamed checklist <0>{0}</0>"
msgstr "heeft checklist <0>{0}</0> hernoemd"
#. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178
msgid "renamed checklist item to <0>{0}</0>"
msgstr "checklistitem hernoemd naar <0>{0}</0>"
#: src/views/boards/components/TemplateBoards.tsx:76 #: src/views/boards/components/TemplateBoards.tsx:76
msgid "Research" msgid "Research"
@@ -1241,7 +1410,7 @@ msgstr "Zelf hosten"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Zelf hosten met Github" msgstr "Zelf hosten met Github"
#: src/views/card/components/ActivityList.tsx:89 #: src/views/card/components/ActivityList.tsx:107
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "heeft de kaart aan zichzelf toegewezen" msgstr "heeft de kaart aan zichzelf toegewezen"
@@ -1253,13 +1422,13 @@ msgstr "Feedback versturen"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/settings/index.tsx:138 #: src/views/settings/index.tsx:140
#: src/components/SideNavigation.tsx:78 #: src/components/SideNavigation.tsx:78
msgid "Settings" msgid "Settings"
msgstr "Instellingen" msgstr "Instellingen"
#. placeholder {0}: workspace.name ?? "Workspace" #. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:134 #: src/views/settings/index.tsx:136
msgid "Settings | {0}" msgid "Settings | {0}"
msgstr "Instellingen | {0}" msgstr "Instellingen | {0}"
@@ -1338,6 +1507,10 @@ msgstr "Servicevoorwaarden"
msgid "Thank you for your feedback!" msgid "Thank you for your feedback!"
msgstr "Bedankt voor je feedback!" msgstr "Bedankt voor je feedback!"
#: src/views/settings/components/ChangePasswordConfirmation.tsx:84
msgid "The current password you entered is incorrect."
msgstr "Het ingevoerde huidige wachtwoord is onjuist."
#: src/views/home/components/Faqs.tsx:33 #: src/views/home/components/Faqs.tsx:33
msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall." msgid "The main difference between Kan and Trello is that Kan is open source, allowing anyone to view, modify, and contribute to our code. Our cloud offering also offers no restrictions on features for individual use, whereas Trello locks basic features such as the number of boards you can create behind a paywall."
msgstr "Het belangrijkste verschil tussen Kan en Trello is dat Kan open source is, waardoor iedereen onze code kan bekijken, wijzigen en eraan kan bijdragen. Onze cloudoplossing biedt ook geen beperkingen op functies voor individueel gebruik, terwijl Trello basisfuncties zoals het aantal borden dat je kunt maken achter een betaalmuur plaatst." msgstr "Het belangrijkste verschil tussen Kan en Trello is dat Kan open source is, waardoor iedereen onze code kan bekijken, wijzigen en eraan kan bijdragen. Onze cloudoplossing biedt ook geen beperkingen op functies voor individueel gebruik, terwijl Trello basisfuncties zoals het aantal borden dat je kunt maken achter een betaalmuur plaatst."
@@ -1360,8 +1533,9 @@ msgid "They won't be able to access this workspace."
msgstr "Ze zullen geen toegang meer hebben tot deze werkruimte." msgstr "Ze zullen geen toegang meer hebben tot deze werkruimte."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42 #: src/components/DeleteLabelConfirmation.tsx:44
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Deze actie kan niet ongedaan worden gemaakt." msgstr "Deze actie kan niet ongedaan worden gemaakt."
@@ -1398,7 +1572,7 @@ msgstr "Menu in-/uitschakelen"
msgid "Track all card changes with detailed activity history." msgid "Track all card changes with detailed activity history."
msgstr "Volg alle kaartwijzigingen met gedetailleerde activiteitengeschiedenis." msgstr "Volg alle kaartwijzigingen met gedetailleerde activiteitengeschiedenis."
#: src/views/settings/index.tsx:92 #: src/views/settings/index.tsx:94
msgid "Trello disconnected" msgid "Trello disconnected"
msgstr "Trello ontkoppeld" msgstr "Trello ontkoppeld"
@@ -1410,14 +1584,22 @@ msgstr "Trello-imports"
msgid "Triaging" msgid "Triaging"
msgstr "Triage" msgstr "Triage"
#: src/views/card/components/NewChecklistItemForm.tsx:88
msgid "Unable to add checklist item"
msgstr "Kan checklistitem niet toevoegen"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:30
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Kan geen reactie toevoegen" msgstr "Kan geen reactie toevoegen"
#: src/views/board/components/NewCardForm.tsx:142 #: src/views/board/components/NewCardForm.tsx:171
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Kan kaart niet aanmaken" msgstr "Kan kaart niet aanmaken"
#: src/views/card/components/NewChecklistForm.tsx:69
msgid "Unable to create checklist"
msgstr "Kan checklist niet maken"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:77
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Kan geen lijst maken" msgstr "Kan geen lijst maken"
@@ -1430,6 +1612,14 @@ msgstr "Kan werkruimte niet aanmaken"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Kan kaart niet verwijderen" msgstr "Kan kaart niet verwijderen"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36
msgid "Unable to delete checklist"
msgstr "Kan checklist niet verwijderen"
#: src/views/card/components/ChecklistItemRow.tsx:87
msgid "Unable to delete checklist item"
msgstr "Kan checklistitem niet verwijderen"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:44
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Kan opmerking niet verwijderen" msgstr "Kan opmerking niet verwijderen"
@@ -1450,11 +1640,19 @@ msgstr "Kan board URL niet bijwerken"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Kan bordzichtbaarheid niet bijwerken" msgstr "Kan bordzichtbaarheid niet bijwerken"
#: src/views/card/index.tsx:158 #: src/views/card/index.tsx:171
#: src/views/board/index.tsx:190 #: src/views/board/index.tsx:189
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Kan kaart niet bijwerken" msgstr "Kan kaart niet bijwerken"
#: src/views/card/components/ChecklistNameInput.tsx:45
msgid "Unable to update checklist"
msgstr "Kan checklist niet bijwerken"
#: src/views/card/components/ChecklistItemRow.tsx:59
msgid "Unable to update checklist item"
msgstr "Kan checklistitem niet bijwerken"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Kan reactie niet bijwerken" msgstr "Kan reactie niet bijwerken"
@@ -1464,7 +1662,7 @@ msgid "Unable to update labels"
msgstr "Kan labels niet bijwerken" msgstr "Kan labels niet bijwerken"
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:134 #: src/views/board/index.tsx:133
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Kan lijst niet bijwerken" msgstr "Kan lijst niet bijwerken"
@@ -1472,11 +1670,12 @@ msgstr "Kan lijst niet bijwerken"
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Kan leden niet bijwerken" msgstr "Kan leden niet bijwerken"
#: src/views/card/components/ActivityList.tsx:102 #. placeholder {0}: truncate(memberName)
msgid "unassigned <0>{memberName}</0> from the card" #: src/views/card/components/ActivityList.tsx:121
msgstr "<0>{memberName}</0> van de kaart verwijderd" msgid "unassigned <0>{0}</0> from the card"
msgstr "<0>{0}</0> van de kaart verwijderd"
#: src/views/card/components/ActivityList.tsx:99 #: src/views/card/components/ActivityList.tsx:118
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "zichzelf van de kaart verwijderd" msgstr "zichzelf van de kaart verwijderd"
@@ -1512,21 +1711,26 @@ msgstr "Onbeperkt aantal lijsten"
msgid "Update" msgid "Update"
msgstr "Bijwerken" msgstr "Bijwerken"
#: src/components/LabelForm.tsx:236 #: src/components/LabelForm.tsx:238
msgid "Update label" msgid "Update label"
msgstr "Label bijwerken" msgstr "Label bijwerken"
#: src/views/card/components/ActivityList.tsx:54 #: src/views/card/components/ActivityList.tsx:73
msgid "updated a checklist item"
msgstr "een checklistitem bijgewerkt"
#: src/views/card/components/ActivityList.tsx:63
msgid "updated the description" msgid "updated the description"
msgstr "beschrijving bijgewerkt" msgstr "beschrijving bijgewerkt"
#: src/views/card/components/ActivityList.tsx:53 #: src/views/card/components/ActivityList.tsx:62
msgid "updated the title" msgid "updated the title"
msgstr "titel bijgewerkt" msgstr "titel bijgewerkt"
#: src/views/card/components/ActivityList.tsx:73 #. placeholder {0}: truncate(toTitle)
msgid "updated the title to <0>{toTitle}</0>" #: src/views/card/components/ActivityList.tsx:90
msgstr "titel bijgewerkt naar <0>{toTitle}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "titel bijgewerkt naar <0>{0}</0>"
#: src/views/settings/components/CustomURLConfirmation.tsx:52 #: src/views/settings/components/CustomURLConfirmation.tsx:52
msgid "Upgrade" msgid "Upgrade"
@@ -1565,11 +1769,11 @@ msgstr "Gebruiker is al lid van deze werkruimte"
msgid "Video" msgid "Video"
msgstr "Video" msgstr "Video"
#: src/views/settings/index.tsx:260 #: src/views/settings/index.tsx:262
msgid "View and manage your API keys." msgid "View and manage your API keys."
msgstr "Bekijk en beheer je API-sleutels." msgstr "Bekijk en beheer je API-sleutels."
#: src/views/settings/index.tsx:199 #: src/views/settings/index.tsx:201
msgid "View and manage your billing and subscription." msgid "View and manage your billing and subscription."
msgstr "Bekijk en beheer je facturering en abonnement." msgstr "Bekijk en beheer je facturering en abonnement."
@@ -1621,7 +1825,7 @@ msgstr "Toen Trello in 2011 werd gelanceerd, blies het iedereen omver met zijn z
msgid "Why make an open source Trello?" msgid "Why make an open source Trello?"
msgstr "Waarom een open source Trello maken?" msgstr "Waarom een open source Trello maken?"
#: src/views/board/index.tsx:332 #: src/views/board/index.tsx:331
msgid "Workspace" msgid "Workspace"
msgstr "Werkruimte" msgstr "Werkruimte"
@@ -1629,7 +1833,7 @@ msgstr "Werkruimte"
msgid "Workspace deleted" msgid "Workspace deleted"
msgstr "Werkruimte verwijderd" msgstr "Werkruimte verwijderd"
#: src/views/settings/index.tsx:175 #: src/views/settings/index.tsx:177
msgid "Workspace description" msgid "Workspace description"
msgstr "Werkruimte beschrijving" msgstr "Werkruimte beschrijving"
@@ -1650,7 +1854,7 @@ msgstr "Werkruimtebeschrijving bijgewerkt"
msgid "Workspace members" msgid "Workspace members"
msgstr "Werkruimteleden" msgstr "Werkruimteleden"
#: src/views/settings/index.tsx:156 #: src/views/settings/index.tsx:158
#: src/components/NewWorkspaceForm.tsx:80 #: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name" msgid "Workspace name"
msgstr "Naam werkruimte" msgstr "Naam werkruimte"
@@ -1671,7 +1875,7 @@ msgstr "Werkruimtenaam bijgewerkt"
msgid "Workspace slug updated" msgid "Workspace slug updated"
msgstr "Werkruimte-slug bijgewerkt" msgstr "Werkruimte-slug bijgewerkt"
#: src/views/settings/index.tsx:165 #: src/views/settings/index.tsx:167
msgid "Workspace URL" msgid "Workspace URL"
msgstr "Werkruimte URL" msgstr "Werkruimte URL"
@@ -1687,6 +1891,10 @@ msgstr "Jaarlijks"
msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits." msgid "Yes, we offer an forever free plan for individual use. No restrictions, no paywalls, no limits."
msgstr "Ja, we bieden een voor altijd gratis plan voor individueel gebruik. Geen beperkingen, geen betaalmuren, geen limieten." msgstr "Ja, we bieden een voor altijd gratis plan voor individueel gebruik. Geen beperkingen, geen betaalmuren, geen limieten."
#: src/views/settings/index.tsx:294
msgid "You are about to change your password."
msgstr "Je staat op het punt je wachtwoord te wijzigen."
#: src/views/home/components/Faqs.tsx:67 #: src/views/home/components/Faqs.tsx:67
msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!" msgid "You can get a custom workspace URL, like <0>kan.bn/kan</0>, by going into your <1>workspace settings</1> and purchasing a pro workspace subscription. All subscriptions help fund the development of the project!"
msgstr "Je kunt een aangepaste werkruimte-URL krijgen, zoals <0>kan.bn/kan</0>, door naar je <1>werkruimte-instellingen</1> te gaan en een pro-werkruimte-abonnement aan te schaffen. Alle abonnementen helpen de ontwikkeling van het project te financieren!" msgstr "Je kunt een aangepaste werkruimte-URL krijgen, zoals <0>kan.bn/kan</0>, door naar je <1>werkruimte-instellingen</1> te gaan en een pro-werkruimte-abonnement aan te schaffen. Alle abonnementen helpen de ontwikkeling van het project te financieren!"
@@ -1719,15 +1927,19 @@ msgstr "Je borden zijn geïmporteerd."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Je weergavenaam is bijgewerkt." msgstr "Je weergavenaam is bijgewerkt."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed."
msgstr "Je wachtwoord is gewijzigd."
#: src/views/settings/components/Avatar.tsx:27 #: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated." msgid "Your profile image has been updated."
msgstr "Je profielafbeelding is bijgewerkt." msgstr "Je profielafbeelding is bijgewerkt."
#: src/views/settings/index.tsx:93 #: src/views/settings/index.tsx:95
msgid "Your Trello account has been disconnected." msgid "Your Trello account has been disconnected."
msgstr "Je Trello-account is ontkoppeld." msgstr "Je Trello-account is ontkoppeld."
#: src/views/settings/index.tsx:242 #: src/views/settings/index.tsx:244
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Je Trello-account is verbonden." msgstr "Je Trello-account is verbonden."

File diff suppressed because one or more lines are too long

View File

@@ -14,7 +14,7 @@ import { useEffect } from "react";
import { LinguiProviderWrapper } from "~/providers/lingui"; import { LinguiProviderWrapper } from "~/providers/lingui";
import { ModalProvider } from "~/providers/modal"; import { ModalProvider } from "~/providers/modal";
import { PopupProvider } from "~/providers/popup"; import { PopupProvider } from "~/providers/popup";
import { ThemeProvider } from "~/providers/theme"; import { ThemeProvider } from "next-themes";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
const jakarta = Plus_Jakarta_Sans({ const jakarta = Plus_Jakarta_Sans({
@@ -81,9 +81,9 @@ const MyApp: AppType = ({ Component, pageProps }: AppPropsWithLayout) => {
<script src="/__ENV.js" /> <script src="/__ENV.js" />
<main className="font-sans"> <main className="font-sans">
<LinguiProviderWrapper> <LinguiProviderWrapper>
<ThemeProvider> <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<ModalProvider> <ModalProvider>
<PopupProvider> <PopupProvider>
{posthogKey ? ( {posthogKey ? (
<PostHogProvider client={posthog}> <PostHogProvider client={posthog}>
{getLayout(<Component {...pageProps} />)} {getLayout(<Component {...pageProps} />)}
@@ -91,8 +91,8 @@ const MyApp: AppType = ({ Component, pageProps }: AppPropsWithLayout) => {
) : ( ) : (
getLayout(<Component {...pageProps} />) getLayout(<Component {...pageProps} />)
)} )}
</PopupProvider> </PopupProvider>
</ModalProvider> </ModalProvider>
</ThemeProvider> </ThemeProvider>
</LinguiProviderWrapper> </LinguiProviderWrapper>
</main> </main>

View File

@@ -10,7 +10,7 @@ interface Props {
children: React.ReactNode; children: React.ReactNode;
} }
type ModalContextType = { interface ModalContextType {
isOpen: boolean; isOpen: boolean;
openModal: ( openModal: (
contentType: string, contentType: string,
@@ -18,6 +18,8 @@ type ModalContextType = {
entityLabel?: string, entityLabel?: string,
) => void; ) => void;
closeModal: () => void; closeModal: () => void;
closeModals: (count: number) => void;
clearAllModals: () => void;
modalContentType: string; modalContentType: string;
entityId: string; entityId: string;
entityLabel: string; entityLabel: string;
@@ -26,7 +28,7 @@ type ModalContextType = {
getModalState: (modalType: string) => any; getModalState: (modalType: string) => any;
clearModalState: (modalType: string) => void; clearModalState: (modalType: string) => void;
clearAllModalStates: () => void; clearAllModalStates: () => void;
}; }
const ModalContext = createContext<ModalContextType | undefined>(undefined); const ModalContext = createContext<ModalContextType | undefined>(undefined);
@@ -46,11 +48,11 @@ export const ModalProvider: React.FC<Props> = ({ children }) => {
entityLabel?: string, entityLabel?: string,
) => { ) => {
const newModal: ModalState = { contentType, entityId, entityLabel }; const newModal: ModalState = { contentType, entityId, entityLabel };
setModalStack(prev => [...prev, newModal]); setModalStack((prev) => [...prev, newModal]);
}; };
const closeModal = () => { const closeModal = () => {
setModalStack(prev => { setModalStack((prev) => {
if (prev.length <= 1) { if (prev.length <= 1) {
return []; return [];
} }
@@ -58,10 +60,21 @@ export const ModalProvider: React.FC<Props> = ({ children }) => {
}); });
}; };
const closeModals = (count: number) => {
setModalStack(prev => {
const newLength = Math.max(0, prev.length - count);
return prev.slice(0, newLength);
});
};
const clearAllModals = () => {
setModalStack([]);
};
const setModalState = (modalType: string, state: any) => { const setModalState = (modalType: string, state: any) => {
setModalStates(prev => ({ setModalStates((prev) => ({
...prev, ...prev,
[modalType]: state [modalType]: state,
})); }));
}; };
@@ -70,7 +83,7 @@ export const ModalProvider: React.FC<Props> = ({ children }) => {
}; };
const clearModalState = (modalType: string) => { const clearModalState = (modalType: string) => {
setModalStates(prev => { setModalStates((prev) => {
const newStates = { ...prev }; const newStates = { ...prev };
delete newStates[modalType]; delete newStates[modalType];
return newStates; return newStates;
@@ -87,6 +100,8 @@ export const ModalProvider: React.FC<Props> = ({ children }) => {
isOpen, isOpen,
openModal, openModal,
closeModal, closeModal,
closeModals,
clearAllModals,
modalContentType, modalContentType,
entityId, entityId,
entityLabel, entityLabel,

View File

@@ -45,10 +45,12 @@ export const formatMemberDisplayName = (
return localPart.replace(/[_-]/g, "."); return localPart.replace(/[_-]/g, ".");
}; };
export const getAvatarUrl = (imageOrKey: string) => { export const getAvatarUrl = (imageOrKey: string | null) => {
if (!imageOrKey) return "";
if (imageOrKey.startsWith("http://") || imageOrKey.startsWith("https://")) { if (imageOrKey.startsWith("http://") || imageOrKey.startsWith("https://")) {
return imageOrKey; return imageOrKey;
} }
return `${env("NEXT_PUBLIC_STORAGE_URL")}/${env("NEXT_PUBLIC_AVATAR_BUCKET_NAME")}/${imageOrKey}`; return `${env("NEXT_PUBLIC_STORAGE_URL")}/${env("NEXT_PUBLIC_AVATAR_BUCKET_NAME")}/${imageOrKey}`;
}; };

View File

@@ -1,5 +1,6 @@
import Avatar from "~/components/Avatar"; import Avatar from "~/components/Avatar";
import Badge from "~/components/Badge"; import Badge from "~/components/Badge";
import CircularProgress from "~/components/CircularProgress";
import LabelIcon from "~/components/LabelIcon"; import LabelIcon from "~/components/LabelIcon";
import { getAvatarUrl } from "~/utils/helpers"; import { getAvatarUrl } from "~/utils/helpers";
@@ -7,6 +8,7 @@ const Card = ({
title, title,
labels, labels,
members, members,
checklists,
}: { }: {
title: string; title: string;
labels: { name: string; colourCode: string | null }[]; labels: { name: string; colourCode: string | null }[];
@@ -15,7 +17,28 @@ const Card = ({
email: string; email: string;
user: { name: string | null; email: string; image: string | null } | null; user: { name: string | null; email: string; image: string | null } | null;
}[]; }[];
checklists: {
publicId: string;
name: string;
items: {
publicId: string;
title: string;
completed: boolean;
index: number;
}[];
}[];
}) => { }) => {
const completedItems = checklists.reduce((acc, checklist) => {
return acc + checklist.items.filter((item) => item.completed).length;
}, 0);
const totalItems = checklists.reduce((acc, checklist) => {
return acc + checklist.items.length;
}, 0);
const progress =
totalItems > 0 ? Math.round((completedItems / totalItems) * 100) : 0;
return ( return (
<div className="flex flex-col rounded-md border border-light-200 bg-light-50 px-3 py-2 text-sm text-neutral-900 dark:border-dark-200 dark:bg-dark-200 dark:text-dark-1000 dark:hover:bg-dark-300"> <div className="flex flex-col rounded-md border border-light-200 bg-light-50 px-3 py-2 text-sm text-neutral-900 dark:border-dark-200 dark:bg-dark-200 dark:text-dark-1000 dark:hover:bg-dark-300">
<span>{title}</span> <span>{title}</span>
@@ -29,21 +52,37 @@ const Card = ({
/> />
))} ))}
</div> </div>
<div className="isolate flex justify-end -space-x-1 overflow-hidden"> <div className="flex items-center justify-end gap-1">
{members.map(({ user, email }) => { {checklists.length > 0 && (
const avatarUrl = user?.image <div className="flex items-center gap-1 rounded-full border-[1px] border-light-300 px-2 py-1 dark:border-dark-600">
? getAvatarUrl(user.image) <CircularProgress
: undefined; progress={progress || 2}
return (
<Avatar
name={user?.name ?? ""}
email={user?.email ?? email}
imageUrl={avatarUrl}
size="sm" size="sm"
className="flex-shrink-0"
/> />
); <span className="text-[10px] text-light-900 dark:text-dark-950">
})} {completedItems}/{totalItems}
</span>
</div>
)}
{members.length > 0 && (
<div className="isolate flex justify-end -space-x-1 overflow-hidden">
{members.map(({ user, email }) => {
const avatarUrl = user?.image
? getAvatarUrl(user.image)
: undefined;
return (
<Avatar
name={user?.name ?? ""}
email={user?.email ?? email}
imageUrl={avatarUrl}
size="sm"
/>
);
})}
</div>
)}
</div> </div>
</div> </div>
) : null} ) : null}

View File

@@ -14,7 +14,7 @@ import { generateUID } from "@kan/shared/utils";
import Avatar from "~/components/Avatar"; import Avatar from "~/components/Avatar";
import Button from "~/components/Button"; import Button from "~/components/Button";
import CheckboxDropdown from "~/components/CheckboxDropdown"; import CheckboxDropdown from "~/components/CheckboxDropdown";
import Editor from "~/components/Editor"; import Editor, { WorkspaceMember } from "~/components/Editor";
import Input from "~/components/Input"; import Input from "~/components/Input";
import LabelIcon from "~/components/LabelIcon"; import LabelIcon from "~/components/LabelIcon";
import Toggle from "~/components/Toggle"; import Toggle from "~/components/Toggle";
@@ -46,7 +46,7 @@ export function NewCardForm({
queryParams, queryParams,
}: NewCardFormProps) { }: NewCardFormProps) {
const { showPopup } = usePopup(); const { showPopup } = usePopup();
const { closeModal, openModal } = useModal(); const { closeModal, openModal, modalStates, clearModalState } = useModal();
const utils = api.useUtils(); const utils = api.useUtils();
@@ -85,10 +85,39 @@ export function NewCardForm({
return () => subscription.unsubscribe(); return () => subscription.unsubscribe();
}, [watch, saveFormState]); }, [watch, saveFormState]);
const { data: boardData } = api.board.byId.useQuery(queryParams, { const { data: boardData } = api.board.byId.useQuery(queryParams, {
enabled: !!boardPublicId, enabled: !!boardPublicId,
}); });
// this adds the new created label to selected labels
useEffect(() => {
const newLabelId = modalStates["NEW_LABEL_CREATED"];
if (newLabelId !== undefined && !labelPublicIds.includes(newLabelId)) {
setValue("labelPublicIds", [...labelPublicIds, newLabelId]);
}
}, [modalStates, labelPublicIds]);
// this removes the deleted label from selected labels if it is selected
useEffect(() => {
if (boardData?.labels) {
const availableLabelIds = boardData.labels.map(label => label.publicId);
const newLabelId = modalStates["NEW_LABEL_CREATED"];
if (newLabelId && availableLabelIds.includes(newLabelId)) {
clearModalState("NEW_LABEL_CREATED");
}
const validLabelIds = labelPublicIds.filter(id =>
availableLabelIds.includes(id) || id === newLabelId
);
if (validLabelIds.length !== labelPublicIds.length) {
setValue("labelPublicIds", validLabelIds);
}
}
}, [boardData?.labels, labelPublicIds, modalStates["NEW_LABEL_CREATED"]]);
const createCard = api.card.create.useMutation({ const createCard = api.card.create.useMutation({
onMutate: async (args) => { onMutate: async (args) => {
await utils.board.byId.cancel(); await utils.board.byId.cancel();
@@ -293,6 +322,17 @@ export function NewCardForm({
setValue("description", value); setValue("description", value);
saveFormState({ ...formState, description: value }); saveFormState({ ...formState, description: value });
}} }}
workspaceMembers={
boardData?.workspace.members?.map((member): WorkspaceMember => ({
publicId: member.publicId,
email: member.email,
user: member.user ? {
id: member.publicId,
name: member.user.name,
image: member.user.image ?? null,
} : null,
})) ?? []
}
/> />
</div> </div>
</div> </div>

View File

@@ -13,7 +13,6 @@ import type { UpdateBoardInput } from "@kan/api/types";
import Button from "~/components/Button"; import Button from "~/components/Button";
import { DeleteLabelConfirmation } from "~/components/DeleteLabelConfirmation"; import { DeleteLabelConfirmation } from "~/components/DeleteLabelConfirmation";
import FeedbackModal from "~/components/FeedbackModal";
import { LabelForm } from "~/components/LabelForm"; import { LabelForm } from "~/components/LabelForm";
import Modal from "~/components/modal"; import Modal from "~/components/modal";
import { NewWorkspaceForm } from "~/components/NewWorkspaceForm"; import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
@@ -238,15 +237,15 @@ export default function BoardPage() {
const renderModalContent = () => { const renderModalContent = () => {
return ( return (
<> <>
<Modal <Modal
modalSize="sm" modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_BOARD"} isVisible={isOpen && modalContentType === "DELETE_BOARD"}
> >
<DeleteBoardConfirmation boardPublicId={boardId ?? ""} /> <DeleteBoardConfirmation boardPublicId={boardId ?? ""} />
</Modal> </Modal>
<Modal <Modal
modalSize="sm" modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_LIST"} isVisible={isOpen && modalContentType === "DELETE_LIST"}
> >
<DeleteListConfirmation <DeleteListConfirmation
@@ -255,8 +254,8 @@ export default function BoardPage() {
/> />
</Modal> </Modal>
<Modal <Modal
modalSize="md" modalSize="md"
isVisible={isOpen && modalContentType === "NEW_CARD"} isVisible={isOpen && modalContentType === "NEW_CARD"}
> >
<NewCardForm <NewCardForm
@@ -266,8 +265,8 @@ export default function BoardPage() {
/> />
</Modal> </Modal>
<Modal <Modal
modalSize="sm" modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_LIST"} isVisible={isOpen && modalContentType === "NEW_LIST"}
> >
<NewListForm <NewListForm
@@ -276,22 +275,22 @@ export default function BoardPage() {
/> />
</Modal> </Modal>
<Modal <Modal
modalSize="sm" modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_WORKSPACE"} isVisible={isOpen && modalContentType === "NEW_WORKSPACE"}
> >
<NewWorkspaceForm /> <NewWorkspaceForm />
</Modal> </Modal>
<Modal <Modal
modalSize="sm" modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_LABEL"} isVisible={isOpen && modalContentType === "NEW_LABEL"}
> >
<LabelForm boardPublicId={boardId ?? ""} refetch={refetchBoard} /> <LabelForm boardPublicId={boardId ?? ""} refetch={refetchBoard} />
</Modal> </Modal>
<Modal <Modal
modalSize="sm" modalSize="sm"
isVisible={isOpen && modalContentType === "EDIT_LABEL"} isVisible={isOpen && modalContentType === "EDIT_LABEL"}
> >
<LabelForm <LabelForm
@@ -301,8 +300,8 @@ export default function BoardPage() {
/> />
</Modal> </Modal>
<Modal <Modal
modalSize="sm" modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_LABEL"} isVisible={isOpen && modalContentType === "DELETE_LABEL"}
> >
<DeleteLabelConfirmation <DeleteLabelConfirmation
@@ -311,8 +310,8 @@ export default function BoardPage() {
/> />
</Modal> </Modal>
<Modal <Modal
modalSize="sm" modalSize="sm"
isVisible={isOpen && modalContentType === "UPDATE_BOARD_SLUG"} isVisible={isOpen && modalContentType === "UPDATE_BOARD_SLUG"}
> >
<UpdateBoardSlugForm <UpdateBoardSlugForm
@@ -376,7 +375,7 @@ export default function BoardPage() {
/> />
<Filters <Filters
labels={boardData?.labels ?? []} labels={boardData?.labels ?? []}
members={boardData?.workspace.members ?? []} members={boardData?.workspace.members?.filter(member => member.user !== null) ?? []}
position="left" position="left"
isLoading={!boardData} isLoading={!boardData}
/> />
@@ -492,6 +491,7 @@ export default function BoardPage() {
title={card.title} title={card.title}
labels={card.labels} labels={card.labels}
members={card.members} members={card.members}
checklists={card.checklists ?? []}
/> />
</Link> </Link>
)} )}

View File

@@ -13,7 +13,7 @@ import { ImportBoardsForm } from "./components/ImportBoardsForm";
import { NewBoardForm } from "./components/NewBoardForm"; import { NewBoardForm } from "./components/NewBoardForm";
export default function BoardsPage() { export default function BoardsPage() {
const { openModal, modalContentType } = useModal(); const { openModal, modalContentType, isOpen } = useModal();
const { workspace, hasLoaded } = useWorkspace(); const { workspace, hasLoaded } = useWorkspace();
if (hasLoaded && !workspace.publicId) openModal("NEW_WORKSPACE"); if (hasLoaded && !workspace.publicId) openModal("NEW_WORKSPACE");
@@ -50,12 +50,35 @@ export default function BoardsPage() {
</div> </div>
</div> </div>
<Modal modalSize={modalContentType === "NEW_FEEDBACK" ? "md" : "sm"}> <>
{modalContentType === "NEW_FEEDBACK" && <FeedbackModal />} <Modal
{modalContentType === "NEW_BOARD" && <NewBoardForm />} modalSize="md"
{modalContentType === "IMPORT_BOARDS" && <ImportBoardsForm />} isVisible={isOpen && modalContentType === "NEW_FEEDBACK"}
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />} >
</Modal> <FeedbackModal />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_BOARD"}
>
<NewBoardForm />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "IMPORT_BOARDS"}
>
<ImportBoardsForm />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_WORKSPACE"}
>
<NewWorkspaceForm />
</Modal>
</>
<div className="flex h-full flex-row"> <div className="flex h-full flex-row">
<BoardsList /> <BoardsList />

View File

@@ -5,9 +5,11 @@ import { de, enGB, es, fr, it, nl } from "date-fns/locale";
import { import {
HiOutlineArrowLeft, HiOutlineArrowLeft,
HiOutlineArrowRight, HiOutlineArrowRight,
HiOutlineCheckCircle,
HiOutlinePencil, HiOutlinePencil,
HiOutlinePlus, HiOutlinePlus,
HiOutlineTag, HiOutlineTag,
HiOutlineTrash,
HiOutlineUserMinus, HiOutlineUserMinus,
HiOutlineUserPlus, HiOutlineUserPlus,
} from "react-icons/hi2"; } from "react-icons/hi2";
@@ -31,6 +33,11 @@ const dateLocaleMap = {
nl: nl, nl: nl,
} as const; } as const;
const truncate = (value: string | null, maxLength = 50) => {
if (!value) return value;
return value.length > maxLength ? `${value.slice(0, maxLength - 1)}` : value;
};
const getActivityText = ({ const getActivityText = ({
type, type,
toTitle, toTitle,
@@ -39,6 +46,7 @@ const getActivityText = ({
memberName, memberName,
isSelf, isSelf,
label, label,
fromTitle,
}: { }: {
type: ActivityType; type: ActivityType;
toTitle: string | null; toTitle: string | null;
@@ -47,6 +55,7 @@ const getActivityText = ({
memberName: string | null; memberName: string | null;
isSelf: boolean; isSelf: boolean;
label: string | null; label: string | null;
fromTitle?: string | null;
}) => { }) => {
const ACTIVITY_TYPE_MAP = { const ACTIVITY_TYPE_MAP = {
"card.created": t`created the card`, "card.created": t`created the card`,
@@ -57,6 +66,14 @@ const getActivityText = ({
"card.updated.label.removed": t`removed a label from the card`, "card.updated.label.removed": t`removed a label from the card`,
"card.updated.member.added": t`added a member to the card`, "card.updated.member.added": t`added a member to the card`,
"card.updated.member.removed": t`removed a member from the card`, "card.updated.member.removed": t`removed a member from the card`,
"card.updated.checklist.added": t`added a checklist`,
"card.updated.checklist.renamed": t`renamed a checklist`,
"card.updated.checklist.deleted": t`deleted a checklist`,
"card.updated.checklist.item.added": t`added a checklist item`,
"card.updated.checklist.item.updated": t`updated a checklist item`,
"card.updated.checklist.item.completed": t`completed a checklist item`,
"card.updated.checklist.item.uncompleted": t`marked a checklist item as incomplete`,
"card.updated.checklist.item.deleted": t`deleted a checklist item`,
} as const; } as const;
if (!(type in ACTIVITY_TYPE_MAP)) return null; if (!(type in ACTIVITY_TYPE_MAP)) return null;
@@ -71,7 +88,7 @@ const getActivityText = ({
if (type === "card.updated.title" && toTitle) { if (type === "card.updated.title" && toTitle) {
return ( return (
<Trans> <Trans>
updated the title to <TextHighlight>{toTitle}</TextHighlight> updated the title to <TextHighlight>{truncate(toTitle)}</TextHighlight>
</Trans> </Trans>
); );
} }
@@ -79,8 +96,9 @@ const getActivityText = ({
if (type === "card.updated.list" && fromList && toList) { if (type === "card.updated.list" && fromList && toList) {
return ( return (
<Trans> <Trans>
moved the card from <TextHighlight>{fromList}</TextHighlight> to moved the card from <TextHighlight>{truncate(fromList)}</TextHighlight>{" "}
<TextHighlight>{toList}</TextHighlight> to
<TextHighlight>{truncate(toList)}</TextHighlight>
</Trans> </Trans>
); );
} }
@@ -90,7 +108,8 @@ const getActivityText = ({
return ( return (
<Trans> <Trans>
assigned <TextHighlight>{memberName}</TextHighlight> to the card assigned <TextHighlight>{truncate(memberName)}</TextHighlight> to the
card
</Trans> </Trans>
); );
} }
@@ -100,7 +119,8 @@ const getActivityText = ({
return ( return (
<Trans> <Trans>
unassigned <TextHighlight>{memberName}</TextHighlight> from the card unassigned <TextHighlight>{truncate(memberName)}</TextHighlight> from
the card
</Trans> </Trans>
); );
} }
@@ -108,7 +128,7 @@ const getActivityText = ({
if (type === "card.updated.label.added" && label) { if (type === "card.updated.label.added" && label) {
return ( return (
<Trans> <Trans>
added label <TextHighlight>{label}</TextHighlight> added label <TextHighlight>{truncate(label)}</TextHighlight>
</Trans> </Trans>
); );
} }
@@ -116,7 +136,75 @@ const getActivityText = ({
if (type === "card.updated.label.removed" && label) { if (type === "card.updated.label.removed" && label) {
return ( return (
<Trans> <Trans>
removed label <TextHighlight>{label}</TextHighlight> removed label <TextHighlight>{truncate(label)}</TextHighlight>
</Trans>
);
}
if (type === "card.updated.checklist.added" && toTitle) {
return (
<Trans>
added checklist <TextHighlight>{truncate(toTitle)}</TextHighlight>
</Trans>
);
}
if (type === "card.updated.checklist.renamed" && toTitle) {
return (
<Trans>
renamed checklist <TextHighlight>{truncate(toTitle)}</TextHighlight>
</Trans>
);
}
if (type === "card.updated.checklist.deleted" && fromTitle) {
return (
<Trans>
deleted checklist <TextHighlight>{truncate(fromTitle)}</TextHighlight>
</Trans>
);
}
if (type === "card.updated.checklist.item.added" && toTitle) {
return (
<Trans>
added checklist item <TextHighlight>{truncate(toTitle)}</TextHighlight>
</Trans>
);
}
if (type === "card.updated.checklist.item.updated" && toTitle) {
return (
<Trans>
renamed checklist item to{" "}
<TextHighlight>{truncate(toTitle)}</TextHighlight>
</Trans>
);
}
if (type === "card.updated.checklist.item.completed" && toTitle) {
return (
<Trans>
completed checklist item{" "}
<TextHighlight>{truncate(toTitle)}</TextHighlight>
</Trans>
);
}
if (type === "card.updated.checklist.item.uncompleted" && toTitle) {
return (
<Trans>
marked checklist item <TextHighlight>{truncate(toTitle)}</TextHighlight>{" "}
as incomplete
</Trans>
);
}
if (type === "card.updated.checklist.item.deleted" && fromTitle) {
return (
<Trans>
deleted checklist item{" "}
<TextHighlight>{truncate(fromTitle)}</TextHighlight>
</Trans> </Trans>
); );
} }
@@ -133,6 +221,14 @@ const ACTIVITY_ICON_MAP: Partial<Record<ActivityType, React.ReactNode | null>> =
"card.updated.label.removed": <HiOutlineTag />, "card.updated.label.removed": <HiOutlineTag />,
"card.updated.member.added": <HiOutlineUserPlus />, "card.updated.member.added": <HiOutlineUserPlus />,
"card.updated.member.removed": <HiOutlineUserMinus />, "card.updated.member.removed": <HiOutlineUserMinus />,
"card.updated.checklist.added": <HiOutlinePlus />,
"card.updated.checklist.renamed": <HiOutlinePencil />,
"card.updated.checklist.deleted": <HiOutlineTrash />,
"card.updated.checklist.item.added": <HiOutlinePlus />,
"card.updated.checklist.item.updated": <HiOutlinePencil />,
"card.updated.checklist.item.completed": <HiOutlineCheckCircle />,
"card.updated.checklist.item.uncompleted": <HiOutlineCheckCircle />,
"card.updated.checklist.item.deleted": <HiOutlineTrash />,
} as const; } as const;
const getActivityIcon = ( const getActivityIcon = (
@@ -179,6 +275,7 @@ const ActivityList = ({
memberName: activity.member?.user?.name ?? null, memberName: activity.member?.user?.name ?? null,
isSelf: activity.member?.user?.id === data?.user.id, isSelf: activity.member?.user?.id === data?.user.id,
label: activity.label?.name ?? null, label: activity.label?.name ?? null,
fromTitle: activity.fromTitle ?? null,
}); });
if (activity.type === "card.updated.comment.added") if (activity.type === "card.updated.comment.added")

View File

@@ -0,0 +1,197 @@
import { t } from "@lingui/core/macro";
import { useEffect, useState } from "react";
import ContentEditable from "react-contenteditable";
import { HiXMark } from "react-icons/hi2";
import { twMerge } from "tailwind-merge";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
interface ChecklistItemRowProps {
item: {
publicId: string;
title: string;
completed: boolean;
};
cardPublicId: string;
viewOnly?: boolean;
}
export default function ChecklistItemRow({
item,
cardPublicId,
viewOnly = false,
}: ChecklistItemRowProps) {
const utils = api.useUtils();
const { showPopup } = usePopup();
const [title, setTitle] = useState("");
const [completed, setCompleted] = useState(false);
const updateItem = api.checklist.updateItem.useMutation({
onMutate: async (vars) => {
await utils.card.byId.cancel({ cardPublicId });
const previous = utils.card.byId.getData({ cardPublicId });
utils.card.byId.setData({ cardPublicId }, (old) => {
if (!old) return old as any;
const updatedChecklists = old.checklists.map((cl) => ({
...cl,
items: cl.items.map((ci) =>
ci.publicId === item.publicId
? {
...ci,
...(vars.title !== undefined ? { title: vars.title } : {}),
...(vars.completed !== undefined
? { completed: vars.completed }
: {}),
}
: ci,
),
}));
return { ...old, checklists: updatedChecklists } as typeof old;
});
return { previous };
},
onError: (_err, _vars, ctx) => {
if (ctx?.previous)
utils.card.byId.setData({ cardPublicId }, ctx.previous);
showPopup({
header: t`Unable to update checklist item`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId });
},
});
const deleteItem = api.checklist.deleteItem.useMutation({
onMutate: async () => {
await utils.card.byId.cancel({ cardPublicId });
const previous = utils.card.byId.getData({ cardPublicId });
utils.card.byId.setData({ cardPublicId }, (old) => {
if (!old) return old as any;
const updatedChecklists = old.checklists.map((cl) => ({
...cl,
items: cl.items.filter((ci) => ci.publicId !== item.publicId),
}));
return { ...old, checklists: updatedChecklists } as typeof old;
});
return { previous };
},
onError: (_err, _vars, ctx) => {
if (ctx?.previous)
utils.card.byId.setData({ cardPublicId }, ctx.previous);
showPopup({
header: t`Unable to delete checklist item`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId });
},
});
// Only resync from props when switching items to avoid clobbering edits
useEffect(() => {
setTitle(item.title);
setCompleted(item.completed);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [item.publicId]);
const sanitizeHtmlToPlainText = (html: string): string =>
html
.replace(/<br\s*\/?>(\n)?/gi, "\n")
.replace(/<div><br\s*\/?><\/div>/gi, "")
.replace(/<[^>]*>/g, "")
.replace(/&nbsp;/g, " ")
.trim();
const handleToggleCompleted = () => {
if (viewOnly) return;
setCompleted((prev) => !prev);
updateItem.mutate({
checklistItemPublicId: item.publicId,
completed: !completed,
});
};
const commitTitle = (rawHtml: string) => {
if (viewOnly) return;
const plain = sanitizeHtmlToPlainText(rawHtml);
if (!plain || plain === item.title) {
setTitle(item.title);
return;
}
setTitle(plain);
updateItem.mutate({
checklistItemPublicId: item.publicId,
title: plain,
});
};
const handleDelete = () => {
if (viewOnly) return;
deleteItem.mutate({ checklistItemPublicId: item.publicId });
};
return (
<div className="group relative flex items-start gap-3 rounded-md py-2 pl-4 hover:bg-light-100 dark:hover:bg-dark-100">
<label
className={`relative mt-[2px] inline-flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center`}
>
<input
type="checkbox"
checked={completed}
onChange={(e) => {
if (viewOnly) {
e.preventDefault();
return;
}
handleToggleCompleted();
}}
className={twMerge(
"h-[16px] w-[16px] appearance-none rounded-md border border-light-500 bg-transparent outline-none ring-0 checked:bg-blue-600 focus:shadow-none focus:ring-0 focus:ring-offset-0 focus-visible:outline-none dark:border-dark-500 dark:hover:border-dark-500",
viewOnly ? "cursor-default" : "cursor-pointer",
)}
/>
</label>
<div className="flex-1 pr-7">
<ContentEditable
html={title}
disabled={viewOnly}
onChange={(e) => setTitle(e.target.value)}
// @ts-expect-error - valid event
onBlur={(e: Event) => commitTitle(e.target.innerHTML as string)}
className={twMerge(
"m-0 min-h-[20px] w-full p-0 text-sm leading-[20px] text-light-950 outline-none focus-visible:outline-none dark:text-dark-950",
viewOnly && "cursor-default",
)}
placeholder={t`Add details...`}
onKeyDown={(e) => {
if (viewOnly) return;
if (e.key === "Enter") {
e.preventDefault();
commitTitle(title);
}
if (e.key === "Escape") {
e.preventDefault();
setTitle(item.title);
}
}}
/>
</div>
{!viewOnly && (
<button
type="button"
onClick={handleDelete}
className="absolute right-1 top-1/2 hidden -translate-y-1/2 rounded-md p-1 text-light-900 group-hover:block hover:bg-light-200 dark:text-dark-700 dark:hover:bg-dark-200"
>
<HiXMark size={16} />
</button>
)}
</div>
);
}

View File

@@ -0,0 +1,90 @@
import { t } from "@lingui/core/macro";
import { useEffect, useRef, useState } from "react";
import { twMerge } from "tailwind-merge";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
export default function ChecklistNameInput({
checklistPublicId,
initialName,
cardPublicId,
viewOnly = false,
}: {
checklistPublicId: string;
initialName: string;
cardPublicId: string;
viewOnly?: boolean;
}) {
const utils = api.useUtils();
const { showPopup } = usePopup();
const [name, setName] = useState(initialName);
const inputRef = useRef<HTMLInputElement | null>(null);
useEffect(() => {
setName(initialName);
}, [initialName, checklistPublicId]);
const update = api.checklist.update.useMutation({
onMutate: async (vars) => {
await utils.card.byId.cancel({ cardPublicId });
const previous = utils.card.byId.getData({ cardPublicId });
utils.card.byId.setData({ cardPublicId }, (old) => {
if (!old) return old as any;
const updated = old.checklists.map((cl) =>
cl.publicId === checklistPublicId ? { ...cl, name: vars.name } : cl,
);
return { ...old, checklists: updated } as typeof old;
});
return { previous };
},
onError: (_err, _vars, ctx) => {
if (ctx?.previous)
utils.card.byId.setData({ cardPublicId }, ctx.previous);
showPopup({
header: t`Unable to update checklist`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId });
},
});
const commit = () => {
if (viewOnly) return;
const trimmed = name.trim();
if (!trimmed || trimmed === initialName) return;
update.mutate({ checklistPublicId, name: trimmed });
};
return (
<input
ref={inputRef}
type="text"
value={name}
readOnly={viewOnly}
onChange={(e) => setName(e.target.value)}
onBlur={commit}
onKeyDown={(e) => {
if (viewOnly) return;
if (e.key === "Enter") {
e.preventDefault();
commit();
inputRef.current?.blur();
}
if (e.key === "Escape") {
e.preventDefault();
setName(initialName);
inputRef.current?.blur();
}
}}
title={name}
className={twMerge(
"text-md block w-full truncate border-0 bg-transparent p-0 py-0 font-medium text-light-1000 outline-none focus:ring-0 dark:text-dark-1000",
viewOnly && "cursor-default",
)}
/>
);
}

View File

@@ -0,0 +1,142 @@
import { HiPlus, HiXMark } from "react-icons/hi2";
import CircularProgress from "~/components/CircularProgress";
import { useModal } from "~/providers/modal";
import ChecklistItemRow from "./ChecklistItemRow";
import ChecklistNameInput from "./ChecklistNameInput";
import NewChecklistItemForm from "./NewChecklistItemForm";
interface ChecklistItem {
publicId: string;
title: string;
completed: boolean;
}
interface Checklist {
publicId: string;
name: string;
items: ChecklistItem[];
}
interface ChecklistsProps {
checklists: Checklist[];
cardPublicId: string;
activeChecklistForm?: string | null;
setActiveChecklistForm?: (id: string | null) => void;
viewOnly?: boolean;
}
export default function Checklists({
checklists,
cardPublicId,
activeChecklistForm,
setActiveChecklistForm,
viewOnly = false,
}: ChecklistsProps) {
const { openModal } = useModal();
if (!checklists || checklists.length === 0) return null;
return (
<div className="border-light-300 pb-4 dark:border-dark-300">
<div>
{checklists.map((checklist) => {
const completedItems = checklist.items.filter(
(item) => item.completed,
);
const progress =
checklist.items.length > 0 && completedItems.length > 0
? (completedItems.length / checklist.items.length) * 100
: 2;
return (
<div key={checklist.publicId} className="mb-4">
<div className="mb-2 flex items-center font-medium text-light-1000 dark:text-dark-1000">
<div className="min-w-0 flex-1">
<ChecklistNameInput
checklistPublicId={checklist.publicId}
initialName={checklist.name}
cardPublicId={cardPublicId}
viewOnly={viewOnly}
/>
</div>
{!viewOnly && (
<div className="ml-2 flex flex-shrink-0 items-center gap-2">
<div className="flex items-center gap-1 rounded-full border-[1px] border-light-300 px-2 py-1 dark:border-dark-300">
<CircularProgress
progress={progress}
size="sm"
className="flex-shrink-0"
/>
<span className="text-[11px] text-light-900 dark:text-dark-700">
{completedItems.length}/{checklist.items.length}
</span>
</div>
<div>
<button
className="rounded-md p-1 text-light-900 hover:bg-light-100 dark:text-dark-700 dark:hover:bg-dark-100"
onClick={() =>
openModal("DELETE_CHECKLIST", checklist.publicId)
}
>
<HiXMark size={16} />
</button>
<button
onClick={() =>
setActiveChecklistForm?.(checklist.publicId)
}
className="rounded-md p-1 text-light-900 hover:bg-light-100 dark:text-dark-700 dark:hover:bg-dark-100"
>
<HiPlus size={16} />
</button>
</div>
</div>
)}
{viewOnly && (
<div className="ml-2 flex flex-shrink-0 items-center gap-2">
<div className="flex items-center gap-1 rounded-full border-[1px] border-light-300 px-2 py-1 dark:border-dark-300">
<CircularProgress
progress={progress}
size="sm"
className="flex-shrink-0"
/>
<span className="text-[11px] text-light-900 dark:text-dark-700">
{completedItems.length}/{checklist.items.length}
</span>
</div>
</div>
)}
</div>
<div className="ml-1">
{checklist.items.map((item) => (
<ChecklistItemRow
key={item.publicId}
item={{
publicId: item.publicId,
title: item.title,
completed: item.completed,
}}
cardPublicId={cardPublicId}
viewOnly={viewOnly}
/>
))}
</div>
{activeChecklistForm === checklist.publicId && !viewOnly && (
<div className="ml-1">
<NewChecklistItemForm
checklistPublicId={checklist.publicId}
cardPublicId={cardPublicId}
onCancel={() => setActiveChecklistForm?.(null)}
readOnly={viewOnly}
/>
</div>
)}
</div>
);
})}
</div>
</div>
);
}

View File

@@ -0,0 +1,71 @@
import { t } from "@lingui/core/macro";
import Button from "~/components/Button";
import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
export function DeleteChecklistConfirmation({
cardPublicId,
checklistPublicId,
}: {
cardPublicId: string;
checklistPublicId: string;
}) {
const { closeModal } = useModal();
const { showPopup } = usePopup();
const utils = api.useUtils();
const deleteChecklist = api.checklist.delete.useMutation({
onMutate: async () => {
await utils.card.byId.cancel({ cardPublicId });
const previous = utils.card.byId.getData({ cardPublicId });
utils.card.byId.setData({ cardPublicId }, (old) => {
if (!old) return old as any;
const updatedChecklists = old.checklists.filter(
(cl) => cl.publicId !== checklistPublicId,
);
return { ...old, checklists: updatedChecklists } as typeof old;
});
return { previous };
},
onError: (_err, _vars, ctx) => {
if (ctx?.previous)
utils.card.byId.setData({ cardPublicId }, ctx.previous);
showPopup({
header: t`Unable to delete checklist`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSettled: async () => {
closeModal();
await utils.card.byId.invalidate({ cardPublicId });
},
});
const handleDelete = () => {
deleteChecklist.mutate({ checklistPublicId });
};
return (
<div className="p-5">
<div className="flex w-full flex-col justify-between pb-4">
<h2 className="text-md pb-4 font-medium text-neutral-900 dark:text-dark-1000">
{t`Are you sure you want to delete this checklist?`}
</h2>
<p className="text-sm font-medium text-light-900 dark:text-dark-900">
{t`This action can't be undone.`}
</p>
</div>
<div className="mt-5 flex justify-end space-x-2 sm:mt-6">
<Button variant="secondary" onClick={() => closeModal()}>
{t`Cancel`}
</Button>
<Button onClick={handleDelete} isLoading={deleteChecklist.isPending}>
{t`Delete`}
</Button>
</div>
</div>
);
}

View File

@@ -1,5 +1,9 @@
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro";
import { HiEllipsisHorizontal, HiOutlineTrash } from "react-icons/hi2"; import {
HiEllipsisHorizontal,
HiOutlineCheckCircle,
HiOutlineTrash,
} from "react-icons/hi2";
import Dropdown from "~/components/Dropdown"; import Dropdown from "~/components/Dropdown";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
@@ -10,6 +14,13 @@ export default function BoardDropdown() {
return ( return (
<Dropdown <Dropdown
items={[ items={[
{
label: t`Add checklist`,
action: () => openModal("ADD_CHECKLIST"),
icon: (
<HiOutlineCheckCircle className="h-[16px] w-[16px] text-dark-900" />
),
},
{ {
label: t`Delete card`, label: t`Delete card`,
action: () => openModal("DELETE_CARD"), action: () => openModal("DELETE_CARD"),

View File

@@ -0,0 +1,140 @@
import { t } from "@lingui/core/macro";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { HiXMark } from "react-icons/hi2";
import { generateUID } from "@kan/shared/utils";
import Button from "~/components/Button";
import Input from "~/components/Input";
import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
interface NewChecklistFormInput {
name: string;
cardPublicId: string;
}
export function NewChecklistForm({ cardPublicId }: { cardPublicId: string }) {
const { closeModal, setModalState } = useModal();
const { showPopup } = usePopup();
const utils = api.useUtils();
const { register, handleSubmit, reset, watch } =
useForm<NewChecklistFormInput>({
defaultValues: {
name: "Checklist",
cardPublicId,
},
});
const createChecklist = api.checklist.create.useMutation({
onMutate: async (args) => {
await utils.card.byId.cancel({ cardPublicId: args.cardPublicId });
const previous = utils.card.byId.getData({
cardPublicId: args.cardPublicId,
});
utils.card.byId.setData({ cardPublicId: args.cardPublicId }, (old) => {
if (!old) return old as any;
const placeholderChecklist = {
publicId: `PLACEHOLDER_${generateUID()}`,
name: args.name,
index: old.checklists.length,
items: [] as {
publicId: string;
title: string;
completed: boolean;
index: number;
}[],
};
return {
...old,
checklists: [...old.checklists, placeholderChecklist],
} as typeof old;
});
return { previous };
},
onSuccess: (data) => {
setModalState("ADD_CHECKLIST", { createdChecklistId: data.publicId });
},
onError: (_error, vars, ctx) => {
if (ctx?.previous)
utils.card.byId.setData(
{ cardPublicId: vars.cardPublicId },
ctx.previous,
);
showPopup({
header: t`Unable to create checklist`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSettled: async (_data, _error, vars) => {
await utils.card.byId.invalidate({ cardPublicId: vars.cardPublicId });
},
});
useEffect(() => {
const nameElement: HTMLElement | null =
document.querySelector<HTMLElement>("#checklist-name");
if (nameElement) nameElement.focus();
}, []);
const onSubmit = (data: NewChecklistFormInput) => {
closeModal();
reset({
name: "",
});
createChecklist.mutate({
name: data.name,
cardPublicId: data.cardPublicId,
});
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="px-5 pt-5">
<div className="flex w-full items-center justify-between pb-4">
<h2 className="text-sm font-bold text-neutral-900 dark:text-dark-1000">
{t`New checklist`}
</h2>
<button
type="button"
className="rounded p-1 hover:bg-light-200 focus:outline-none dark:hover:bg-dark-300"
onClick={(e) => {
e.preventDefault();
closeModal();
}}
>
<HiXMark size={18} className="text-light-900 dark:text-dark-900" />
</button>
</div>
<Input
id="checklist-name"
placeholder={t`Checklist name`}
{...register("name")}
onKeyDown={async (e) => {
if (e.key === "Enter") {
e.preventDefault();
await handleSubmit(onSubmit)();
}
}}
/>
</div>
<div className="mt-12 flex items-center justify-end border-t border-light-600 px-5 pb-5 pt-5 dark:border-dark-600">
<div>
<Button
type="submit"
disabled={createChecklist.isPending || !watch("name")}
>
{t`Create checklist`}
</Button>
</div>
</div>
</form>
);
}

View File

@@ -0,0 +1,167 @@
import { t } from "@lingui/core/macro";
import { useEffect, useRef } from "react";
import ContentEditable from "react-contenteditable";
import { useForm } from "react-hook-form";
import { generateUID } from "@kan/shared/utils";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
interface FormValues {
title: string;
}
interface NewChecklistItemFormProps {
checklistPublicId: string;
cardPublicId: string;
onCancel: () => void;
readOnly?: boolean;
}
const NewChecklistItemForm = ({
checklistPublicId,
cardPublicId,
onCancel,
readOnly = false,
}: NewChecklistItemFormProps) => {
const utils = api.useUtils();
const { showPopup } = usePopup();
const { setValue, watch, reset, getValues } = useForm<FormValues>({
defaultValues: {
title: "",
},
});
const title = watch("title");
const editableRef = useRef<HTMLElement | null>(null);
const keepOpenRef = useRef(false);
const refocusEditable = () => {
const el = editableRef.current;
if (!el) return;
if (readOnly) return;
el.focus();
// hack to ensure the input is focused after creating new checklist item
setTimeout(() => {
el.focus();
}, 100);
};
const addChecklistItemMutation = api.checklist.createItem.useMutation({
onMutate: async (vars) => {
await utils.card.byId.cancel({ cardPublicId });
const previous = utils.card.byId.getData({ cardPublicId });
utils.card.byId.setData({ cardPublicId }, (old) => {
if (!old) return old as any;
const placeholder = {
publicId: `PLACEHOLDER_${generateUID()}`,
title: vars.title,
completed: false,
};
const updatedChecklists = old.checklists.map((cl) =>
cl.publicId === checklistPublicId
? { ...cl, items: [...cl.items, placeholder] }
: cl,
);
return { ...old, checklists: updatedChecklists } as typeof old;
});
if (keepOpenRef.current) {
reset({ title: "" });
if (editableRef.current) editableRef.current.innerHTML = "";
refocusEditable();
} else {
onCancel();
}
return { previous };
},
onError: (_err, _vars, ctx) => {
if (ctx?.previous)
utils.card.byId.setData({ cardPublicId }, ctx.previous);
showPopup({
header: t`Unable to add checklist item`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId });
},
});
const sanitizeHtmlToPlainText = (html: string): string => {
return html
.replace(/<br\s*\/?>(\n)?/gi, "\n")
.replace(/<div><br\s*\/?><\/div>/gi, "")
.replace(/<[^>]*>/g, "")
.replace(/&nbsp;/g, " ")
.trim();
};
const submitIfNotEmpty = (keepOpen: boolean) => {
if (readOnly) return;
keepOpenRef.current = keepOpen;
const currentHtml = getValues("title") ?? "";
const plain = sanitizeHtmlToPlainText(currentHtml);
if (!plain) {
onCancel();
return;
}
addChecklistItemMutation.mutate({
checklistPublicId,
title: plain,
});
};
useEffect(() => {
refocusEditable();
}, []);
return (
<form onSubmit={(e) => e.preventDefault()}>
<div className="group relative flex h-9 items-center gap-3 rounded-md pl-4 hover:bg-light-100 dark:hover:bg-dark-100">
<label className="relative inline-flex h-[16px] w-[16px] flex-shrink-0 cursor-default items-center justify-center">
<input
type="checkbox"
disabled
className="peer h-[16px] w-[16px] appearance-none rounded-md border border-light-500 bg-transparent outline-none ring-0 hover:border-light-500 hover:bg-transparent focus:outline-none focus:ring-0 focus-visible:outline-none dark:border-dark-500 dark:hover:border-dark-500"
/>
</label>
<div className="flex-1 pr-7">
<ContentEditable
id={`checklist-item-input-${checklistPublicId}`}
tabIndex={readOnly ? -1 : 0}
placeholder={t`Add an item...`}
html={title}
disabled={readOnly}
onChange={(e) => setValue("title", e.target.value)}
className="m-0 min-h-[20px] w-full p-0 text-sm leading-5 text-light-900 outline-none focus-visible:outline-none dark:text-dark-950"
onBlur={() => submitIfNotEmpty(false)}
onKeyDown={async (e) => {
if (readOnly) return;
if (e.key === "Enter") {
e.preventDefault();
submitIfNotEmpty(true);
}
if (e.key === "Escape") {
e.preventDefault();
onCancel();
}
}}
innerRef={(el) => {
editableRef.current = (el as unknown as HTMLElement) ?? null;
}}
/>
</div>
</div>
</form>
);
};
export default NewChecklistItemForm;

View File

@@ -1,6 +1,7 @@
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { IoChevronForwardSharp } from "react-icons/io5"; import { IoChevronForwardSharp } from "react-icons/io5";
@@ -19,12 +20,15 @@ import { api } from "~/utils/api";
import { formatMemberDisplayName, getAvatarUrl } from "~/utils/helpers"; import { formatMemberDisplayName, getAvatarUrl } from "~/utils/helpers";
import { DeleteLabelConfirmation } from "../../components/DeleteLabelConfirmation"; import { DeleteLabelConfirmation } from "../../components/DeleteLabelConfirmation";
import ActivityList from "./components/ActivityList"; import ActivityList from "./components/ActivityList";
import Checklists from "./components/Checklists";
import { DeleteCardConfirmation } from "./components/DeleteCardConfirmation"; import { DeleteCardConfirmation } from "./components/DeleteCardConfirmation";
import { DeleteChecklistConfirmation } from "./components/DeleteChecklistConfirmation";
import { DeleteCommentConfirmation } from "./components/DeleteCommentConfirmation"; import { DeleteCommentConfirmation } from "./components/DeleteCommentConfirmation";
import Dropdown from "./components/Dropdown"; import Dropdown from "./components/Dropdown";
import LabelSelector from "./components/LabelSelector"; import LabelSelector from "./components/LabelSelector";
import ListSelector from "./components/ListSelector"; import ListSelector from "./components/ListSelector";
import MemberSelector from "./components/MemberSelector"; import MemberSelector from "./components/MemberSelector";
import { NewChecklistForm } from "./components/NewChecklistForm";
import NewCommentForm from "./components/NewCommentForm"; import NewCommentForm from "./components/NewCommentForm";
interface FormValues { interface FormValues {
@@ -132,9 +136,19 @@ export function CardRightPanel() {
export default function CardPage() { export default function CardPage() {
const router = useRouter(); const router = useRouter();
const utils = api.useUtils(); const utils = api.useUtils();
const { modalContentType, entityId } = useModal(); const {
modalContentType,
entityId,
openModal,
getModalState,
clearModalState,
isOpen,
} = useModal();
const { showPopup } = usePopup(); const { showPopup } = usePopup();
const { workspace } = useWorkspace(); const { workspace } = useWorkspace();
const [activeChecklistForm, setActiveChecklistForm] = useState<string | null>(
null,
);
const cardId = Array.isArray(router.query.cardId) const cardId = Array.isArray(router.query.cardId)
? router.query.cardId[0] ? router.query.cardId[0]
@@ -181,6 +195,17 @@ export default function CardPage() {
}); });
}; };
// Open the new item form after creating a new checklist
useEffect(() => {
if (!card) return;
const state = getModalState("ADD_CHECKLIST");
const createdId: string | undefined = state?.createdChecklistId;
if (createdId) {
setActiveChecklistForm(createdId);
clearModalState("ADD_CHECKLIST");
}
}, [card, getModalState, clearModalState]);
if (!cardId) return <></>; if (!cardId) return <></>;
return ( return (
@@ -188,122 +213,179 @@ export default function CardPage() {
<PageHead <PageHead
title={t`${card?.title ?? "Card"} | ${board?.name ?? "Board"}`} title={t`${card?.title ?? "Card"} | ${board?.name ?? "Board"}`}
/> />
<div className="flex h-full flex-1 flex-row"> <div className="flex h-full flex-1 flex-row overflow-hidden">
<div className="m-auto flex h-full w-full max-w-[800px] flex-col overflow-hidden"> <div className="scrollbar-thumb-rounded-[4px] scrollbar-track-rounded-[4px] w-full flex-1 overflow-y-auto scrollbar scrollbar-track-light-200 scrollbar-thumb-light-400 hover:scrollbar-thumb-light-400 dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-300 dark:hover:scrollbar-thumb-dark-300">
<div className="h-full max-h-[calc(100dvh-3rem)] overflow-y-auto p-6 md:max-h-[calc(100dvh-4rem)] md:p-8"> <div className="p-auto mx-auto flex h-full w-full max-w-[800px] flex-col">
<div className="mb-8 flex w-full items-center justify-between md:mt-6"> <div className="p-6 md:p-8">
{!card && isLoading && ( <div className="mb-8 flex w-full items-center justify-between md:mt-6">
<div className="flex space-x-2"> {!card && isLoading && (
<div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" /> <div className="flex space-x-2">
<div className="h-[2.3rem] w-[300px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" /> <div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" />
</div> <div className="h-[2.3rem] w-[300px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" />
)} </div>
)}
{card && (
<>
<Link
className="whitespace-nowrap font-bold leading-[2.3rem] tracking-tight text-light-900 dark:text-dark-900 sm:text-[1.2rem]"
href={`/boards/${board?.publicId}`}
>
{board?.name}
</Link>
<IoChevronForwardSharp
size={18}
className="mx-2 text-light-900 dark:text-dark-900"
/>
<form
onSubmit={handleSubmit(onSubmit)}
className="w-full space-y-6"
>
<div>
<input
type="text"
id="title"
{...register("title")}
onBlur={handleSubmit(onSubmit)}
className="block w-full border-0 bg-transparent p-0 py-0 font-bold tracking-tight text-neutral-900 focus:ring-0 dark:text-dark-1000 sm:text-[1.2rem]"
/>
</div>
</form>
<div className="flex">
<Dropdown />
</div>
</>
)}
{!card && !isLoading && (
<p className="block p-0 py-0 font-bold leading-[2.3rem] tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
{t`Card not found`}
</p>
)}
</div>
{card && ( {card && (
<> <>
<Link <div className="mb-10 flex w-full max-w-2xl flex-col justify-between">
className="whitespace-nowrap font-bold leading-[2.3rem] tracking-tight text-light-900 dark:text-dark-900 sm:text-[1.2rem]" <form
href={`/boards/${board?.publicId}`} onSubmit={handleSubmit(onSubmit)}
> className="w-full space-y-6"
{board?.name} >
</Link> <div className="mt-2">
<IoChevronForwardSharp <Editor
size={18} content={card.description}
className="mx-2 text-light-900 dark:text-dark-900" onChange={(e) => setValue("description", e)}
onBlur={() => handleSubmit(onSubmit)()}
workspaceMembers={board?.workspace.members ?? []}
/>
</div>
</form>
</div>
<Checklists
checklists={card.checklists}
cardPublicId={cardId}
activeChecklistForm={activeChecklistForm}
setActiveChecklistForm={setActiveChecklistForm}
/> />
<form <div className="border-t-[1px] border-light-300 pt-12 dark:border-dark-300">
onSubmit={handleSubmit(onSubmit)} <h2 className="text-md pb-4 font-medium text-light-1000 dark:text-dark-1000">
className="w-full space-y-6" {t`Activity`}
> </h2>
<div> <div>
<input <ActivityList
type="text" cardPublicId={cardId}
id="title" activities={activities ?? []}
{...register("title")} isLoading={!card}
onBlur={handleSubmit(onSubmit)} isAdmin={workspace.role === "admin"}
className="block w-full border-0 bg-transparent p-0 py-0 font-bold tracking-tight text-neutral-900 focus:ring-0 dark:text-dark-1000 sm:text-[1.2rem]"
/> />
</div> </div>
</form> <div className="mt-6">
<div className="flex"> <NewCommentForm cardPublicId={cardId} />
<Dropdown /> </div>
</div> </div>
</> </>
)} )}
{!card && !isLoading && (
<p className="block p-0 py-0 font-bold leading-[2.3rem] tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
{t`Card not found`}
</p>
)}
</div> </div>
{card && (
<>
<div className="mb-10 flex w-full max-w-2xl flex-col justify-between">
<form
onSubmit={handleSubmit(onSubmit)}
className="w-full space-y-6"
>
<div className="mt-2">
<Editor
content={card.description}
onChange={(e) => setValue("description", e)}
onBlur={() => handleSubmit(onSubmit)()}
/>
</div>
</form>
</div>
<div className="border-t-[1px] border-light-300 pt-12 dark:border-dark-300">
<h2 className="text-md pb-4 font-medium text-light-900 dark:text-dark-1000">
{t`Activity`}
</h2>
<div>
<ActivityList
cardPublicId={cardId}
activities={activities ?? []}
isLoading={!card}
isAdmin={workspace.role === "admin"}
/>
</div>
<div className="mt-6">
<NewCommentForm cardPublicId={cardId} />
</div>
</div>
</>
)}
</div> </div>
</div> </div>
<Modal modalSize={modalContentType === "NEW_FEEDBACK" ? "md" : "sm"}> <>
{modalContentType === "NEW_FEEDBACK" && <FeedbackModal />} <Modal
{modalContentType === "NEW_LABEL" && ( modalSize="md"
isVisible={isOpen && modalContentType === "NEW_FEEDBACK"}
>
<FeedbackModal />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_LABEL"}
>
<LabelForm boardPublicId={boardId ?? ""} refetch={refetchCard} /> <LabelForm boardPublicId={boardId ?? ""} refetch={refetchCard} />
)} </Modal>
{modalContentType === "EDIT_LABEL" && (
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "EDIT_LABEL"}
>
<LabelForm <LabelForm
boardPublicId={boardId ?? ""} boardPublicId={boardId ?? ""}
refetch={refetchCard} refetch={refetchCard}
isEdit isEdit
/> />
)} </Modal>
{modalContentType === "DELETE_LABEL" && (
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_LABEL"}
>
<DeleteLabelConfirmation <DeleteLabelConfirmation
refetch={refetchCard} refetch={refetchCard}
labelPublicId={entityId} labelPublicId={entityId}
/> />
)} </Modal>
{modalContentType === "DELETE_CARD" && (
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_CARD"}
>
<DeleteCardConfirmation <DeleteCardConfirmation
boardPublicId={boardId ?? ""} boardPublicId={boardId ?? ""}
cardPublicId={cardId} cardPublicId={cardId}
/> />
)} </Modal>
{modalContentType === "DELETE_COMMENT" && (
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_COMMENT"}
>
<DeleteCommentConfirmation <DeleteCommentConfirmation
cardPublicId={cardId} cardPublicId={cardId}
commentPublicId={entityId} commentPublicId={entityId}
/> />
)} </Modal>
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />}
</Modal> <Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_WORKSPACE"}
>
<NewWorkspaceForm />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "ADD_CHECKLIST"}
>
<NewChecklistForm cardPublicId={cardId} />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_CHECKLIST"}
>
<DeleteChecklistConfirmation
cardPublicId={cardId}
checklistPublicId={entityId}
/>
</Modal>
</>
</div> </div>
</> </>
); );

View File

@@ -1,17 +1,17 @@
import PatternedBackground from "~/components/PatternedBackground"; import PatternedBackground from "~/components/PatternedBackground";
import { useTheme } from "~/providers/theme"; import { useTheme } from "next-themes";
import Footer from "./Footer"; import Footer from "./Footer";
import Header from "./Header"; import Header from "./Header";
import { authClient } from "@kan/auth/client"; import { authClient } from "@kan/auth/client";
export default function Layout({ children }: { children: React.ReactNode }) { export default function Layout({ children }: { children: React.ReactNode }) {
const theme = useTheme(); const { theme } = useTheme();
const { data: session } = authClient.useSession(); const { data: session } = authClient.useSession();
const isLoggedIn = !!session?.user; const isLoggedIn = !!session?.user;
const isDarkMode = theme.activeTheme === "dark"; const isDarkMode = theme === "dark";
return ( return (
<> <>

View File

@@ -6,7 +6,7 @@ import { IoLogoGithub, IoLogoHackernews } from "react-icons/io";
import Button from "~/components/Button"; import Button from "~/components/Button";
import { PageHead } from "~/components/PageHead"; import { PageHead } from "~/components/PageHead";
import { useTheme } from "~/providers/theme"; import { useTheme } from "next-themes";
import Cta from "./components/Cta"; import Cta from "./components/Cta";
import FAQs from "./components/Faqs"; import FAQs from "./components/Faqs";
import Features from "./components/Features"; import Features from "./components/Features";
@@ -14,9 +14,10 @@ import Layout from "./components/Layout";
import Pricing from "./components/Pricing"; import Pricing from "./components/Pricing";
export default function HomeView() { export default function HomeView() {
const theme = useTheme(); const { resolvedTheme } = useTheme();
const isDarkMode = resolvedTheme === "dark";
const isDarkMode = theme.activeTheme === "dark";
return ( return (
<Layout> <Layout>
<PageHead title="Kan.bn | The open source alternative to Trello" /> <PageHead title="Kan.bn | The open source alternative to Trello" />
@@ -88,19 +89,27 @@ export default function HomeView() {
</div> </div>
<div className="px-4"> <div className="px-4">
<div className="mb-24 rounded-[16px] border border-light-300 bg-light-50 p-1 shadow-md dark:border-dark-300 dark:bg-dark-100 lg:rounded-[24px] lg:p-2"> <div className="mb-24 rounded-[16px] border border-light-300 bg-light-50 p-1 shadow-md dark:border-dark-300 dark:bg-dark-100 lg:rounded-[24px] lg:p-2">
<div className="overflow-hidden rounded-[12px] border border-light-300 shadow-sm dark:border-dark-300 lg:rounded-[16px]"> <div className="relative overflow-hidden rounded-[12px] border border-light-300 shadow-sm dark:border-dark-300 lg:rounded-[16px]">
<Image <Image
src={`/hero-${isDarkMode ? "dark" : "light"}.png`} src={`/hero-light.png`}
alt="kanban" alt="kanban"
width={1100} width={1100}
height={1000} height={1000}
className="block dark:hidden"
/>
<Image
src={`/hero-dark.png`}
alt="kanban"
width={1100}
height={1000}
className="hidden dark:block"
/> />
</div> </div>
</div> </div>
</div> </div>
<div className="relative pt-10"> <div className="relative pt-10">
<div id="features" className="absolute -top-20" /> <div id="features" className="absolute -top-20" />
<Features theme={theme.activeTheme} /> <Features theme={resolvedTheme === "dark" ? "dark" : "light"} />
</div> </div>
<div className="relative pt-10"> <div className="relative pt-10">
<div id="pricing" className="absolute -top-20" /> <div id="pricing" className="absolute -top-20" />
@@ -111,7 +120,7 @@ export default function HomeView() {
<FAQs /> <FAQs />
</div> </div>
<div className="relative"> <div className="relative">
<Cta theme={theme.activeTheme} /> <Cta theme={resolvedTheme ?? "light"} />
</div> </div>
</div> </div>
</Layout> </Layout>

View File

@@ -19,7 +19,7 @@ import { DeleteMemberConfirmation } from "./components/DeleteMemberConfirmation"
import { InviteMemberForm } from "./components/InviteMemberForm"; import { InviteMemberForm } from "./components/InviteMemberForm";
export default function MembersPage() { export default function MembersPage() {
const { modalContentType, openModal } = useModal(); const { modalContentType, openModal, isOpen } = useModal();
const { workspace } = useWorkspace(); const { workspace } = useWorkspace();
const { data, isLoading } = api.workspace.byId.useQuery( const { data, isLoading } = api.workspace.byId.useQuery(
@@ -222,12 +222,35 @@ export default function MembersPage() {
</div> </div>
</div> </div>
<Modal modalSize={modalContentType === "NEW_FEEDBACK" ? "md" : "sm"}> <>
{modalContentType === "NEW_FEEDBACK" && <FeedbackModal />} <Modal
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />} modalSize="md"
{modalContentType === "INVITE_MEMBER" && <InviteMemberForm />} isVisible={isOpen && modalContentType === "NEW_FEEDBACK"}
{modalContentType === "REMOVE_MEMBER" && <DeleteMemberConfirmation />} >
</Modal> <FeedbackModal />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_WORKSPACE"}
>
<NewWorkspaceForm />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "INVITE_MEMBER"}
>
<InviteMemberForm />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "REMOVE_MEMBER"}
>
<DeleteMemberConfirmation />
</Modal>
</>
</div> </div>
</> </>
); );

View File

@@ -9,6 +9,7 @@ import LabelIcon from "~/components/LabelIcon";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import ActivityList from "~/views/card/components/ActivityList"; import ActivityList from "~/views/card/components/ActivityList";
import Checklists from "~/views/card/components/Checklists";
export function CardModal({ export function CardModal({
cardPublicId, cardPublicId,
@@ -68,17 +69,20 @@ export function CardModal({
onClick={async (e) => { onClick={async (e) => {
e.preventDefault(); e.preventDefault();
closeModal(); closeModal();
try {
await router.replace( setTimeout(async () => {
`/${workspaceSlug}/${boardSlug}`, try {
undefined, await router.replace(
{ `/${workspaceSlug}/${boardSlug}`,
shallow: true, undefined,
}, {
); shallow: true,
} catch (error) { },
console.error(error); );
} } catch (error) {
console.error(error);
}
}, 400);
}} }}
> >
<HiXMark <HiXMark
@@ -119,10 +123,21 @@ export function CardModal({
{data?.description && ( {data?.description && (
<div className="mb-10 flex w-full max-w-2xl justify-between"> <div className="mb-10 flex w-full max-w-2xl justify-between">
<div className="mt-2"> <div className="mt-2">
<Editor content={data.description} readOnly /> <Editor
content={data.description}
readOnly
workspaceMembers={data?.list.board.workspace.members ?? []}
/>
</div> </div>
</div> </div>
)} )}
{data?.checklists && data.checklists.length > 0 && (
<Checklists
checklists={data.checklists}
cardPublicId={cardPublicId ?? ""}
viewOnly
/>
)}
<div className="border-t-[1px] border-light-600 pb-4 pt-12 dark:border-dark-400"> <div className="border-t-[1px] border-light-600 pb-4 pt-12 dark:border-dark-400">
<h2 className="text-md pb-4 font-medium text-light-900 dark:text-dark-1000"> <h2 className="text-md pb-4 font-medium text-light-900 dark:text-dark-1000">
{t`Activity`} {t`Activity`}

View File

@@ -2,6 +2,7 @@ import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro";
import { keepPreviousData } from "@tanstack/react-query"; import { keepPreviousData } from "@tanstack/react-query";
import { env } from "next-runtime-env";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { HiLink, HiOutlineLockClosed } from "react-icons/hi2"; import { HiLink, HiOutlineLockClosed } from "react-icons/hi2";
@@ -19,6 +20,10 @@ import Card from "~/views/board/components/Card";
import Filters from "~/views/board/components/Filters"; import Filters from "~/views/board/components/Filters";
import { CardModal } from "./CardModal"; import { CardModal } from "./CardModal";
const IS_CLOUD = env("NEXT_PUBLIC_KAN_ENV") === "cloud";
const HIDE_POWERED_BY =
env("NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY") === "true";
export default function PublicBoardView() { export default function PublicBoardView() {
const router = useRouter(); const router = useRouter();
const { showPopup } = usePopup(); const { showPopup } = usePopup();
@@ -40,7 +45,7 @@ export default function PublicBoardView() {
members: formatToArray(router.query.members), members: formatToArray(router.query.members),
labels: formatToArray(router.query.labels), labels: formatToArray(router.query.labels),
}, },
{ enabled: !!boardSlug, placeholderData: keepPreviousData }, { enabled: router.isReady && !!boardSlug, placeholderData: keepPreviousData },
); );
const CopyBoardLink = () => { const CopyBoardLink = () => {
@@ -102,7 +107,7 @@ export default function PublicBoardView() {
<div className="relative h-full overflow-hidden rounded-md border pb-8 dark:border-dark-200"> <div className="relative h-full overflow-hidden rounded-md border pb-8 dark:border-dark-200">
<PatternedBackground /> <PatternedBackground />
<div className="z-10 flex w-full justify-between p-8"> <div className="z-10 flex w-full justify-between p-8">
{isLoading ? ( {isLoading || !router.isReady ? (
<div className="flex space-x-2"> <div className="flex space-x-2">
<div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-200 dark:bg-dark-100" /> <div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-200 dark:bg-dark-100" />
</div> </div>
@@ -129,13 +134,13 @@ export default function PublicBoardView() {
</div> </div>
<div className="scrollbar-w-none scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-h-[8px] relative h-full flex-1 overflow-y-hidden overflow-x-scroll overscroll-contain scrollbar scrollbar-track-light-200 scrollbar-thumb-light-400 dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-300"> <div className="scrollbar-w-none scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-h-[8px] relative h-full flex-1 overflow-y-hidden overflow-x-scroll overscroll-contain scrollbar scrollbar-track-light-200 scrollbar-thumb-light-400 dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-300">
{isLoading ? ( {isLoading || !router.isReady ? (
<div className="ml-[2rem] flex"> <div className="ml-[2rem] flex">
<div className="0 mr-5 h-[500px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" /> <div className="0 mr-5 h-[500px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
<div className="0 mr-5 h-[275px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" /> <div className="0 mr-5 h-[275px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
<div className="0 mr-5 h-[375px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" /> <div className="0 mr-5 h-[375px] w-[18rem] animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
</div> </div>
) : !data ? ( ) : !data && !isLoading && router.isReady && !!boardSlug ? (
<div className="z-10 flex h-full w-full flex-col items-center justify-center space-y-8 pb-[150px]"> <div className="z-10 flex h-full w-full flex-col items-center justify-center space-y-8 pb-[150px]">
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<HiOutlineLockClosed className="h-10 w-10 text-light-800 dark:text-dark-800" /> <HiOutlineLockClosed className="h-10 w-10 text-light-800 dark:text-dark-800" />
@@ -175,6 +180,7 @@ export default function PublicBoardView() {
<Card <Card
title={card.title} title={card.title}
labels={card.labels} labels={card.labels}
checklists={card.checklists ?? []}
members={[]} members={[]}
/> />
</Link> </Link>
@@ -193,12 +199,26 @@ export default function PublicBoardView() {
<CopyBoardLink /> <CopyBoardLink />
</div> </div>
<Link {IS_CLOUD && (
className="text-lg font-bold tracking-tight text-neutral-900 dark:text-dark-1000" <Link
href="/" className="text-lg font-bold tracking-tight text-neutral-900 dark:text-dark-1000"
> href="/"
kan.bn >
</Link> kan.bn
</Link>
)}
{!IS_CLOUD && !HIDE_POWERED_BY && (
<a
href="https://kan.bn"
target="_blank"
rel="noreferrer noopener"
className="absolute right-[1rem] inline-flex items-center gap-[0.175rem] rounded-full border border-light-300 bg-light-50 px-3 py-1 text-[11px] font-medium text-light-950 shadow-sm transition-colors hover:bg-light-100 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900 dark:hover:bg-dark-100"
>
<span>{`Powered by`}</span>
<span className="font-semibold">kan.bn</span>
</a>
)}
</div> </div>
</div> </div>
<Popup /> <Popup />

View File

@@ -0,0 +1,184 @@
import { useRouter } from "next/navigation";
import { zodResolver } from "@hookform/resolvers/zod";
import { t } from "@lingui/core/macro";
import { useMutation } from "@tanstack/react-query";
import { env } from "next-runtime-env";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { authClient } from "@kan/auth/client";
import Button from "~/components/Button";
import Input from "~/components/Input";
import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
const FormSchema = z
.object({
currentPassword: z.string().min(1, t`Current password is required`),
newPassword: z
.string()
.min(8, t`Password must be at least 8 characters`)
.min(1, t`New password is required`),
confirmPassword: z.string().min(1, t`Please confirm your new password`),
})
.refine((data) => data.newPassword === data.confirmPassword, {
message: t`Passwords do not match`,
path: ["confirmPassword"],
})
.refine((data) => data.currentPassword !== data.newPassword, {
message: t`New password must be different from current password`,
path: ["newPassword"],
});
type FormValues = z.infer<typeof FormSchema>;
export function ChangePasswordFormConfirmation() {
const { closeModal } = useModal();
const { showPopup } = usePopup();
const router = useRouter();
const utils = api.useUtils();
const {
register,
handleSubmit,
formState: { errors, isValid },
reset,
setError,
} = useForm<FormValues>({
resolver: zodResolver(FormSchema),
mode: "onChange",
});
const changePasswordMutation = useMutation({
mutationFn: async (data: FormValues) => {
const response = await authClient.changePassword({
newPassword: data.newPassword,
currentPassword: data.currentPassword,
revokeOtherSessions: true,
});
if (response?.error) {
throw new Error(response?.error.message || "Invalid Password");
}
},
onSuccess: async () => {
closeModal();
showPopup({
header: t`Password Changed`,
message: t`Your password has been changed.`,
icon: "success",
});
utils.invalidate();
reset();
router.push("/");
},
onError: async (error: any) => {
const errorMessage = error.message.toLowerCase();
if (errorMessage.includes("invalid password")) {
setError("currentPassword", {
type: "manual",
message: t`The current password you entered is incorrect.`,
});
} else {
closeModal();
showPopup({
header: t`Error Changing Password`,
message: t`An unexpected error occurred. Please try again later.`,
icon: "error",
});
}
},
});
const onSubmit = (data: FormValues) => {
changePasswordMutation.mutate(data);
};
const handleCancel = () => {
reset();
closeModal();
};
return (
<div className="p-5">
<div className="flex w-full flex-col justify-between pb-4">
<h2 className="text-md pb-4 font-medium dark:text-white">{t`Change Password`}</h2>
<p className="mb-4 text-sm text-light-900">
{t`Enter your current password and choose a new secure password.`}
</p>
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="space-y-2">
<div>
<Input
id="currentPassword"
type="password"
{...register("currentPassword")}
placeholder={t`Enter your current password`}
/>
{errors.currentPassword && (
<p className="mt-2 text-xs text-red-400">
{errors.currentPassword.message}
</p>
)}
</div>
<div>
<Input
id="newPassword"
type="password"
{...register("newPassword")}
placeholder={t`Enter your new password`}
/>
{errors.newPassword && (
<p className="mt-2 text-xs text-red-400">
{errors.newPassword.message}
</p>
)}
</div>
<div>
<Input
id="confirmPassword"
type="password"
{...register("confirmPassword")}
placeholder={t`Confirm your new password`}
/>
{errors.confirmPassword && (
<p className="mt-2 text-xs text-red-400">
{errors.confirmPassword.message}
</p>
)}
</div>
</div>
<div className="mt-[1.5rem] flex items-center gap-4">
<Button
variant="secondary"
onClick={handleCancel}
type="button"
fullWidth
size="lg"
>
{t`Cancel`}
</Button>
<Button
variant="primary"
type="submit"
disabled={!isValid || changePasswordMutation.isPending}
isLoading={changePasswordMutation.isPending}
fullWidth
size="lg"
>
{t`Change Password`}
</Button>
</div>
</form>
</div>
);
}

View File

@@ -15,6 +15,7 @@ import { usePopup } from "~/providers/popup";
import { useWorkspace } from "~/providers/workspace"; import { useWorkspace } from "~/providers/workspace";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import Avatar from "./components/Avatar"; import Avatar from "./components/Avatar";
import { ChangePasswordFormConfirmation } from "./components/ChangePasswordConfirmation";
import CreateAPIKeyForm from "./components/CreateAPIKeyForm"; import CreateAPIKeyForm from "./components/CreateAPIKeyForm";
import { CustomURLConfirmation } from "./components/CustomURLConfirmation"; import { CustomURLConfirmation } from "./components/CustomURLConfirmation";
import { DeleteAccountConfirmation } from "./components/DeleteAccountConfirmation"; import { DeleteAccountConfirmation } from "./components/DeleteAccountConfirmation";
@@ -25,14 +26,15 @@ import UpdateWorkspaceNameForm from "./components/UpdateWorkspaceNameForm";
import UpdateWorkspaceUrlForm from "./components/UpdateWorkspaceUrlForm"; import UpdateWorkspaceUrlForm from "./components/UpdateWorkspaceUrlForm";
export default function SettingsPage() { export default function SettingsPage() {
const { modalContentType, openModal } = useModal(); const { modalContentType, openModal, isOpen } = useModal();
const { workspace } = useWorkspace(); const { workspace } = useWorkspace();
const utils = api.useUtils(); const utils = api.useUtils();
const { showPopup } = usePopup(); const { showPopup } = usePopup();
const router = useRouter(); const router = useRouter();
const workspaceUrlSectionRef = useRef<HTMLDivElement>(null); const workspaceUrlSectionRef = useRef<HTMLDivElement>(null);
const scrollContainerRef = useRef<HTMLDivElement>(null); const scrollContainerRef = useRef<HTMLDivElement>(null);
const isCredentialsEnabled =
env("NEXT_PUBLIC_ALLOW_CREDENTIALS")?.toLowerCase() === "true";
const { data } = api.user.getUser.useQuery(); const { data } = api.user.getUser.useQuery();
const { const {
@@ -283,6 +285,25 @@ export default function SettingsPage() {
</div> </div>
</div> </div>
{isCredentialsEnabled && (
<div className="mb-8 border-t border-light-300 dark:border-dark-300">
<h2 className="mb-4 mt-8 text-[14px] text-neutral-900 dark:text-dark-1000">
{t`Change Password`}
</h2>
<p className="mb-8 text-sm text-neutral-500 dark:text-dark-900">
{t`You are about to change your password.`}
</p>
<div className="mt-4">
<Button
variant="secondary"
onClick={() => openModal("CHANGE_PASSWORD")}
>
{t`Change Password`}
</Button>
</div>
</div>
)}
<div className="mb-8 border-t border-light-300 dark:border-dark-300"> <div className="mb-8 border-t border-light-300 dark:border-dark-300">
<h2 className="mb-4 mt-8 text-[14px] text-neutral-900 dark:text-dark-1000"> <h2 className="mb-4 mt-8 text-[14px] text-neutral-900 dark:text-dark-1000">
{t`Delete account`} {t`Delete account`}
@@ -301,19 +322,49 @@ export default function SettingsPage() {
</div> </div>
</div> </div>
<Modal modalSize={modalContentType === "NEW_FEEDBACK" ? "md" : "sm"}> <>
{modalContentType === "NEW_FEEDBACK" && <FeedbackModal />} <Modal
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />} modalSize="md"
{modalContentType === "DELETE_WORKSPACE" && ( isVisible={isOpen && modalContentType === "NEW_FEEDBACK"}
>
<FeedbackModal />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_WORKSPACE"}
>
<NewWorkspaceForm />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_WORKSPACE"}
>
<DeleteWorkspaceConfirmation /> <DeleteWorkspaceConfirmation />
)} </Modal>
{modalContentType === "UPDATE_WORKSPACE_URL" && (
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "UPDATE_WORKSPACE_URL"}
>
<CustomURLConfirmation workspacePublicId={workspace.publicId} /> <CustomURLConfirmation workspacePublicId={workspace.publicId} />
)} </Modal>
{modalContentType === "DELETE_ACCOUNT" && (
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_ACCOUNT"}
>
<DeleteAccountConfirmation /> <DeleteAccountConfirmation />
)} </Modal>
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "CHANGE_PASSWORD"}
>
<ChangePasswordFormConfirmation />
</Modal>
</>
</div> </div>
</div> </div>
</> </>

View File

@@ -4,6 +4,7 @@ import { fontFamily } from "tailwindcss/defaultTheme";
import baseConfig from "@kan/tailwind-config/web"; import baseConfig from "@kan/tailwind-config/web";
export default { export default {
darkMode: "class",
content: [...baseConfig.content], content: [...baseConfig.content],
plugins: [require("@tailwindcss/typography")], plugins: [require("@tailwindcss/typography")],
presets: [baseConfig], presets: [baseConfig],

View File

@@ -35,6 +35,9 @@ services:
- NEXT_PUBLIC_AVATAR_BUCKET_NAME=${NEXT_PUBLIC_AVATAR_BUCKET_NAME} - NEXT_PUBLIC_AVATAR_BUCKET_NAME=${NEXT_PUBLIC_AVATAR_BUCKET_NAME}
- NEXT_PUBLIC_STORAGE_DOMAIN=${NEXT_PUBLIC_STORAGE_DOMAIN} - NEXT_PUBLIC_STORAGE_DOMAIN=${NEXT_PUBLIC_STORAGE_DOMAIN}
# White label
- NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY=${NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY}
# Auth config (optional) # Auth config (optional)
- NEXT_PUBLIC_ALLOW_CREDENTIALS=${NEXT_PUBLIC_ALLOW_CREDENTIALS} - NEXT_PUBLIC_ALLOW_CREDENTIALS=${NEXT_PUBLIC_ALLOW_CREDENTIALS}
- NEXT_PUBLIC_DISABLE_SIGN_UP=${NEXT_PUBLIC_DISABLE_SIGN_UP} - NEXT_PUBLIC_DISABLE_SIGN_UP=${NEXT_PUBLIC_DISABLE_SIGN_UP}
@@ -43,6 +46,11 @@ services:
- TRELLO_APP_API_KEY=${TRELLO_APP_API_KEY} - TRELLO_APP_API_KEY=${TRELLO_APP_API_KEY}
- TRELLO_APP_SECRET=${TRELLO_APP_SECRET} - TRELLO_APP_SECRET=${TRELLO_APP_SECRET}
# Generic OIDC provider (optional)
- OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
- OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
- OIDC_DISCOVERY_URL=${OIDC_DISCOVERY_URL}
# OAuth providers (optional) # OAuth providers (optional)
- BETTER_AUTH_TRUSTED_ORIGINS=${BETTER_AUTH_TRUSTED_ORIGINS} - BETTER_AUTH_TRUSTED_ORIGINS=${BETTER_AUTH_TRUSTED_ORIGINS}
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}

View File

@@ -1,5 +1,6 @@
import { boardRouter } from "./routers/board"; import { boardRouter } from "./routers/board";
import { cardRouter } from "./routers/card"; import { cardRouter } from "./routers/card";
import { checklistRouter } from "./routers/checklist";
import { feedbackRouter } from "./routers/feedback"; import { feedbackRouter } from "./routers/feedback";
import { importRouter } from "./routers/import"; import { importRouter } from "./routers/import";
import { integrationRouter } from "./routers/integration"; import { integrationRouter } from "./routers/integration";
@@ -13,6 +14,7 @@ import { createTRPCRouter } from "./trpc";
export const appRouter = createTRPCRouter({ export const appRouter = createTRPCRouter({
board: boardRouter, board: boardRouter,
card: cardRouter, card: cardRouter,
checklist: checklistRouter,
feedback: feedbackRouter, feedback: feedbackRouter,
label: labelRouter, label: labelRouter,
list: listRouter, list: listRouter,

View File

@@ -0,0 +1,410 @@
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import * as cardRepo from "@kan/db/repository/card.repo";
import * as cardActivityRepo from "@kan/db/repository/cardActivity.repo";
import * as checklistRepo from "@kan/db/repository/checklist.repo";
import { createTRPCRouter, protectedProcedure } from "../trpc";
import { assertUserInWorkspace } from "../utils/auth";
const checklistSchema = z.object({
publicId: z.string().length(12),
name: z.string().min(1).max(255),
});
const checklistItemSchema = z.object({
publicId: z.string().length(12),
title: z.string().min(1).max(500),
completed: z.boolean(),
});
export const checklistRouter = createTRPCRouter({
create: protectedProcedure
.meta({
openapi: {
summary: "Add a checklist to a card",
method: "POST",
path: "/cards/{cardPublicId}/checklists",
description: "Adds a checklist to a card",
tags: ["Cards"],
protect: true,
},
})
.input(
z.object({
cardPublicId: z.string().length(12),
name: z.string().min(1).max(255),
}),
)
.output(checklistSchema)
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
const card = await cardRepo.getWorkspaceAndCardIdByCardPublicId(
ctx.db,
input.cardPublicId,
);
if (!card)
throw new TRPCError({
message: `Card with public ID ${input.cardPublicId} not found`,
code: "NOT_FOUND",
});
await assertUserInWorkspace(ctx.db, userId, card.workspaceId);
const newChecklist = await checklistRepo.create(ctx.db, {
name: input.name,
createdBy: userId,
cardId: card.id,
});
if (!newChecklist?.id)
throw new TRPCError({
message: `Failed to create checklist`,
code: "INTERNAL_SERVER_ERROR",
});
await cardActivityRepo.create(ctx.db, {
type: "card.updated.checklist.added",
cardId: card.id,
toTitle: newChecklist.name,
createdBy: userId,
});
return newChecklist;
}),
update: protectedProcedure
.input(
z.object({
checklistPublicId: z.string().length(12),
name: z.string().min(1).max(255),
}),
)
.output(z.object({ publicId: z.string().length(12), name: z.string() }))
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
const checklist = await checklistRepo.getChecklistByPublicId(
ctx.db,
input.checklistPublicId,
);
if (!checklist)
throw new TRPCError({
message: `Checklist with public ID ${input.checklistPublicId} not found`,
code: "NOT_FOUND",
});
await assertUserInWorkspace(
ctx.db,
userId,
checklist.card.list.board.workspace.id,
);
const previousName = checklist.name;
const updated = await checklistRepo.updateChecklistById(ctx.db, {
id: checklist.id,
name: input.name,
});
if (!updated)
throw new TRPCError({
message: `Failed to update checklist`,
code: "INTERNAL_SERVER_ERROR",
});
await cardActivityRepo.create(ctx.db, {
type: "card.updated.checklist.renamed",
cardId: checklist.cardId,
fromTitle: previousName,
toTitle: updated.name,
createdBy: userId,
});
return updated;
}),
delete: protectedProcedure
.meta({
openapi: {
summary: "Delete a checklist",
method: "DELETE",
path: "/checklists/{checklistPublicId}",
description: "Deletes a checklist by its public ID",
tags: ["Cards"],
protect: true,
},
})
.input(z.object({ checklistPublicId: z.string().length(12) }))
.output(z.object({ success: z.boolean() }))
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
const checklist = await checklistRepo.getChecklistByPublicId(
ctx.db,
input.checklistPublicId,
);
if (!checklist)
throw new TRPCError({
message: `Checklist with public ID ${input.checklistPublicId} not found`,
code: "NOT_FOUND",
});
await assertUserInWorkspace(
ctx.db,
userId,
checklist.card.list.board.workspace.id,
);
await checklistRepo.softDeleteAllItemsByChecklistId(ctx.db, {
checklistId: checklist.id,
deletedAt: new Date(),
deletedBy: userId,
});
const deleted = await checklistRepo.softDeleteById(ctx.db, {
id: checklist.id,
deletedAt: new Date(),
deletedBy: userId,
});
if (!deleted)
throw new TRPCError({
message: `Failed to delete checklist`,
code: "INTERNAL_SERVER_ERROR",
});
await cardActivityRepo.create(ctx.db, {
type: "card.updated.checklist.deleted",
cardId: checklist.cardId,
fromTitle: checklist.name,
createdBy: userId,
});
return { success: true };
}),
createItem: protectedProcedure
.meta({
openapi: {
summary: "Add an item to a checklist",
method: "POST",
path: "/checklists/{checklistPublicId}/items",
description: "Adds an item to a checklist",
tags: ["Cards"],
protect: true,
},
})
.input(
z.object({
checklistPublicId: z.string().length(12),
title: z.string().min(1).max(500),
}),
)
.output(checklistItemSchema)
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
const checklist = await checklistRepo.getChecklistByPublicId(
ctx.db,
input.checklistPublicId,
);
if (!checklist)
throw new TRPCError({
message: `Checklist with public ID ${input.checklistPublicId} not found`,
code: "NOT_FOUND",
});
await assertUserInWorkspace(
ctx.db,
userId,
checklist.card.list.board.workspace.id,
);
const newChecklistItem = await checklistRepo.createItem(ctx.db, {
title: input.title,
createdBy: userId,
checklistId: checklist.id,
});
if (!newChecklistItem?.id)
throw new TRPCError({
message: `Failed to create checklist item`,
code: "INTERNAL_SERVER_ERROR",
});
await cardActivityRepo.create(ctx.db, {
type: "card.updated.checklist.item.added",
cardId: checklist.cardId,
toTitle: newChecklistItem.title,
createdBy: userId,
});
return newChecklistItem;
}),
updateItem: protectedProcedure
.meta({
openapi: {
summary: "Update a checklist item",
method: "PUT",
path: "/checklists/items/{checklistItemPublicId}",
description: "Updates a checklist item (title/completed)",
tags: ["Cards"],
protect: true,
},
})
.input(
z.object({
checklistItemPublicId: z.string().length(12),
title: z.string().min(1).max(500).optional(),
completed: z.boolean().optional(),
}),
)
.output(checklistItemSchema)
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
const item = await checklistRepo.getChecklistItemByPublicIdWithChecklist(
ctx.db,
input.checklistItemPublicId,
);
if (!item)
throw new TRPCError({
message: `Checklist item with public ID ${input.checklistItemPublicId} not found`,
code: "NOT_FOUND",
});
await assertUserInWorkspace(
ctx.db,
userId,
item.checklist.card.list.board.workspace.id,
);
const previousTitle = item.title;
const updated = await checklistRepo.updateItemById(ctx.db, {
id: item.id,
title: input.title,
completed: input.completed,
});
if (!updated)
throw new TRPCError({
message: `Failed to update checklist item`,
code: "INTERNAL_SERVER_ERROR",
});
// Log completion toggle
if (input.completed !== undefined) {
await cardActivityRepo.create(ctx.db, {
type: input.completed
? "card.updated.checklist.item.completed"
: "card.updated.checklist.item.uncompleted",
cardId: item.checklist.cardId,
toTitle: updated.title,
createdBy: userId,
});
}
// Log title change
if (input.title !== undefined && input.title !== previousTitle) {
await cardActivityRepo.create(ctx.db, {
type: "card.updated.checklist.item.updated",
cardId: item.checklist.cardId,
fromTitle: previousTitle,
toTitle: updated.title,
createdBy: userId,
});
}
return updated;
}),
deleteItem: protectedProcedure
.meta({
openapi: {
summary: "Delete a checklist item",
method: "DELETE",
path: "/checklists/items/{checklistItemPublicId}",
description: "Deletes a checklist item",
tags: ["Cards"],
protect: true,
},
})
.input(z.object({ checklistItemPublicId: z.string().length(12) }))
.output(z.object({ success: z.boolean() }))
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
const item = await checklistRepo.getChecklistItemByPublicIdWithChecklist(
ctx.db,
input.checklistItemPublicId,
);
if (!item)
throw new TRPCError({
message: `Checklist item with public ID ${input.checklistItemPublicId} not found`,
code: "NOT_FOUND",
});
await assertUserInWorkspace(
ctx.db,
userId,
item.checklist.card.list.board.workspace.id,
);
const deleted = await checklistRepo.softDeleteItemById(ctx.db, {
id: item.id,
deletedAt: new Date(),
deletedBy: userId,
});
if (!deleted)
throw new TRPCError({
message: `Failed to delete item`,
code: "INTERNAL_SERVER_ERROR",
});
await cardActivityRepo.create(ctx.db, {
type: "card.updated.checklist.item.deleted",
cardId: item.checklist.cardId,
fromTitle: item.title,
createdBy: userId,
});
return { success: true };
}),
});

View File

@@ -2,7 +2,7 @@ import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { betterAuth } from "better-auth"; import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { createAuthEndpoint, createAuthMiddleware } from "better-auth/api"; import { createAuthEndpoint, createAuthMiddleware } from "better-auth/api";
import { apiKey } from "better-auth/plugins"; import { apiKey, genericOAuth } from "better-auth/plugins";
import { magicLink } from "better-auth/plugins/magic-link"; import { magicLink } from "better-auth/plugins/magic-link";
import { socialProviderList } from "better-auth/social-providers"; import { socialProviderList } from "better-auth/social-providers";
import { env } from "next-runtime-env"; import { env } from "next-runtime-env";
@@ -83,8 +83,20 @@ export const socialProvidersPlugin = () => ({
{ {
method: "GET", method: "GET",
}, },
async (ctx) => async (ctx) => {
ctx.json(ctx.context.socialProviders.map((p) => p.id.toLowerCase())), const providers = ctx.context.socialProviders.map((p) =>
p.id.toLowerCase(),
);
// Add OIDC provider if configured
if (
process.env.OIDC_CLIENT_ID &&
process.env.OIDC_CLIENT_SECRET &&
process.env.OIDC_DISCOVERY_URL
) {
providers.push("oidc");
}
return ctx.json(providers);
},
), ),
}, },
}); });
@@ -162,6 +174,25 @@ export const initAuth = (db: dbClient) => {
} }
}, },
}), }),
// Generic OIDC provider
...(process.env.OIDC_CLIENT_ID &&
process.env.OIDC_CLIENT_SECRET &&
process.env.OIDC_DISCOVERY_URL
? [
genericOAuth({
config: [
{
providerId: "oidc",
clientId: process.env.OIDC_CLIENT_ID,
clientSecret: process.env.OIDC_CLIENT_SECRET,
discoveryUrl: process.env.OIDC_DISCOVERY_URL,
scopes: ["openid", "email", "profile"],
pkce: true,
},
],
}),
]
: []),
], ],
databaseHooks: { databaseHooks: {
user: { user: {

View File

@@ -1,8 +1,13 @@
import { BetterAuthClientPlugin } from "better-auth"; import type { BetterAuthClientPlugin } from "better-auth";
import { apiKeyClient, magicLinkClient } from "better-auth/client/plugins"; import type { BetterFetchOption } from "better-auth/react";
import { BetterFetchOption, createAuthClient } from "better-auth/react"; import {
apiKeyClient,
genericOAuthClient,
magicLinkClient,
} from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";
import { socialProvidersPlugin } from "./auth"; import type { socialProvidersPlugin } from "./auth";
const socialProvidersPluginClient = { const socialProvidersPluginClient = {
id: "social-providers-plugin", id: "social-providers-plugin",
@@ -21,5 +26,10 @@ const socialProvidersPluginClient = {
} satisfies BetterAuthClientPlugin; } satisfies BetterAuthClientPlugin;
export const authClient = createAuthClient({ export const authClient = createAuthClient({
plugins: [magicLinkClient(), apiKeyClient(), socialProvidersPluginClient], plugins: [
magicLinkClient(),
apiKeyClient(),
genericOAuthClient(),
socialProvidersPluginClient,
],
}); });

View File

@@ -1,4 +1,4 @@
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS "uuid-ossp";--> statement-breakpoint
CREATE TYPE "public"."board_visibility" AS ENUM('private', 'public');--> statement-breakpoint CREATE TYPE "public"."board_visibility" AS ENUM('private', 'public');--> statement-breakpoint
CREATE TYPE "public"."card_activity_type" AS ENUM('card.created', 'card.updated.title', 'card.updated.description', 'card.updated.index', 'card.updated.list', 'card.updated.label.added', 'card.updated.label.removed', 'card.updated.member.added', 'card.updated.member.removed', 'card.updated.comment.added', 'card.updated.comment.updated', 'card.updated.comment.deleted', 'card.archived');--> statement-breakpoint CREATE TYPE "public"."card_activity_type" AS ENUM('card.created', 'card.updated.title', 'card.updated.description', 'card.updated.index', 'card.updated.list', 'card.updated.label.added', 'card.updated.label.removed', 'card.updated.member.added', 'card.updated.member.removed', 'card.updated.comment.added', 'card.updated.comment.updated', 'card.updated.comment.deleted', 'card.archived');--> statement-breakpoint

View File

@@ -0,0 +1,84 @@
CREATE TABLE IF NOT EXISTS "card_checklist_item" (
"id" bigserial PRIMARY KEY NOT NULL,
"publicId" varchar(12) NOT NULL,
"title" varchar(500) NOT NULL,
"completed" boolean DEFAULT false NOT NULL,
"index" integer NOT NULL,
"checklistId" bigint NOT NULL,
"createdBy" uuid,
"createdAt" timestamp DEFAULT now() NOT NULL,
"updatedAt" timestamp,
"deletedAt" timestamp,
"deletedBy" uuid,
CONSTRAINT "card_checklist_item_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
ALTER TABLE "card_checklist_item" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "card_checklist" (
"id" bigserial PRIMARY KEY NOT NULL,
"publicId" varchar(12) NOT NULL,
"name" varchar(255) NOT NULL,
"index" integer NOT NULL,
"cardId" bigint NOT NULL,
"createdBy" uuid,
"createdAt" timestamp DEFAULT now() NOT NULL,
"updatedAt" timestamp,
"deletedAt" timestamp,
"deletedBy" uuid,
CONSTRAINT "card_checklist_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
ALTER TABLE "card_checklist" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "integration" (
"provider" varchar(255) NOT NULL,
"userId" uuid NOT NULL,
"accessToken" varchar(255) NOT NULL,
"refreshToken" varchar(255),
"expiresAt" timestamp NOT NULL,
"createdAt" timestamp NOT NULL,
"updatedAt" timestamp,
CONSTRAINT "integration_pkey" PRIMARY KEY("userId","provider")
);
--> statement-breakpoint
ALTER TABLE "integration" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_checklist_item" ADD CONSTRAINT "card_checklist_item_checklistId_card_checklist_id_fk" FOREIGN KEY ("checklistId") REFERENCES "public"."card_checklist"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_checklist_item" ADD CONSTRAINT "card_checklist_item_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_checklist_item" ADD CONSTRAINT "card_checklist_item_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_checklist" ADD CONSTRAINT "card_checklist_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "public"."card"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_checklist" ADD CONSTRAINT "card_checklist_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_checklist" ADD CONSTRAINT "card_checklist_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "integration" ADD CONSTRAINT "integration_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -0,0 +1,8 @@
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.checklist.added' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.checklist.renamed' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.checklist.deleted' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.checklist.item.added' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.checklist.item.updated' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.checklist.item.completed' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.checklist.item.uncompleted' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.checklist.item.deleted' BEFORE 'card.archived';

View File

@@ -1,6 +1,6 @@
{ {
"id": "91f9a2fa-31e2-4f3a-bdb9-852292fd7501", "id": "91f9a2fa-31e2-4f3a-bdb9-852292fd7501",
"prevId": "058e8521-2814-46f0-a33f-1bbd86f450ce", "prevId": "d170c8e0-bf75-4c71-abd9-0ecbeeb14003",
"version": "7", "version": "7",
"dialect": "postgresql", "dialect": "postgresql",
"tables": { "tables": {
@@ -92,13 +92,9 @@
"account_userId_user_id_fk": { "account_userId_user_id_fk": {
"name": "account_userId_user_id_fk", "name": "account_userId_user_id_fk",
"tableFrom": "account", "tableFrom": "account",
"columnsFrom": [ "columnsFrom": ["userId"],
"userId"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
} }
@@ -245,13 +241,9 @@
"apiKey_userId_user_id_fk": { "apiKey_userId_user_id_fk": {
"name": "apiKey_userId_user_id_fk", "name": "apiKey_userId_user_id_fk",
"tableFrom": "apiKey", "tableFrom": "apiKey",
"columnsFrom": [ "columnsFrom": ["userId"],
"userId"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
} }
@@ -320,13 +312,9 @@
"session_userId_user_id_fk": { "session_userId_user_id_fk": {
"name": "session_userId_user_id_fk", "name": "session_userId_user_id_fk",
"tableFrom": "session", "tableFrom": "session",
"columnsFrom": [ "columnsFrom": ["userId"],
"userId"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
} }
@@ -335,9 +323,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"session_token_unique": { "session_token_unique": {
"name": "session_token_unique", "name": "session_token_unique",
"columns": [ "columns": ["token"],
"token"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -523,52 +509,36 @@
"board_createdBy_user_id_fk": { "board_createdBy_user_id_fk": {
"name": "board_createdBy_user_id_fk", "name": "board_createdBy_user_id_fk",
"tableFrom": "board", "tableFrom": "board",
"columnsFrom": [ "columnsFrom": ["createdBy"],
"createdBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"board_deletedBy_user_id_fk": { "board_deletedBy_user_id_fk": {
"name": "board_deletedBy_user_id_fk", "name": "board_deletedBy_user_id_fk",
"tableFrom": "board", "tableFrom": "board",
"columnsFrom": [ "columnsFrom": ["deletedBy"],
"deletedBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"board_importId_import_id_fk": { "board_importId_import_id_fk": {
"name": "board_importId_import_id_fk", "name": "board_importId_import_id_fk",
"tableFrom": "board", "tableFrom": "board",
"columnsFrom": [ "columnsFrom": ["importId"],
"importId"
],
"tableTo": "import", "tableTo": "import",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "no action" "onDelete": "no action"
}, },
"board_workspaceId_workspace_id_fk": { "board_workspaceId_workspace_id_fk": {
"name": "board_workspaceId_workspace_id_fk", "name": "board_workspaceId_workspace_id_fk",
"tableFrom": "board", "tableFrom": "board",
"columnsFrom": [ "columnsFrom": ["workspaceId"],
"workspaceId"
],
"tableTo": "workspace", "tableTo": "workspace",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
} }
@@ -577,9 +547,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"board_publicId_unique": { "board_publicId_unique": {
"name": "board_publicId_unique", "name": "board_publicId_unique",
"columns": [ "columns": ["publicId"],
"publicId"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -713,91 +681,63 @@
"card_activity_cardId_card_id_fk": { "card_activity_cardId_card_id_fk": {
"name": "card_activity_cardId_card_id_fk", "name": "card_activity_cardId_card_id_fk",
"tableFrom": "card_activity", "tableFrom": "card_activity",
"columnsFrom": [ "columnsFrom": ["cardId"],
"cardId"
],
"tableTo": "card", "tableTo": "card",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"card_activity_fromListId_list_id_fk": { "card_activity_fromListId_list_id_fk": {
"name": "card_activity_fromListId_list_id_fk", "name": "card_activity_fromListId_list_id_fk",
"tableFrom": "card_activity", "tableFrom": "card_activity",
"columnsFrom": [ "columnsFrom": ["fromListId"],
"fromListId"
],
"tableTo": "list", "tableTo": "list",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"card_activity_toListId_list_id_fk": { "card_activity_toListId_list_id_fk": {
"name": "card_activity_toListId_list_id_fk", "name": "card_activity_toListId_list_id_fk",
"tableFrom": "card_activity", "tableFrom": "card_activity",
"columnsFrom": [ "columnsFrom": ["toListId"],
"toListId"
],
"tableTo": "list", "tableTo": "list",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"card_activity_labelId_label_id_fk": { "card_activity_labelId_label_id_fk": {
"name": "card_activity_labelId_label_id_fk", "name": "card_activity_labelId_label_id_fk",
"tableFrom": "card_activity", "tableFrom": "card_activity",
"columnsFrom": [ "columnsFrom": ["labelId"],
"labelId"
],
"tableTo": "label", "tableTo": "label",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"card_activity_workspaceMemberId_workspace_members_id_fk": { "card_activity_workspaceMemberId_workspace_members_id_fk": {
"name": "card_activity_workspaceMemberId_workspace_members_id_fk", "name": "card_activity_workspaceMemberId_workspace_members_id_fk",
"tableFrom": "card_activity", "tableFrom": "card_activity",
"columnsFrom": [ "columnsFrom": ["workspaceMemberId"],
"workspaceMemberId"
],
"tableTo": "workspace_members", "tableTo": "workspace_members",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"card_activity_createdBy_user_id_fk": { "card_activity_createdBy_user_id_fk": {
"name": "card_activity_createdBy_user_id_fk", "name": "card_activity_createdBy_user_id_fk",
"tableFrom": "card_activity", "tableFrom": "card_activity",
"columnsFrom": [ "columnsFrom": ["createdBy"],
"createdBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"card_activity_commentId_card_comments_id_fk": { "card_activity_commentId_card_comments_id_fk": {
"name": "card_activity_commentId_card_comments_id_fk", "name": "card_activity_commentId_card_comments_id_fk",
"tableFrom": "card_activity", "tableFrom": "card_activity",
"columnsFrom": [ "columnsFrom": ["commentId"],
"commentId"
],
"tableTo": "card_comments", "tableTo": "card_comments",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
} }
@@ -806,9 +746,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"card_activity_publicId_unique": { "card_activity_publicId_unique": {
"name": "card_activity_publicId_unique", "name": "card_activity_publicId_unique",
"columns": [ "columns": ["publicId"],
"publicId"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -838,26 +776,18 @@
"_card_workspace_members_cardId_card_id_fk": { "_card_workspace_members_cardId_card_id_fk": {
"name": "_card_workspace_members_cardId_card_id_fk", "name": "_card_workspace_members_cardId_card_id_fk",
"tableFrom": "_card_workspace_members", "tableFrom": "_card_workspace_members",
"columnsFrom": [ "columnsFrom": ["cardId"],
"cardId"
],
"tableTo": "card", "tableTo": "card",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"_card_workspace_members_workspaceMemberId_workspace_members_id_fk": { "_card_workspace_members_workspaceMemberId_workspace_members_id_fk": {
"name": "_card_workspace_members_workspaceMemberId_workspace_members_id_fk", "name": "_card_workspace_members_workspaceMemberId_workspace_members_id_fk",
"tableFrom": "_card_workspace_members", "tableFrom": "_card_workspace_members",
"columnsFrom": [ "columnsFrom": ["workspaceMemberId"],
"workspaceMemberId"
],
"tableTo": "workspace_members", "tableTo": "workspace_members",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
} }
@@ -865,10 +795,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"_card_workspace_members_cardId_workspaceMemberId_pk": { "_card_workspace_members_cardId_workspaceMemberId_pk": {
"name": "_card_workspace_members_cardId_workspaceMemberId_pk", "name": "_card_workspace_members_cardId_workspaceMemberId_pk",
"columns": [ "columns": ["cardId", "workspaceMemberId"]
"cardId",
"workspaceMemberId"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -959,52 +886,36 @@
"card_createdBy_user_id_fk": { "card_createdBy_user_id_fk": {
"name": "card_createdBy_user_id_fk", "name": "card_createdBy_user_id_fk",
"tableFrom": "card", "tableFrom": "card",
"columnsFrom": [ "columnsFrom": ["createdBy"],
"createdBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"card_deletedBy_user_id_fk": { "card_deletedBy_user_id_fk": {
"name": "card_deletedBy_user_id_fk", "name": "card_deletedBy_user_id_fk",
"tableFrom": "card", "tableFrom": "card",
"columnsFrom": [ "columnsFrom": ["deletedBy"],
"deletedBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"card_listId_list_id_fk": { "card_listId_list_id_fk": {
"name": "card_listId_list_id_fk", "name": "card_listId_list_id_fk",
"tableFrom": "card", "tableFrom": "card",
"columnsFrom": [ "columnsFrom": ["listId"],
"listId"
],
"tableTo": "list", "tableTo": "list",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"card_importId_import_id_fk": { "card_importId_import_id_fk": {
"name": "card_importId_import_id_fk", "name": "card_importId_import_id_fk",
"tableFrom": "card", "tableFrom": "card",
"columnsFrom": [ "columnsFrom": ["importId"],
"importId"
],
"tableTo": "import", "tableTo": "import",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "no action" "onDelete": "no action"
} }
@@ -1013,9 +924,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"card_publicId_unique": { "card_publicId_unique": {
"name": "card_publicId_unique", "name": "card_publicId_unique",
"columns": [ "columns": ["publicId"],
"publicId"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -1045,26 +954,18 @@
"_card_labels_cardId_card_id_fk": { "_card_labels_cardId_card_id_fk": {
"name": "_card_labels_cardId_card_id_fk", "name": "_card_labels_cardId_card_id_fk",
"tableFrom": "_card_labels", "tableFrom": "_card_labels",
"columnsFrom": [ "columnsFrom": ["cardId"],
"cardId"
],
"tableTo": "card", "tableTo": "card",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"_card_labels_labelId_label_id_fk": { "_card_labels_labelId_label_id_fk": {
"name": "_card_labels_labelId_label_id_fk", "name": "_card_labels_labelId_label_id_fk",
"tableFrom": "_card_labels", "tableFrom": "_card_labels",
"columnsFrom": [ "columnsFrom": ["labelId"],
"labelId"
],
"tableTo": "label", "tableTo": "label",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
} }
@@ -1072,10 +973,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"_card_labels_cardId_labelId_pk": { "_card_labels_cardId_labelId_pk": {
"name": "_card_labels_cardId_labelId_pk", "name": "_card_labels_cardId_labelId_pk",
"columns": [ "columns": ["cardId", "labelId"]
"cardId",
"labelId"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -1148,39 +1046,27 @@
"card_comments_cardId_card_id_fk": { "card_comments_cardId_card_id_fk": {
"name": "card_comments_cardId_card_id_fk", "name": "card_comments_cardId_card_id_fk",
"tableFrom": "card_comments", "tableFrom": "card_comments",
"columnsFrom": [ "columnsFrom": ["cardId"],
"cardId"
],
"tableTo": "card", "tableTo": "card",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"card_comments_createdBy_user_id_fk": { "card_comments_createdBy_user_id_fk": {
"name": "card_comments_createdBy_user_id_fk", "name": "card_comments_createdBy_user_id_fk",
"tableFrom": "card_comments", "tableFrom": "card_comments",
"columnsFrom": [ "columnsFrom": ["createdBy"],
"createdBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"card_comments_deletedBy_user_id_fk": { "card_comments_deletedBy_user_id_fk": {
"name": "card_comments_deletedBy_user_id_fk", "name": "card_comments_deletedBy_user_id_fk",
"tableFrom": "card_comments", "tableFrom": "card_comments",
"columnsFrom": [ "columnsFrom": ["deletedBy"],
"deletedBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
} }
@@ -1189,9 +1075,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"card_comments_publicId_unique": { "card_comments_publicId_unique": {
"name": "card_comments_publicId_unique", "name": "card_comments_publicId_unique",
"columns": [ "columns": ["publicId"],
"publicId"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -1253,13 +1137,9 @@
"feedback_createdBy_user_id_fk": { "feedback_createdBy_user_id_fk": {
"name": "feedback_createdBy_user_id_fk", "name": "feedback_createdBy_user_id_fk",
"tableFrom": "feedback", "tableFrom": "feedback",
"columnsFrom": [ "columnsFrom": ["createdBy"],
"createdBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
} }
@@ -1319,13 +1199,9 @@
"import_createdBy_user_id_fk": { "import_createdBy_user_id_fk": {
"name": "import_createdBy_user_id_fk", "name": "import_createdBy_user_id_fk",
"tableFrom": "import", "tableFrom": "import",
"columnsFrom": [ "columnsFrom": ["createdBy"],
"createdBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
} }
@@ -1334,9 +1210,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"import_publicId_unique": { "import_publicId_unique": {
"name": "import_publicId_unique", "name": "import_publicId_unique",
"columns": [ "columns": ["publicId"],
"publicId"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -1421,52 +1295,36 @@
"label_createdBy_user_id_fk": { "label_createdBy_user_id_fk": {
"name": "label_createdBy_user_id_fk", "name": "label_createdBy_user_id_fk",
"tableFrom": "label", "tableFrom": "label",
"columnsFrom": [ "columnsFrom": ["createdBy"],
"createdBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"label_boardId_board_id_fk": { "label_boardId_board_id_fk": {
"name": "label_boardId_board_id_fk", "name": "label_boardId_board_id_fk",
"tableFrom": "label", "tableFrom": "label",
"columnsFrom": [ "columnsFrom": ["boardId"],
"boardId"
],
"tableTo": "board", "tableTo": "board",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"label_importId_import_id_fk": { "label_importId_import_id_fk": {
"name": "label_importId_import_id_fk", "name": "label_importId_import_id_fk",
"tableFrom": "label", "tableFrom": "label",
"columnsFrom": [ "columnsFrom": ["importId"],
"importId"
],
"tableTo": "import", "tableTo": "import",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "no action" "onDelete": "no action"
}, },
"label_deletedBy_user_id_fk": { "label_deletedBy_user_id_fk": {
"name": "label_deletedBy_user_id_fk", "name": "label_deletedBy_user_id_fk",
"tableFrom": "label", "tableFrom": "label",
"columnsFrom": [ "columnsFrom": ["deletedBy"],
"deletedBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
} }
@@ -1475,9 +1333,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"label_publicId_unique": { "label_publicId_unique": {
"name": "label_publicId_unique", "name": "label_publicId_unique",
"columns": [ "columns": ["publicId"],
"publicId"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -1562,52 +1418,36 @@
"list_createdBy_user_id_fk": { "list_createdBy_user_id_fk": {
"name": "list_createdBy_user_id_fk", "name": "list_createdBy_user_id_fk",
"tableFrom": "list", "tableFrom": "list",
"columnsFrom": [ "columnsFrom": ["createdBy"],
"createdBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"list_deletedBy_user_id_fk": { "list_deletedBy_user_id_fk": {
"name": "list_deletedBy_user_id_fk", "name": "list_deletedBy_user_id_fk",
"tableFrom": "list", "tableFrom": "list",
"columnsFrom": [ "columnsFrom": ["deletedBy"],
"deletedBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"list_boardId_board_id_fk": { "list_boardId_board_id_fk": {
"name": "list_boardId_board_id_fk", "name": "list_boardId_board_id_fk",
"tableFrom": "list", "tableFrom": "list",
"columnsFrom": [ "columnsFrom": ["boardId"],
"boardId"
],
"tableTo": "board", "tableTo": "board",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"list_importId_import_id_fk": { "list_importId_import_id_fk": {
"name": "list_importId_import_id_fk", "name": "list_importId_import_id_fk",
"tableFrom": "list", "tableFrom": "list",
"columnsFrom": [ "columnsFrom": ["importId"],
"importId"
],
"tableTo": "import", "tableTo": "import",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "no action" "onDelete": "no action"
} }
@@ -1616,9 +1456,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"list_publicId_unique": { "list_publicId_unique": {
"name": "list_publicId_unique", "name": "list_publicId_unique",
"columns": [ "columns": ["publicId"],
"publicId"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -1688,9 +1526,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"user_email_unique": { "user_email_unique": {
"name": "user_email_unique", "name": "user_email_unique",
"columns": [ "columns": ["email"],
"email"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -1722,9 +1558,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"workspace_slugs_slug_unique": { "workspace_slugs_slug_unique": {
"name": "workspace_slugs_slug_unique", "name": "workspace_slugs_slug_unique",
"columns": [ "columns": ["slug"],
"slug"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -1818,39 +1652,27 @@
"workspace_members_userId_user_id_fk": { "workspace_members_userId_user_id_fk": {
"name": "workspace_members_userId_user_id_fk", "name": "workspace_members_userId_user_id_fk",
"tableFrom": "workspace_members", "tableFrom": "workspace_members",
"columnsFrom": [ "columnsFrom": ["userId"],
"userId"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"workspace_members_workspaceId_workspace_id_fk": { "workspace_members_workspaceId_workspace_id_fk": {
"name": "workspace_members_workspaceId_workspace_id_fk", "name": "workspace_members_workspaceId_workspace_id_fk",
"tableFrom": "workspace_members", "tableFrom": "workspace_members",
"columnsFrom": [ "columnsFrom": ["workspaceId"],
"workspaceId"
],
"tableTo": "workspace", "tableTo": "workspace",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "cascade" "onDelete": "cascade"
}, },
"workspace_members_deletedBy_user_id_fk": { "workspace_members_deletedBy_user_id_fk": {
"name": "workspace_members_deletedBy_user_id_fk", "name": "workspace_members_deletedBy_user_id_fk",
"tableFrom": "workspace_members", "tableFrom": "workspace_members",
"columnsFrom": [ "columnsFrom": ["deletedBy"],
"deletedBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
} }
@@ -1859,9 +1681,7 @@
"uniqueConstraints": { "uniqueConstraints": {
"workspace_members_publicId_unique": { "workspace_members_publicId_unique": {
"name": "workspace_members_publicId_unique", "name": "workspace_members_publicId_unique",
"columns": [ "columns": ["publicId"],
"publicId"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -1948,26 +1768,18 @@
"workspace_createdBy_user_id_fk": { "workspace_createdBy_user_id_fk": {
"name": "workspace_createdBy_user_id_fk", "name": "workspace_createdBy_user_id_fk",
"tableFrom": "workspace", "tableFrom": "workspace",
"columnsFrom": [ "columnsFrom": ["createdBy"],
"createdBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
}, },
"workspace_deletedBy_user_id_fk": { "workspace_deletedBy_user_id_fk": {
"name": "workspace_deletedBy_user_id_fk", "name": "workspace_deletedBy_user_id_fk",
"tableFrom": "workspace", "tableFrom": "workspace",
"columnsFrom": [ "columnsFrom": ["deletedBy"],
"deletedBy"
],
"tableTo": "user", "tableTo": "user",
"columnsTo": [ "columnsTo": ["id"],
"id"
],
"onUpdate": "no action", "onUpdate": "no action",
"onDelete": "set null" "onDelete": "set null"
} }
@@ -1976,16 +1788,12 @@
"uniqueConstraints": { "uniqueConstraints": {
"workspace_publicId_unique": { "workspace_publicId_unique": {
"name": "workspace_publicId_unique", "name": "workspace_publicId_unique",
"columns": [ "columns": ["publicId"],
"publicId"
],
"nullsNotDistinct": false "nullsNotDistinct": false
}, },
"workspace_slug_unique": { "workspace_slug_unique": {
"name": "workspace_slug_unique", "name": "workspace_slug_unique",
"columns": [ "columns": ["slug"],
"slug"
],
"nullsNotDistinct": false "nullsNotDistinct": false
} }
}, },
@@ -1998,10 +1806,7 @@
"public.board_visibility": { "public.board_visibility": {
"name": "board_visibility", "name": "board_visibility",
"schema": "public", "schema": "public",
"values": [ "values": ["private", "public"]
"private",
"public"
]
}, },
"public.card_activity_type": { "public.card_activity_type": {
"name": "card_activity_type", "name": "card_activity_type",
@@ -2025,53 +1830,32 @@
"public.source": { "public.source": {
"name": "source", "name": "source",
"schema": "public", "schema": "public",
"values": [ "values": ["trello"]
"trello"
]
}, },
"public.status": { "public.status": {
"name": "status", "name": "status",
"schema": "public", "schema": "public",
"values": [ "values": ["started", "success", "failed"]
"started",
"success",
"failed"
]
}, },
"public.role": { "public.role": {
"name": "role", "name": "role",
"schema": "public", "schema": "public",
"values": [ "values": ["admin", "member", "guest"]
"admin",
"member",
"guest"
]
}, },
"public.member_status": { "public.member_status": {
"name": "member_status", "name": "member_status",
"schema": "public", "schema": "public",
"values": [ "values": ["invited", "active", "removed"]
"invited",
"active",
"removed"
]
}, },
"public.slug_type": { "public.slug_type": {
"name": "slug_type", "name": "slug_type",
"schema": "public", "schema": "public",
"values": [ "values": ["reserved", "premium"]
"reserved",
"premium"
]
}, },
"public.workspace_plan": { "public.workspace_plan": {
"name": "workspace_plan", "name": "workspace_plan",
"schema": "public", "schema": "public",
"values": [ "values": ["free", "pro", "enterprise"]
"free",
"pro",
"enterprise"
]
} }
}, },
"schemas": {}, "schemas": {},
@@ -2084,4 +1868,4 @@
"schemas": {}, "schemas": {},
"tables": {} "tables": {}
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -50,6 +50,20 @@
"when": 1749585889984, "when": 1749585889984,
"tag": "20250610200449_ReaddIntegrationTable", "tag": "20250610200449_ReaddIntegrationTable",
"breakpoints": true "breakpoints": true
},
{
"idx": 7,
"version": "7",
"when": 1754511666265,
"tag": "20250806202106_glossy_luminals",
"breakpoints": true
},
{
"idx": 8,
"version": "7",
"when": 1755094668761,
"tag": "20250813141748_AddChecklistActivityTypes",
"breakpoints": true
} }
] ]
} }

View File

@@ -39,6 +39,7 @@
"with-env": "dotenv -e ../../.env --" "with-env": "dotenv -e ../../.env --"
}, },
"dependencies": { "dependencies": {
"@electric-sql/pglite": "^0.3.7",
"@kan/shared": "workspace:^", "@kan/shared": "workspace:^",
"drizzle-orm": "^0.42.0", "drizzle-orm": "^0.42.0",
"drizzle-zod": "^0.5.1", "drizzle-zod": "^0.5.1",

View File

@@ -1,8 +1,12 @@
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { drizzle as drizzlePgLite } from "drizzle-orm/pglite";
import { uuid_ossp } from "@electric-sql/pglite/contrib/uuid_ossp";
import { drizzle as drizzlePg } from "drizzle-orm/node-postgres"; import { drizzle as drizzlePg } from "drizzle-orm/node-postgres";
import { Pool } from "pg"; import { Pool } from "pg";
import * as schema from "./schema"; import * as schema from "./schema";
import { PGlite } from "@electric-sql/pglite";
import { migrate } from "drizzle-orm/pglite/migrator";
export type dbClient = NodePgDatabase<typeof schema> & { export type dbClient = NodePgDatabase<typeof schema> & {
$client: Pool; $client: Pool;
@@ -12,7 +16,14 @@ export const createDrizzleClient = (): dbClient => {
const connectionString = process.env.POSTGRES_URL; const connectionString = process.env.POSTGRES_URL;
if (!connectionString) { if (!connectionString) {
throw new Error("POSTGRES_URL environment variable is not set"); console.log("POSTGRES_URL environment variable is not set, using PGLite");
const client = new PGlite({ dataDir: "./pgdata", extensions: { uuid_ossp }});
const db = drizzlePgLite(client, { schema });
migrate(db, { migrationsFolder: "../../packages/db/migrations" });
return db as unknown as dbClient;
} }
const pool = new Pool({ const pool = new Pool({

View File

@@ -7,6 +7,8 @@ import {
cards, cards,
cardsToLabels, cardsToLabels,
cardToWorkspaceMembers, cardToWorkspaceMembers,
checklistItems,
checklists,
labels, labels,
lists, lists,
workspaceMembers, workspaceMembers,
@@ -164,6 +166,27 @@ export const getByPublicId = async (
}, },
}, },
}, },
checklists: {
columns: {
publicId: true,
name: true,
index: true,
},
where: isNull(checklists.deletedAt),
orderBy: asc(checklists.index),
with: {
items: {
columns: {
publicId: true,
title: true,
completed: true,
index: true,
},
where: isNull(checklistItems.deletedAt),
orderBy: asc(checklistItems.index),
},
},
},
}, },
where: and( where: and(
cardIds.length > 0 ? inArray(cards.publicId, cardIds) : undefined, cardIds.length > 0 ? inArray(cards.publicId, cardIds) : undefined,
@@ -280,6 +303,27 @@ export const getBySlug = async (
}, },
}, },
}, },
checklists: {
columns: {
publicId: true,
name: true,
index: true,
},
where: isNull(checklists.deletedAt),
orderBy: asc(checklists.index),
with: {
items: {
columns: {
publicId: true,
title: true,
completed: true,
index: true,
},
where: isNull(checklistItems.deletedAt),
orderBy: asc(checklistItems.index),
},
},
},
}, },
where: and( where: and(
cardIds.length > 0 ? inArray(cards.publicId, cardIds) : undefined, cardIds.length > 0 ? inArray(cards.publicId, cardIds) : undefined,

View File

@@ -6,6 +6,8 @@ import {
cards, cards,
cardsToLabels, cardsToLabels,
cardToWorkspaceMembers, cardToWorkspaceMembers,
checklistItems,
checklists,
labels, labels,
lists, lists,
workspaceMembers, workspaceMembers,
@@ -300,6 +302,27 @@ export const getWithListAndMembersByPublicId = async (
}, },
}, },
}, },
checklists: {
columns: {
publicId: true,
name: true,
index: true,
},
where: isNull(checklists.deletedAt),
orderBy: asc(checklists.index),
with: {
items: {
columns: {
publicId: true,
title: true,
completed: true,
index: true,
},
where: isNull(checklistItems.deletedAt),
orderBy: asc(checklistItems.index),
},
},
},
list: { list: {
columns: { columns: {
publicId: true, publicId: true,

View File

@@ -0,0 +1,216 @@
import { and, desc, eq, isNull } from "drizzle-orm";
import type { dbClient } from "@kan/db/client";
import { checklistItems, checklists } from "@kan/db/schema";
import { generateUID } from "@kan/shared/utils";
export const create = async (
db: dbClient,
checklistInput: {
cardId: number;
name: string;
createdBy: string;
},
) => {
return db.transaction(async (tx) => {
const card = await tx.query.checklists.findFirst({
where: and(
eq(checklists.cardId, checklistInput.cardId),
isNull(checklists.deletedAt),
),
orderBy: desc(checklists.index),
});
const [result] = await tx
.insert(checklists)
.values({
publicId: generateUID(),
name: checklistInput.name,
createdBy: checklistInput.createdBy,
cardId: checklistInput.cardId,
index: card ? card.index + 1 : 0,
})
.returning({
id: checklists.id,
publicId: checklists.publicId,
name: checklists.name,
});
return result;
});
};
export const createItem = async (
db: dbClient,
checklistItemInput: {
checklistId: number;
title: string;
createdBy: string;
},
) => {
return db.transaction(async (tx) => {
const lastItem = await tx.query.checklistItems.findFirst({
where: and(
eq(checklistItems.checklistId, checklistItemInput.checklistId),
isNull(checklistItems.deletedAt),
),
orderBy: desc(checklistItems.index),
});
const [result] = await tx
.insert(checklistItems)
.values({
publicId: generateUID(),
title: checklistItemInput.title,
createdBy: checklistItemInput.createdBy,
checklistId: checklistItemInput.checklistId,
index: lastItem ? lastItem.index + 1 : 0,
completed: false,
})
.returning({
id: checklistItems.id,
publicId: checklistItems.publicId,
title: checklistItems.title,
completed: checklistItems.completed,
});
return result;
});
};
export const getChecklistByPublicId = async (
db: dbClient,
checklistPublicId: string,
) => {
const checklist = await db.query.checklists.findFirst({
where: and(
eq(checklists.publicId, checklistPublicId),
isNull(checklists.deletedAt),
),
with: {
card: {
with: {
list: {
with: {
board: {
with: {
workspace: true,
},
},
},
},
},
},
},
});
return checklist;
};
export const getChecklistItemByPublicIdWithChecklist = async (
db: dbClient,
checklistItemPublicId: string,
) => {
const item = await db.query.checklistItems.findFirst({
where: and(
eq(checklistItems.publicId, checklistItemPublicId),
isNull(checklistItems.deletedAt),
),
with: {
checklist: {
with: {
card: {
with: {
list: {
with: {
board: {
with: { workspace: true },
},
},
},
},
},
},
},
},
});
return item;
};
export const updateItemById = async (
db: dbClient,
args: { id: number; title?: string; completed?: boolean },
) => {
const [result] = await db
.update(checklistItems)
.set({
...(args.title !== undefined ? { title: args.title } : {}),
...(args.completed !== undefined ? { completed: args.completed } : {}),
updatedAt: new Date(),
})
.where(eq(checklistItems.id, args.id))
.returning({
publicId: checklistItems.publicId,
title: checklistItems.title,
completed: checklistItems.completed,
});
return result;
};
export const softDeleteItemById = async (
db: dbClient,
args: { id: number; deletedAt: Date; deletedBy: string },
) => {
const [result] = await db
.update(checklistItems)
.set({ deletedAt: args.deletedAt, deletedBy: args.deletedBy })
.where(eq(checklistItems.id, args.id))
.returning({ id: checklistItems.id });
return result;
};
export const softDeleteAllItemsByChecklistId = async (
db: dbClient,
args: { checklistId: number; deletedAt: Date; deletedBy: string },
) => {
const result = await db
.update(checklistItems)
.set({ deletedAt: args.deletedAt, deletedBy: args.deletedBy })
.where(
and(
eq(checklistItems.checklistId, args.checklistId),
isNull(checklistItems.deletedAt),
),
)
.returning({ id: checklistItems.id });
return result;
};
export const softDeleteById = async (
db: dbClient,
args: { id: number; deletedAt: Date; deletedBy: string },
) => {
const [result] = await db
.update(checklists)
.set({ deletedAt: args.deletedAt, deletedBy: args.deletedBy })
.where(eq(checklists.id, args.id))
.returning({ id: checklists.id });
return result;
};
export const updateChecklistById = async (
db: dbClient,
args: { id: number; name: string },
) => {
const [result] = await db
.update(checklists)
.set({ name: args.name, updatedAt: new Date() })
.where(eq(checklists.id, args.id))
.returning({ publicId: checklists.publicId, name: checklists.name });
return result;
};

View File

@@ -12,6 +12,7 @@ import {
varchar, varchar,
} from "drizzle-orm/pg-core"; } from "drizzle-orm/pg-core";
import { checklists } from "./checklists";
import { imports } from "./imports"; import { imports } from "./imports";
import { labels } from "./labels"; import { labels } from "./labels";
import { lists } from "./lists"; import { lists } from "./lists";
@@ -31,6 +32,15 @@ export const activityTypes = [
"card.updated.comment.added", "card.updated.comment.added",
"card.updated.comment.updated", "card.updated.comment.updated",
"card.updated.comment.deleted", "card.updated.comment.deleted",
// Checklist activities
"card.updated.checklist.added",
"card.updated.checklist.renamed",
"card.updated.checklist.deleted",
"card.updated.checklist.item.added",
"card.updated.checklist.item.updated",
"card.updated.checklist.item.completed",
"card.updated.checklist.item.uncompleted",
"card.updated.checklist.item.deleted",
"card.archived", "card.archived",
] as const; ] as const;
@@ -84,6 +94,7 @@ export const cardsRelations = relations(cards, ({ one, many }) => ({
}), }),
comments: many(comments), comments: many(comments),
activities: many(cardActivities), activities: many(cardActivities),
checklists: many(checklists),
})); }));
export const cardActivities = pgTable("card_activity", { export const cardActivities = pgTable("card_activity", {

View File

@@ -0,0 +1,90 @@
import { relations } from "drizzle-orm";
import {
bigint,
bigserial,
boolean,
integer,
pgTable,
timestamp,
uuid,
varchar,
} from "drizzle-orm/pg-core";
import { cards } from "./cards";
import { users } from "./users";
export const checklists = pgTable("card_checklist", {
id: bigserial("id", { mode: "number" }).primaryKey(),
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
name: varchar("name", { length: 255 }).notNull(),
index: integer("index").notNull(),
cardId: bigint("cardId", { mode: "number" })
.notNull()
.references(() => cards.id, { onDelete: "cascade" }),
createdBy: uuid("createdBy").references(() => users.id, {
onDelete: "set null",
}),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt"),
deletedAt: timestamp("deletedAt"),
deletedBy: uuid("deletedBy").references(() => users.id, {
onDelete: "set null",
}),
}).enableRLS();
export const checklistsRelations = relations(checklists, ({ one, many }) => ({
card: one(cards, {
fields: [checklists.cardId],
references: [cards.id],
relationName: "checklistsCard",
}),
createdBy: one(users, {
fields: [checklists.createdBy],
references: [users.id],
relationName: "checklistsCreatedByUser",
}),
deletedBy: one(users, {
fields: [checklists.deletedBy],
references: [users.id],
relationName: "checklistsDeletedByUser",
}),
items: many(checklistItems),
}));
export const checklistItems = pgTable("card_checklist_item", {
id: bigserial("id", { mode: "number" }).primaryKey(),
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
title: varchar("title", { length: 500 }).notNull(),
completed: boolean("completed").notNull().default(false),
index: integer("index").notNull(),
checklistId: bigint("checklistId", { mode: "number" })
.notNull()
.references(() => checklists.id, { onDelete: "cascade" }),
createdBy: uuid("createdBy").references(() => users.id, {
onDelete: "set null",
}),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt"),
deletedAt: timestamp("deletedAt"),
deletedBy: uuid("deletedBy").references(() => users.id, {
onDelete: "set null",
}),
}).enableRLS();
export const checklistItemsRelations = relations(checklistItems, ({ one }) => ({
checklist: one(checklists, {
fields: [checklistItems.checklistId],
references: [checklists.id],
relationName: "checklistItemsChecklist",
}),
createdBy: one(users, {
fields: [checklistItems.createdBy],
references: [users.id],
relationName: "checklistItemsCreatedByUser",
}),
deletedBy: one(users, {
fields: [checklistItems.deletedBy],
references: [users.id],
relationName: "checklistItemsDeletedByUser",
}),
}));

View File

@@ -2,6 +2,7 @@ export * from "./auth";
export * from "./boards"; export * from "./boards";
export * from "./auth"; export * from "./auth";
export * from "./cards"; export * from "./cards";
export * from "./checklists";
export * from "./feedback"; export * from "./feedback";
export * from "./imports"; export * from "./imports";
export * from "./labels"; export * from "./labels";

View File

@@ -1,7 +1,9 @@
import Plunk from "@plunk/node"; import Plunk from "@plunk/node";
export const cloudMailerClient = export const cloudMailerClient =
process.env.NEXT_PUBLIC_KAN_ENV === "cloud" process.env.NEXT_PUBLIC_KAN_ENV === "cloud" &&
process.env.PLUNK_API_KEY &&
process.env.PLUNK_API_URL
? new Plunk(process.env.PLUNK_API_KEY ?? "", { ? new Plunk(process.env.PLUNK_API_KEY ?? "", {
baseUrl: process.env.PLUNK_API_URL, baseUrl: process.env.PLUNK_API_URL,
}) })

50
pnpm-lock.yaml generated
View File

@@ -123,6 +123,9 @@ importers:
'@tiptap/extension-link': '@tiptap/extension-link':
specifier: ^2.22.2 specifier: ^2.22.2
version: 2.22.2(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0) version: 2.22.2(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)
'@tiptap/extension-mention':
specifier: ^3.0.9
version: 3.0.9(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)(@tiptap/suggestion@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0))
'@tiptap/extension-placeholder': '@tiptap/extension-placeholder':
specifier: ^2.14.0 specifier: ^2.14.0
version: 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0) version: 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)
@@ -168,6 +171,9 @@ importers:
next-runtime-env: next-runtime-env:
specifier: ^1.7.2 specifier: ^1.7.2
version: 1.8.0 version: 1.8.0
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
nextjs-cors: nextjs-cors:
specifier: ^2.2.0 specifier: ^2.2.0
version: 2.2.0(next@15.3.4(@babel/core@7.24.5)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) version: 2.2.0(next@15.3.4(@babel/core@7.24.5)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
@@ -360,15 +366,18 @@ importers:
packages/db: packages/db:
dependencies: dependencies:
'@electric-sql/pglite':
specifier: ^0.3.7
version: 0.3.7
'@kan/shared': '@kan/shared':
specifier: workspace:^ specifier: workspace:^
version: link:../shared version: link:../shared
drizzle-orm: drizzle-orm:
specifier: ^0.42.0 specifier: ^0.42.0
version: 0.42.0(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5) version: 0.42.0(@electric-sql/pglite@0.3.7)(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5)
drizzle-zod: drizzle-zod:
specifier: ^0.5.1 specifier: ^0.5.1
version: 0.5.1(drizzle-orm@0.42.0(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5))(zod@3.24.0) version: 0.5.1(drizzle-orm@0.42.0(@electric-sql/pglite@0.3.7)(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5))(zod@3.24.0)
pg: pg:
specifier: ^8.11.3 specifier: ^8.11.3
version: 8.13.1 version: 8.13.1
@@ -888,6 +897,9 @@ packages:
'@drizzle-team/brocli@0.10.2': '@drizzle-team/brocli@0.10.2':
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
'@electric-sql/pglite@0.3.7':
resolution: {integrity: sha512-5c3mybVrhxu5s47zFZtIGdG8YHkKCBENOmqxnNBjY53ZoDhADY/c5UqBDl159b7qtkzNPtbbb893wL9zi1kAuw==}
'@emnapi/runtime@1.3.1': '@emnapi/runtime@1.3.1':
resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==}
@@ -2770,6 +2782,13 @@ packages:
peerDependencies: peerDependencies:
'@tiptap/core': ^2.7.0 '@tiptap/core': ^2.7.0
'@tiptap/extension-mention@3.0.9':
resolution: {integrity: sha512-DTQNAQkHZ+7Enlt3KvjqN6eECINlqPpET4Drzwj8Mmz9kMILc87cz3G2cwEKRrS9A1Xn3H3VpWvElWE2Wq9JHw==}
peerDependencies:
'@tiptap/core': ^3.0.9
'@tiptap/pm': ^3.0.9
'@tiptap/suggestion': ^3.0.9
'@tiptap/extension-ordered-list@2.14.0': '@tiptap/extension-ordered-list@2.14.0':
resolution: {integrity: sha512-QUZcyuW9AKvSfpFHcGmbyRCqxcpY0VNf0xipEtogxbA+JDDw3ZSPqU1dUgz9wk00RahPTwNDdY5aVjdQ5N4N9Q==} resolution: {integrity: sha512-QUZcyuW9AKvSfpFHcGmbyRCqxcpY0VNf0xipEtogxbA+JDDw3ZSPqU1dUgz9wk00RahPTwNDdY5aVjdQ5N4N9Q==}
peerDependencies: peerDependencies:
@@ -5441,6 +5460,12 @@ packages:
next-runtime-env@1.8.0: next-runtime-env@1.8.0:
resolution: {integrity: sha512-QJVxzmr2gTao/vZKFgcrByFrifl0YOMTvuUVxcI/X7ratlW+9zMvMmA9AGU9cFsumXJtohWkCvwPdBNdkTCYfw==} resolution: {integrity: sha512-QJVxzmr2gTao/vZKFgcrByFrifl0YOMTvuUVxcI/X7ratlW+9zMvMmA9AGU9cFsumXJtohWkCvwPdBNdkTCYfw==}
next-themes@0.4.6:
resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
peerDependencies:
react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
next@15.0.4: next@15.0.4:
resolution: {integrity: sha512-nuy8FH6M1FG0lktGotamQDCXhh5hZ19Vo0ht1AOIQWrYJLP598TIUagKtvJrfJ5AGwB/WmDqkKaKhMpVifvGPA==} resolution: {integrity: sha512-nuy8FH6M1FG0lktGotamQDCXhh5hZ19Vo0ht1AOIQWrYJLP598TIUagKtvJrfJ5AGwB/WmDqkKaKhMpVifvGPA==}
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
@@ -6484,6 +6509,7 @@ packages:
source-map@0.8.0-beta.0: source-map@0.8.0-beta.0:
resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
deprecated: The work that was done in this beta branch won't be included in future versions
space-separated-tokens@2.0.2: space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
@@ -7852,6 +7878,8 @@ snapshots:
'@drizzle-team/brocli@0.10.2': {} '@drizzle-team/brocli@0.10.2': {}
'@electric-sql/pglite@0.3.7': {}
'@emnapi/runtime@1.3.1': '@emnapi/runtime@1.3.1':
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
@@ -9612,6 +9640,12 @@ snapshots:
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.14.0)
'@tiptap/extension-mention@3.0.9(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)(@tiptap/suggestion@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0))':
dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0)
'@tiptap/pm': 2.14.0
'@tiptap/suggestion': 2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))(@tiptap/pm@2.14.0)
'@tiptap/extension-ordered-list@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))': '@tiptap/extension-ordered-list@2.14.0(@tiptap/core@2.14.0(@tiptap/pm@2.14.0))':
dependencies: dependencies:
'@tiptap/core': 2.14.0(@tiptap/pm@2.14.0) '@tiptap/core': 2.14.0(@tiptap/pm@2.14.0)
@@ -10845,8 +10879,9 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
drizzle-orm@0.42.0(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5): drizzle-orm@0.42.0(@electric-sql/pglite@0.3.7)(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5):
optionalDependencies: optionalDependencies:
'@electric-sql/pglite': 0.3.7
'@neondatabase/serverless': 0.10.4 '@neondatabase/serverless': 0.10.4
'@types/pg': 8.11.6 '@types/pg': 8.11.6
'@vercel/postgres': 0.10.0(utf-8-validate@6.0.3) '@vercel/postgres': 0.10.0(utf-8-validate@6.0.3)
@@ -10854,9 +10889,9 @@ snapshots:
pg: 8.13.1 pg: 8.13.1
postgres: 3.4.5 postgres: 3.4.5
drizzle-zod@0.5.1(drizzle-orm@0.42.0(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5))(zod@3.24.0): drizzle-zod@0.5.1(drizzle-orm@0.42.0(@electric-sql/pglite@0.3.7)(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5))(zod@3.24.0):
dependencies: dependencies:
drizzle-orm: 0.42.0(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5) drizzle-orm: 0.42.0(@electric-sql/pglite@0.3.7)(@neondatabase/serverless@0.10.4)(@types/pg@8.11.6)(@vercel/postgres@0.10.0(utf-8-validate@6.0.3))(kysely@0.28.2)(pg@8.13.1)(postgres@3.4.5)
zod: 3.24.0 zod: 3.24.0
dunder-proto@1.0.0: dunder-proto@1.0.0:
@@ -13002,6 +13037,11 @@ snapshots:
dependencies: dependencies:
chalk: 4.1.2 chalk: 4.1.2
next-themes@0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
next@15.0.4(@babel/core@7.24.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): next@15.0.4(@babel/core@7.24.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies: dependencies:
'@next/env': 15.0.4 '@next/env': 15.0.4

View File

@@ -72,6 +72,9 @@
"VK_CLIENT_SECRET", "VK_CLIENT_SECRET",
"LINKEDIN_CLIENT_ID", "LINKEDIN_CLIENT_ID",
"LINKEDIN_CLIENT_SECRET", "LINKEDIN_CLIENT_SECRET",
"OIDC_CLIENT_ID",
"OIDC_CLIENT_SECRET",
"OIDC_DISCOVERY_URL",
"REDDIT_CLIENT_ID", "REDDIT_CLIENT_ID",
"REDDIT_CLIENT_SECRET", "REDDIT_CLIENT_SECRET",
"ROBLOX_CLIENT_ID", "ROBLOX_CLIENT_ID",
@@ -93,6 +96,7 @@
"SMTP_PASSWORD", "SMTP_PASSWORD",
"SMTP_SECURE", "SMTP_SECURE",
"NEXT_PUBLIC_KAN_ENV", "NEXT_PUBLIC_KAN_ENV",
"NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY",
"STRIPE_SECRET_KEY", "STRIPE_SECRET_KEY",
"STRIPE_WEBHOOK_SECRET", "STRIPE_WEBHOOK_SECRET",
"STRIPE_PRO_PLAN_PRICE_ID", "STRIPE_PRO_PLAN_PRICE_ID",