Compare commits

..

24 Commits

Author SHA1 Message Date
Henry
872a5fad28 feat: public board enhancements (#134)
* feat: hide dropdown on comments for public boards

* feat: fix height of modal and add scrollable content area

* feat: add view only badge to public boards

* feat: prevent card title from overlapping close button

* chore: gen translations
2025-08-01 22:03:38 +01:00
Henry
400b94a5f2 feat: enhance member invite error handling and add invite more toggle (#133) 2025-07-30 22:24:05 +01:00
Henry
638b8b6b79 fix: update public board lookup to filter by workspace slug and show not found message (#131)
* fix: update public board lookup to filter by workspace slug

* feat: show not found message for public boards

* chore: update lang
2025-07-28 22:59:28 +01:00
Ridham Khandar
ca1dd92ab4 fix: disable create list and label button when input is empty (#130) 2025-07-28 21:49:24 +01:00
Ridham Khandar
f8827da73a fix: creating a new label when adding a new card resets all fields (#119)
* fix: creating a new label when adding a new card resets all fields

* fix: persist form data and modal stacking without breaking the animations
2025-07-28 21:49:13 +01:00
Henry
babaa9f1b1 feat: setup plunk for transactional/marketing emails 2025-07-28 07:09:30 +01:00
Henry
0cefd17484 fix: prevent member dropdown from being cutoff (#127) 2025-07-26 21:34:05 +01:00
Henry
974a5ff0f3 fix: update board slug availability check to be unique to workspace (#126) 2025-07-26 21:18:26 +01:00
Henry
0ec71b589d feat: dashboard 2.0 redesign (#124)
* feat: add patterned background to boards

* feat: setup dashboard 2.0

* fix: prevent patterned background from overlaying buttons

* feat: set max width for main card view

* feat: adjust colour scheme for card view

* feat: adjust dashboard border colour scheme and radius

* fix: use correct colour for description placeholder

* fix: use getLayout to persist layout state across pages

* feat: reduce max width for settings and members pages

* feat: add feedback button and modal

* feat: adjust page max width

* feat: extend mobile layout support

* fix: hide pro badge when collapsed

* feat: tweak nav styling for light mode

* feat: tweak skeleton loaders for board list

* feat: extend list max height

* fix: hide side nav right border on desktop

* chore: update hero images

* chore: update hero images for docs

* chore: update translations
2025-07-24 12:14:46 +01:00
Henry
0cb69e2087 fix: allow member invites when signup is disabled (#121) 2025-07-20 11:18:19 +01:00
Henry
1305c55100 fix: affix avatar fileName with UID to invalidate next image cache (#117) 2025-07-14 22:39:05 +01:00
Henry
425c91865b feat: redirect from root to login for self hosted instances (#118) 2025-07-14 22:38:57 +01:00
Henry
a0096a9eb0 fix: use server-side signInMagicLink for member invites (#116) 2025-07-14 22:34:10 +01:00
Connor Goldberg
4058169079 fix: auth /social-providers endpoint ids (#115)
The `/social-providers` endpoint should return a list of the provider ids, not their names.
This was found when trying to use the microsoft endpoint and the endpoint was returning `"microsoft entraid"`, when the `AuthForm` expects it to just be `"microsoft"`.
2025-07-14 22:14:20 +01:00
Henry
ecc42f988f chore: update changelog 2025-07-11 22:28:21 +01:00
Henry
1ded560b75 feat: redirect from root to login for self hosted instances (#111) 2025-07-10 21:49:48 +01:00
Henry
f8dc062903 chore: add verbose error logging to magic link invitation (#110) 2025-07-10 21:27:25 +01:00
Henry
2169a379f2 feat: add button to view/update board public URL from board page (#107)
* feat: add update board slug button

* feat: add edit workspace url button

* feat: add loading state to update board slug button

* chore: add translations
2025-07-09 21:59:33 +01:00
Henry
03816b192f chore: hide hacker news button 2025-07-08 21:34:54 +01:00
Henry
f4ef1217dc feat: enhance label router with consistent output (#104) 2025-07-07 22:33:01 +01:00
Henry
1c920e3983 fix: update trpc dependencies and add openapi meta to providers endpoint (#103) 2025-07-07 22:32:49 +01:00
Henry
9daf657db2 chore: update changelog 2025-07-07 22:32:07 +01:00
Rees Morris
fdfd1f3d03 feat: add S3_FORCE_PATH_STYLE configuration for MinIO compatibility (#100)
* feat: add S3_FORCE_PATH_STYLE configuration for MinIO compatibility

* docs: add S3_FORCE_PATH_STYLE to env example
2025-07-07 21:06:51 +01:00
Henry
392be38f10 feat: improve mobile support on ios (#99)
* fix: add min width to dashboard

* fix: display theme background and set dynamic viewport height

* fix: prevent zooming on ios

* fix: enable scroll on card page
2025-07-03 09:12:06 +01:00
87 changed files with 2630 additions and 1446 deletions

View File

@@ -21,6 +21,7 @@ S3_REGION=
S3_ENDPOINT=
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_FORCE_PATH_STYLE=
NEXT_PUBLIC_STORAGE_URL=
NEXT_PUBLIC_AVATAR_BUCKET_NAME=
NEXT_PUBLIC_STORAGE_DOMAIN=

4
.vscode/launch.json vendored
View File

@@ -6,7 +6,7 @@
"type": "node-terminal",
"request": "launch",
"command": "pnpm dev",
"cwd": "${workspaceFolder}/apps/nextjs",
"cwd": "${workspaceFolder}/apps/web",
"skipFiles": ["<node_internals>/**"],
"sourceMaps": true,
"sourceMapPathOverrides": {
@@ -14,4 +14,4 @@
}
}
]
}
}

View File

@@ -5,7 +5,43 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased](https://github.com/kanbn/kan/compare/v0.2.2...HEAD)
## [Unreleased](https://github.com/kanbn/kan/compare/v0.2.4...HEAD)
## [0.2.4](https://github.com/kanbn/kan/compare/v0.2.3...v0.2.4) - 2025-01-14
### Added
- Button to view and update board public URL directly from board page
- Redirect from root to login page for self-hosted instances
### Changed
- Updated all label router endpoints to return consistent structure
- Added verbose error logging to magic link invitation process
### Fixed
- Updated tRPC dependencies and added OpenAPI meta to providers endpoint
## [0.2.3](https://github.com/kanbn/kan/compare/v0.2.2...v0.2.3) - 2025-07-07
### Added
- Mobile support with responsive navigation and layout
- Template selection when creating new boards with predefined lists and labels
- S3_FORCE_PATH_STYLE configuration for MinIO compatibility
### Changed
- Improved mobile UI styling and layout containers
- Enhanced iOS mobile support with viewport fixes and zoom prevention
- Improved card view layout for mobile devices
### Fixed
- Mobile dashboard min-width issues
- Dynamic viewport height on mobile devices
- Scroll functionality on card pages
## [0.2.2](https://github.com/kanbn/kan/compare/v0.2.1...v0.2.2) - 2025-06-28

View File

@@ -162,6 +162,7 @@ pnpm dev
| `S3_ENDPOINT` | S3 endpoint URL | For file uploads | `https://xxx.r2.cloudflarestorage.com` |
| `S3_ACCESS_KEY_ID` | S3 access key | For file uploads | `xxx` |
| `S3_SECRET_ACCESS_KEY` | S3 secret key | For file uploads | `xxx` |
| `S3_FORCE_PATH_STYLE` | Use path-style URLs for S3 | For file uploads | `true` |
| `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` |
| `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` |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

@@ -6,7 +6,6 @@ checksums:
"%7B0%7D%20%7C%20%7B1%7D/singular": 4628f9c6ec13c2dc2984a6ab80e19f8b
"%7B0%7D%20labels/singular": 785f92bedf786ff3e285adfc07c69d18
"%7BboardCount%2C%20plural%2C%20one%20%7BImport%20board%20(1)%7D%20other%20%7BImport%20boards%20(%7BboardCount%7D)%7D%7D/singular": 72358c550bd1a99fcb6e8952f0f947ef
"%231%20Hacker%20News/singular": de271b412c6c022d5c427d29fc70e0ba
1%20user/singular: 3b547431ab12f0fba84307e6a81109d8
A%20powerful%2C%20flexible%20kanban%20app%20that%20helps%20you%20organise%20work%2C%20track%20progress%2C%20and%20deliver%20results%E2%80%94all%20in%20one%20place./singular: d405b83b0d631cb72f4347c10bcbb643
Account%20deleted/singular: a25da96a1579c4491be0a95669ef18a4
@@ -33,6 +32,7 @@ checksums:
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%20comment%3F/singular: 55fe6f1b52b71b91b2a079cfda3cc7fe
Are%20you%20sure%20you%20want%20to%20delete%20this%20label%3F/singular: 037fbaf1d04356937e6afb574714f51f
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
Awaiting%20Customer/singular: 122c108794f321c10e05a08f09b11457
@@ -119,6 +119,7 @@ checksums:
Edit%20board%20URL/singular: d8276dfc0189f371ec7d80a2047c07aa
Edit%20comment/singular: 7e4b46525fcb6b47b71798e31c46e374
Edit%20label/singular: 0309e0be1512b1e0b0ceb87c69a53d03
Edit%20workspace%20URL/singular: bbae5f2f8a442947d33099979bbbe899
Editing/singular: 3449a7988cd69207b7c6929af1f4abf1
email/singular: f31eb214738e037d58e26149797739df
Email/singular: e7f34943a0c2fb849db1839ff6ef5cb5
@@ -127,8 +128,10 @@ checksums:
Enter%20your%20name/singular: cd95fbdd0533f2c2e8edf9d9bd9aa8df
Enter%20your%20password/singular: ea4fdd034522dead21bae0c0abb52eae
Error%20deleting%20account/singular: d42965a9bc9e5ec4ed57890268924643
Error%20deleting%20label/singular: 94387e3a45ec768ae7715701ae00136e
Error%20deleting%20workspace/singular: 0aec9bd8170bc84f5ea5c9a47c52ed26
Error%20disconnecting%20Trello/singular: a8766853864eddc480113778a708871b
Error%20inviting%20member/singular: 91553b606a6ebed3534cd2e5635ce004
Error%20updating%20display%20name/singular: 0d7979a25d290123ed8b8906bf468f1a
Error%20updating%20profile%20image/singular: 462a56a6e574abc9e13cb48f1266adad
Error%20updating%20workspace%20description/singular: 7a9fd7c69b90ab848ee1f1d4a4995381
@@ -185,7 +188,9 @@ checksums:
Individuals/singular: 83bfc81f20e60556c44ec80c7d0603ec
Integrations/singular: 0ccce343287704cd90150c32e2fcad36
Interviewing/singular: 4ccdcdc784547e925077c3297bddee95
Invalid%20email%20address/singular: b2d9f25626f2d15c7c63e0281bccc247
Invite/singular: 181884cea804cbde665f160811ee7ad0
Invite%20another/singular: acb543563dab7edbcf46060a53ade3a3
Invite%20member/singular: ade922db1be6b26bc979565ce5de2bc7
Junior/singular: ed1bd2c59a824fdcdd56fc8a0660fe9f
Kanban%20is%20better%20with%20a%20team.%20Perfect%20for%20small%20and%20growing%20teams%20looking%20to%20collaborate./singular: a77bee43046b260797c8936ad23e9223
@@ -280,7 +285,7 @@ checksums:
Self%20Host/singular: 43fbce2027548b712002e489a20a621a
Self%20host%20with%20Github/singular: 972155419bcc9f8f9bad9f5ad3538774
self-assigned%20the%20card/singular: 24a8d97bcd747643772ebe883be69698
Send/singular: 76a8497d7b546628b03bb81d5c1ce995
Send%20feedback/singular: 9631cc08d49da04475b30a0d320ce97c
Senior/singular: 3fff865dc00435f82896fc302ea45630
Settings/singular: 8df6777277469c1fd88cc18dde2f1cc3
Settings%20%7C%20%7B0%7D/singular: b8fc73080bc9c8f4f1403b2a69bd1ac5
@@ -295,6 +300,7 @@ checksums:
Software%20Development/singular: 67659097ef6bcb194839858b2c4f3a3c
Star%20on%20Github/singular: e5cb0428f1ac6485688f120d78742875
Success/singular: c43827becada6750f7a25890905f38b9
Support/singular: 55aab5fd0f31a9cb055a2edeeedfaf63
Support%20the%20development%20of%20the%20project/singular: c63bab228ab2b1be4370c668a99cd278
System/singular: 803281c327a02a2feba182f4a2b38311
Teams/singular: b63448c05270497973ac4407047dae02
@@ -307,6 +313,7 @@ checksums:
Theme/singular: 21fe00b7a518089576fb83c08631107a
They%20won't%20be%20able%20to%20access%20this%20workspace./singular: 93b740350fe3430319fbca85349e41d9
This%20action%20can't%20be%20undone./singular: cb222ff89715d8c971e8c25d121e1dbd
This%20board%20is%20private%20or%20does%20not%20exist/singular: a217ff3f04463b4df8c86adb6f83c6bc
This%20board%20URL%20has%20already%20been%20taken/singular: 1d8b40332a031b5b77a3658e48dd51ca
This%20will%20result%20in%20the%20permanent%20deletion%20of%20all%20data%20associated%20with%20this%20workspace./singular: a31141558af793635c1ddd2fa0a33499
This%20will%20result%20in%20the%20permanent%20deletion%20of%20all%20data%20associated%20with%20your%20account./singular: b49224632bd6c3b7f5e462912aeb1081
@@ -352,11 +359,14 @@ checksums:
URL%20must%20be%20at%20least%203%20characters%20long/singular: 1b74ac9ec61fd34b16530ed599009ed1
Use%20template/singular: 33f0ca0aa8f4b0de99aad267a61a094d
User/singular: 61073457a5c3901084b557d065f876be
User%20is%20already%20a%20member%20of%20this%20workspace/singular: bc246386f0975f750f2133222bb4735e
Video/singular: 8050c90e4289b105a0780f0fdda6ff66
View%20and%20manage%20your%20API%20keys./singular: 88e23ee79056846dd9ce63ceee690549
View%20and%20manage%20your%20billing%20and%20subscription./singular: 7469502543aac6f02149813546d1cb38
View%20docs/singular: 43ce54f27bb1e3f1880b56e03ab38871
View%20only/singular: 21f5f7ba3b49050c4f406113479d6a7a
View%20our%20roadmap./singular: 1dd7ec80e1635951b1c90d592d1d07dc
View%20workspace/singular: c9e4b789330b08c18ca8db7044409e5f
Visibility/singular: 1ff412f8fcde0f460acbf11153649646
We%20are%20using%20the%20%3C0%3EAGPL-3.0%20license%3C%2F0%3E./singular: 08c5ddd938a2a70f61d684e41e18697a
We're%20just%20getting%20started.%20/singular: 2dfa121e0ff1914e08068308a81973c0

View File

@@ -31,9 +31,12 @@ const config = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: `*.${env("NEXT_PUBLIC_STORAGE_DOMAIN")}`,
hostname: process.env.S3_FORCE_PATH_STYLE === "true"
? `${env("NEXT_PUBLIC_STORAGE_DOMAIN")}`
: `*.${env("NEXT_PUBLIC_STORAGE_DOMAIN")}`,
},
{
protocol: "http",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

@@ -259,6 +259,7 @@ export function Auth({ setIsMagicLinkSent, isSignUp }: AuthProps) {
}
return (
<Button
key={key}
onClick={() => handleLoginWithProvider(key as SocialProvider)}
isLoading={isLoginWithProviderPending === key}
iconLeft={<provider.icon />}

View File

@@ -86,8 +86,10 @@ export default function CheckboxDropdown({
</label>
{handleEdit && (
<button
type="button"
className="invisible ml-auto group-hover:visible"
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
handleEdit(item.key);
}}
@@ -100,8 +102,12 @@ export default function CheckboxDropdown({
))}
{handleCreate && (
<button
type="button"
className="flex w-full items-center rounded-[5px] p-2 px-2 text-[12px] text-dark-900 hover:bg-light-200 dark:hover:bg-dark-300"
onClick={() => handleCreate()}
onClick={(e) => {
e.preventDefault();
handleCreate();
}}
>
<HiMiniPlus size={20} className="pr-1.5" />
{createNewItemLabel}

View File

@@ -1,4 +1,3 @@
import Link from "next/link";
import { useRef, useState } from "react";
import {
TbLayoutSidebarLeftCollapse,
@@ -10,7 +9,11 @@ import {
import { authClient } from "@kan/auth/client";
import { useClickOutside } from "~/hooks/useClickOutside";
import FeedbackButton from "./FeedbackButton";
import { useModal } from "~/providers/modal";
import { useTheme } from "~/providers/theme";
import { WorkspaceProvider } from "~/providers/workspace";
import FeedbackModal from "./FeedbackModal";
import Modal from "./modal";
import SideNavigation from "./SideNavigation";
interface DashboardProps {
@@ -19,12 +22,30 @@ interface DashboardProps {
hasRightPanel?: boolean;
}
export function getDashboardLayout(
page: React.ReactElement,
rightPanel?: React.ReactNode,
hasRightPanel = false,
) {
return (
<WorkspaceProvider>
<Dashboard rightPanel={rightPanel} hasRightPanel={hasRightPanel}>
{page}
</Dashboard>
</WorkspaceProvider>
);
}
export default function Dashboard({
children,
rightPanel,
hasRightPanel = false,
}: DashboardProps) {
const theme = useTheme();
const { modalContentType } = useModal();
const { data: session, isPending: sessionLoading } = authClient.useSession();
const [isSideNavOpen, setIsSideNavOpen] = useState(false);
const [isRightPanelOpen, setIsRightPanelOpen] = useState(false);
@@ -40,6 +61,10 @@ export default function Dashboard({
}
};
const closeSideNav = () => {
setIsSideNavOpen(false);
};
const toggleRightPanel = () => {
setIsRightPanelOpen(!isRightPanelOpen);
if (!isRightPanelOpen) {
@@ -65,98 +90,93 @@ export default function Dashboard({
}
});
const isDarkMode = theme.activeTheme === "dark";
return (
<>
<style jsx global>{`
html {
height: 100vh;
overflow: hidden;
min-width: 320px;
background-color: ${!isDarkMode ? "hsl(0deg 0% 97.3%)" : "#1c1c1c"};
}
`}</style>
<div className="h-screen flex-col items-center bg-light-100 dark:bg-dark-50 md:flex md:min-w-[800px]">
<div className="m-auto flex h-12 min-h-12 w-full justify-between border-b border-light-600 px-5 py-2 align-middle dark:border-dark-400 md:h-16 md:min-h-16">
<div className="my-auto flex w-full items-center justify-between">
<div className="relative flex h-screen flex-col bg-light-50 dark:bg-dark-50 md:bg-light-100 md:p-3 md:dark:bg-dark-100">
{/* Mobile Header */}
<div className="flex h-12 items-center justify-between border-b border-light-300 bg-light-50 px-3 dark:border-dark-300 dark:bg-dark-50 md:hidden">
<button
ref={sideNavButtonRef}
onClick={toggleSideNav}
className="rounded p-1.5 transition-all hover:bg-light-200 dark:hover:bg-dark-100"
>
{isSideNavOpen ? (
<TbLayoutSidebarLeftCollapse
size={20}
className="text-light-900 dark:text-dark-900"
/>
) : (
<TbLayoutSidebarLeftExpand
size={20}
className="text-light-900 dark:text-dark-900"
/>
)}
</button>
{hasRightPanel && (
<button
ref={sideNavButtonRef}
onClick={toggleSideNav}
className="text-neutral-900 dark:text-dark-1000 md:hidden"
ref={rightPanelButtonRef}
onClick={toggleRightPanel}
className="rounded p-1.5 transition-all hover:bg-light-200 dark:hover:bg-dark-100"
>
{isSideNavOpen ? (
<TbLayoutSidebarLeftCollapse
{isRightPanelOpen ? (
<TbLayoutSidebarRightCollapse
size={20}
className="text-light-900 dark:text-dark-900"
/>
) : (
<TbLayoutSidebarLeftExpand
<TbLayoutSidebarRightExpand
size={20}
className="text-light-900 dark:text-dark-900"
/>
)}
</button>
<Link href="/" className="hidden md:block">
<h1 className="text-lg font-bold tracking-tight text-neutral-900 dark:text-dark-1000">
kan.bn
</h1>
</Link>
<div className="flex items-center gap-2">
{hasRightPanel && (
<button
ref={rightPanelButtonRef}
onClick={toggleRightPanel}
className="text-neutral-900 dark:text-dark-1000 md:hidden"
>
{isRightPanelOpen ? (
<TbLayoutSidebarRightCollapse
size={20}
className="text-light-900 dark:text-dark-900"
/>
) : (
<TbLayoutSidebarRightExpand
size={20}
className="text-light-900 dark:text-dark-900"
/>
)}
</button>
)}
<div className="hidden md:block">
<FeedbackButton />
</div>
</div>
</div>
)}
</div>
<div className="flex h-full w-full">
<div className="flex h-[calc(100dvh-4.5rem)] min-h-0 w-full md:h-[calc(100dvh-1.5rem)]">
<div
ref={sideNavRef}
className={`fixed left-0 z-50 h-[calc(100vh-3rem)] transform transition-transform duration-300 ease-in-out md:relative md:h-[calc(100vh-4rem)] md:translate-x-0 ${isSideNavOpen ? "translate-x-0" : "-translate-x-full md:translate-x-0"} `}
className={`fixed top-12 z-40 h-[calc(100dvh-3rem)] w-[calc(100vw-1.5rem)] transform transition-transform duration-300 ease-in-out md:relative md:top-0 md:h-full md:w-auto md:translate-x-0 ${isSideNavOpen ? "translate-x-0" : "-translate-x-full md:translate-x-0"} `}
>
<SideNavigation
user={{ email: session?.user.email, image: session?.user.image }}
isLoading={sessionLoading}
onCloseSideNav={closeSideNav}
/>
</div>
<div className="relative flex w-full overflow-hidden">
<div className="w-full overflow-hidden">{children}</div>
<div className="relative h-full min-h-0 w-full overflow-hidden md:rounded-lg md:border md:border-light-300 md:bg-light-50 md:dark:border-dark-300 md:dark:bg-dark-50">
<div className="relative flex h-full min-h-0 w-full overflow-hidden">
<div className="h-full w-full overflow-y-auto">{children}</div>
{/* Mobile Right Panel */}
{hasRightPanel && rightPanel && (
<div
ref={rightPanelRef}
className={`fixed right-0 top-12 z-50 h-[calc(100vh-3rem)] w-80 transform bg-light-200 transition-transform duration-300 ease-in-out dark:bg-dark-100 md:hidden ${
isRightPanelOpen ? "translate-x-0" : "translate-x-full"
}`}
>
<div className="h-full overflow-y-auto">{rightPanel}</div>
</div>
)}
{/* Mobile Right Panel */}
{hasRightPanel && rightPanel && (
<div
ref={rightPanelRef}
className={`fixed right-0 top-12 z-40 h-[calc(100dvh-3rem)] w-80 transform border-l border-light-300 bg-light-200 transition-transform duration-300 ease-in-out dark:border-dark-300 dark:bg-dark-100 md:hidden ${
isRightPanelOpen ? "translate-x-0" : "translate-x-full"
}`}
>
<div className="h-full">{rightPanel}</div>
</div>
)}
{/* Desktop Right Panel */}
{hasRightPanel && rightPanel && (
<div className="hidden md:block">{rightPanel}</div>
)}
{/* Desktop Right Panel */}
{hasRightPanel && rightPanel && (
<div className="hidden md:block">{rightPanel}</div>
)}
</div>
</div>
</div>
</div>

View File

@@ -1,3 +1,5 @@
import { t } from "@lingui/core/macro";
import Button from "~/components/Button";
import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup";
@@ -17,8 +19,8 @@ export function DeleteLabelConfirmation({
onSuccess: () => refetch(),
onError: () =>
showPopup({
header: "Error deleting label",
message: "Please try again later, or contact customer support.",
header: t`Error deleting label`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
}),
});
@@ -34,17 +36,17 @@ export function DeleteLabelConfirmation({
<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">
Are you sure you want to delete this label?
{t`Are you sure you want to delete this label?`}
</h2>
<p className="text-sm font-medium text-light-900 dark:text-dark-900">
{"This action can't be undone."}
{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()}>
Cancel
{t`Cancel`}
</Button>
<Button onClick={handleDeleteLabel}>Delete</Button>
<Button onClick={handleDeleteLabel}>{t`Delete`}</Button>
</div>
</div>
);

View File

@@ -15,6 +15,7 @@ import {
ReactRenderer,
useEditor,
} from "@tiptap/react";
import { useEffect } from "react";
import StarterKit from "@tiptap/starter-kit";
import Suggestion from "@tiptap/suggestion";
import { forwardRef, useImperativeHandle, useRef, useState } from "react";
@@ -343,14 +344,23 @@ export default function Editor({
editable: !readOnly,
injectCSS: false,
},
[content],
[], // creating the editor only once
);
// this will sync external content changes without re-creating the editor instance
useEffect(() => {
if (!editor) return;
const currentHTML = editor.getHTML();
const safeContent = content ?? "";
if (safeContent !== currentHTML) {
editor.commands.setContent(safeContent, false);
}
}, [content, editor]);
return (
<div ref={containerRef}>
<style jsx global>{`
.tiptap p.is-empty::before {
color: #adb5bd;
content: attr(data-placeholder);
float: left;
height: 0;
@@ -363,7 +373,7 @@ export default function Editor({
{!readOnly && editor && <EditorBubbleMenu editor={editor} />}
<EditorContent
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-dark-800 [&_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-black [&_p]:dark:text-white [&_ul]:!text-xs"
/>
</div>
);

View File

@@ -1,149 +0,0 @@
import Link from "next/link";
import { Menu, Transition } from "@headlessui/react";
import { t } from "@lingui/core/macro";
import { Fragment, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import chatIconDark from "~/assets/chat-dark.json";
import chatIconLight from "~/assets/chat-light.json";
import Button from "~/components/Button";
import Input from "~/components/Input";
import LottieIcon from "~/components/LottieIcon";
import { usePopup } from "~/providers/popup";
import { useTheme } from "~/providers/theme";
import { api } from "~/utils/api";
interface NewFeedbackFormInput {
feedback: string;
}
const FeedbackButton: React.FC = () => {
const outsideRef = useRef<HTMLDivElement>(null);
const { activeTheme } = useTheme();
const { showPopup } = usePopup();
const [isHovered, setIsHovered] = useState(false);
const [index, setIndex] = useState(0);
const { handleSubmit, setValue, watch, reset } =
useForm<NewFeedbackFormInput>({
defaultValues: {
feedback: "",
},
});
const createFeedback = api.feedback.create.useMutation({
onSuccess: async () => {
reset();
showPopup({
header: t`Feedback sent`,
message: t`Thank you for your feedback!`,
icon: "success",
});
},
onError: async () => {
showPopup({
header: t`Unable to send feedback`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
});
const handleMouseEnter = () => {
setIsHovered(true);
setIndex((index) => index + 1);
};
const onSubmit = (values: NewFeedbackFormInput) => {
createFeedback.mutate({
feedback: values.feedback,
url: window.location.href,
});
};
return (
<>
<div ref={outsideRef} />
<Menu as="div" className="relative inline-block text-left">
<div>
<Menu.Button
onMouseEnter={handleMouseEnter}
className="flex items-center rounded-md border-[1px] border-light-600 bg-light-50 px-2.5 py-1.5 text-sm font-normal text-neutral-900 shadow-sm dark:border-dark-400 dark:bg-dark-50 dark:text-dark-1000"
>
<LottieIcon
index={index}
json={activeTheme === "dark" ? chatIconDark : chatIconLight}
isPlaying={isHovered}
/>
<span className="ml-1">{t`Feedback`}</span>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items
as="div"
static
className="absolute right-0 z-30 mt-2 w-[350px] origin-top-right rounded-md border border-light-200 bg-light-50 p-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-400 dark:bg-dark-300"
>
<form onSubmit={handleSubmit(onSubmit)} className="p-1">
<Input
placeholder={t`Ideas to improve this page...`}
onChange={(e) => {
setValue("feedback", e.target.value);
}}
value={watch("feedback")}
contentEditable
className="max-h-[300px] min-h-[100px]"
onKeyDown={async (e) => {
e.stopPropagation();
if (e.key === "Enter" && e.shiftKey) {
e.preventDefault();
await handleSubmit(onSubmit)();
}
}}
/>
<div className="flex flex-row items-center justify-between pt-2">
<div>
<p className="ml-2 text-xs text-neutral-900 dark:text-dark-1000">
{t`Need help?`}{" "}
<Link
href="mailto:support@kan.bn"
className="text-blue-600 underline dark:text-blue-300"
>
{t`Contact us`}
</Link>
{t`, or see our`}{" "}
<Link
href="https://docs.kan.bn"
target="_blank"
rel="noreferrer"
className="text-blue-600 underline dark:text-blue-300"
>
{t`docs`}
</Link>
.
</p>
</div>
<div className="justify-end">
<Button size="sm" isLoading={createFeedback.isPending}>
{t`Send`}
</Button>
</div>
</div>
</form>
</Menu.Items>
</Transition>
</Menu>
</>
);
};
export default FeedbackButton;

View File

@@ -0,0 +1,122 @@
import Link from "next/link";
import { t } from "@lingui/core/macro";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { HiXMark } from "react-icons/hi2";
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 NewFeedbackFormInput {
feedback: string;
}
export default function FeedbackModal() {
const { closeModal } = useModal();
const { showPopup } = usePopup();
const { handleSubmit, setValue, watch, reset } =
useForm<NewFeedbackFormInput>({
defaultValues: {
feedback: "",
},
});
const createFeedback = api.feedback.create.useMutation({
onSuccess: async () => {
reset();
closeModal();
showPopup({
header: t`Feedback sent`,
message: t`Thank you for your feedback!`,
icon: "success",
});
},
onError: async () => {
showPopup({
header: t`Unable to send feedback`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
});
const onSubmit = (values: NewFeedbackFormInput) => {
createFeedback.mutate({
feedback: values.feedback,
url: window.location.href,
});
};
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`Feedback`}
</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="feedback"
placeholder={t`Ideas to improve this page...`}
onChange={(e) => setValue("feedback", e.target.value)}
contentEditable
value={watch("feedback")}
className="min-h-[120px]"
onKeyDown={async (e) => {
e.stopPropagation();
if (e.key === "Enter" && e.shiftKey) {
e.preventDefault();
await handleSubmit(onSubmit)();
}
if (e.key === "Escape") {
closeModal();
}
}}
/>
</div>
<div className="mt-6 flex items-center justify-between border-t border-light-600 px-5 pb-5 pt-5 dark:border-dark-600">
<div className="text-xs text-neutral-600 dark:text-dark-800">
<p>
{t`Need help?`}{" "}
<Link
href="mailto:support@kan.bn"
className="text-blue-600 underline dark:text-blue-300"
>
{t`Contact us`}
</Link>
{t`, or see our`}{" "}
<Link
href="https://docs.kan.bn"
target="_blank"
rel="noreferrer"
className="text-blue-600 underline dark:text-blue-300"
>
{t`docs`}
</Link>
.
</p>
</div>
<div>
<Button type="submit" isLoading={createFeedback.isPending}>
{t`Send feedback`}
</Button>
</div>
</div>
</form>
);
}

View File

@@ -63,12 +63,16 @@ export function LabelForm({
);
try {
refetch();
if (!isCreateAnotherEnabled) closeModal();
reset({
name: "",
colour: colours[(currentColourIndex + 1) % colours.length],
isCreateAnotherEnabled,
});
if (!isCreateAnotherEnabled) {
closeModal();
} else {
const newFormState = {
name: "",
colour: colours[(currentColourIndex + 1) % colours.length],
isCreateAnotherEnabled,
};
reset(newFormState);
}
} catch (e) {
console.log(e);
}
@@ -79,10 +83,6 @@ export function LabelForm({
onSuccess: () => {
refetch();
closeModal();
reset({
name: "",
colour: colours[0],
});
},
});
@@ -229,6 +229,9 @@ export function LabelForm({
<Button
type="submit"
isLoading={updateLabel.isPending || createLabel.isPending}
disabled={
!watch("name")
}
>
{isEdit ? t`Update label` : t`Create label`}
</Button>

View File

@@ -2,11 +2,11 @@ import dynamic from "next/dynamic";
const Lottie = dynamic(() => import("react-lottie-player"), { ssr: false });
type IconProps = {
interface IconProps {
isPlaying: boolean;
index: number;
json: object;
};
}
const Icon: React.FC<IconProps> = ({ isPlaying, index, json }) => {
return (
@@ -15,7 +15,7 @@ const Icon: React.FC<IconProps> = ({ isPlaying, index, json }) => {
animationData={json}
play={isPlaying}
loop={false}
style={{ width: 20, height: 20, fill: "white" }}
style={{ width: 18, height: 18, fill: "white" }}
rendererSettings={{ preserveAspectRatio: "xMidYMid slice" }}
/>
);

View File

@@ -4,6 +4,10 @@ export const PageHead = ({ title }: { title: string }) => {
return (
<Head>
<title>{title}</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1"
/>
</Head>
);
};

View File

@@ -3,8 +3,8 @@ const PatternedBackground = () => (
<svg className="h-full w-full">
<pattern
id="pattern"
x="0.034759358288862785"
y="3.335370511841166"
x="10"
y="10"
width="14.423223834988539"
height="14.423223834988539"
patternUnits="userSpaceOnUse"

View File

@@ -1,37 +1,51 @@
import Link from "next/link";
import { useState } from "react";
import { twMerge } from "tailwind-merge";
import LottieIcon from "~/components/LottieIcon";
function classNames(...classes: string[]): string {
return classes.filter(Boolean).join(" ");
}
import { useIsMobile } from "~/hooks/useMediaQuery";
const Button: React.FC<{
href: string;
current: boolean;
name: string;
json: object;
}> = ({ href, current, name, json }) => {
isCollapsed?: boolean;
onCloseSideNav?: () => void;
}> = ({ href, current, name, json, isCollapsed = false, onCloseSideNav }) => {
const [isHovered, setIsHovered] = useState(false);
const [index, setIndex] = useState(0);
const isMobile = useIsMobile();
const handleMouseEnter = () => {
setIsHovered(true);
setIndex((index) => index + 1);
};
const handleClick = () => {
if (onCloseSideNav && isMobile) {
onCloseSideNav();
}
};
return (
<Link
href={href}
onMouseEnter={handleMouseEnter}
className={classNames(
current ? "bg-light-200 dark:bg-dark-200" : "dark:bg-dark-50",
"group flex items-center gap-x-3 rounded-md p-1.5 text-sm font-normal leading-6 text-neutral-900 hover:bg-light-200 dark:text-dark-1000 dark:hover:bg-dark-200",
onClick={handleClick}
className={twMerge(
"group flex h-[34px] items-center rounded-md p-1.5 text-sm font-normal leading-6 hover:bg-light-200 hover:text-light-1000 dark:hover:bg-dark-200 dark:hover:text-dark-1000",
current
? "bg-light-200 text-light-1000 dark:bg-dark-200 dark:text-dark-1000"
: "text-neutral-600 dark:bg-dark-100 dark:text-dark-900",
isCollapsed
? "justify-start gap-x-3 md:justify-center md:gap-x-0"
: "gap-x-3",
)}
title={isCollapsed ? name : undefined}
>
<LottieIcon index={index} json={json} isPlaying={isHovered} />
{name}
<span className={twMerge(isCollapsed && "md:hidden")}>{name}</span>
</Link>
);
};

View File

@@ -1,5 +1,13 @@
import Link from "next/link";
import { useRouter } from "next/router";
import { Button } from "@headlessui/react";
import { t } from "@lingui/core/macro";
import { useEffect, useState } from "react";
import {
TbLayoutSidebarLeftCollapse,
TbLayoutSidebarLeftExpand,
} from "react-icons/tb";
import { twMerge } from "tailwind-merge";
import boardsIconDark from "~/assets/boards-dark.json";
import boardsIconLight from "~/assets/boards-light.json";
@@ -15,6 +23,7 @@ import { useTheme } from "~/providers/theme";
interface SideNavigationProps {
user: UserType;
isLoading: boolean;
onCloseSideNav?: () => void;
}
interface UserType {
@@ -25,8 +34,28 @@ interface UserType {
export default function SideNavigation({
user,
isLoading,
onCloseSideNav,
}: SideNavigationProps) {
const router = useRouter();
const [isCollapsed, setIsCollapsed] = useState(false);
const [isInitialised, setIsInitialised] = useState(false);
useEffect(() => {
const savedState = localStorage.getItem("kan_sidebar-collapsed");
if (savedState !== null) {
setIsCollapsed(JSON.parse(savedState));
}
setIsInitialised(true);
}, []);
useEffect(() => {
if (isInitialised) {
localStorage.setItem(
"kan_sidebar-collapsed",
JSON.stringify(isCollapsed),
);
}
}, [isCollapsed, isInitialised]);
const { pathname } = router;
@@ -52,11 +81,50 @@ export default function SideNavigation({
},
];
const toggleCollapse = () => {
setIsCollapsed(!isCollapsed);
};
return (
<>
<nav className="flex h-full w-64 flex-col justify-between border-r border-light-600 bg-light-50 px-3 pb-3 pt-5 dark:border-dark-400 dark:bg-dark-50">
<nav
className={twMerge(
"flex h-full w-64 flex-col justify-between border-r border-light-300 bg-light-100 p-3 dark:border-dark-300 dark:bg-dark-100 md:border-r-0 md:py-0 md:pl-0",
isCollapsed && "md:w-auto",
)}
>
<div>
<WorkspaceMenu />
<div className="hidden h-14 items-center justify-between pb-[18px] pt-1.5 md:flex">
{!isCollapsed && (
<Link href="/" className="block">
<h1 className="pl-2 text-lg font-bold tracking-tight text-neutral-900 dark:text-dark-1000">
kan.bn
</h1>
</Link>
)}
<Button
onClick={toggleCollapse}
className={twMerge(
"flex h-8 items-center justify-center rounded-md hover:bg-light-200 dark:hover:bg-dark-200",
isCollapsed ? "w-full" : "w-8",
)}
>
{isCollapsed ? (
<TbLayoutSidebarLeftExpand
size={18}
className="text-light-900 dark:text-dark-900"
/>
) : (
<TbLayoutSidebarLeftCollapse
size={18}
className="text-light-900 dark:text-dark-900"
/>
)}
</Button>
</div>
<div className="mx-1 mb-4 hidden w-auto border-b border-light-300 dark:border-dark-400 md:block" />
<WorkspaceMenu isCollapsed={isCollapsed} />
<ul role="list" className="space-y-1">
{navigation.map((item) => (
<li key={item.name}>
@@ -65,16 +133,23 @@ export default function SideNavigation({
current={pathname.includes(item.href)}
name={item.name}
json={item.icon}
isCollapsed={isCollapsed}
onCloseSideNav={onCloseSideNav}
/>
</li>
))}
</ul>
</div>
<UserMenu
email={user.email ?? ""}
imageUrl={user.image ?? undefined}
isLoading={isLoading}
/>
<div className="space-y-3">
<UserMenu
email={user.email ?? ""}
imageUrl={user.image ?? undefined}
isLoading={isLoading}
isCollapsed={isCollapsed}
onCloseSideNav={onCloseSideNav}
/>
</div>
</nav>
</>
);

View File

@@ -1,11 +1,15 @@
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { Menu, Transition } from "@headlessui/react";
import { t } from "@lingui/core/macro";
import { Fragment } from "react";
import { twMerge } from "tailwind-merge";
import { authClient } from "@kan/auth/client";
import { useIsMobile } from "~/hooks/useMediaQuery";
import { useModal } from "~/providers/modal";
import { useTheme } from "~/providers/theme";
import { getAvatarUrl } from "~/utils/helpers";
@@ -13,38 +17,63 @@ interface UserMenuProps {
imageUrl: string | undefined;
email: string;
isLoading: boolean;
}
function classNames(...classes: string[]): string {
return classes.filter(Boolean).join(" ");
isCollapsed?: boolean;
onCloseSideNav?: () => void;
}
export default function UserMenu({
imageUrl,
email,
isLoading,
isCollapsed = false,
onCloseSideNav,
}: UserMenuProps) {
const router = useRouter();
const { themePreference, switchTheme } = useTheme();
const { openModal } = useModal();
const isMobile = useIsMobile();
const handleLogout = async () => {
if (onCloseSideNav && isMobile) {
onCloseSideNav();
}
await authClient.signOut();
router.push("/login");
};
const handleLinkClick = () => {
if (onCloseSideNav && isMobile) {
onCloseSideNav();
}
};
const handleModalOpen = (modalType: string) => {
if (onCloseSideNav && isMobile) {
onCloseSideNav();
}
openModal(modalType);
};
const avatarUrl = imageUrl ? getAvatarUrl(imageUrl) : null;
return (
<Menu as="div" className="relative inline-block w-full text-left">
<div>
{isLoading ? (
<div className="flex">
<div className={twMerge(!isCollapsed && "flex")}>
<div className="h-[30px] w-[30px] animate-pulse rounded-full bg-light-200 dark:bg-dark-200" />
<div className="mx-2 h-[30px] w-[175px] animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
<div
className={twMerge(
"mx-2 h-[30px] w-[175px] animate-pulse rounded-md bg-light-200 dark:bg-dark-200",
isCollapsed && "md:hidden",
)}
/>
</div>
) : (
<Menu.Button className="flex w-full items-center rounded-md p-1.5 text-neutral-900 hover:bg-light-200 dark:text-dark-900 dark:hover:bg-dark-200 dark:hover:text-dark-1000">
<Menu.Button
className="flex w-full items-center rounded-md p-1.5 text-neutral-900 hover:bg-light-200 dark:text-dark-900 dark:hover:bg-dark-200 dark:hover:text-dark-1000"
title={isCollapsed ? email : undefined}
>
{avatarUrl ? (
<Image
src={avatarUrl}
@@ -64,7 +93,14 @@ export default function UserMenu({
</svg>
</span>
)}
<span className="mx-2 truncate text-sm">{email}</span>
<span
className={twMerge(
"mx-2 truncate text-sm",
isCollapsed && "md:hidden",
)}
>
{email}
</span>
</Menu.Button>
)}
</div>
@@ -78,7 +114,12 @@ export default function UserMenu({
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute bottom-[40px] left-0 z-10 mt-2 w-full origin-top-left rounded-md border border-light-600 bg-light-50 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-600 dark:bg-dark-300">
<Menu.Items
className={twMerge(
"absolute bottom-[40px] z-10 mt-2 origin-top-left rounded-md border border-light-600 bg-light-50 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-600 dark:bg-dark-300",
isCollapsed ? "left-0 w-48" : "left-0 w-full",
)}
>
<div className="flex flex-col text-neutral-900 dark:text-dark-1000">
<div className="p-1">
<div className="flex w-full items-center px-3 py-2 text-left text-xs">
@@ -90,7 +131,7 @@ export default function UserMenu({
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
className={classNames(
className={twMerge(
themePreference === "system" ? "visible" : "invisible",
"mr-4 h-[6px] w-[6px] rounded-full bg-light-900 dark:bg-dark-900",
)}
@@ -104,7 +145,7 @@ export default function UserMenu({
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
className={classNames(
className={twMerge(
themePreference === "dark" ? "visible" : "invisible",
"mr-4 h-[6px] w-[6px] rounded-full bg-light-900 dark:bg-dark-900",
)}
@@ -118,7 +159,7 @@ export default function UserMenu({
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
className={classNames(
className={twMerge(
themePreference === "light" ? "visible" : "invisible",
"mr-4 h-[6px] w-[6px] rounded-full bg-light-900 dark:bg-dark-900",
)}
@@ -127,6 +168,38 @@ export default function UserMenu({
</button>
</Menu.Item>
</div>
<div className="light-border-600 border-t-[1px] p-1 dark:border-dark-600">
<Menu.Item>
<Link
href="mailto:support@kan.bn"
target="_blank"
rel="noreferrer"
onClick={handleLinkClick}
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"
>
{t`Support`}
</Link>
</Menu.Item>
<Menu.Item>
<Link
href="https://docs.kan.bn"
target="_blank"
rel="noreferrer"
onClick={handleLinkClick}
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"
>
{t`Documentation`}
</Link>
</Menu.Item>
<Menu.Item>
<button
onClick={() => handleModalOpen("NEW_FEEDBACK")}
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"
>
{t`Feedback`}
</button>
</Menu.Item>
</div>
<div className="light-border-600 border-t-[1px] p-1 dark:border-dark-600">
<Menu.Item>
<button

View File

@@ -2,11 +2,16 @@ import { Menu, Transition } from "@headlessui/react";
import { t } from "@lingui/core/macro";
import { Fragment } from "react";
import { HiCheck } from "react-icons/hi2";
import { twMerge } from "tailwind-merge";
import { useModal } from "~/providers/modal";
import { useWorkspace } from "~/providers/workspace";
export default function WorkspaceMenu() {
export default function WorkspaceMenu({
isCollapsed = false,
}: {
isCollapsed?: boolean;
}) {
const { workspace, isLoading, availableWorkspaces, switchWorkspace } =
useWorkspace();
const { openModal } = useModal();
@@ -15,22 +20,43 @@ export default function WorkspaceMenu() {
<Menu as="div" className="relative inline-block w-full pb-3 text-left">
<div>
{isLoading ? (
<div className="mb-1 flex p-1.5">
<div className="h-6 w-6 animate-pulse rounded-[5px] bg-light-200 dark:bg-dark-200" />
<div className="ml-2 h-6 w-[150px] animate-pulse rounded-[5px] bg-light-200 dark:bg-dark-200" />
<div className={twMerge("mb-1", isCollapsed && "md:flex md:p-1.5")}>
<div className="h-6 w-6 animate-pulse rounded-md bg-light-200 dark:bg-dark-200" />
<div
className={twMerge(
"ml-2 h-6 w-[150px] animate-pulse rounded-md bg-light-200 dark:bg-dark-200",
isCollapsed && "hidden md:block",
)}
/>
</div>
) : (
<Menu.Button className="mb-1 flex w-full items-center rounded-[5px] p-1.5 hover:bg-light-200 dark:hover:bg-dark-200">
<span className="inline-flex h-6 w-6 items-center justify-center rounded-[5px] bg-indigo-700">
<Menu.Button
className={twMerge(
"mb-1 flex h-[34px] w-full items-center rounded-md p-1.5 hover:bg-light-200 dark:hover:bg-dark-200",
isCollapsed && "md:mb-1.5 md:h-9 md:p-1",
)}
title={isCollapsed ? workspace.name : undefined}
>
<span className="inline-flex h-6 w-6 items-center justify-center rounded-md bg-indigo-700">
<span className="text-xs font-bold leading-none text-white">
{workspace.name.charAt(0).toUpperCase()}
</span>
</span>
<span className="ml-2 text-sm font-bold text-neutral-900 dark:text-dark-1000">
<span
className={twMerge(
"ml-2 text-sm font-bold text-neutral-900 dark:text-dark-1000",
isCollapsed && "md:hidden",
)}
>
{workspace.name}
</span>
{workspace.plan === "pro" && (
<span className="ml-2 inline-flex items-center rounded-md bg-indigo-100 px-2 py-1 text-[10px] font-medium text-indigo-700">
<span
className={twMerge(
"ml-2 inline-flex items-center rounded-md bg-indigo-100 px-2 py-1 text-[10px] font-medium text-indigo-700",
isCollapsed && "md:hidden",
)}
>
Pro
</span>
)}
@@ -47,7 +73,12 @@ export default function WorkspaceMenu() {
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute left-0 z-10 w-full origin-top-left rounded-md border border-light-600 bg-light-50 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-600 dark:bg-dark-300">
<Menu.Items
className={twMerge(
"absolute left-0 z-10 origin-top-left rounded-md border border-light-600 bg-light-50 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-600 dark:bg-dark-300",
isCollapsed ? "w-48" : "w-full",
)}
>
<div className="p-1">
{availableWorkspaces.map((availableWorkspace) => (
<div key={availableWorkspace.publicId} className="flex">

View File

@@ -7,15 +7,19 @@ interface Props {
children: React.ReactNode;
modalSize?: "sm" | "md" | "lg";
positionFromTop?: "sm" | "md" | "lg";
isVisible?: boolean;
}
const Modal: React.FC<Props> = ({
children,
modalSize = "sm",
positionFromTop = "md",
isVisible,
}) => {
const { isOpen, closeModal } = useModal();
const shouldShow = isVisible !== undefined ? isVisible : isOpen;
const modalSizeMap = {
sm: "max-w-[400px]",
md: "max-w-[550px]",
@@ -29,7 +33,7 @@ const Modal: React.FC<Props> = ({
};
return (
<Transition.Root show={isOpen} as={Fragment}>
<Transition.Root show={shouldShow} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={closeModal}>
<Transition.Child
as={Fragment}

View File

@@ -69,6 +69,7 @@ export const env = createEnv({
S3_SECRET_ACCESS_KEY: z.string().optional(),
S3_REGION: z.string().optional(),
S3_ENDPOINT: z.string().optional(),
S3_FORCE_PATH_STYLE: z.string().optional(),
EMAIL_FROM: z.string().optional(),
},

View File

@@ -0,0 +1,23 @@
import { useEffect, useState } from "react";
export function useMediaQuery(query: string): boolean {
const [matches, setMatches] = useState(false);
useEffect(() => {
const media = window.matchMedia(query);
setMatches(media.matches);
const listener = (event: MediaQueryListEvent) => {
setMatches(event.matches);
};
media.addEventListener("change", listener);
return () => media.removeEventListener("change", listener);
}, [query]);
return matches;
}
export function useIsMobile(): boolean {
return useMediaQuery("(max-width: 767px)");
}

View File

@@ -0,0 +1,48 @@
import { useEffect } from "react";
import { useModal } from "~/providers/modal";
interface UseModalFormStateOptions<T> {
modalType: string;
initialValues: T;
resetOnClose?: boolean;
}
export function useModalFormState<T extends Record<string, any>>({
modalType,
initialValues,
resetOnClose = false,
}: UseModalFormStateOptions<T>) {
const { modalContentType, isOpen, getModalState, setModalState, clearModalState } = useModal();
const isCurrentModal = modalContentType === modalType;
const savedState = getModalState(modalType) as T | undefined;
// get current form state (using the saved values if available, otherwise the initial values)
const formState = savedState || initialValues;
const saveFormState = (state: Partial<T>) => {
if (!isCurrentModal) return;
const currentState = getModalState(modalType) || initialValues;
const newState = { ...currentState, ...state };
setModalState(modalType, newState);
};
const clearFormState = () => {
clearModalState(modalType);
};
useEffect(() => {
if (resetOnClose && !isOpen && savedState) {
clearModalState(modalType);
}
}, [isOpen, resetOnClose, savedState, modalType, clearModalState]);
return {
formState,
saveFormState,
clearFormState,
isCurrentModal,
hasSavedState: !!savedState,
};
}

View File

@@ -13,22 +13,22 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:121
#: src/views/card/components/Comment.tsx:123
msgid " (edited)"
msgstr " (bearbeitet)"
#: src/components/FeedbackButton.tsx:123
#: src/components/FeedbackModal.tsx:102
msgid ", or see our"
msgstr ", oder besuche unsere"
#. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:148
#: src/views/card/index.tsx:189
msgid "{0} | {1}"
msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:365
#: src/views/board/components/NewCardForm.tsx:392
msgid "{0} labels"
msgstr "{0} Labels"
@@ -36,10 +36,6 @@ msgstr "{0} Labels"
msgid "{boardCount, plural, one {Import board (1)} other {Import boards ({boardCount})}}"
msgstr "{boardCount, plural, one {Board importieren (1)} other {Boards importieren ({boardCount})}}"
#: src/views/home/index.tsx:51
msgid "#1 Hacker News"
msgstr "#1 Hacker News"
#: src/views/home/components/Pricing.tsx:36
msgid "1 user"
msgstr "1 Benutzer"
@@ -52,8 +48,8 @@ msgstr "Eine leistungsstarke, flexible Kanban-App, die dir hilft, Arbeit zu orga
msgid "Account deleted"
msgstr "Konto gelöscht"
#: src/views/public/board/CardModal.tsx:104
#: src/views/card/index.tsx:215
#: src/views/public/board/CardModal.tsx:128
#: src/views/card/index.tsx:256
msgid "Activity"
msgstr "Aktivität"
@@ -66,11 +62,11 @@ msgid "Add a card"
msgstr "Karte hinzufügen"
#: src/views/card/components/NewCommentForm.tsx:57
#: src/views/card/components/Comment.tsx:144
#: src/views/card/components/Comment.tsx:146
msgid "Add a comment..."
msgstr "Kommentar hinzufügen..."
#: src/components/Editor.tsx:302
#: src/components/Editor.tsx:303
msgid "Add description... (type '/' to open commands)"
msgstr "Beschreibung hinzufügen... (tippe '/' um Befehle zu öffnen)"
@@ -79,7 +75,7 @@ msgstr "Beschreibung hinzufügen... (tippe '/' um Befehle zu öffnen)"
msgid "Add label"
msgstr "Label hinzufügen"
#: src/views/members/components/InviteMemberForm.tsx:50
#: src/views/members/components/InviteMemberForm.tsx:85
#: src/views/card/components/MemberSelector.tsx:130
msgid "Add member"
msgstr "Mitglied hinzufügen"
@@ -112,11 +108,11 @@ msgstr "Alle Systeme funktionieren"
msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "Du hast bereits ein Konto? <0><1>Anmelden</1></0>"
#: src/views/settings/index.tsx:77
#: src/views/settings/index.tsx:100
msgid "An error occurred while disconnecting your Trello account."
msgstr "Beim Trennen deines Trello-Kontos ist ein Fehler aufgetreten."
#: src/views/settings/index.tsx:229
#: src/views/settings/index.tsx:257
msgid "API keys"
msgstr "API-Schlüssel"
@@ -149,6 +145,10 @@ msgstr "Bist du sicher, dass du diese Karte löschen möchtest?"
msgid "Are you sure you want to delete this comment?"
msgstr "Bist du sicher, dass du diesen Kommentar löschen möchtest?"
#: src/components/DeleteLabelConfirmation.tsx:39
msgid "Are you sure you want to delete this label?"
msgstr "Sind Sie sicher, dass Sie dieses Label löschen möchten?"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:54
msgid "Are you sure you want to delete your account?"
msgstr "Bist du sicher, dass du dein Konto löschen möchtest?"
@@ -169,12 +169,12 @@ msgstr "Backlog"
msgid "Basic Kanban"
msgstr "Einfaches Kanban"
#: src/views/settings/index.tsx:168
#: src/views/settings/index.tsx:196
#: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing"
msgstr "Abrechnung"
#: src/views/settings/index.tsx:178
#: src/views/settings/index.tsx:206
msgid "Billing portal"
msgstr "Abrechnungsportal"
@@ -182,7 +182,7 @@ msgstr "Abrechnungsportal"
msgid "Blog Post"
msgstr "Blogbeitrag"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Board"
msgstr "Board"
@@ -194,7 +194,8 @@ msgstr "Der Name des Boards darf 100 Zeichen nicht überschreiten"
msgid "Board name is required"
msgstr "Boardname ist erforderlich"
#: src/views/board/index.tsx:265
#: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358
msgid "Board not found"
msgstr "Board nicht gefunden"
@@ -206,7 +207,7 @@ msgstr "Board-URL darf nur Buchstaben, Zahlen und Bindestriche enthalten"
msgid "Board URL cannot exceed 60 characters"
msgstr "Board-URL darf 60 Zeichen nicht überschreiten"
#: src/views/public/board/index.tsx:53
#: src/views/public/board/index.tsx:59
msgid "Board URL copied to clipboard"
msgstr "Board-URL in die Zwischenablage kopiert"
@@ -222,13 +223,13 @@ msgstr "Board-Sichtbarkeit"
msgid "Board visibility updated"
msgstr "Board-Sichtbarkeit aktualisiert"
#: src/views/boards/index.tsx:25
#: src/components/SideNavigation.tsx:39
#: src/views/boards/index.tsx:27
#: src/components/SideNavigation.tsx:68
msgid "Boards"
msgstr "Boards"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/boards/index.tsx:21
#: src/views/boards/index.tsx:23
msgid "Boards | {0}"
msgstr "Boards | {0}"
@@ -250,19 +251,20 @@ msgstr "Fehlerbericht"
#: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:156
#: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47
msgid "Cancel"
msgstr "Abbrechen"
#: src/views/card/index.tsx:193
#: src/views/card/index.tsx:234
msgid "Card not found"
msgstr "Karte nicht gefunden"
#: src/views/board/components/NewCardForm.tsx:254
#: src/views/board/components/NewCardForm.tsx:278
msgid "Card title"
msgstr "Kartentitel"
#: src/views/settings/index.tsx:160
#: src/views/settings/index.tsx:188
msgid "Change the language of the app."
msgstr "Ändere die Sprache der App."
@@ -312,7 +314,7 @@ msgstr "Vollständige Kontrolle und Eigentum:"
msgid "Confirm URL change"
msgstr "URL-Änderung bestätigen"
#: src/views/settings/index.tsx:205
#: src/views/settings/index.tsx:233
#: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello"
msgstr "Trello verbinden"
@@ -321,7 +323,7 @@ msgstr "Trello verbinden"
msgid "Connect your favorite tools to streamline your workflow."
msgstr "Verbinde deine Lieblingstools, um deinen Arbeitsablauf zu optimieren."
#: src/views/settings/index.tsx:192
#: src/views/settings/index.tsx:220
msgid "Connect your Trello account to import boards."
msgstr "Verbinde dein Trello-Konto, um Boards zu importieren."
@@ -329,7 +331,7 @@ msgstr "Verbinde dein Trello-Konto, um Boards zu importieren."
msgid "Contact"
msgstr "Kontakt"
#: src/components/FeedbackButton.tsx:121
#: src/components/FeedbackModal.tsx:100
msgid "Contact us"
msgstr "Kontaktiere uns"
@@ -337,12 +339,12 @@ msgstr "Kontaktiere uns"
msgid "Content Creation"
msgstr "Content-Erstellung"
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Continue with "
msgstr "Fortfahren mit "
#. placeholder {0}: provider.name
#: src/components/AuthForm.tsx:268
#: src/components/AuthForm.tsx:269
msgid "Continue with {0}"
msgstr "Fortfahren mit {0}"
@@ -351,7 +353,7 @@ msgid "Control who can view and edit your boards."
msgstr "Kontrolliere, wer deine Boards ansehen und bearbeiten kann."
#: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:391
#: src/views/board/components/NewCardForm.tsx:418
#: src/components/LabelForm.tsx:212
msgid "Create another"
msgstr "Weitere erstellen"
@@ -360,15 +362,15 @@ msgstr "Weitere erstellen"
msgid "Create board"
msgstr "Board erstellen"
#: src/views/board/components/NewCardForm.tsx:401
#: src/views/board/components/NewCardForm.tsx:428
msgid "Create card"
msgstr "Karte erstellen"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Create label"
msgstr "Label erstellen"
#: src/views/board/components/NewListForm.tsx:148
#: src/views/board/components/NewListForm.tsx:152
msgid "Create list"
msgstr "Liste erstellen"
@@ -381,16 +383,16 @@ msgid "Create new key"
msgstr "Neuen Schlüssel erstellen"
#: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:327
#: src/views/board/components/NewCardForm.tsx:354
msgid "Create new label"
msgstr "Neues Label erstellen"
#: src/views/board/index.tsx:327
#: src/views/board/index.tsx:426
msgid "Create new list"
msgstr "Neue Liste erstellen"
#: src/components/WorkspaceMenu.tsx:85
#: src/components/NewWorkspaceForm.tsx:91
#: src/components/WorkspaceMenu.tsx:116
#: src/components/NewWorkspaceForm.tsx:93
msgid "Create workspace"
msgstr "Arbeitsbereich erstellen"
@@ -414,18 +416,19 @@ msgstr "Benutzerdefinierte URLs sind eine Premium-Funktion. Du wirst zur Aktuali
msgid "Customer Support"
msgstr "Kundensupport"
#: src/components/UserMenu.tsx:112
#: src/components/UserMenu.tsx:153
msgid "Dark"
msgstr "Dunkel"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226
#: src/components/DeleteLabelConfirmation.tsx:49
msgid "Delete"
msgstr "Löschen"
#: src/views/settings/index.tsx:260
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:288
#: src/views/settings/index.tsx:298
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account"
msgstr "Konto löschen"
@@ -438,7 +441,7 @@ msgstr "Board löschen"
msgid "Delete card"
msgstr "Karte löschen"
#: src/views/card/components/Comment.tsx:89
#: src/views/card/components/Comment.tsx:91
msgid "Delete comment"
msgstr "Kommentar löschen"
@@ -446,8 +449,8 @@ msgstr "Kommentar löschen"
msgid "Delete list"
msgstr "Liste löschen"
#: src/views/settings/index.tsx:242
#: src/views/settings/index.tsx:253
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:281
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace"
msgstr "Workspace löschen"
@@ -456,7 +459,7 @@ msgstr "Workspace löschen"
msgid "Design"
msgstr "Design"
#: src/views/settings/index.tsx:220
#: src/views/settings/index.tsx:248
msgid "Disconnect Trello"
msgstr "Trello trennen"
@@ -464,7 +467,7 @@ msgstr "Trello trennen"
msgid "Discuss and collaborate on cards."
msgstr "Diskutiere und arbeite gemeinsam an Karten."
#: src/views/settings/index.tsx:123
#: src/views/settings/index.tsx:149
msgid "Display name"
msgstr "Anzeigename"
@@ -484,7 +487,7 @@ msgstr "Anzeigename aktualisiert"
msgid "Do you offer a free plan?"
msgstr "Bietet ihr einen kostenlosen Plan an?"
#: src/components/FeedbackButton.tsx:130
#: src/components/FeedbackModal.tsx:109
msgid "docs"
msgstr "Dokumente"
@@ -494,6 +497,7 @@ msgstr "Dokumente"
#: src/views/home/components/Footer.tsx:77
#: src/views/boards/components/TemplateBoards.tsx:23
#: src/components/UserMenu.tsx:191
msgid "Documentation"
msgstr "Dokumentation"
@@ -513,7 +517,7 @@ msgstr "Erledigt"
msgid "Edit board URL"
msgstr "Board-URL bearbeiten"
#: src/views/card/components/Comment.tsx:80
#: src/views/card/components/Comment.tsx:82
msgid "Edit comment"
msgstr "Kommentar bearbeiten"
@@ -521,15 +525,19 @@ msgstr "Kommentar bearbeiten"
msgid "Edit label"
msgstr "Label bearbeiten"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161
msgid "Edit workspace URL"
msgstr "Workspace-URL bearbeiten"
#: src/views/boards/components/TemplateBoards.tsx:31
msgid "Editing"
msgstr "Bearbeitung"
#: src/components/AuthForm.tsx:336
#: src/components/AuthForm.tsx:337
msgid "email"
msgstr "E-Mail"
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/InviteMemberForm.tsx:99
msgid "Email"
msgstr "E-Mail"
@@ -537,15 +545,15 @@ msgstr "E-Mail"
msgid "Enhancement"
msgstr "Verbesserung"
#: src/components/AuthForm.tsx:301
#: src/components/AuthForm.tsx:302
msgid "Enter your email address"
msgstr "Gib deine E-Mail-Adresse ein"
#: src/components/AuthForm.tsx:289
#: src/components/AuthForm.tsx:290
msgid "Enter your name"
msgstr "Gib deinen Namen ein"
#: src/components/AuthForm.tsx:314
#: src/components/AuthForm.tsx:315
msgid "Enter your password"
msgstr "Gib dein Passwort ein"
@@ -553,19 +561,28 @@ msgstr "Gib dein Passwort ein"
msgid "Error deleting account"
msgstr "Fehler beim Löschen des Kontos"
#: src/components/DeleteLabelConfirmation.tsx:22
msgid "Error deleting label"
msgstr "Fehler beim Löschen des Labels"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:45
msgid "Error deleting workspace"
msgstr "Fehler beim Löschen des Arbeitsbereichs"
#: src/views/settings/index.tsx:76
#: src/views/settings/index.tsx:99
msgid "Error disconnecting Trello"
msgstr "Fehler beim Trennen von Trello"
#: src/views/members/components/InviteMemberForm.tsx:57
#: src/views/members/components/InviteMemberForm.tsx:63
msgid "Error inviting member"
msgstr "Fehler beim Einladen des Mitglieds"
#: src/views/settings/components/UpdateDisplayNameForm.tsx:54
msgid "Error updating display name"
msgstr "Fehler beim Aktualisieren des Anzeigenamens"
#: src/views/settings/components/Avatar.tsx:37
#: src/views/settings/components/Avatar.tsx:39
msgid "Error updating profile image"
msgstr "Fehler beim Aktualisieren des Profilbilds"
@@ -581,8 +598,8 @@ msgstr "Fehler beim Aktualisieren des Arbeitsbereichsnamens"
msgid "Error updating workspace URL"
msgstr "Fehler beim Aktualisieren der Workspace-URL"
#: src/views/settings/components/Avatar.tsx:54
#: src/views/settings/components/Avatar.tsx:95
#: src/views/settings/components/Avatar.tsx:56
#: src/views/settings/components/Avatar.tsx:97
msgid "Error uploading profile image"
msgstr "Fehler beim Hochladen des Profilbilds"
@@ -622,11 +639,12 @@ msgstr "Feature-Anfrage"
msgid "Features"
msgstr "Features"
#: src/components/FeedbackButton.tsx:78
#: src/components/UserMenu.tsx:199
#: src/components/FeedbackModal.tsx:59
msgid "Feedback"
msgstr "Feedback"
#: src/components/FeedbackButton.tsx:38
#: src/components/FeedbackModal.tsx:33
msgid "Feedback sent"
msgstr "Feedback gesendet"
@@ -674,7 +692,7 @@ msgstr "Loslegen"
msgid "Get started by creating a new board"
msgstr "Beginne, indem du ein neues Board erstellst"
#: src/views/board/index.tsx:319
#: src/views/board/index.tsx:418
msgid "Get started by creating a new list"
msgstr "Beginne mit dem Erstellen einer neuen Liste"
@@ -747,11 +765,11 @@ msgstr "Ich bestätige, dass alle Daten des Arbeitsbereichs dauerhaft gelöscht
msgid "Ideas"
msgstr "Ideen"
#: src/components/FeedbackButton.tsx:98
#: src/components/FeedbackModal.tsx:75
msgid "Ideas to improve this page..."
msgstr "Ideen zur Verbesserung dieser Seite..."
#: src/views/boards/index.tsx:39
#: src/views/boards/index.tsx:38
msgid "Import"
msgstr "Importieren"
@@ -797,11 +815,19 @@ msgstr "Integrationen"
msgid "Interviewing"
msgstr "Vorstellungsgespräch"
#: src/views/members/index.tsx:156
#: src/views/members/components/InviteMemberForm.tsx:26
msgid "Invalid email address"
msgstr "Ungültige E-Mail-Adresse"
#: src/views/members/index.tsx:169
msgid "Invite"
msgstr "Einladen"
#: src/views/members/components/InviteMemberForm.tsx:82
#: src/views/members/components/InviteMemberForm.tsx:113
msgid "Invite another"
msgstr "Weitere Person einladen"
#: src/views/members/components/InviteMemberForm.tsx:123
#: src/views/card/components/MemberSelector.tsx:112
msgid "Invite member"
msgstr "Mitglied einladen"
@@ -823,8 +849,8 @@ msgstr "Kanban neu gedacht"
msgid "Keep in mind that this action is irreversible."
msgstr "Beachten Sie, dass diese Aktion nicht rückgängig gemacht werden kann."
#: src/views/card/index.tsx:243
#: src/views/board/components/NewCardForm.tsx:331
#: src/views/card/index.tsx:113
#: src/views/board/components/NewCardForm.tsx:358
#: src/views/board/components/Filters.tsx:101
msgid "Labels"
msgstr "Labels"
@@ -833,7 +859,7 @@ msgstr "Labels"
msgid "Labels & Filters"
msgstr "Labels & Filter"
#: src/views/settings/index.tsx:157
#: src/views/settings/index.tsx:185
msgid "Language"
msgstr "Sprache"
@@ -849,15 +875,15 @@ msgstr "Rechtliches"
msgid "License"
msgstr "Lizenz"
#: src/components/UserMenu.tsx:126
#: src/components/UserMenu.tsx:167
msgid "Light"
msgstr "Hell"
#: src/views/public/board/index.tsx:51
#: src/views/public/board/index.tsx:57
msgid "Link copied"
msgstr "Link kopiert"
#: src/views/card/index.tsx:235
#: src/views/card/index.tsx:105
msgid "List"
msgstr "Liste"
@@ -869,7 +895,7 @@ msgstr "Listenname"
msgid "Login | kan.bn"
msgstr "Login | kan.bn"
#: src/components/UserMenu.tsx:136
#: src/components/UserMenu.tsx:209
msgid "Logout"
msgstr "Abmelden"
@@ -881,7 +907,7 @@ msgstr "Langfristig"
msgid "Low Priority"
msgstr "Niedrige Priorität"
#: src/components/AuthForm.tsx:337
#: src/components/AuthForm.tsx:338
msgid "magic link"
msgstr "Magic Link"
@@ -889,16 +915,16 @@ msgstr "Magic Link"
msgid "Medium Priority"
msgstr "Mittlere Priorität"
#: src/views/members/index.tsx:148
#: src/views/card/index.tsx:251
#: src/views/board/components/NewCardForm.tsx:290
#: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121
#: src/views/board/components/NewCardForm.tsx:317
#: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:44
#: src/components/SideNavigation.tsx:73
msgid "Members"
msgstr "Mitglieder"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/members/index.tsx:144
#: src/views/members/index.tsx:157
msgid "Members | {0}"
msgstr "Mitglieder | {0}"
@@ -919,11 +945,11 @@ msgstr "hat die Karte in eine andere Liste verschoben"
msgid "Name"
msgstr "Name"
#: src/components/FeedbackButton.tsx:116
#: src/components/FeedbackModal.tsx:95
msgid "Need help?"
msgstr "Brauchst du Hilfe?"
#: src/views/boards/index.tsx:52
#: src/views/boards/index.tsx:48
msgid "New"
msgstr "Neu"
@@ -931,7 +957,7 @@ msgstr "Neu"
msgid "New board"
msgstr "Neues Board"
#: src/views/board/components/NewCardForm.tsx:237
#: src/views/board/components/NewCardForm.tsx:261
msgid "New card"
msgstr "Neue Karte"
@@ -943,7 +969,7 @@ msgstr "Neuer Import"
msgid "New label"
msgstr "Neues Label"
#: src/views/board/index.tsx:296
#: src/views/board/index.tsx:395
#: src/views/board/components/NewListForm.tsx:112
msgid "New list"
msgstr "Neue Liste"
@@ -952,7 +978,7 @@ msgstr "Neue Liste"
msgid "New Ticket"
msgstr "Neues Ticket"
#: src/components/NewWorkspaceForm.tsx:62
#: src/components/NewWorkspaceForm.tsx:64
msgid "New workspace"
msgstr "Neuer Workspace"
@@ -976,7 +1002,7 @@ msgstr "Keine Boards gefunden"
msgid "No credit card required"
msgstr "Keine Kreditkarte erforderlich"
#: src/views/board/index.tsx:316
#: src/views/board/index.tsx:415
msgid "No lists"
msgstr "Keine Listen"
@@ -988,15 +1014,15 @@ msgstr "Angebot"
msgid "Onboarding"
msgstr "Einarbeitung"
#: src/views/settings/index.tsx:263
#: src/views/settings/index.tsx:291
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."
#: src/views/settings/index.tsx:245
#: src/views/settings/index.tsx:273
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."
#: src/components/AuthForm.tsx:279
#: src/components/AuthForm.tsx:280
msgid "or"
msgstr "oder"
@@ -1016,7 +1042,7 @@ msgstr "Teilzeit"
msgid "Payment frequency"
msgstr "Zahlungshäufigkeit"
#: src/views/members/index.tsx:107
#: src/views/members/index.tsx:118
msgid "Pending"
msgstr "Ausstehend"
@@ -1033,19 +1059,19 @@ msgstr "Persönliches Projekt"
msgid "Planning"
msgstr "Planung"
#: src/components/AuthForm.tsx:305
#: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address"
msgstr "Bitte gib eine gültige E-Mail-Adresse ein"
#: src/components/AuthForm.tsx:293
#: src/components/AuthForm.tsx:294
msgid "Please enter a valid name"
msgstr "Bitte gib einen gültigen Namen ein"
#: src/components/AuthForm.tsx:318
#: src/components/AuthForm.tsx:319
msgid "Please enter a valid password"
msgstr "Bitte gib ein gültiges Passwort ein"
#: src/views/settings/components/Avatar.tsx:55
#: src/views/settings/components/Avatar.tsx:57
msgid "Please select a file to upload."
msgstr "Bitte wähle eine Datei zum Hochladen aus."
@@ -1055,26 +1081,28 @@ msgstr "Bitte wähle eine Datei zum Hochladen aus."
#: src/views/settings/components/UpdateDisplayNameForm.tsx:55
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:46
#: src/views/settings/components/DeleteAccountConfirmation.tsx:40
#: src/views/settings/components/Avatar.tsx:38
#: src/views/settings/components/Avatar.tsx:96
#: src/views/settings/components/Avatar.tsx:40
#: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:116
#: src/views/card/index.tsx:159
#: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:62
#: src/views/card/components/Comment.tsx:64
#: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:133
#: src/views/board/index.tsx:189
#: src/views/board/index.tsx:135
#: src/views/board/index.tsx:191
#: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:128
#: src/components/NewWorkspaceForm.tsx:39
#: src/components/FeedbackButton.tsx:46
#: src/views/board/components/NewCardForm.tsx:145
#: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23
msgid "Please try again later, or contact customer support."
msgstr "Bitte versuche es später noch einmal oder kontaktiere den Kundensupport."
@@ -1096,11 +1124,11 @@ msgstr "Datenschutzrichtlinie"
msgid "Private"
msgstr "Privat"
#: src/views/settings/components/Avatar.tsx:24
#: src/views/settings/components/Avatar.tsx:26
msgid "Profile image updated"
msgstr "Profilbild aktualisiert"
#: src/views/settings/index.tsx:118
#: src/views/settings/index.tsx:144
msgid "Profile picture"
msgstr "Profilbild"
@@ -1136,7 +1164,7 @@ msgstr "Remote"
msgid "Remove"
msgstr "Entfernen"
#: src/views/members/index.tsx:120
#: src/views/members/index.tsx:132
msgid "Remove member"
msgstr "Mitglied entfernen"
@@ -1177,7 +1205,7 @@ msgstr "Widerrufen"
msgid "Roadmap"
msgstr "Roadmap"
#: src/views/members/index.tsx:178
#: src/views/members/index.tsx:191
msgid "Role"
msgstr "Rolle"
@@ -1185,7 +1213,7 @@ msgstr "Rolle"
msgid "Run on your own infrastructure"
msgstr "Auf eigener Infrastruktur betreiben"
#: src/views/card/components/Comment.tsx:163
#: src/views/card/components/Comment.tsx:165
msgid "Save"
msgstr "Speichern"
@@ -1217,21 +1245,21 @@ msgstr "Selbst hosten mit Github"
msgid "self-assigned the card"
msgstr "hat sich selbst die Karte zugewiesen"
#: src/components/FeedbackButton.tsx:137
msgid "Send"
msgstr "Senden"
#: src/components/FeedbackModal.tsx:116
msgid "Send feedback"
msgstr "Feedback senden"
#: src/views/boards/components/TemplateBoards.tsx:69
msgid "Senior"
msgstr "Senior"
#: src/views/settings/index.tsx:112
#: src/components/SideNavigation.tsx:49
#: src/views/settings/index.tsx:138
#: src/components/SideNavigation.tsx:78
msgid "Settings"
msgstr "Einstellungen"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:108
#: src/views/settings/index.tsx:134
msgid "Settings | {0}"
msgstr "Einstellungen | {0}"
@@ -1253,7 +1281,7 @@ msgstr "Registrierung deaktiviert"
msgid "Sign up is currently disabled. Please try again later."
msgstr "Die Registrierung ist derzeit deaktiviert. Bitte versuche es später erneut."
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Sign up with "
msgstr "Registrieren mit "
@@ -1282,11 +1310,15 @@ msgstr "Stern auf Github"
msgid "Success"
msgstr "Erfolg"
#: src/components/UserMenu.tsx:180
msgid "Support"
msgstr "Support"
#: src/views/home/components/Pricing.tsx:57
msgid "Support the development of the project"
msgstr "Unterstütze die Entwicklung des Projekts"
#: src/components/UserMenu.tsx:98
#: src/components/UserMenu.tsx:139
msgid "System"
msgstr "System"
@@ -1302,7 +1334,7 @@ msgstr "Vorlagen"
msgid "Terms of service"
msgstr "Nutzungsbedingungen"
#: src/components/FeedbackButton.tsx:39
#: src/components/FeedbackModal.tsx:34
msgid "Thank you for your feedback!"
msgstr "Vielen Dank für dein Feedback!"
@@ -1319,7 +1351,7 @@ msgstr "Die open source <0/> alternative zu Trello"
msgid "The visibility of your board has been set to {0}."
msgstr "Die Sichtbarkeit deines Boards wurde auf {0} gesetzt."
#: src/components/UserMenu.tsx:85
#: src/components/UserMenu.tsx:126
msgid "Theme"
msgstr "Design"
@@ -1329,9 +1361,14 @@ msgstr "Sie werden keinen Zugriff mehr auf diesen Workspace haben."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42
msgid "This action can't be undone."
msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
#: src/views/public/board/index.tsx:146
msgid "This board is private or does not exist"
msgstr "Dieses Board ist privat oder existiert nicht"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135
msgid "This board URL has already been taken"
msgstr "Diese Board-URL ist bereits vergeben"
@@ -1361,7 +1398,7 @@ msgstr "Menü umschalten"
msgid "Track all card changes with detailed activity history."
msgstr "Verfolge alle kartenänderungen mit detaillierter aktivitätshistorie."
#: src/views/settings/index.tsx:69
#: src/views/settings/index.tsx:92
msgid "Trello disconnected"
msgstr "Trello getrennt"
@@ -1377,7 +1414,7 @@ msgstr "Priorisierung"
msgid "Unable to add comment"
msgstr "Kommentar konnte nicht hinzugefügt werden"
#: src/views/board/components/NewCardForm.tsx:125
#: src/views/board/components/NewCardForm.tsx:142
msgid "Unable to create card"
msgstr "Karte konnte nicht erstellt werden"
@@ -1385,7 +1422,7 @@ msgstr "Karte konnte nicht erstellt werden"
msgid "Unable to create list"
msgstr "Liste konnte nicht erstellt werden"
#: src/components/NewWorkspaceForm.tsx:38
#: src/components/NewWorkspaceForm.tsx:40
msgid "Unable to create workspace"
msgstr "Workspace konnte nicht erstellt werden"
@@ -1401,7 +1438,7 @@ msgstr "Kommentar konnte nicht gelöscht werden"
msgid "Unable to remove member"
msgstr "Mitglied konnte nicht entfernt werden"
#: src/components/FeedbackButton.tsx:45
#: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback"
msgstr "Feedback konnte nicht gesendet werden"
@@ -1413,12 +1450,12 @@ msgstr "Board-URL kann nicht aktualisiert werden"
msgid "Unable to update board visibility"
msgstr "Board-Sichtbarkeit konnte nicht aktualisiert werden"
#: src/views/card/index.tsx:115
#: src/views/board/index.tsx:188
#: src/views/card/index.tsx:158
#: src/views/board/index.tsx:190
msgid "Unable to update card"
msgstr "Karte konnte nicht aktualisiert werden"
#: src/views/card/components/Comment.tsx:61
#: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment"
msgstr "Kommentar konnte nicht aktualisiert werden"
@@ -1427,7 +1464,7 @@ msgid "Unable to update labels"
msgstr "Labels konnten nicht aktualisiert werden"
#: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:132
#: src/views/board/index.tsx:134
msgid "Unable to update list"
msgstr "Liste konnte nicht aktualisiert werden"
@@ -1471,11 +1508,11 @@ msgstr "Unbegrenzte listen"
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:82
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:90
#: src/views/settings/components/UpdateDisplayNameForm.tsx:79
#: src/views/board/components/UpdateBoardSlugForm.tsx:166
#: src/views/board/components/UpdateBoardSlugForm.tsx:174
msgid "Update"
msgstr "Aktualisieren"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Update label"
msgstr "Label aktualisieren"
@@ -1516,19 +1553,23 @@ msgstr "URL muss mindestens 3 Zeichen lang sein"
msgid "Use template"
msgstr "Vorlage verwenden"
#: src/views/members/index.tsx:172
#: src/views/members/index.tsx:185
msgid "User"
msgstr "Benutzer"
#: src/views/members/components/InviteMemberForm.tsx:58
msgid "User is already a member of this workspace"
msgstr "Benutzer ist bereits Mitglied dieses Arbeitsbereichs"
#: src/views/boards/components/TemplateBoards.tsx:37
msgid "Video"
msgstr "Video"
#: src/views/settings/index.tsx:232
#: src/views/settings/index.tsx:260
msgid "View and manage your API keys."
msgstr "API-Schlüssel anzeigen und verwalten."
#: src/views/settings/index.tsx:171
#: src/views/settings/index.tsx:199
msgid "View and manage your billing and subscription."
msgstr "Verwalte deine Abrechnung und dein Abonnement."
@@ -1536,10 +1577,18 @@ msgstr "Verwalte deine Abrechnung und dein Abonnement."
msgid "View docs"
msgstr "Dokumentation ansehen"
#: src/views/public/board/index.tsx:120
msgid "View only"
msgstr "Nur ansehen"
#: src/views/home/components/Features.tsx:147
msgid "View our roadmap."
msgstr "Sieh dir unsere roadmap an."
#: src/views/public/board/index.tsx:149
msgid "View workspace"
msgstr "Workspace anzeigen"
#: src/views/board/components/VisibilityButton.tsx:91
msgid "Visibility"
msgstr "Sichtbarkeit"
@@ -1572,7 +1621,7 @@ msgstr "Als Trello 2011 auf den markt kam, beeindruckte es alle mit seiner sorgf
msgid "Why make an open source Trello?"
msgstr "Warum ein open source Trello entwickeln?"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Workspace"
msgstr "Arbeitsbereich"
@@ -1580,7 +1629,7 @@ msgstr "Arbeitsbereich"
msgid "Workspace deleted"
msgstr "Workspace gelöscht"
#: src/views/settings/index.tsx:147
#: src/views/settings/index.tsx:175
msgid "Workspace description"
msgstr "Workspace-Beschreibung"
@@ -1601,8 +1650,8 @@ msgstr "Workspace-Beschreibung aktualisiert"
msgid "Workspace members"
msgstr "Workspace-mitglieder"
#: src/views/settings/index.tsx:130
#: src/components/NewWorkspaceForm.tsx:78
#: src/views/settings/index.tsx:156
#: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name"
msgstr "Name des Workspaces"
@@ -1622,7 +1671,7 @@ msgstr "Workspace-Name aktualisiert"
msgid "Workspace slug updated"
msgstr "Workspace-Slug aktualisiert"
#: src/views/settings/index.tsx:138
#: src/views/settings/index.tsx:165
msgid "Workspace URL"
msgstr "Workspace-URL"
@@ -1670,15 +1719,15 @@ msgstr "Deine Boards wurden importiert."
msgid "Your display name has been updated."
msgstr "Dein Anzeigename wurde aktualisiert."
#: src/views/settings/components/Avatar.tsx:25
#: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated."
msgstr "Dein Profilbild wurde aktualisiert."
#: src/views/settings/index.tsx:70
#: src/views/settings/index.tsx:93
msgid "Your Trello account has been disconnected."
msgstr "Dein Trello-Konto wurde getrennt."
#: src/views/settings/index.tsx:214
#: src/views/settings/index.tsx:242
msgid "Your Trello account is connected."
msgstr "Dein Trello-Konto ist verbunden."

File diff suppressed because one or more lines are too long

View File

@@ -13,22 +13,22 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:121
#: src/views/card/components/Comment.tsx:123
msgid " (edited)"
msgstr " (edited)"
#: src/components/FeedbackButton.tsx:123
#: src/components/FeedbackModal.tsx:102
msgid ", or see our"
msgstr ", or see our"
#. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:148
#: src/views/card/index.tsx:189
msgid "{0} | {1}"
msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:365
#: src/views/board/components/NewCardForm.tsx:392
msgid "{0} labels"
msgstr "{0} labels"
@@ -37,8 +37,8 @@ msgid "{boardCount, plural, one {Import board (1)} other {Import boards ({boardC
msgstr "{boardCount, plural, one {Import board (1)} other {Import boards ({boardCount})}}"
#: src/views/home/index.tsx:51
msgid "#1 Hacker News"
msgstr "#1 Hacker News"
#~ msgid "#1 Hacker News"
#~ msgstr "#1 Hacker News"
#: src/views/home/components/Pricing.tsx:36
msgid "1 user"
@@ -60,8 +60,8 @@ msgstr "A powerful, flexible kanban app that helps you organise work, track prog
msgid "Account deleted"
msgstr "Account deleted"
#: src/views/public/board/CardModal.tsx:104
#: src/views/card/index.tsx:215
#: src/views/public/board/CardModal.tsx:128
#: src/views/card/index.tsx:256
msgid "Activity"
msgstr "Activity"
@@ -74,11 +74,11 @@ msgid "Add a card"
msgstr "Add a card"
#: src/views/card/components/NewCommentForm.tsx:57
#: src/views/card/components/Comment.tsx:144
#: src/views/card/components/Comment.tsx:146
msgid "Add a comment..."
msgstr "Add a comment..."
#: src/components/Editor.tsx:302
#: src/components/Editor.tsx:303
msgid "Add description... (type '/' to open commands)"
msgstr "Add description... (type '/' to open commands)"
@@ -87,7 +87,7 @@ msgstr "Add description... (type '/' to open commands)"
msgid "Add label"
msgstr "Add label"
#: src/views/members/components/InviteMemberForm.tsx:50
#: src/views/members/components/InviteMemberForm.tsx:85
#: src/views/card/components/MemberSelector.tsx:130
msgid "Add member"
msgstr "Add member"
@@ -120,11 +120,11 @@ msgstr "All systems operational"
msgid "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:77
#: src/views/settings/index.tsx:100
msgid "An error occurred while disconnecting your Trello account."
msgstr "An error occurred while disconnecting your Trello account."
#: src/views/settings/index.tsx:229
#: src/views/settings/index.tsx:257
msgid "API keys"
msgstr "API keys"
@@ -161,6 +161,10 @@ msgstr "Are you sure you want to delete this card?"
msgid "Are you sure you want to delete this comment?"
msgstr "Are you sure you want to delete this comment?"
#: src/components/DeleteLabelConfirmation.tsx:39
msgid "Are you sure you want to delete this label?"
msgstr "Are you sure you want to delete this label?"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:54
msgid "Are you sure you want to delete your account?"
msgstr "Are you sure you want to delete your account?"
@@ -185,12 +189,12 @@ msgstr "Backlog"
msgid "Basic Kanban"
msgstr "Basic Kanban"
#: src/views/settings/index.tsx:168
#: src/views/settings/index.tsx:196
#: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing"
msgstr "Billing"
#: src/views/settings/index.tsx:178
#: src/views/settings/index.tsx:206
msgid "Billing portal"
msgstr "Billing portal"
@@ -198,7 +202,7 @@ msgstr "Billing portal"
msgid "Blog Post"
msgstr "Blog Post"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Board"
msgstr "Board"
@@ -214,7 +218,8 @@ msgstr "Board name cannot exceed 100 characters"
msgid "Board name is required"
msgstr "Board name is required"
#: src/views/board/index.tsx:265
#: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358
msgid "Board not found"
msgstr "Board not found"
@@ -226,7 +231,7 @@ msgstr "Board URL can only contain letters, numbers, and hyphens"
msgid "Board URL cannot exceed 60 characters"
msgstr "Board URL cannot exceed 60 characters"
#: src/views/public/board/index.tsx:53
#: src/views/public/board/index.tsx:59
msgid "Board URL copied to clipboard"
msgstr "Board URL copied to clipboard"
@@ -242,13 +247,13 @@ msgstr "Board visibility"
msgid "Board visibility updated"
msgstr "Board visibility updated"
#: src/views/boards/index.tsx:25
#: src/components/SideNavigation.tsx:39
#: src/views/boards/index.tsx:27
#: src/components/SideNavigation.tsx:68
msgid "Boards"
msgstr "Boards"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/boards/index.tsx:21
#: src/views/boards/index.tsx:23
msgid "Boards | {0}"
msgstr "Boards | {0}"
@@ -274,19 +279,20 @@ msgstr "Bug Report"
#: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:156
#: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47
msgid "Cancel"
msgstr "Cancel"
#: src/views/card/index.tsx:193
#: src/views/card/index.tsx:234
msgid "Card not found"
msgstr "Card not found"
#: src/views/board/components/NewCardForm.tsx:254
#: src/views/board/components/NewCardForm.tsx:278
msgid "Card title"
msgstr "Card title"
#: src/views/settings/index.tsx:160
#: src/views/settings/index.tsx:188
msgid "Change the language of the app."
msgstr "Change the language of the app."
@@ -336,7 +342,7 @@ msgstr "Complete control and ownership:"
msgid "Confirm URL change"
msgstr "Confirm URL change"
#: src/views/settings/index.tsx:205
#: src/views/settings/index.tsx:233
#: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello"
msgstr "Connect Trello"
@@ -345,7 +351,7 @@ msgstr "Connect Trello"
msgid "Connect your favorite tools to streamline your workflow."
msgstr "Connect your favorite tools to streamline your workflow."
#: src/views/settings/index.tsx:192
#: src/views/settings/index.tsx:220
msgid "Connect your Trello account to import boards."
msgstr "Connect your Trello account to import boards."
@@ -353,7 +359,7 @@ msgstr "Connect your Trello account to import boards."
msgid "Contact"
msgstr "Contact"
#: src/components/FeedbackButton.tsx:121
#: src/components/FeedbackModal.tsx:100
msgid "Contact us"
msgstr "Contact us"
@@ -361,12 +367,12 @@ msgstr "Contact us"
msgid "Content Creation"
msgstr "Content Creation"
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Continue with "
msgstr "Continue with "
#. placeholder {0}: provider.name
#: src/components/AuthForm.tsx:268
#: src/components/AuthForm.tsx:269
msgid "Continue with {0}"
msgstr "Continue with {0}"
@@ -375,7 +381,7 @@ msgid "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/NewCardForm.tsx:391
#: src/views/board/components/NewCardForm.tsx:418
#: src/components/LabelForm.tsx:212
msgid "Create another"
msgstr "Create another"
@@ -392,15 +398,15 @@ msgstr "Create another"
msgid "Create board"
msgstr "Create board"
#: src/views/board/components/NewCardForm.tsx:401
#: src/views/board/components/NewCardForm.tsx:428
msgid "Create card"
msgstr "Create card"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Create label"
msgstr "Create label"
#: src/views/board/components/NewListForm.tsx:148
#: src/views/board/components/NewListForm.tsx:152
msgid "Create list"
msgstr "Create list"
@@ -413,16 +419,16 @@ msgid "Create new key"
msgstr "Create new key"
#: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:327
#: src/views/board/components/NewCardForm.tsx:354
msgid "Create new label"
msgstr "Create new label"
#: src/views/board/index.tsx:327
#: src/views/board/index.tsx:426
msgid "Create new list"
msgstr "Create new list"
#: src/components/WorkspaceMenu.tsx:85
#: src/components/NewWorkspaceForm.tsx:91
#: src/components/WorkspaceMenu.tsx:116
#: src/components/NewWorkspaceForm.tsx:93
msgid "Create workspace"
msgstr "Create workspace"
@@ -446,18 +452,19 @@ msgstr "Custom URLs are a premium feature. You'll be directed to upgrade your ac
msgid "Customer Support"
msgstr "Customer Support"
#: src/components/UserMenu.tsx:112
#: src/components/UserMenu.tsx:153
msgid "Dark"
msgstr "Dark"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226
#: src/components/DeleteLabelConfirmation.tsx:49
msgid "Delete"
msgstr "Delete"
#: src/views/settings/index.tsx:260
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:288
#: src/views/settings/index.tsx:298
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account"
msgstr "Delete account"
@@ -470,7 +477,7 @@ msgstr "Delete board"
msgid "Delete card"
msgstr "Delete card"
#: src/views/card/components/Comment.tsx:89
#: src/views/card/components/Comment.tsx:91
msgid "Delete comment"
msgstr "Delete comment"
@@ -478,8 +485,8 @@ msgstr "Delete comment"
msgid "Delete list"
msgstr "Delete list"
#: src/views/settings/index.tsx:242
#: src/views/settings/index.tsx:253
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:281
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace"
msgstr "Delete workspace"
@@ -488,7 +495,7 @@ msgstr "Delete workspace"
msgid "Design"
msgstr "Design"
#: src/views/settings/index.tsx:220
#: src/views/settings/index.tsx:248
msgid "Disconnect Trello"
msgstr "Disconnect Trello"
@@ -496,7 +503,7 @@ msgstr "Disconnect Trello"
msgid "Discuss and collaborate on cards."
msgstr "Discuss and collaborate on cards."
#: src/views/settings/index.tsx:123
#: src/views/settings/index.tsx:149
msgid "Display name"
msgstr "Display name"
@@ -516,7 +523,7 @@ msgstr "Display name updated"
msgid "Do you offer a free plan?"
msgstr "Do you offer a free plan?"
#: src/components/FeedbackButton.tsx:130
#: src/components/FeedbackModal.tsx:109
msgid "docs"
msgstr "docs"
@@ -526,6 +533,7 @@ msgstr "Docs"
#: src/views/home/components/Footer.tsx:77
#: src/views/boards/components/TemplateBoards.tsx:23
#: src/components/UserMenu.tsx:191
msgid "Documentation"
msgstr "Documentation"
@@ -545,7 +553,7 @@ msgstr "Done"
msgid "Edit board URL"
msgstr "Edit board URL"
#: src/views/card/components/Comment.tsx:80
#: src/views/card/components/Comment.tsx:82
msgid "Edit comment"
msgstr "Edit comment"
@@ -553,15 +561,19 @@ msgstr "Edit comment"
msgid "Edit label"
msgstr "Edit label"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161
msgid "Edit workspace URL"
msgstr "Edit workspace URL"
#: src/views/boards/components/TemplateBoards.tsx:31
msgid "Editing"
msgstr "Editing"
#: src/components/AuthForm.tsx:336
#: src/components/AuthForm.tsx:337
msgid "email"
msgstr "email"
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/InviteMemberForm.tsx:99
msgid "Email"
msgstr "Email"
@@ -569,15 +581,15 @@ msgstr "Email"
msgid "Enhancement"
msgstr "Enhancement"
#: src/components/AuthForm.tsx:301
#: src/components/AuthForm.tsx:302
msgid "Enter your email address"
msgstr "Enter your email address"
#: src/components/AuthForm.tsx:289
#: src/components/AuthForm.tsx:290
msgid "Enter your name"
msgstr "Enter your name"
#: src/components/AuthForm.tsx:314
#: src/components/AuthForm.tsx:315
msgid "Enter your password"
msgstr "Enter your password"
@@ -585,19 +597,28 @@ msgstr "Enter your password"
msgid "Error deleting account"
msgstr "Error deleting account"
#: src/components/DeleteLabelConfirmation.tsx:22
msgid "Error deleting label"
msgstr "Error deleting label"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:45
msgid "Error deleting workspace"
msgstr "Error deleting workspace"
#: src/views/settings/index.tsx:76
#: src/views/settings/index.tsx:99
msgid "Error disconnecting Trello"
msgstr "Error disconnecting Trello"
#: src/views/members/components/InviteMemberForm.tsx:57
#: src/views/members/components/InviteMemberForm.tsx:63
msgid "Error inviting member"
msgstr "Error inviting member"
#: src/views/settings/components/UpdateDisplayNameForm.tsx:54
msgid "Error updating display name"
msgstr "Error updating display name"
#: src/views/settings/components/Avatar.tsx:37
#: src/views/settings/components/Avatar.tsx:39
msgid "Error updating profile image"
msgstr "Error updating profile image"
@@ -613,8 +634,8 @@ msgstr "Error updating workspace name"
msgid "Error updating workspace URL"
msgstr "Error updating workspace URL"
#: src/views/settings/components/Avatar.tsx:54
#: src/views/settings/components/Avatar.tsx:95
#: src/views/settings/components/Avatar.tsx:56
#: src/views/settings/components/Avatar.tsx:97
msgid "Error uploading profile image"
msgstr "Error uploading profile image"
@@ -654,11 +675,12 @@ msgstr "Feature Request"
msgid "Features"
msgstr "Features"
#: src/components/FeedbackButton.tsx:78
#: src/components/UserMenu.tsx:199
#: src/components/FeedbackModal.tsx:59
msgid "Feedback"
msgstr "Feedback"
#: src/components/FeedbackButton.tsx:38
#: src/components/FeedbackModal.tsx:33
msgid "Feedback sent"
msgstr "Feedback sent"
@@ -707,7 +729,7 @@ msgstr "Get Started"
msgid "Get started by creating a new board"
msgstr "Get started by creating a new board"
#: src/views/board/index.tsx:319
#: src/views/board/index.tsx:418
msgid "Get started by creating a new list"
msgstr "Get started by creating a new list"
@@ -780,7 +802,7 @@ msgstr "I acknowledge that all of the workspace data will be permanently deleted
msgid "Ideas"
msgstr "Ideas"
#: src/components/FeedbackButton.tsx:98
#: src/components/FeedbackModal.tsx:75
msgid "Ideas to improve this page..."
msgstr "Ideas to improve this page..."
@@ -788,7 +810,7 @@ msgstr "Ideas to improve this page..."
#~ msgid "Ideas, Research, Planning, Execution, Review, Next Steps, Complete"
#~ msgstr "Ideas, Research, Planning, Execution, Review, Next Steps, Complete"
#: src/views/boards/index.tsx:39
#: src/views/boards/index.tsx:38
msgid "Import"
msgstr "Import"
@@ -834,11 +856,19 @@ msgstr "Integrations"
msgid "Interviewing"
msgstr "Interviewing"
#: src/views/members/index.tsx:156
#: src/views/members/components/InviteMemberForm.tsx:26
msgid "Invalid email address"
msgstr "Invalid email address"
#: src/views/members/index.tsx:169
msgid "Invite"
msgstr "Invite"
#: src/views/members/components/InviteMemberForm.tsx:82
#: src/views/members/components/InviteMemberForm.tsx:113
msgid "Invite another"
msgstr "Invite another"
#: src/views/members/components/InviteMemberForm.tsx:123
#: src/views/card/components/MemberSelector.tsx:112
msgid "Invite member"
msgstr "Invite member"
@@ -860,8 +890,8 @@ msgstr "Kanban reimagined"
msgid "Keep in mind that this action is irreversible."
msgstr "Keep in mind that this action is irreversible."
#: src/views/card/index.tsx:243
#: src/views/board/components/NewCardForm.tsx:331
#: src/views/card/index.tsx:113
#: src/views/board/components/NewCardForm.tsx:358
#: src/views/board/components/Filters.tsx:101
msgid "Labels"
msgstr "Labels"
@@ -870,7 +900,7 @@ msgstr "Labels"
msgid "Labels & Filters"
msgstr "Labels & Filters"
#: src/views/settings/index.tsx:157
#: src/views/settings/index.tsx:185
msgid "Language"
msgstr "Language"
@@ -886,15 +916,15 @@ msgstr "Legal"
msgid "License"
msgstr "License"
#: src/components/UserMenu.tsx:126
#: src/components/UserMenu.tsx:167
msgid "Light"
msgstr "Light"
#: src/views/public/board/index.tsx:51
#: src/views/public/board/index.tsx:57
msgid "Link copied"
msgstr "Link copied"
#: src/views/card/index.tsx:235
#: src/views/card/index.tsx:105
msgid "List"
msgstr "List"
@@ -906,7 +936,7 @@ msgstr "List name"
msgid "Login | kan.bn"
msgstr "Login | kan.bn"
#: src/components/UserMenu.tsx:136
#: src/components/UserMenu.tsx:209
msgid "Logout"
msgstr "Logout"
@@ -918,7 +948,7 @@ msgstr "Long-term"
msgid "Low Priority"
msgstr "Low Priority"
#: src/components/AuthForm.tsx:337
#: src/components/AuthForm.tsx:338
msgid "magic link"
msgstr "magic link"
@@ -926,16 +956,16 @@ msgstr "magic link"
msgid "Medium Priority"
msgstr "Medium Priority"
#: src/views/members/index.tsx:148
#: src/views/card/index.tsx:251
#: src/views/board/components/NewCardForm.tsx:290
#: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121
#: src/views/board/components/NewCardForm.tsx:317
#: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:44
#: src/components/SideNavigation.tsx:73
msgid "Members"
msgstr "Members"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/members/index.tsx:144
#: src/views/members/index.tsx:157
msgid "Members | {0}"
msgstr "Members | {0}"
@@ -956,11 +986,11 @@ msgstr "moved the card to another list"
msgid "Name"
msgstr "Name"
#: src/components/FeedbackButton.tsx:116
#: src/components/FeedbackModal.tsx:95
msgid "Need help?"
msgstr "Need help?"
#: src/views/boards/index.tsx:52
#: src/views/boards/index.tsx:48
msgid "New"
msgstr "New"
@@ -968,7 +998,7 @@ msgstr "New"
msgid "New board"
msgstr "New board"
#: src/views/board/components/NewCardForm.tsx:237
#: src/views/board/components/NewCardForm.tsx:261
msgid "New card"
msgstr "New card"
@@ -980,7 +1010,7 @@ msgstr "New import"
msgid "New label"
msgstr "New label"
#: src/views/board/index.tsx:296
#: src/views/board/index.tsx:395
#: src/views/board/components/NewListForm.tsx:112
msgid "New list"
msgstr "New list"
@@ -993,7 +1023,7 @@ msgstr "New Ticket"
#~ msgid "New Ticket, Triaging, In Progress, Awaiting Customer, Resolution, Done"
#~ msgstr "New Ticket, Triaging, In Progress, Awaiting Customer, Resolution, Done"
#: src/components/NewWorkspaceForm.tsx:62
#: src/components/NewWorkspaceForm.tsx:64
msgid "New workspace"
msgstr "New workspace"
@@ -1017,7 +1047,7 @@ msgstr "No boards found"
msgid "No credit card required"
msgstr "No credit card required"
#: src/views/board/index.tsx:316
#: src/views/board/index.tsx:415
msgid "No lists"
msgstr "No lists"
@@ -1029,15 +1059,15 @@ msgstr "Offer"
msgid "Onboarding"
msgstr "Onboarding"
#: src/views/settings/index.tsx:263
#: src/views/settings/index.tsx:291
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."
#: src/views/settings/index.tsx:245
#: src/views/settings/index.tsx:273
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."
#: src/components/AuthForm.tsx:279
#: src/components/AuthForm.tsx:280
msgid "or"
msgstr "or"
@@ -1057,7 +1087,7 @@ msgstr "Part-time"
msgid "Payment frequency"
msgstr "Payment frequency"
#: src/views/members/index.tsx:107
#: src/views/members/index.tsx:118
msgid "Pending"
msgstr "Pending"
@@ -1074,19 +1104,19 @@ msgstr "Personal Project"
msgid "Planning"
msgstr "Planning"
#: src/components/AuthForm.tsx:305
#: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address"
msgstr "Please enter a valid email address"
#: src/components/AuthForm.tsx:293
#: src/components/AuthForm.tsx:294
msgid "Please enter a valid name"
msgstr "Please enter a valid name"
#: src/components/AuthForm.tsx:318
#: src/components/AuthForm.tsx:319
msgid "Please enter a valid password"
msgstr "Please enter a valid password"
#: src/views/settings/components/Avatar.tsx:55
#: src/views/settings/components/Avatar.tsx:57
msgid "Please select a file to upload."
msgstr "Please select a file to upload."
@@ -1096,26 +1126,28 @@ msgstr "Please select a file to upload."
#: src/views/settings/components/UpdateDisplayNameForm.tsx:55
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:46
#: src/views/settings/components/DeleteAccountConfirmation.tsx:40
#: src/views/settings/components/Avatar.tsx:38
#: src/views/settings/components/Avatar.tsx:96
#: src/views/settings/components/Avatar.tsx:40
#: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:116
#: src/views/card/index.tsx:159
#: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:62
#: src/views/card/components/Comment.tsx:64
#: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:133
#: src/views/board/index.tsx:189
#: src/views/board/index.tsx:135
#: src/views/board/index.tsx:191
#: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:128
#: src/components/NewWorkspaceForm.tsx:39
#: src/components/FeedbackButton.tsx:46
#: src/views/board/components/NewCardForm.tsx:145
#: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23
msgid "Please try again later, or contact customer support."
msgstr "Please try again later, or contact customer support."
@@ -1137,11 +1169,11 @@ msgstr "Privacy policy"
msgid "Private"
msgstr "Private"
#: src/views/settings/components/Avatar.tsx:24
#: src/views/settings/components/Avatar.tsx:26
msgid "Profile image updated"
msgstr "Profile image updated"
#: src/views/settings/index.tsx:118
#: src/views/settings/index.tsx:144
msgid "Profile picture"
msgstr "Profile picture"
@@ -1177,7 +1209,7 @@ msgstr "Remote"
msgid "Remove"
msgstr "Remove"
#: src/views/members/index.tsx:120
#: src/views/members/index.tsx:132
msgid "Remove member"
msgstr "Remove member"
@@ -1218,7 +1250,7 @@ msgstr "Revoke"
msgid "Roadmap"
msgstr "Roadmap"
#: src/views/members/index.tsx:178
#: src/views/members/index.tsx:191
msgid "Role"
msgstr "Role"
@@ -1226,7 +1258,7 @@ msgstr "Role"
msgid "Run on your own infrastructure"
msgstr "Run on your own infrastructure"
#: src/views/card/components/Comment.tsx:163
#: src/views/card/components/Comment.tsx:165
msgid "Save"
msgstr "Save"
@@ -1259,20 +1291,24 @@ msgid "self-assigned the card"
msgstr "self-assigned the card"
#: src/components/FeedbackButton.tsx:137
msgid "Send"
msgstr "Send"
#~ msgid "Send"
#~ msgstr "Send"
#: src/components/FeedbackModal.tsx:116
msgid "Send feedback"
msgstr "Send feedback"
#: src/views/boards/components/TemplateBoards.tsx:69
msgid "Senior"
msgstr "Senior"
#: src/views/settings/index.tsx:112
#: src/components/SideNavigation.tsx:49
#: src/views/settings/index.tsx:138
#: src/components/SideNavigation.tsx:78
msgid "Settings"
msgstr "Settings"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:108
#: src/views/settings/index.tsx:134
msgid "Settings | {0}"
msgstr "Settings | {0}"
@@ -1294,7 +1330,7 @@ msgstr "Sign up disabled"
msgid "Sign up is currently disabled. Please try again later."
msgstr "Sign up is currently disabled. Please try again later."
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Sign up with "
msgstr "Sign up with "
@@ -1323,11 +1359,15 @@ msgstr "Star on Github"
msgid "Success"
msgstr "Success"
#: src/components/UserMenu.tsx:180
msgid "Support"
msgstr "Support"
#: src/views/home/components/Pricing.tsx:57
msgid "Support the development of the project"
msgstr "Support the development of the project"
#: src/components/UserMenu.tsx:98
#: src/components/UserMenu.tsx:139
msgid "System"
msgstr "System"
@@ -1343,7 +1383,7 @@ msgstr "Templates"
msgid "Terms of service"
msgstr "Terms of service"
#: src/components/FeedbackButton.tsx:39
#: src/components/FeedbackModal.tsx:34
msgid "Thank you for your feedback!"
msgstr "Thank you for your feedback!"
@@ -1360,7 +1400,7 @@ msgstr "The open source <0/> alternative to Trello"
msgid "The visibility of your board has been set to {0}."
msgstr "The visibility of your board has been set to {0}."
#: src/components/UserMenu.tsx:85
#: src/components/UserMenu.tsx:126
msgid "Theme"
msgstr "Theme"
@@ -1370,9 +1410,14 @@ msgstr "They won't be able to access this workspace."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42
msgid "This action can't be undone."
msgstr "This action can't be undone."
#: src/views/public/board/index.tsx:146
msgid "This board is private or does not exist"
msgstr "This board is private or does not exist"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135
msgid "This board URL has already been taken"
msgstr "This board URL has already been taken"
@@ -1406,7 +1451,7 @@ msgstr "Toggle menu"
msgid "Track all card changes with detailed activity history."
msgstr "Track all card changes with detailed activity history."
#: src/views/settings/index.tsx:69
#: src/views/settings/index.tsx:92
msgid "Trello disconnected"
msgstr "Trello disconnected"
@@ -1422,7 +1467,7 @@ msgstr "Triaging"
msgid "Unable to add comment"
msgstr "Unable to add comment"
#: src/views/board/components/NewCardForm.tsx:125
#: src/views/board/components/NewCardForm.tsx:142
msgid "Unable to create card"
msgstr "Unable to create card"
@@ -1430,7 +1475,7 @@ msgstr "Unable to create card"
msgid "Unable to create list"
msgstr "Unable to create list"
#: src/components/NewWorkspaceForm.tsx:38
#: src/components/NewWorkspaceForm.tsx:40
msgid "Unable to create workspace"
msgstr "Unable to create workspace"
@@ -1446,7 +1491,7 @@ msgstr "Unable to delete comment"
msgid "Unable to remove member"
msgstr "Unable to remove member"
#: src/components/FeedbackButton.tsx:45
#: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback"
msgstr "Unable to send feedback"
@@ -1458,12 +1503,12 @@ msgstr "Unable to update board URL"
msgid "Unable to update board visibility"
msgstr "Unable to update board visibility"
#: src/views/card/index.tsx:115
#: src/views/board/index.tsx:188
#: src/views/card/index.tsx:158
#: src/views/board/index.tsx:190
msgid "Unable to update card"
msgstr "Unable to update card"
#: src/views/card/components/Comment.tsx:61
#: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment"
msgstr "Unable to update comment"
@@ -1472,7 +1517,7 @@ msgid "Unable to update labels"
msgstr "Unable to update labels"
#: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:132
#: src/views/board/index.tsx:134
msgid "Unable to update list"
msgstr "Unable to update list"
@@ -1516,11 +1561,11 @@ msgstr "Unlimited lists"
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:82
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:90
#: src/views/settings/components/UpdateDisplayNameForm.tsx:79
#: src/views/board/components/UpdateBoardSlugForm.tsx:166
#: src/views/board/components/UpdateBoardSlugForm.tsx:174
msgid "Update"
msgstr "Update"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Update label"
msgstr "Update label"
@@ -1561,19 +1606,23 @@ msgstr "URL must be at least 3 characters long"
msgid "Use template"
msgstr "Use template"
#: src/views/members/index.tsx:172
#: src/views/members/index.tsx:185
msgid "User"
msgstr "User"
#: src/views/members/components/InviteMemberForm.tsx:58
msgid "User is already a member of this workspace"
msgstr "User is already a member of this workspace"
#: src/views/boards/components/TemplateBoards.tsx:37
msgid "Video"
msgstr "Video"
#: src/views/settings/index.tsx:232
#: src/views/settings/index.tsx:260
msgid "View and manage your API keys."
msgstr "View and manage your API keys."
#: src/views/settings/index.tsx:171
#: src/views/settings/index.tsx:199
msgid "View and manage your billing and subscription."
msgstr "View and manage your billing and subscription."
@@ -1581,10 +1630,18 @@ msgstr "View and manage your billing and subscription."
msgid "View docs"
msgstr "View docs"
#: src/views/public/board/index.tsx:120
msgid "View only"
msgstr "View only"
#: src/views/home/components/Features.tsx:147
msgid "View our roadmap."
msgstr "View our roadmap."
#: src/views/public/board/index.tsx:149
msgid "View workspace"
msgstr "View workspace"
#: src/views/board/components/VisibilityButton.tsx:91
msgid "Visibility"
msgstr "Visibility"
@@ -1621,7 +1678,7 @@ msgstr "When Trello launched in 2011, it blew everyone away with its carefully d
msgid "Why make an open source Trello?"
msgstr "Why make an open source Trello?"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Workspace"
msgstr "Workspace"
@@ -1629,7 +1686,7 @@ msgstr "Workspace"
msgid "Workspace deleted"
msgstr "Workspace deleted"
#: src/views/settings/index.tsx:147
#: src/views/settings/index.tsx:175
msgid "Workspace description"
msgstr "Workspace description"
@@ -1650,8 +1707,8 @@ msgstr "Workspace description updated"
msgid "Workspace members"
msgstr "Workspace members"
#: src/views/settings/index.tsx:130
#: src/components/NewWorkspaceForm.tsx:78
#: src/views/settings/index.tsx:156
#: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name"
msgstr "Workspace name"
@@ -1671,7 +1728,7 @@ msgstr "Workspace name updated"
msgid "Workspace slug updated"
msgstr "Workspace slug updated"
#: src/views/settings/index.tsx:138
#: src/views/settings/index.tsx:165
msgid "Workspace URL"
msgstr "Workspace URL"
@@ -1719,15 +1776,15 @@ msgstr "Your boards have been imported."
msgid "Your display name has been updated."
msgstr "Your display name has been updated."
#: src/views/settings/components/Avatar.tsx:25
#: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated."
msgstr "Your profile image has been updated."
#: src/views/settings/index.tsx:70
#: src/views/settings/index.tsx:93
msgid "Your Trello account has been disconnected."
msgstr "Your Trello account has been disconnected."
#: src/views/settings/index.tsx:214
#: src/views/settings/index.tsx:242
msgid "Your Trello account is connected."
msgstr "Your Trello account is connected."

File diff suppressed because one or more lines are too long

View File

@@ -13,22 +13,22 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:121
#: src/views/card/components/Comment.tsx:123
msgid " (edited)"
msgstr " (editado)"
#: src/components/FeedbackButton.tsx:123
#: src/components/FeedbackModal.tsx:102
msgid ", or see our"
msgstr ", o consulta nuestra"
#. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:148
#: src/views/card/index.tsx:189
msgid "{0} | {1}"
msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:365
#: src/views/board/components/NewCardForm.tsx:392
msgid "{0} labels"
msgstr "{0} etiquetas"
@@ -36,10 +36,6 @@ msgstr "{0} etiquetas"
msgid "{boardCount, plural, one {Import board (1)} other {Import boards ({boardCount})}}"
msgstr "{boardCount, plural, one {Importar tablero (1)} other {Importar tableros ({boardCount})}}"
#: src/views/home/index.tsx:51
msgid "#1 Hacker News"
msgstr "#1 Hacker News"
#: src/views/home/components/Pricing.tsx:36
msgid "1 user"
msgstr "1 usuario"
@@ -52,8 +48,8 @@ msgstr "Una aplicación kanban potente y flexible que te ayuda a organizar el tr
msgid "Account deleted"
msgstr "Cuenta eliminada"
#: src/views/public/board/CardModal.tsx:104
#: src/views/card/index.tsx:215
#: src/views/public/board/CardModal.tsx:128
#: src/views/card/index.tsx:256
msgid "Activity"
msgstr "Actividad"
@@ -66,11 +62,11 @@ msgid "Add a card"
msgstr "Añadir una tarjeta"
#: src/views/card/components/NewCommentForm.tsx:57
#: src/views/card/components/Comment.tsx:144
#: src/views/card/components/Comment.tsx:146
msgid "Add a comment..."
msgstr "Añadir un comentario..."
#: src/components/Editor.tsx:302
#: src/components/Editor.tsx:303
msgid "Add description... (type '/' to open commands)"
msgstr "Añadir descripción... (escribe '/' para abrir comandos)"
@@ -79,7 +75,7 @@ msgstr "Añadir descripción... (escribe '/' para abrir comandos)"
msgid "Add label"
msgstr "Añadir etiqueta"
#: src/views/members/components/InviteMemberForm.tsx:50
#: src/views/members/components/InviteMemberForm.tsx:85
#: src/views/card/components/MemberSelector.tsx:130
msgid "Add member"
msgstr "Añadir miembro"
@@ -112,11 +108,11 @@ msgstr "Todos los sistemas operativos"
msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "¿Ya tienes una cuenta? <0><1>Iniciar sesión</1></0>"
#: src/views/settings/index.tsx:77
#: src/views/settings/index.tsx:100
msgid "An error occurred while disconnecting your Trello account."
msgstr "Ocurrió un error al desconectar tu cuenta de Trello."
#: src/views/settings/index.tsx:229
#: src/views/settings/index.tsx:257
msgid "API keys"
msgstr "Claves API"
@@ -149,6 +145,10 @@ msgstr "¿Estás seguro de que quieres eliminar esta tarjeta?"
msgid "Are you sure you want to delete this comment?"
msgstr "¿Estás seguro de que quieres eliminar este comentario?"
#: src/components/DeleteLabelConfirmation.tsx:39
msgid "Are you sure you want to delete this label?"
msgstr "¿Estás seguro de que quieres eliminar esta etiqueta?"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:54
msgid "Are you sure you want to delete your account?"
msgstr "¿Estás seguro de que quieres eliminar tu cuenta?"
@@ -169,12 +169,12 @@ msgstr "Pendientes"
msgid "Basic Kanban"
msgstr "Kanban básico"
#: src/views/settings/index.tsx:168
#: src/views/settings/index.tsx:196
#: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing"
msgstr "Facturación"
#: src/views/settings/index.tsx:178
#: src/views/settings/index.tsx:206
msgid "Billing portal"
msgstr "Portal de facturación"
@@ -182,7 +182,7 @@ msgstr "Portal de facturación"
msgid "Blog Post"
msgstr "Entrada de blog"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Board"
msgstr "Tablero"
@@ -194,7 +194,8 @@ msgstr "El nombre del tablero no puede exceder los 100 caracteres"
msgid "Board name is required"
msgstr "El nombre del tablero es obligatorio"
#: src/views/board/index.tsx:265
#: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358
msgid "Board not found"
msgstr "Tablero no encontrado"
@@ -206,7 +207,7 @@ msgstr "La URL del tablero solo puede contener letras, números y guiones"
msgid "Board URL cannot exceed 60 characters"
msgstr "La URL del tablero no puede exceder los 60 caracteres"
#: src/views/public/board/index.tsx:53
#: src/views/public/board/index.tsx:59
msgid "Board URL copied to clipboard"
msgstr "URL del tablero copiada al portapapeles"
@@ -222,13 +223,13 @@ msgstr "Visibilidad del tablero"
msgid "Board visibility updated"
msgstr "Visibilidad del tablero actualizada"
#: src/views/boards/index.tsx:25
#: src/components/SideNavigation.tsx:39
#: src/views/boards/index.tsx:27
#: src/components/SideNavigation.tsx:68
msgid "Boards"
msgstr "Tableros"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/boards/index.tsx:21
#: src/views/boards/index.tsx:23
msgid "Boards | {0}"
msgstr "Tableros | {0}"
@@ -250,19 +251,20 @@ msgstr "Informe de error"
#: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:156
#: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47
msgid "Cancel"
msgstr "Cancelar"
#: src/views/card/index.tsx:193
#: src/views/card/index.tsx:234
msgid "Card not found"
msgstr "Tarjeta no encontrada"
#: src/views/board/components/NewCardForm.tsx:254
#: src/views/board/components/NewCardForm.tsx:278
msgid "Card title"
msgstr "Título de la tarjeta"
#: src/views/settings/index.tsx:160
#: src/views/settings/index.tsx:188
msgid "Change the language of the app."
msgstr "Cambiar el idioma de la aplicación."
@@ -312,7 +314,7 @@ msgstr "Control y propiedad completos:"
msgid "Confirm URL change"
msgstr "Confirmar cambio de URL"
#: src/views/settings/index.tsx:205
#: src/views/settings/index.tsx:233
#: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello"
msgstr "Conectar Trello"
@@ -321,7 +323,7 @@ msgstr "Conectar Trello"
msgid "Connect your favorite tools to streamline your workflow."
msgstr "Conecta tus herramientas favoritas para agilizar tu flujo de trabajo."
#: src/views/settings/index.tsx:192
#: src/views/settings/index.tsx:220
msgid "Connect your Trello account to import boards."
msgstr "Conecta tu cuenta de Trello para importar tableros."
@@ -329,7 +331,7 @@ msgstr "Conecta tu cuenta de Trello para importar tableros."
msgid "Contact"
msgstr "Contacto"
#: src/components/FeedbackButton.tsx:121
#: src/components/FeedbackModal.tsx:100
msgid "Contact us"
msgstr "Contáctanos"
@@ -337,12 +339,12 @@ msgstr "Contáctanos"
msgid "Content Creation"
msgstr "Creación de contenido"
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Continue with "
msgstr "Continuar con "
#. placeholder {0}: provider.name
#: src/components/AuthForm.tsx:268
#: src/components/AuthForm.tsx:269
msgid "Continue with {0}"
msgstr "Continuar con {0}"
@@ -351,7 +353,7 @@ msgid "Control who can view and edit your boards."
msgstr "Controla quién puede ver y editar tus tableros."
#: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:391
#: src/views/board/components/NewCardForm.tsx:418
#: src/components/LabelForm.tsx:212
msgid "Create another"
msgstr "Crear otro"
@@ -360,15 +362,15 @@ msgstr "Crear otro"
msgid "Create board"
msgstr "Crear tablero"
#: src/views/board/components/NewCardForm.tsx:401
#: src/views/board/components/NewCardForm.tsx:428
msgid "Create card"
msgstr "Crear tarjeta"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Create label"
msgstr "Crear etiqueta"
#: src/views/board/components/NewListForm.tsx:148
#: src/views/board/components/NewListForm.tsx:152
msgid "Create list"
msgstr "Crear lista"
@@ -381,16 +383,16 @@ msgid "Create new key"
msgstr "Crear nueva clave"
#: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:327
#: src/views/board/components/NewCardForm.tsx:354
msgid "Create new label"
msgstr "Crear nueva etiqueta"
#: src/views/board/index.tsx:327
#: src/views/board/index.tsx:426
msgid "Create new list"
msgstr "Crear nueva lista"
#: src/components/WorkspaceMenu.tsx:85
#: src/components/NewWorkspaceForm.tsx:91
#: src/components/WorkspaceMenu.tsx:116
#: src/components/NewWorkspaceForm.tsx:93
msgid "Create workspace"
msgstr "Crear espacio de trabajo"
@@ -414,18 +416,19 @@ msgstr "Las URL personalizadas son una función premium. Serás dirigido a actua
msgid "Customer Support"
msgstr "Atención al cliente"
#: src/components/UserMenu.tsx:112
#: src/components/UserMenu.tsx:153
msgid "Dark"
msgstr "Oscuro"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226
#: src/components/DeleteLabelConfirmation.tsx:49
msgid "Delete"
msgstr "Eliminar"
#: src/views/settings/index.tsx:260
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:288
#: src/views/settings/index.tsx:298
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account"
msgstr "Eliminar cuenta"
@@ -438,7 +441,7 @@ msgstr "Eliminar tablero"
msgid "Delete card"
msgstr "Eliminar tarjeta"
#: src/views/card/components/Comment.tsx:89
#: src/views/card/components/Comment.tsx:91
msgid "Delete comment"
msgstr "Eliminar comentario"
@@ -446,8 +449,8 @@ msgstr "Eliminar comentario"
msgid "Delete list"
msgstr "Eliminar lista"
#: src/views/settings/index.tsx:242
#: src/views/settings/index.tsx:253
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:281
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace"
msgstr "Eliminar espacio de trabajo"
@@ -456,7 +459,7 @@ msgstr "Eliminar espacio de trabajo"
msgid "Design"
msgstr "Diseño"
#: src/views/settings/index.tsx:220
#: src/views/settings/index.tsx:248
msgid "Disconnect Trello"
msgstr "Desconectar Trello"
@@ -464,7 +467,7 @@ msgstr "Desconectar Trello"
msgid "Discuss and collaborate on cards."
msgstr "Discute y colabora en las tarjetas."
#: src/views/settings/index.tsx:123
#: src/views/settings/index.tsx:149
msgid "Display name"
msgstr "Nombre visible"
@@ -484,7 +487,7 @@ msgstr "Nombre visible actualizado"
msgid "Do you offer a free plan?"
msgstr "¿Ofrecen un plan gratuito?"
#: src/components/FeedbackButton.tsx:130
#: src/components/FeedbackModal.tsx:109
msgid "docs"
msgstr "documentos"
@@ -494,6 +497,7 @@ msgstr "Documentos"
#: src/views/home/components/Footer.tsx:77
#: src/views/boards/components/TemplateBoards.tsx:23
#: src/components/UserMenu.tsx:191
msgid "Documentation"
msgstr "Documentación"
@@ -513,7 +517,7 @@ msgstr "Terminado"
msgid "Edit board URL"
msgstr "Editar URL del tablero"
#: src/views/card/components/Comment.tsx:80
#: src/views/card/components/Comment.tsx:82
msgid "Edit comment"
msgstr "Editar comentario"
@@ -521,15 +525,19 @@ msgstr "Editar comentario"
msgid "Edit label"
msgstr "Editar etiqueta"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161
msgid "Edit workspace URL"
msgstr "Editar URL del espacio de trabajo"
#: src/views/boards/components/TemplateBoards.tsx:31
msgid "Editing"
msgstr "Editando"
#: src/components/AuthForm.tsx:336
#: src/components/AuthForm.tsx:337
msgid "email"
msgstr "correo electrónico"
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/InviteMemberForm.tsx:99
msgid "Email"
msgstr "Correo electrónico"
@@ -537,15 +545,15 @@ msgstr "Correo electrónico"
msgid "Enhancement"
msgstr "Mejora"
#: src/components/AuthForm.tsx:301
#: src/components/AuthForm.tsx:302
msgid "Enter your email address"
msgstr "Introduce tu dirección de correo electrónico"
#: src/components/AuthForm.tsx:289
#: src/components/AuthForm.tsx:290
msgid "Enter your name"
msgstr "Introduce tu nombre"
#: src/components/AuthForm.tsx:314
#: src/components/AuthForm.tsx:315
msgid "Enter your password"
msgstr "Introduce tu contraseña"
@@ -553,19 +561,28 @@ msgstr "Introduce tu contraseña"
msgid "Error deleting account"
msgstr "Error al eliminar la cuenta"
#: src/components/DeleteLabelConfirmation.tsx:22
msgid "Error deleting label"
msgstr "Error al eliminar la etiqueta"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:45
msgid "Error deleting workspace"
msgstr "Error al eliminar el espacio de trabajo"
#: src/views/settings/index.tsx:76
#: src/views/settings/index.tsx:99
msgid "Error disconnecting Trello"
msgstr "Error al desconectar Trello"
#: src/views/members/components/InviteMemberForm.tsx:57
#: src/views/members/components/InviteMemberForm.tsx:63
msgid "Error inviting member"
msgstr "Error al invitar al miembro"
#: src/views/settings/components/UpdateDisplayNameForm.tsx:54
msgid "Error updating display name"
msgstr "Error al actualizar el nombre visible"
#: src/views/settings/components/Avatar.tsx:37
#: src/views/settings/components/Avatar.tsx:39
msgid "Error updating profile image"
msgstr "Error al actualizar la imagen de perfil"
@@ -581,8 +598,8 @@ msgstr "Error al actualizar el nombre del espacio de trabajo"
msgid "Error updating workspace URL"
msgstr "Error al actualizar la URL del espacio de trabajo"
#: src/views/settings/components/Avatar.tsx:54
#: src/views/settings/components/Avatar.tsx:95
#: src/views/settings/components/Avatar.tsx:56
#: src/views/settings/components/Avatar.tsx:97
msgid "Error uploading profile image"
msgstr "Error al subir la imagen de perfil"
@@ -622,11 +639,12 @@ msgstr "Solicitud de función"
msgid "Features"
msgstr "Características"
#: src/components/FeedbackButton.tsx:78
#: src/components/UserMenu.tsx:199
#: src/components/FeedbackModal.tsx:59
msgid "Feedback"
msgstr "Comentarios"
#: src/components/FeedbackButton.tsx:38
#: src/components/FeedbackModal.tsx:33
msgid "Feedback sent"
msgstr "Comentarios enviados"
@@ -674,7 +692,7 @@ msgstr "Comenzar"
msgid "Get started by creating a new board"
msgstr "Comienza creando un nuevo tablero"
#: src/views/board/index.tsx:319
#: src/views/board/index.tsx:418
msgid "Get started by creating a new list"
msgstr "Comienza creando una nueva lista"
@@ -747,11 +765,11 @@ msgstr "Reconozco que todos los datos del espacio de trabajo serán eliminados p
msgid "Ideas"
msgstr "Ideas"
#: src/components/FeedbackButton.tsx:98
#: src/components/FeedbackModal.tsx:75
msgid "Ideas to improve this page..."
msgstr "Ideas para mejorar esta página..."
#: src/views/boards/index.tsx:39
#: src/views/boards/index.tsx:38
msgid "Import"
msgstr "Importar"
@@ -797,11 +815,19 @@ msgstr "Integraciones"
msgid "Interviewing"
msgstr "Entrevistando"
#: src/views/members/index.tsx:156
#: src/views/members/components/InviteMemberForm.tsx:26
msgid "Invalid email address"
msgstr "Dirección de correo electrónico no válida"
#: src/views/members/index.tsx:169
msgid "Invite"
msgstr "Invitar"
#: src/views/members/components/InviteMemberForm.tsx:82
#: src/views/members/components/InviteMemberForm.tsx:113
msgid "Invite another"
msgstr "Invitar a otro"
#: src/views/members/components/InviteMemberForm.tsx:123
#: src/views/card/components/MemberSelector.tsx:112
msgid "Invite member"
msgstr "Invitar miembro"
@@ -823,8 +849,8 @@ msgstr "Kanban reinventado"
msgid "Keep in mind that this action is irreversible."
msgstr "Ten en cuenta que esta acción es irreversible."
#: src/views/card/index.tsx:243
#: src/views/board/components/NewCardForm.tsx:331
#: src/views/card/index.tsx:113
#: src/views/board/components/NewCardForm.tsx:358
#: src/views/board/components/Filters.tsx:101
msgid "Labels"
msgstr "Etiquetas"
@@ -833,7 +859,7 @@ msgstr "Etiquetas"
msgid "Labels & Filters"
msgstr "Etiquetas y filtros"
#: src/views/settings/index.tsx:157
#: src/views/settings/index.tsx:185
msgid "Language"
msgstr "Idioma"
@@ -849,15 +875,15 @@ msgstr "Legal"
msgid "License"
msgstr "Licencia"
#: src/components/UserMenu.tsx:126
#: src/components/UserMenu.tsx:167
msgid "Light"
msgstr "Claro"
#: src/views/public/board/index.tsx:51
#: src/views/public/board/index.tsx:57
msgid "Link copied"
msgstr "Enlace copiado"
#: src/views/card/index.tsx:235
#: src/views/card/index.tsx:105
msgid "List"
msgstr "Lista"
@@ -869,7 +895,7 @@ msgstr "Nombre de la lista"
msgid "Login | kan.bn"
msgstr "Iniciar sesión | kan.bn"
#: src/components/UserMenu.tsx:136
#: src/components/UserMenu.tsx:209
msgid "Logout"
msgstr "Cerrar sesión"
@@ -881,7 +907,7 @@ msgstr "Largo plazo"
msgid "Low Priority"
msgstr "Prioridad baja"
#: src/components/AuthForm.tsx:337
#: src/components/AuthForm.tsx:338
msgid "magic link"
msgstr "enlace mágico"
@@ -889,16 +915,16 @@ msgstr "enlace mágico"
msgid "Medium Priority"
msgstr "Prioridad media"
#: src/views/members/index.tsx:148
#: src/views/card/index.tsx:251
#: src/views/board/components/NewCardForm.tsx:290
#: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121
#: src/views/board/components/NewCardForm.tsx:317
#: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:44
#: src/components/SideNavigation.tsx:73
msgid "Members"
msgstr "Miembros"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/members/index.tsx:144
#: src/views/members/index.tsx:157
msgid "Members | {0}"
msgstr "Miembros | {0}"
@@ -919,11 +945,11 @@ msgstr "movió la tarjeta a otra lista"
msgid "Name"
msgstr "Nombre"
#: src/components/FeedbackButton.tsx:116
#: src/components/FeedbackModal.tsx:95
msgid "Need help?"
msgstr "¿Necesitas ayuda?"
#: src/views/boards/index.tsx:52
#: src/views/boards/index.tsx:48
msgid "New"
msgstr "Nuevo"
@@ -931,7 +957,7 @@ msgstr "Nuevo"
msgid "New board"
msgstr "Nuevo tablero"
#: src/views/board/components/NewCardForm.tsx:237
#: src/views/board/components/NewCardForm.tsx:261
msgid "New card"
msgstr "Nueva tarjeta"
@@ -943,7 +969,7 @@ msgstr "Nueva importación"
msgid "New label"
msgstr "Nueva etiqueta"
#: src/views/board/index.tsx:296
#: src/views/board/index.tsx:395
#: src/views/board/components/NewListForm.tsx:112
msgid "New list"
msgstr "Nueva lista"
@@ -952,7 +978,7 @@ msgstr "Nueva lista"
msgid "New Ticket"
msgstr "Nuevo ticket"
#: src/components/NewWorkspaceForm.tsx:62
#: src/components/NewWorkspaceForm.tsx:64
msgid "New workspace"
msgstr "Nuevo espacio de trabajo"
@@ -976,7 +1002,7 @@ msgstr "No se encontraron tableros"
msgid "No credit card required"
msgstr "No se requiere tarjeta de crédito"
#: src/views/board/index.tsx:316
#: src/views/board/index.tsx:415
msgid "No lists"
msgstr "Sin listas"
@@ -988,15 +1014,15 @@ msgstr "Oferta"
msgid "Onboarding"
msgstr "Incorporación"
#: src/views/settings/index.tsx:263
#: src/views/settings/index.tsx:291
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."
#: src/views/settings/index.tsx:245
#: src/views/settings/index.tsx:273
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."
#: src/components/AuthForm.tsx:279
#: src/components/AuthForm.tsx:280
msgid "or"
msgstr "o"
@@ -1016,7 +1042,7 @@ msgstr "Tiempo parcial"
msgid "Payment frequency"
msgstr "Frecuencia de pago"
#: src/views/members/index.tsx:107
#: src/views/members/index.tsx:118
msgid "Pending"
msgstr "Pendiente"
@@ -1033,19 +1059,19 @@ msgstr "Proyecto personal"
msgid "Planning"
msgstr "Planificación"
#: src/components/AuthForm.tsx:305
#: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address"
msgstr "Por favor, introduce una dirección de correo electrónico válida"
#: src/components/AuthForm.tsx:293
#: src/components/AuthForm.tsx:294
msgid "Please enter a valid name"
msgstr "Por favor, introduce un nombre válido"
#: src/components/AuthForm.tsx:318
#: src/components/AuthForm.tsx:319
msgid "Please enter a valid password"
msgstr "Por favor, introduce una contraseña válida"
#: src/views/settings/components/Avatar.tsx:55
#: src/views/settings/components/Avatar.tsx:57
msgid "Please select a file to upload."
msgstr "Por favor selecciona un archivo para subir."
@@ -1055,26 +1081,28 @@ msgstr "Por favor selecciona un archivo para subir."
#: src/views/settings/components/UpdateDisplayNameForm.tsx:55
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:46
#: src/views/settings/components/DeleteAccountConfirmation.tsx:40
#: src/views/settings/components/Avatar.tsx:38
#: src/views/settings/components/Avatar.tsx:96
#: src/views/settings/components/Avatar.tsx:40
#: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:116
#: src/views/card/index.tsx:159
#: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:62
#: src/views/card/components/Comment.tsx:64
#: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:133
#: src/views/board/index.tsx:189
#: src/views/board/index.tsx:135
#: src/views/board/index.tsx:191
#: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:128
#: src/components/NewWorkspaceForm.tsx:39
#: src/components/FeedbackButton.tsx:46
#: src/views/board/components/NewCardForm.tsx:145
#: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23
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."
@@ -1096,11 +1124,11 @@ msgstr "Política de privacidad"
msgid "Private"
msgstr "Privado"
#: src/views/settings/components/Avatar.tsx:24
#: src/views/settings/components/Avatar.tsx:26
msgid "Profile image updated"
msgstr "Imagen de perfil actualizada"
#: src/views/settings/index.tsx:118
#: src/views/settings/index.tsx:144
msgid "Profile picture"
msgstr "Foto de perfil"
@@ -1136,7 +1164,7 @@ msgstr "Remoto"
msgid "Remove"
msgstr "Eliminar"
#: src/views/members/index.tsx:120
#: src/views/members/index.tsx:132
msgid "Remove member"
msgstr "Eliminar miembro"
@@ -1177,7 +1205,7 @@ msgstr "Revocar"
msgid "Roadmap"
msgstr "Hoja de ruta"
#: src/views/members/index.tsx:178
#: src/views/members/index.tsx:191
msgid "Role"
msgstr "Rol"
@@ -1185,7 +1213,7 @@ msgstr "Rol"
msgid "Run on your own infrastructure"
msgstr "Ejecuta en tu propia infraestructura"
#: src/views/card/components/Comment.tsx:163
#: src/views/card/components/Comment.tsx:165
msgid "Save"
msgstr "Guardar"
@@ -1217,21 +1245,21 @@ msgstr "Autoalojamiento con Github"
msgid "self-assigned the card"
msgstr "se autoasignó la tarjeta"
#: src/components/FeedbackButton.tsx:137
msgid "Send"
msgstr "Enviar"
#: src/components/FeedbackModal.tsx:116
msgid "Send feedback"
msgstr "Enviar comentarios"
#: src/views/boards/components/TemplateBoards.tsx:69
msgid "Senior"
msgstr "Senior"
#: src/views/settings/index.tsx:112
#: src/components/SideNavigation.tsx:49
#: src/views/settings/index.tsx:138
#: src/components/SideNavigation.tsx:78
msgid "Settings"
msgstr "Configuración"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:108
#: src/views/settings/index.tsx:134
msgid "Settings | {0}"
msgstr "Configuración | {0}"
@@ -1253,7 +1281,7 @@ msgstr "Registro deshabilitado"
msgid "Sign up is currently disabled. Please try again later."
msgstr "El registro está actualmente deshabilitado. Por favor, inténtalo de nuevo más tarde."
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Sign up with "
msgstr "Registrarse con "
@@ -1282,11 +1310,15 @@ msgstr "Estrella en Github"
msgid "Success"
msgstr "Éxito"
#: src/components/UserMenu.tsx:180
msgid "Support"
msgstr "Soporte"
#: src/views/home/components/Pricing.tsx:57
msgid "Support the development of the project"
msgstr "Apoya el desarrollo del proyecto"
#: src/components/UserMenu.tsx:98
#: src/components/UserMenu.tsx:139
msgid "System"
msgstr "Sistema"
@@ -1302,7 +1334,7 @@ msgstr "Plantillas"
msgid "Terms of service"
msgstr "Términos de servicio"
#: src/components/FeedbackButton.tsx:39
#: src/components/FeedbackModal.tsx:34
msgid "Thank you for your feedback!"
msgstr "¡Gracias por tus comentarios!"
@@ -1319,7 +1351,7 @@ msgstr "La alternativa de código abierto <0/> a Trello"
msgid "The visibility of your board has been set to {0}."
msgstr "La visibilidad de tu tablero ha sido establecida a {0}."
#: src/components/UserMenu.tsx:85
#: src/components/UserMenu.tsx:126
msgid "Theme"
msgstr "Tema"
@@ -1329,9 +1361,14 @@ msgstr "No podrán acceder a este espacio de trabajo."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42
msgid "This action can't be undone."
msgstr "Esta acción no se puede deshacer."
#: src/views/public/board/index.tsx:146
msgid "This board is private or does not exist"
msgstr "Este tablero es privado o no existe"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135
msgid "This board URL has already been taken"
msgstr "Esta URL de tablero ya ha sido utilizada"
@@ -1361,7 +1398,7 @@ msgstr "Alternar menú"
msgid "Track all card changes with detailed activity history."
msgstr "Rastrea todos los cambios en las tarjetas con un historial de actividad detallado."
#: src/views/settings/index.tsx:69
#: src/views/settings/index.tsx:92
msgid "Trello disconnected"
msgstr "Trello desconectado"
@@ -1377,7 +1414,7 @@ msgstr "Clasificación"
msgid "Unable to add comment"
msgstr "No se puede añadir el comentario"
#: src/views/board/components/NewCardForm.tsx:125
#: src/views/board/components/NewCardForm.tsx:142
msgid "Unable to create card"
msgstr "No se puede crear la tarjeta"
@@ -1385,7 +1422,7 @@ msgstr "No se puede crear la tarjeta"
msgid "Unable to create list"
msgstr "No se puede crear la lista"
#: src/components/NewWorkspaceForm.tsx:38
#: src/components/NewWorkspaceForm.tsx:40
msgid "Unable to create workspace"
msgstr "No se puede crear el espacio de trabajo"
@@ -1401,7 +1438,7 @@ msgstr "No se puede eliminar el comentario"
msgid "Unable to remove member"
msgstr "No se puede eliminar al miembro"
#: src/components/FeedbackButton.tsx:45
#: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback"
msgstr "No se pudieron enviar los comentarios"
@@ -1413,12 +1450,12 @@ msgstr "No se puede actualizar la URL del tablero"
msgid "Unable to update board visibility"
msgstr "No se puede actualizar la visibilidad del tablero"
#: src/views/card/index.tsx:115
#: src/views/board/index.tsx:188
#: src/views/card/index.tsx:158
#: src/views/board/index.tsx:190
msgid "Unable to update card"
msgstr "No se puede actualizar la tarjeta"
#: src/views/card/components/Comment.tsx:61
#: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment"
msgstr "No se puede actualizar el comentario"
@@ -1427,7 +1464,7 @@ msgid "Unable to update labels"
msgstr "No se pueden actualizar las etiquetas"
#: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:132
#: src/views/board/index.tsx:134
msgid "Unable to update list"
msgstr "No se puede actualizar la lista"
@@ -1471,11 +1508,11 @@ msgstr "Listas ilimitadas"
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:82
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:90
#: src/views/settings/components/UpdateDisplayNameForm.tsx:79
#: src/views/board/components/UpdateBoardSlugForm.tsx:166
#: src/views/board/components/UpdateBoardSlugForm.tsx:174
msgid "Update"
msgstr "Actualizar"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Update label"
msgstr "Actualizar etiqueta"
@@ -1516,19 +1553,23 @@ msgstr "La URL debe tener al menos 3 caracteres"
msgid "Use template"
msgstr "Usar plantilla"
#: src/views/members/index.tsx:172
#: src/views/members/index.tsx:185
msgid "User"
msgstr "Usuario"
#: src/views/members/components/InviteMemberForm.tsx:58
msgid "User is already a member of this workspace"
msgstr "El usuario ya es miembro de este espacio de trabajo"
#: src/views/boards/components/TemplateBoards.tsx:37
msgid "Video"
msgstr "Video"
#: src/views/settings/index.tsx:232
#: src/views/settings/index.tsx:260
msgid "View and manage your API keys."
msgstr "Ver y gestionar tus claves API."
#: src/views/settings/index.tsx:171
#: src/views/settings/index.tsx:199
msgid "View and manage your billing and subscription."
msgstr "Ver y gestionar tu facturación y suscripción."
@@ -1536,10 +1577,18 @@ msgstr "Ver y gestionar tu facturación y suscripción."
msgid "View docs"
msgstr "Ver documentación"
#: src/views/public/board/index.tsx:120
msgid "View only"
msgstr "Solo visualización"
#: src/views/home/components/Features.tsx:147
msgid "View our roadmap."
msgstr "Ver nuestra hoja de ruta."
#: src/views/public/board/index.tsx:149
msgid "View workspace"
msgstr "Ver espacio de trabajo"
#: src/views/board/components/VisibilityButton.tsx:91
msgid "Visibility"
msgstr "Visibilidad"
@@ -1572,7 +1621,7 @@ msgstr "Cuando Trello se lanzó en 2011, impresionó a todos con su simplicidad
msgid "Why make an open source Trello?"
msgstr "¿Por qué crear un Trello de código abierto?"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Workspace"
msgstr "Espacio de trabajo"
@@ -1580,7 +1629,7 @@ msgstr "Espacio de trabajo"
msgid "Workspace deleted"
msgstr "Espacio de trabajo eliminado"
#: src/views/settings/index.tsx:147
#: src/views/settings/index.tsx:175
msgid "Workspace description"
msgstr "Descripción del espacio de trabajo"
@@ -1601,8 +1650,8 @@ msgstr "Descripción del espacio de trabajo actualizada"
msgid "Workspace members"
msgstr "Miembros del espacio de trabajo"
#: src/views/settings/index.tsx:130
#: src/components/NewWorkspaceForm.tsx:78
#: src/views/settings/index.tsx:156
#: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name"
msgstr "Nombre del espacio de trabajo"
@@ -1622,7 +1671,7 @@ msgstr "Nombre del espacio de trabajo actualizado"
msgid "Workspace slug updated"
msgstr "Slug del espacio de trabajo actualizado"
#: src/views/settings/index.tsx:138
#: src/views/settings/index.tsx:165
msgid "Workspace URL"
msgstr "URL del espacio de trabajo"
@@ -1670,15 +1719,15 @@ msgstr "Tus tableros han sido importados."
msgid "Your display name has been updated."
msgstr "Tu nombre de visualización ha sido actualizado."
#: src/views/settings/components/Avatar.tsx:25
#: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated."
msgstr "Tu imagen de perfil ha sido actualizada."
#: src/views/settings/index.tsx:70
#: src/views/settings/index.tsx:93
msgid "Your Trello account has been disconnected."
msgstr "Tu cuenta de Trello ha sido desconectada."
#: src/views/settings/index.tsx:214
#: src/views/settings/index.tsx:242
msgid "Your Trello account is connected."
msgstr "Tu cuenta de Trello está conectada."

File diff suppressed because one or more lines are too long

View File

@@ -13,22 +13,22 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:121
#: src/views/card/components/Comment.tsx:123
msgid " (edited)"
msgstr " (modifié)"
#: src/components/FeedbackButton.tsx:123
#: src/components/FeedbackModal.tsx:102
msgid ", or see our"
msgstr ", ou consultez notre"
#. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:148
#: src/views/card/index.tsx:189
msgid "{0} | {1}"
msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:365
#: src/views/board/components/NewCardForm.tsx:392
msgid "{0} labels"
msgstr "{0} étiquettes"
@@ -36,10 +36,6 @@ msgstr "{0} étiquettes"
msgid "{boardCount, plural, one {Import board (1)} other {Import boards ({boardCount})}}"
msgstr "{boardCount, plural, one {Importer le tableau (1)} other {Importer les tableaux ({boardCount})}}"
#: src/views/home/index.tsx:51
msgid "#1 Hacker News"
msgstr "#1 Hacker News"
#: src/views/home/components/Pricing.tsx:36
msgid "1 user"
msgstr "1 utilisateur"
@@ -52,8 +48,8 @@ msgstr "Une application kanban puissante et flexible qui vous aide à organiser
msgid "Account deleted"
msgstr "Compte supprimé"
#: src/views/public/board/CardModal.tsx:104
#: src/views/card/index.tsx:215
#: src/views/public/board/CardModal.tsx:128
#: src/views/card/index.tsx:256
msgid "Activity"
msgstr "Activité"
@@ -66,11 +62,11 @@ msgid "Add a card"
msgstr "Ajouter une carte"
#: src/views/card/components/NewCommentForm.tsx:57
#: src/views/card/components/Comment.tsx:144
#: src/views/card/components/Comment.tsx:146
msgid "Add a comment..."
msgstr "Ajouter un commentaire..."
#: src/components/Editor.tsx:302
#: src/components/Editor.tsx:303
msgid "Add description... (type '/' to open commands)"
msgstr "Ajouter une description... (tapez '/' pour ouvrir les commandes)"
@@ -79,7 +75,7 @@ msgstr "Ajouter une description... (tapez '/' pour ouvrir les commandes)"
msgid "Add label"
msgstr "Ajouter une étiquette"
#: src/views/members/components/InviteMemberForm.tsx:50
#: src/views/members/components/InviteMemberForm.tsx:85
#: src/views/card/components/MemberSelector.tsx:130
msgid "Add member"
msgstr "Ajouter un membre"
@@ -112,11 +108,11 @@ msgstr "Tous les systèmes opérationnels"
msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "Vous avez déjà un compte ? <0><1>Connectez-vous</1></0>"
#: src/views/settings/index.tsx:77
#: src/views/settings/index.tsx:100
msgid "An error occurred while disconnecting your Trello account."
msgstr "Une erreur s'est produite lors de la déconnexion de votre compte Trello."
#: src/views/settings/index.tsx:229
#: src/views/settings/index.tsx:257
msgid "API keys"
msgstr "Clés API"
@@ -149,6 +145,10 @@ msgstr "Êtes-vous sûr de vouloir supprimer cette carte ?"
msgid "Are you sure you want to delete this comment?"
msgstr "Êtes-vous sûr de vouloir supprimer ce commentaire ?"
#: src/components/DeleteLabelConfirmation.tsx:39
msgid "Are you sure you want to delete this label?"
msgstr "Êtes-vous sûr de vouloir supprimer cette étiquette ?"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:54
msgid "Are you sure you want to delete your account?"
msgstr "Êtes-vous sûr de vouloir supprimer votre compte ?"
@@ -169,12 +169,12 @@ msgstr "Backlog"
msgid "Basic Kanban"
msgstr "Kanban basique"
#: src/views/settings/index.tsx:168
#: src/views/settings/index.tsx:196
#: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing"
msgstr "Facturation"
#: src/views/settings/index.tsx:178
#: src/views/settings/index.tsx:206
msgid "Billing portal"
msgstr "Portail de facturation"
@@ -182,7 +182,7 @@ msgstr "Portail de facturation"
msgid "Blog Post"
msgstr "Article de blog"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Board"
msgstr "Tableau"
@@ -194,7 +194,8 @@ msgstr "Le nom du tableau ne peut pas dépasser 100 caractères"
msgid "Board name is required"
msgstr "Le nom du tableau est requis"
#: src/views/board/index.tsx:265
#: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358
msgid "Board not found"
msgstr "Tableau introuvable"
@@ -206,7 +207,7 @@ msgstr "L'URL du tableau ne peut contenir que des lettres, des chiffres et des t
msgid "Board URL cannot exceed 60 characters"
msgstr "L'URL du tableau ne peut pas dépasser 60 caractères"
#: src/views/public/board/index.tsx:53
#: src/views/public/board/index.tsx:59
msgid "Board URL copied to clipboard"
msgstr "URL du tableau copiée dans le presse-papiers"
@@ -222,13 +223,13 @@ msgstr "Visibilité du tableau"
msgid "Board visibility updated"
msgstr "Visibilité du tableau mise à jour"
#: src/views/boards/index.tsx:25
#: src/components/SideNavigation.tsx:39
#: src/views/boards/index.tsx:27
#: src/components/SideNavigation.tsx:68
msgid "Boards"
msgstr "Tableaux"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/boards/index.tsx:21
#: src/views/boards/index.tsx:23
msgid "Boards | {0}"
msgstr "Tableaux | {0}"
@@ -250,19 +251,20 @@ msgstr "Rapport de bug"
#: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:156
#: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47
msgid "Cancel"
msgstr "Annuler"
#: src/views/card/index.tsx:193
#: src/views/card/index.tsx:234
msgid "Card not found"
msgstr "Carte introuvable"
#: src/views/board/components/NewCardForm.tsx:254
#: src/views/board/components/NewCardForm.tsx:278
msgid "Card title"
msgstr "Titre de la carte"
#: src/views/settings/index.tsx:160
#: src/views/settings/index.tsx:188
msgid "Change the language of the app."
msgstr "Changer la langue de l'application."
@@ -312,7 +314,7 @@ msgstr "Contrôle et propriété complets :"
msgid "Confirm URL change"
msgstr "Confirmer le changement d'URL"
#: src/views/settings/index.tsx:205
#: src/views/settings/index.tsx:233
#: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello"
msgstr "Connecter Trello"
@@ -321,7 +323,7 @@ msgstr "Connecter Trello"
msgid "Connect your favorite tools to streamline your workflow."
msgstr "Connectez vos outils favoris pour simplifier votre flux de travail."
#: src/views/settings/index.tsx:192
#: src/views/settings/index.tsx:220
msgid "Connect your Trello account to import boards."
msgstr "Connectez votre compte Trello pour importer des tableaux."
@@ -329,7 +331,7 @@ msgstr "Connectez votre compte Trello pour importer des tableaux."
msgid "Contact"
msgstr "Contact"
#: src/components/FeedbackButton.tsx:121
#: src/components/FeedbackModal.tsx:100
msgid "Contact us"
msgstr "Contactez-nous"
@@ -337,12 +339,12 @@ msgstr "Contactez-nous"
msgid "Content Creation"
msgstr "Création de contenu"
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Continue with "
msgstr "Continuer avec "
#. placeholder {0}: provider.name
#: src/components/AuthForm.tsx:268
#: src/components/AuthForm.tsx:269
msgid "Continue with {0}"
msgstr "Continuer avec {0}"
@@ -351,7 +353,7 @@ msgid "Control who can view and edit your boards."
msgstr "Contrôlez qui peut voir et modifier vos tableaux."
#: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:391
#: src/views/board/components/NewCardForm.tsx:418
#: src/components/LabelForm.tsx:212
msgid "Create another"
msgstr "Créer un autre"
@@ -360,15 +362,15 @@ msgstr "Créer un autre"
msgid "Create board"
msgstr "Créer un tableau"
#: src/views/board/components/NewCardForm.tsx:401
#: src/views/board/components/NewCardForm.tsx:428
msgid "Create card"
msgstr "Créer une carte"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Create label"
msgstr "Créer une étiquette"
#: src/views/board/components/NewListForm.tsx:148
#: src/views/board/components/NewListForm.tsx:152
msgid "Create list"
msgstr "Créer une liste"
@@ -381,16 +383,16 @@ msgid "Create new key"
msgstr "Créer une nouvelle clé"
#: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:327
#: src/views/board/components/NewCardForm.tsx:354
msgid "Create new label"
msgstr "Créer une nouvelle étiquette"
#: src/views/board/index.tsx:327
#: src/views/board/index.tsx:426
msgid "Create new list"
msgstr "Créer une nouvelle liste"
#: src/components/WorkspaceMenu.tsx:85
#: src/components/NewWorkspaceForm.tsx:91
#: src/components/WorkspaceMenu.tsx:116
#: src/components/NewWorkspaceForm.tsx:93
msgid "Create workspace"
msgstr "Créer un espace de travail"
@@ -414,18 +416,19 @@ msgstr "Les URL personnalisées sont une fonctionnalité premium. Vous serez dir
msgid "Customer Support"
msgstr "Support client"
#: src/components/UserMenu.tsx:112
#: src/components/UserMenu.tsx:153
msgid "Dark"
msgstr "Sombre"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226
#: src/components/DeleteLabelConfirmation.tsx:49
msgid "Delete"
msgstr "Supprimer"
#: src/views/settings/index.tsx:260
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:288
#: src/views/settings/index.tsx:298
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account"
msgstr "Supprimer le compte"
@@ -438,7 +441,7 @@ msgstr "Supprimer le tableau"
msgid "Delete card"
msgstr "Supprimer la carte"
#: src/views/card/components/Comment.tsx:89
#: src/views/card/components/Comment.tsx:91
msgid "Delete comment"
msgstr "Supprimer le commentaire"
@@ -446,8 +449,8 @@ msgstr "Supprimer le commentaire"
msgid "Delete list"
msgstr "Supprimer la liste"
#: src/views/settings/index.tsx:242
#: src/views/settings/index.tsx:253
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:281
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace"
msgstr "Supprimer l'espace de travail"
@@ -456,7 +459,7 @@ msgstr "Supprimer l'espace de travail"
msgid "Design"
msgstr "Design"
#: src/views/settings/index.tsx:220
#: src/views/settings/index.tsx:248
msgid "Disconnect Trello"
msgstr "Déconnecter Trello"
@@ -464,7 +467,7 @@ msgstr "Déconnecter Trello"
msgid "Discuss and collaborate on cards."
msgstr "Discutez et collaborez sur les cartes."
#: src/views/settings/index.tsx:123
#: src/views/settings/index.tsx:149
msgid "Display name"
msgstr "Nom d'affichage"
@@ -484,7 +487,7 @@ msgstr "Nom d'affichage mis à jour"
msgid "Do you offer a free plan?"
msgstr "Proposez-vous un plan gratuit ?"
#: src/components/FeedbackButton.tsx:130
#: src/components/FeedbackModal.tsx:109
msgid "docs"
msgstr "documentation"
@@ -494,6 +497,7 @@ msgstr "Documentation"
#: src/views/home/components/Footer.tsx:77
#: src/views/boards/components/TemplateBoards.tsx:23
#: src/components/UserMenu.tsx:191
msgid "Documentation"
msgstr "Documentation"
@@ -513,7 +517,7 @@ msgstr "Fait"
msgid "Edit board URL"
msgstr "Modifier l'URL du tableau"
#: src/views/card/components/Comment.tsx:80
#: src/views/card/components/Comment.tsx:82
msgid "Edit comment"
msgstr "Modifier le commentaire"
@@ -521,15 +525,19 @@ msgstr "Modifier le commentaire"
msgid "Edit label"
msgstr "Modifier l'étiquette"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161
msgid "Edit workspace URL"
msgstr "Modifier l'URL de l'espace de travail"
#: src/views/boards/components/TemplateBoards.tsx:31
msgid "Editing"
msgstr "Édition"
#: src/components/AuthForm.tsx:336
#: src/components/AuthForm.tsx:337
msgid "email"
msgstr "e-mail"
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/InviteMemberForm.tsx:99
msgid "Email"
msgstr "E-mail"
@@ -537,15 +545,15 @@ msgstr "E-mail"
msgid "Enhancement"
msgstr "Amélioration"
#: src/components/AuthForm.tsx:301
#: src/components/AuthForm.tsx:302
msgid "Enter your email address"
msgstr "Saisissez votre adresse e-mail"
#: src/components/AuthForm.tsx:289
#: src/components/AuthForm.tsx:290
msgid "Enter your name"
msgstr "Saisissez votre nom"
#: src/components/AuthForm.tsx:314
#: src/components/AuthForm.tsx:315
msgid "Enter your password"
msgstr "Saisissez votre mot de passe"
@@ -553,19 +561,28 @@ msgstr "Saisissez votre mot de passe"
msgid "Error deleting account"
msgstr "Erreur lors de la suppression du compte"
#: src/components/DeleteLabelConfirmation.tsx:22
msgid "Error deleting label"
msgstr "Erreur lors de la suppression de l'étiquette"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:45
msgid "Error deleting workspace"
msgstr "Erreur lors de la suppression de l'espace de travail"
#: src/views/settings/index.tsx:76
#: src/views/settings/index.tsx:99
msgid "Error disconnecting Trello"
msgstr "Erreur lors de la déconnexion de Trello"
#: src/views/members/components/InviteMemberForm.tsx:57
#: src/views/members/components/InviteMemberForm.tsx:63
msgid "Error inviting member"
msgstr "Erreur lors de l'invitation du membre"
#: src/views/settings/components/UpdateDisplayNameForm.tsx:54
msgid "Error updating display name"
msgstr "Erreur lors de la mise à jour du nom d'affichage"
#: src/views/settings/components/Avatar.tsx:37
#: src/views/settings/components/Avatar.tsx:39
msgid "Error updating profile image"
msgstr "Erreur lors de la mise à jour de l'image de profil"
@@ -581,8 +598,8 @@ msgstr "Erreur lors de la mise à jour du nom de l'espace de travail"
msgid "Error updating workspace URL"
msgstr "Erreur lors de la mise à jour de l'URL de l'espace de travail"
#: src/views/settings/components/Avatar.tsx:54
#: src/views/settings/components/Avatar.tsx:95
#: src/views/settings/components/Avatar.tsx:56
#: src/views/settings/components/Avatar.tsx:97
msgid "Error uploading profile image"
msgstr "Erreur lors du téléchargement de l'image de profil"
@@ -622,11 +639,12 @@ msgstr "Demande de fonctionnalité"
msgid "Features"
msgstr "Fonctionnalités"
#: src/components/FeedbackButton.tsx:78
#: src/components/UserMenu.tsx:199
#: src/components/FeedbackModal.tsx:59
msgid "Feedback"
msgstr "Commentaires"
#: src/components/FeedbackButton.tsx:38
#: src/components/FeedbackModal.tsx:33
msgid "Feedback sent"
msgstr "Commentaires envoyés"
@@ -674,7 +692,7 @@ msgstr "Commencer"
msgid "Get started by creating a new board"
msgstr "Commencez par créer un nouveau tableau"
#: src/views/board/index.tsx:319
#: src/views/board/index.tsx:418
msgid "Get started by creating a new list"
msgstr "Commencez par créer une nouvelle liste"
@@ -747,11 +765,11 @@ msgstr "Je reconnais que toutes les données de l'espace de travail seront défi
msgid "Ideas"
msgstr "Idées"
#: src/components/FeedbackButton.tsx:98
#: src/components/FeedbackModal.tsx:75
msgid "Ideas to improve this page..."
msgstr "Idées pour améliorer cette page..."
#: src/views/boards/index.tsx:39
#: src/views/boards/index.tsx:38
msgid "Import"
msgstr "Importer"
@@ -797,11 +815,19 @@ msgstr "Intégrations"
msgid "Interviewing"
msgstr "Entretien"
#: src/views/members/index.tsx:156
#: src/views/members/components/InviteMemberForm.tsx:26
msgid "Invalid email address"
msgstr "Adresse e-mail invalide"
#: src/views/members/index.tsx:169
msgid "Invite"
msgstr "Inviter"
#: src/views/members/components/InviteMemberForm.tsx:82
#: src/views/members/components/InviteMemberForm.tsx:113
msgid "Invite another"
msgstr "Inviter un autre"
#: src/views/members/components/InviteMemberForm.tsx:123
#: src/views/card/components/MemberSelector.tsx:112
msgid "Invite member"
msgstr "Inviter un membre"
@@ -823,8 +849,8 @@ msgstr "Kanban réinventé"
msgid "Keep in mind that this action is irreversible."
msgstr "Gardez à l'esprit que cette action est irréversible."
#: src/views/card/index.tsx:243
#: src/views/board/components/NewCardForm.tsx:331
#: src/views/card/index.tsx:113
#: src/views/board/components/NewCardForm.tsx:358
#: src/views/board/components/Filters.tsx:101
msgid "Labels"
msgstr "Étiquettes"
@@ -833,7 +859,7 @@ msgstr "Étiquettes"
msgid "Labels & Filters"
msgstr "Étiquettes & filtres"
#: src/views/settings/index.tsx:157
#: src/views/settings/index.tsx:185
msgid "Language"
msgstr "Langue"
@@ -849,15 +875,15 @@ msgstr "Mentions légales"
msgid "License"
msgstr "Licence"
#: src/components/UserMenu.tsx:126
#: src/components/UserMenu.tsx:167
msgid "Light"
msgstr "Clair"
#: src/views/public/board/index.tsx:51
#: src/views/public/board/index.tsx:57
msgid "Link copied"
msgstr "Lien copié"
#: src/views/card/index.tsx:235
#: src/views/card/index.tsx:105
msgid "List"
msgstr "Liste"
@@ -869,7 +895,7 @@ msgstr "Nom de la liste"
msgid "Login | kan.bn"
msgstr "Connexion | kan.bn"
#: src/components/UserMenu.tsx:136
#: src/components/UserMenu.tsx:209
msgid "Logout"
msgstr "Déconnexion"
@@ -881,7 +907,7 @@ msgstr "Long terme"
msgid "Low Priority"
msgstr "Priorité basse"
#: src/components/AuthForm.tsx:337
#: src/components/AuthForm.tsx:338
msgid "magic link"
msgstr "lien magique"
@@ -889,16 +915,16 @@ msgstr "lien magique"
msgid "Medium Priority"
msgstr "Priorité moyenne"
#: src/views/members/index.tsx:148
#: src/views/card/index.tsx:251
#: src/views/board/components/NewCardForm.tsx:290
#: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121
#: src/views/board/components/NewCardForm.tsx:317
#: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:44
#: src/components/SideNavigation.tsx:73
msgid "Members"
msgstr "Membres"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/members/index.tsx:144
#: src/views/members/index.tsx:157
msgid "Members | {0}"
msgstr "Membres | {0}"
@@ -919,11 +945,11 @@ msgstr "a déplacé la carte vers une autre liste"
msgid "Name"
msgstr "Nom"
#: src/components/FeedbackButton.tsx:116
#: src/components/FeedbackModal.tsx:95
msgid "Need help?"
msgstr "Besoin d'aide ?"
#: src/views/boards/index.tsx:52
#: src/views/boards/index.tsx:48
msgid "New"
msgstr "Nouveau"
@@ -931,7 +957,7 @@ msgstr "Nouveau"
msgid "New board"
msgstr "Nouveau tableau"
#: src/views/board/components/NewCardForm.tsx:237
#: src/views/board/components/NewCardForm.tsx:261
msgid "New card"
msgstr "Nouvelle carte"
@@ -943,7 +969,7 @@ msgstr "Nouvel import"
msgid "New label"
msgstr "Nouvelle étiquette"
#: src/views/board/index.tsx:296
#: src/views/board/index.tsx:395
#: src/views/board/components/NewListForm.tsx:112
msgid "New list"
msgstr "Nouvelle liste"
@@ -952,7 +978,7 @@ msgstr "Nouvelle liste"
msgid "New Ticket"
msgstr "Nouveau ticket"
#: src/components/NewWorkspaceForm.tsx:62
#: src/components/NewWorkspaceForm.tsx:64
msgid "New workspace"
msgstr "Nouvel espace de travail"
@@ -976,7 +1002,7 @@ msgstr "Aucun tableau trouvé"
msgid "No credit card required"
msgstr "Aucune carte de crédit requise"
#: src/views/board/index.tsx:316
#: src/views/board/index.tsx:415
msgid "No lists"
msgstr "Aucune liste"
@@ -988,15 +1014,15 @@ msgstr "Offre"
msgid "Onboarding"
msgstr "Intégration"
#: src/views/settings/index.tsx:263
#: src/views/settings/index.tsx:291
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."
#: src/views/settings/index.tsx:245
#: src/views/settings/index.tsx:273
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."
#: src/components/AuthForm.tsx:279
#: src/components/AuthForm.tsx:280
msgid "or"
msgstr "ou"
@@ -1016,7 +1042,7 @@ msgstr "Temps partiel"
msgid "Payment frequency"
msgstr "Fréquence de paiement"
#: src/views/members/index.tsx:107
#: src/views/members/index.tsx:118
msgid "Pending"
msgstr "En attente"
@@ -1033,19 +1059,19 @@ msgstr "Projet personnel"
msgid "Planning"
msgstr "Planification"
#: src/components/AuthForm.tsx:305
#: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address"
msgstr "Veuillez saisir une adresse e-mail valide"
#: src/components/AuthForm.tsx:293
#: src/components/AuthForm.tsx:294
msgid "Please enter a valid name"
msgstr "Veuillez saisir un nom valide"
#: src/components/AuthForm.tsx:318
#: src/components/AuthForm.tsx:319
msgid "Please enter a valid password"
msgstr "Veuillez saisir un mot de passe valide"
#: src/views/settings/components/Avatar.tsx:55
#: src/views/settings/components/Avatar.tsx:57
msgid "Please select a file to upload."
msgstr "Veuillez sélectionner un fichier à télécharger."
@@ -1055,26 +1081,28 @@ msgstr "Veuillez sélectionner un fichier à télécharger."
#: src/views/settings/components/UpdateDisplayNameForm.tsx:55
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:46
#: src/views/settings/components/DeleteAccountConfirmation.tsx:40
#: src/views/settings/components/Avatar.tsx:38
#: src/views/settings/components/Avatar.tsx:96
#: src/views/settings/components/Avatar.tsx:40
#: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:116
#: src/views/card/index.tsx:159
#: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:62
#: src/views/card/components/Comment.tsx:64
#: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:133
#: src/views/board/index.tsx:189
#: src/views/board/index.tsx:135
#: src/views/board/index.tsx:191
#: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:128
#: src/components/NewWorkspaceForm.tsx:39
#: src/components/FeedbackButton.tsx:46
#: src/views/board/components/NewCardForm.tsx:145
#: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23
msgid "Please try again later, or contact customer support."
msgstr "Veuillez réessayer plus tard ou contacter le service client."
@@ -1096,11 +1124,11 @@ msgstr "Politique de confidentialité"
msgid "Private"
msgstr "Privé"
#: src/views/settings/components/Avatar.tsx:24
#: src/views/settings/components/Avatar.tsx:26
msgid "Profile image updated"
msgstr "Image de profil mise à jour"
#: src/views/settings/index.tsx:118
#: src/views/settings/index.tsx:144
msgid "Profile picture"
msgstr "Photo de profil"
@@ -1136,7 +1164,7 @@ msgstr "À distance"
msgid "Remove"
msgstr "Supprimer"
#: src/views/members/index.tsx:120
#: src/views/members/index.tsx:132
msgid "Remove member"
msgstr "Supprimer le membre"
@@ -1177,7 +1205,7 @@ msgstr "Révoquer"
msgid "Roadmap"
msgstr "Feuille de route"
#: src/views/members/index.tsx:178
#: src/views/members/index.tsx:191
msgid "Role"
msgstr "Rôle"
@@ -1185,7 +1213,7 @@ msgstr "Rôle"
msgid "Run on your own infrastructure"
msgstr "Exécutez sur votre propre infrastructure"
#: src/views/card/components/Comment.tsx:163
#: src/views/card/components/Comment.tsx:165
msgid "Save"
msgstr "Enregistrer"
@@ -1217,21 +1245,21 @@ msgstr "Auto-hébergement avec Github"
msgid "self-assigned the card"
msgstr "s'est auto-assigné la carte"
#: src/components/FeedbackButton.tsx:137
msgid "Send"
msgstr "Envoyer"
#: src/components/FeedbackModal.tsx:116
msgid "Send feedback"
msgstr "Envoyer des commentaires"
#: src/views/boards/components/TemplateBoards.tsx:69
msgid "Senior"
msgstr "Senior"
#: src/views/settings/index.tsx:112
#: src/components/SideNavigation.tsx:49
#: src/views/settings/index.tsx:138
#: src/components/SideNavigation.tsx:78
msgid "Settings"
msgstr "Paramètres"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:108
#: src/views/settings/index.tsx:134
msgid "Settings | {0}"
msgstr "Paramètres | {0}"
@@ -1253,7 +1281,7 @@ msgstr "Inscription désactivée"
msgid "Sign up is currently disabled. Please try again later."
msgstr "L'inscription est actuellement désactivée. Veuillez réessayer plus tard."
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Sign up with "
msgstr "S'inscrire avec "
@@ -1282,11 +1310,15 @@ msgstr "Étoile sur Github"
msgid "Success"
msgstr "Succès"
#: src/components/UserMenu.tsx:180
msgid "Support"
msgstr "Assistance"
#: src/views/home/components/Pricing.tsx:57
msgid "Support the development of the project"
msgstr "Soutenir le développement du projet"
#: src/components/UserMenu.tsx:98
#: src/components/UserMenu.tsx:139
msgid "System"
msgstr "Système"
@@ -1302,7 +1334,7 @@ msgstr "Modèles"
msgid "Terms of service"
msgstr "Conditions d'utilisation"
#: src/components/FeedbackButton.tsx:39
#: src/components/FeedbackModal.tsx:34
msgid "Thank you for your feedback!"
msgstr "Merci pour vos commentaires !"
@@ -1319,7 +1351,7 @@ msgstr "L'alternative open source <0/> à Trello"
msgid "The visibility of your board has been set to {0}."
msgstr "La visibilité de votre tableau a été définie sur {0}."
#: src/components/UserMenu.tsx:85
#: src/components/UserMenu.tsx:126
msgid "Theme"
msgstr "Thème"
@@ -1329,9 +1361,14 @@ msgstr "Ils ne pourront plus accéder à cet espace de travail."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42
msgid "This action can't be undone."
msgstr "Cette action ne peut pas être annulée."
#: src/views/public/board/index.tsx:146
msgid "This board is private or does not exist"
msgstr "Ce tableau est privé ou n'existe pas"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135
msgid "This board URL has already been taken"
msgstr "Cette URL de tableau est déjà utilisée"
@@ -1361,7 +1398,7 @@ msgstr "Basculer le menu"
msgid "Track all card changes with detailed activity history."
msgstr "Suivez tous les changements de cartes avec un historique d'activité détaillé."
#: src/views/settings/index.tsx:69
#: src/views/settings/index.tsx:92
msgid "Trello disconnected"
msgstr "Trello déconnecté"
@@ -1377,7 +1414,7 @@ msgstr "Triage"
msgid "Unable to add comment"
msgstr "Impossible d'ajouter un commentaire"
#: src/views/board/components/NewCardForm.tsx:125
#: src/views/board/components/NewCardForm.tsx:142
msgid "Unable to create card"
msgstr "Impossible de créer la carte"
@@ -1385,7 +1422,7 @@ msgstr "Impossible de créer la carte"
msgid "Unable to create list"
msgstr "Impossible de créer une liste"
#: src/components/NewWorkspaceForm.tsx:38
#: src/components/NewWorkspaceForm.tsx:40
msgid "Unable to create workspace"
msgstr "Impossible de créer l'espace de travail"
@@ -1401,7 +1438,7 @@ msgstr "Impossible de supprimer le commentaire"
msgid "Unable to remove member"
msgstr "Impossible de supprimer le membre"
#: src/components/FeedbackButton.tsx:45
#: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback"
msgstr "Impossible d'envoyer les commentaires"
@@ -1413,12 +1450,12 @@ msgstr "Impossible de mettre à jour l'URL du tableau"
msgid "Unable to update board visibility"
msgstr "Impossible de mettre à jour la visibilité du tableau"
#: src/views/card/index.tsx:115
#: src/views/board/index.tsx:188
#: src/views/card/index.tsx:158
#: src/views/board/index.tsx:190
msgid "Unable to update card"
msgstr "Impossible de mettre à jour la carte"
#: src/views/card/components/Comment.tsx:61
#: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment"
msgstr "Impossible de mettre à jour le commentaire"
@@ -1427,7 +1464,7 @@ msgid "Unable to update labels"
msgstr "Impossible de mettre à jour les étiquettes"
#: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:132
#: src/views/board/index.tsx:134
msgid "Unable to update list"
msgstr "Impossible de mettre à jour la liste"
@@ -1471,11 +1508,11 @@ msgstr "Listes illimitées"
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:82
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:90
#: src/views/settings/components/UpdateDisplayNameForm.tsx:79
#: src/views/board/components/UpdateBoardSlugForm.tsx:166
#: src/views/board/components/UpdateBoardSlugForm.tsx:174
msgid "Update"
msgstr "Mettre à jour"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Update label"
msgstr "Mettre à jour l'étiquette"
@@ -1516,19 +1553,23 @@ msgstr "L'URL doit comporter au moins 3 caractères"
msgid "Use template"
msgstr "Utiliser le modèle"
#: src/views/members/index.tsx:172
#: src/views/members/index.tsx:185
msgid "User"
msgstr "Utilisateur"
#: src/views/members/components/InviteMemberForm.tsx:58
msgid "User is already a member of this workspace"
msgstr "L'utilisateur est déjà membre de cet espace de travail"
#: src/views/boards/components/TemplateBoards.tsx:37
msgid "Video"
msgstr "Vidéo"
#: src/views/settings/index.tsx:232
#: src/views/settings/index.tsx:260
msgid "View and manage your API keys."
msgstr "Consultez et gérez vos clés API."
#: src/views/settings/index.tsx:171
#: src/views/settings/index.tsx:199
msgid "View and manage your billing and subscription."
msgstr "Consultez et gérez votre facturation et votre abonnement."
@@ -1536,10 +1577,18 @@ msgstr "Consultez et gérez votre facturation et votre abonnement."
msgid "View docs"
msgstr "Voir la documentation"
#: src/views/public/board/index.tsx:120
msgid "View only"
msgstr "Affichage uniquement"
#: src/views/home/components/Features.tsx:147
msgid "View our roadmap."
msgstr "Consultez notre feuille de route."
#: src/views/public/board/index.tsx:149
msgid "View workspace"
msgstr "Voir l'espace de travail"
#: src/views/board/components/VisibilityButton.tsx:91
msgid "Visibility"
msgstr "Visibilité"
@@ -1572,7 +1621,7 @@ msgstr "Quand Trello a été lancé en 2011, il a impressionné tout le monde pa
msgid "Why make an open source Trello?"
msgstr "Pourquoi créer un Trello open source ?"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Workspace"
msgstr "Espace de travail"
@@ -1580,7 +1629,7 @@ msgstr "Espace de travail"
msgid "Workspace deleted"
msgstr "Espace de travail supprimé"
#: src/views/settings/index.tsx:147
#: src/views/settings/index.tsx:175
msgid "Workspace description"
msgstr "Description de l'espace de travail"
@@ -1601,8 +1650,8 @@ msgstr "Description de l'espace de travail mise à jour"
msgid "Workspace members"
msgstr "Membres de l'espace de travail"
#: src/views/settings/index.tsx:130
#: src/components/NewWorkspaceForm.tsx:78
#: src/views/settings/index.tsx:156
#: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name"
msgstr "Nom de l'espace de travail"
@@ -1622,7 +1671,7 @@ msgstr "Nom de l'espace de travail mis à jour"
msgid "Workspace slug updated"
msgstr "Slug de l'espace de travail mis à jour"
#: src/views/settings/index.tsx:138
#: src/views/settings/index.tsx:165
msgid "Workspace URL"
msgstr "URL de l'espace de travail"
@@ -1670,15 +1719,15 @@ msgstr "Vos tableaux ont été importés."
msgid "Your display name has been updated."
msgstr "Votre nom d'affichage a été mis à jour."
#: src/views/settings/components/Avatar.tsx:25
#: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated."
msgstr "Votre image de profil a été mise à jour."
#: src/views/settings/index.tsx:70
#: src/views/settings/index.tsx:93
msgid "Your Trello account has been disconnected."
msgstr "Votre compte Trello a été déconnecté."
#: src/views/settings/index.tsx:214
#: src/views/settings/index.tsx:242
msgid "Your Trello account is connected."
msgstr "Votre compte Trello est connecté."

File diff suppressed because one or more lines are too long

View File

@@ -13,22 +13,22 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:121
#: src/views/card/components/Comment.tsx:123
msgid " (edited)"
msgstr " (modificato)"
#: src/components/FeedbackButton.tsx:123
#: src/components/FeedbackModal.tsx:102
msgid ", or see our"
msgstr ", o consulta i nostri"
#. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:148
#: src/views/card/index.tsx:189
msgid "{0} | {1}"
msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:365
#: src/views/board/components/NewCardForm.tsx:392
msgid "{0} labels"
msgstr "{0} etichette"
@@ -36,10 +36,6 @@ msgstr "{0} etichette"
msgid "{boardCount, plural, one {Import board (1)} other {Import boards ({boardCount})}}"
msgstr "{boardCount, plural, one {Importa bacheca (1)} other {Importa bacheche ({boardCount})}}"
#: src/views/home/index.tsx:51
msgid "#1 Hacker News"
msgstr "#1 Hacker News"
#: src/views/home/components/Pricing.tsx:36
msgid "1 user"
msgstr "1 utente"
@@ -52,8 +48,8 @@ msgstr "Un'app kanban potente e flessibile che ti aiuta a organizzare il lavoro,
msgid "Account deleted"
msgstr "Account eliminato"
#: src/views/public/board/CardModal.tsx:104
#: src/views/card/index.tsx:215
#: src/views/public/board/CardModal.tsx:128
#: src/views/card/index.tsx:256
msgid "Activity"
msgstr "Attività"
@@ -66,11 +62,11 @@ msgid "Add a card"
msgstr "Aggiungi una carta"
#: src/views/card/components/NewCommentForm.tsx:57
#: src/views/card/components/Comment.tsx:144
#: src/views/card/components/Comment.tsx:146
msgid "Add a comment..."
msgstr "Aggiungi un commento..."
#: src/components/Editor.tsx:302
#: src/components/Editor.tsx:303
msgid "Add description... (type '/' to open commands)"
msgstr "Aggiungi descrizione... (digita '/' per aprire i comandi)"
@@ -79,7 +75,7 @@ msgstr "Aggiungi descrizione... (digita '/' per aprire i comandi)"
msgid "Add label"
msgstr "Aggiungi etichetta"
#: src/views/members/components/InviteMemberForm.tsx:50
#: src/views/members/components/InviteMemberForm.tsx:85
#: src/views/card/components/MemberSelector.tsx:130
msgid "Add member"
msgstr "Aggiungi membro"
@@ -112,11 +108,11 @@ msgstr "Tutti i sistemi operativi"
msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "Hai già un account? <0><1>Accedi</1></0>"
#: src/views/settings/index.tsx:77
#: src/views/settings/index.tsx:100
msgid "An error occurred while disconnecting your Trello account."
msgstr "Si è verificato un errore durante la disconnessione del tuo account Trello."
#: src/views/settings/index.tsx:229
#: src/views/settings/index.tsx:257
msgid "API keys"
msgstr "Chiavi API"
@@ -149,6 +145,10 @@ msgstr "Sei sicuro di voler eliminare questa carta?"
msgid "Are you sure you want to delete this comment?"
msgstr "Sei sicuro di voler eliminare questo commento?"
#: src/components/DeleteLabelConfirmation.tsx:39
msgid "Are you sure you want to delete this label?"
msgstr "Sei sicuro di voler eliminare questa etichetta?"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:54
msgid "Are you sure you want to delete your account?"
msgstr "Sei sicuro di voler eliminare il tuo account?"
@@ -169,12 +169,12 @@ msgstr "Backlog"
msgid "Basic Kanban"
msgstr "Kanban base"
#: src/views/settings/index.tsx:168
#: src/views/settings/index.tsx:196
#: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing"
msgstr "Fatturazione"
#: src/views/settings/index.tsx:178
#: src/views/settings/index.tsx:206
msgid "Billing portal"
msgstr "Portale di fatturazione"
@@ -182,7 +182,7 @@ msgstr "Portale di fatturazione"
msgid "Blog Post"
msgstr "Post del blog"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Board"
msgstr "Bacheca"
@@ -194,7 +194,8 @@ msgstr "Il nome della bacheca non può superare i 100 caratteri"
msgid "Board name is required"
msgstr "Il nome della bacheca è obbligatorio"
#: src/views/board/index.tsx:265
#: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358
msgid "Board not found"
msgstr "Bacheca non trovata"
@@ -206,7 +207,7 @@ msgstr "L'URL della bacheca può contenere solo lettere, numeri e trattini"
msgid "Board URL cannot exceed 60 characters"
msgstr "L'URL della bacheca non può superare i 60 caratteri"
#: src/views/public/board/index.tsx:53
#: src/views/public/board/index.tsx:59
msgid "Board URL copied to clipboard"
msgstr "URL della bacheca copiato negli appunti"
@@ -222,13 +223,13 @@ msgstr "Visibilità bacheca"
msgid "Board visibility updated"
msgstr "Visibilità della bacheca aggiornata"
#: src/views/boards/index.tsx:25
#: src/components/SideNavigation.tsx:39
#: src/views/boards/index.tsx:27
#: src/components/SideNavigation.tsx:68
msgid "Boards"
msgstr "Bacheche"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/boards/index.tsx:21
#: src/views/boards/index.tsx:23
msgid "Boards | {0}"
msgstr "Bacheche | {0}"
@@ -250,19 +251,20 @@ msgstr "Segnalazione bug"
#: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:156
#: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47
msgid "Cancel"
msgstr "Annulla"
#: src/views/card/index.tsx:193
#: src/views/card/index.tsx:234
msgid "Card not found"
msgstr "Carta non trovata"
#: src/views/board/components/NewCardForm.tsx:254
#: src/views/board/components/NewCardForm.tsx:278
msgid "Card title"
msgstr "Titolo della carta"
#: src/views/settings/index.tsx:160
#: src/views/settings/index.tsx:188
msgid "Change the language of the app."
msgstr "Cambia la lingua dell'app."
@@ -312,7 +314,7 @@ msgstr "Controllo e proprietà completi:"
msgid "Confirm URL change"
msgstr "Conferma modifica URL"
#: src/views/settings/index.tsx:205
#: src/views/settings/index.tsx:233
#: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello"
msgstr "Connetti Trello"
@@ -321,7 +323,7 @@ msgstr "Connetti Trello"
msgid "Connect your favorite tools to streamline your workflow."
msgstr "Connetti i tuoi strumenti preferiti per semplificare il tuo flusso di lavoro."
#: src/views/settings/index.tsx:192
#: src/views/settings/index.tsx:220
msgid "Connect your Trello account to import boards."
msgstr "Connetti il tuo account Trello per importare le bacheche."
@@ -329,7 +331,7 @@ msgstr "Connetti il tuo account Trello per importare le bacheche."
msgid "Contact"
msgstr "Contatti"
#: src/components/FeedbackButton.tsx:121
#: src/components/FeedbackModal.tsx:100
msgid "Contact us"
msgstr "Contattaci"
@@ -337,12 +339,12 @@ msgstr "Contattaci"
msgid "Content Creation"
msgstr "Creazione contenuti"
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Continue with "
msgstr "Continua con "
#. placeholder {0}: provider.name
#: src/components/AuthForm.tsx:268
#: src/components/AuthForm.tsx:269
msgid "Continue with {0}"
msgstr "Continua con {0}"
@@ -351,7 +353,7 @@ msgid "Control who can view and edit your boards."
msgstr "Controlla chi può visualizzare e modificare le tue bacheche."
#: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:391
#: src/views/board/components/NewCardForm.tsx:418
#: src/components/LabelForm.tsx:212
msgid "Create another"
msgstr "Crea un altro"
@@ -360,15 +362,15 @@ msgstr "Crea un altro"
msgid "Create board"
msgstr "Crea bacheca"
#: src/views/board/components/NewCardForm.tsx:401
#: src/views/board/components/NewCardForm.tsx:428
msgid "Create card"
msgstr "Crea carta"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Create label"
msgstr "Crea etichetta"
#: src/views/board/components/NewListForm.tsx:148
#: src/views/board/components/NewListForm.tsx:152
msgid "Create list"
msgstr "Crea lista"
@@ -381,16 +383,16 @@ msgid "Create new key"
msgstr "Crea nuova chiave"
#: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:327
#: src/views/board/components/NewCardForm.tsx:354
msgid "Create new label"
msgstr "Crea nuova etichetta"
#: src/views/board/index.tsx:327
#: src/views/board/index.tsx:426
msgid "Create new list"
msgstr "Crea nuova lista"
#: src/components/WorkspaceMenu.tsx:85
#: src/components/NewWorkspaceForm.tsx:91
#: src/components/WorkspaceMenu.tsx:116
#: src/components/NewWorkspaceForm.tsx:93
msgid "Create workspace"
msgstr "Crea spazio di lavoro"
@@ -414,18 +416,19 @@ msgstr "Gli URL personalizzati sono una funzionalità premium. Sarai indirizzato
msgid "Customer Support"
msgstr "Assistenza clienti"
#: src/components/UserMenu.tsx:112
#: src/components/UserMenu.tsx:153
msgid "Dark"
msgstr "Scuro"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226
#: src/components/DeleteLabelConfirmation.tsx:49
msgid "Delete"
msgstr "Elimina"
#: src/views/settings/index.tsx:260
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:288
#: src/views/settings/index.tsx:298
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account"
msgstr "Elimina account"
@@ -438,7 +441,7 @@ msgstr "Elimina bacheca"
msgid "Delete card"
msgstr "Elimina carta"
#: src/views/card/components/Comment.tsx:89
#: src/views/card/components/Comment.tsx:91
msgid "Delete comment"
msgstr "Elimina commento"
@@ -446,8 +449,8 @@ msgstr "Elimina commento"
msgid "Delete list"
msgstr "Elimina lista"
#: src/views/settings/index.tsx:242
#: src/views/settings/index.tsx:253
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:281
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace"
msgstr "Elimina spazio di lavoro"
@@ -456,7 +459,7 @@ msgstr "Elimina spazio di lavoro"
msgid "Design"
msgstr "Design"
#: src/views/settings/index.tsx:220
#: src/views/settings/index.tsx:248
msgid "Disconnect Trello"
msgstr "Disconnetti Trello"
@@ -464,7 +467,7 @@ msgstr "Disconnetti Trello"
msgid "Discuss and collaborate on cards."
msgstr "Discuti e collabora sulle schede."
#: src/views/settings/index.tsx:123
#: src/views/settings/index.tsx:149
msgid "Display name"
msgstr "Nome visualizzato"
@@ -484,7 +487,7 @@ msgstr "Nome visualizzato aggiornato"
msgid "Do you offer a free plan?"
msgstr "Offrite un piano gratuito?"
#: src/components/FeedbackButton.tsx:130
#: src/components/FeedbackModal.tsx:109
msgid "docs"
msgstr "documenti"
@@ -494,6 +497,7 @@ msgstr "Documenti"
#: src/views/home/components/Footer.tsx:77
#: src/views/boards/components/TemplateBoards.tsx:23
#: src/components/UserMenu.tsx:191
msgid "Documentation"
msgstr "Documentazione"
@@ -513,7 +517,7 @@ msgstr "Fatto"
msgid "Edit board URL"
msgstr "Modifica URL della bacheca"
#: src/views/card/components/Comment.tsx:80
#: src/views/card/components/Comment.tsx:82
msgid "Edit comment"
msgstr "Modifica commento"
@@ -521,15 +525,19 @@ msgstr "Modifica commento"
msgid "Edit label"
msgstr "Modifica etichetta"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161
msgid "Edit workspace URL"
msgstr "Modifica URL dell'area di lavoro"
#: src/views/boards/components/TemplateBoards.tsx:31
msgid "Editing"
msgstr "Modifica"
#: src/components/AuthForm.tsx:336
#: src/components/AuthForm.tsx:337
msgid "email"
msgstr "email"
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/InviteMemberForm.tsx:99
msgid "Email"
msgstr "Email"
@@ -537,15 +545,15 @@ msgstr "Email"
msgid "Enhancement"
msgstr "Miglioramento"
#: src/components/AuthForm.tsx:301
#: src/components/AuthForm.tsx:302
msgid "Enter your email address"
msgstr "Inserisci il tuo indirizzo email"
#: src/components/AuthForm.tsx:289
#: src/components/AuthForm.tsx:290
msgid "Enter your name"
msgstr "Inserisci il tuo nome"
#: src/components/AuthForm.tsx:314
#: src/components/AuthForm.tsx:315
msgid "Enter your password"
msgstr "Inserisci la tua password"
@@ -553,19 +561,28 @@ msgstr "Inserisci la tua password"
msgid "Error deleting account"
msgstr "Errore durante l'eliminazione dell'account"
#: src/components/DeleteLabelConfirmation.tsx:22
msgid "Error deleting label"
msgstr "Errore durante l'eliminazione dell'etichetta"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:45
msgid "Error deleting workspace"
msgstr "Errore durante l'eliminazione dell'area di lavoro"
#: src/views/settings/index.tsx:76
#: src/views/settings/index.tsx:99
msgid "Error disconnecting Trello"
msgstr "Errore durante la disconnessione da Trello"
#: src/views/members/components/InviteMemberForm.tsx:57
#: src/views/members/components/InviteMemberForm.tsx:63
msgid "Error inviting member"
msgstr "Errore durante l'invito del membro"
#: src/views/settings/components/UpdateDisplayNameForm.tsx:54
msgid "Error updating display name"
msgstr "Errore durante l'aggiornamento del nome visualizzato"
#: src/views/settings/components/Avatar.tsx:37
#: src/views/settings/components/Avatar.tsx:39
msgid "Error updating profile image"
msgstr "Errore durante l'aggiornamento dell'immagine del profilo"
@@ -581,8 +598,8 @@ msgstr "Errore durante l'aggiornamento del nome dell'area di lavoro"
msgid "Error updating workspace URL"
msgstr "Errore durante l'aggiornamento dell'URL dell'area di lavoro"
#: src/views/settings/components/Avatar.tsx:54
#: src/views/settings/components/Avatar.tsx:95
#: src/views/settings/components/Avatar.tsx:56
#: src/views/settings/components/Avatar.tsx:97
msgid "Error uploading profile image"
msgstr "Errore durante il caricamento dell'immagine del profilo"
@@ -622,11 +639,12 @@ msgstr "Richiesta funzionalità"
msgid "Features"
msgstr "Funzionalità"
#: src/components/FeedbackButton.tsx:78
#: src/components/UserMenu.tsx:199
#: src/components/FeedbackModal.tsx:59
msgid "Feedback"
msgstr "Feedback"
#: src/components/FeedbackButton.tsx:38
#: src/components/FeedbackModal.tsx:33
msgid "Feedback sent"
msgstr "Feedback inviato"
@@ -674,7 +692,7 @@ msgstr "Inizia ora"
msgid "Get started by creating a new board"
msgstr "Inizia creando una nuova bacheca"
#: src/views/board/index.tsx:319
#: src/views/board/index.tsx:418
msgid "Get started by creating a new list"
msgstr "Inizia creando una nuova lista"
@@ -747,11 +765,11 @@ msgstr "Riconosco che tutti i dati dell'area di lavoro saranno eliminati permane
msgid "Ideas"
msgstr "Idee"
#: src/components/FeedbackButton.tsx:98
#: src/components/FeedbackModal.tsx:75
msgid "Ideas to improve this page..."
msgstr "Idee per migliorare questa pagina..."
#: src/views/boards/index.tsx:39
#: src/views/boards/index.tsx:38
msgid "Import"
msgstr "Importa"
@@ -797,11 +815,19 @@ msgstr "Integrazioni"
msgid "Interviewing"
msgstr "Colloquio"
#: src/views/members/index.tsx:156
#: src/views/members/components/InviteMemberForm.tsx:26
msgid "Invalid email address"
msgstr "Indirizzo email non valido"
#: src/views/members/index.tsx:169
msgid "Invite"
msgstr "Invita"
#: src/views/members/components/InviteMemberForm.tsx:82
#: src/views/members/components/InviteMemberForm.tsx:113
msgid "Invite another"
msgstr "Invita un altro"
#: src/views/members/components/InviteMemberForm.tsx:123
#: src/views/card/components/MemberSelector.tsx:112
msgid "Invite member"
msgstr "Invita membro"
@@ -823,8 +849,8 @@ msgstr "Kanban reinventato"
msgid "Keep in mind that this action is irreversible."
msgstr "Tieni presente che questa azione è irreversibile."
#: src/views/card/index.tsx:243
#: src/views/board/components/NewCardForm.tsx:331
#: src/views/card/index.tsx:113
#: src/views/board/components/NewCardForm.tsx:358
#: src/views/board/components/Filters.tsx:101
msgid "Labels"
msgstr "Etichette"
@@ -833,7 +859,7 @@ msgstr "Etichette"
msgid "Labels & Filters"
msgstr "Etichette & Filtri"
#: src/views/settings/index.tsx:157
#: src/views/settings/index.tsx:185
msgid "Language"
msgstr "Lingua"
@@ -849,15 +875,15 @@ msgstr "Legale"
msgid "License"
msgstr "Licenza"
#: src/components/UserMenu.tsx:126
#: src/components/UserMenu.tsx:167
msgid "Light"
msgstr "Chiaro"
#: src/views/public/board/index.tsx:51
#: src/views/public/board/index.tsx:57
msgid "Link copied"
msgstr "Link copiato"
#: src/views/card/index.tsx:235
#: src/views/card/index.tsx:105
msgid "List"
msgstr "Lista"
@@ -869,7 +895,7 @@ msgstr "Nome lista"
msgid "Login | kan.bn"
msgstr "Login | kan.bn"
#: src/components/UserMenu.tsx:136
#: src/components/UserMenu.tsx:209
msgid "Logout"
msgstr "Esci"
@@ -881,7 +907,7 @@ msgstr "A lungo termine"
msgid "Low Priority"
msgstr "Bassa priorità"
#: src/components/AuthForm.tsx:337
#: src/components/AuthForm.tsx:338
msgid "magic link"
msgstr "link magico"
@@ -889,16 +915,16 @@ msgstr "link magico"
msgid "Medium Priority"
msgstr "Media priorità"
#: src/views/members/index.tsx:148
#: src/views/card/index.tsx:251
#: src/views/board/components/NewCardForm.tsx:290
#: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121
#: src/views/board/components/NewCardForm.tsx:317
#: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:44
#: src/components/SideNavigation.tsx:73
msgid "Members"
msgstr "Membri"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/members/index.tsx:144
#: src/views/members/index.tsx:157
msgid "Members | {0}"
msgstr "Membri | {0}"
@@ -919,11 +945,11 @@ msgstr "ha spostato la scheda in un'altra lista"
msgid "Name"
msgstr "Nome"
#: src/components/FeedbackButton.tsx:116
#: src/components/FeedbackModal.tsx:95
msgid "Need help?"
msgstr "Hai bisogno di aiuto?"
#: src/views/boards/index.tsx:52
#: src/views/boards/index.tsx:48
msgid "New"
msgstr "Nuovo"
@@ -931,7 +957,7 @@ msgstr "Nuovo"
msgid "New board"
msgstr "Nuova bacheca"
#: src/views/board/components/NewCardForm.tsx:237
#: src/views/board/components/NewCardForm.tsx:261
msgid "New card"
msgstr "Nuova carta"
@@ -943,7 +969,7 @@ msgstr "Nuova importazione"
msgid "New label"
msgstr "Nuova etichetta"
#: src/views/board/index.tsx:296
#: src/views/board/index.tsx:395
#: src/views/board/components/NewListForm.tsx:112
msgid "New list"
msgstr "Nuova lista"
@@ -952,7 +978,7 @@ msgstr "Nuova lista"
msgid "New Ticket"
msgstr "Nuovo ticket"
#: src/components/NewWorkspaceForm.tsx:62
#: src/components/NewWorkspaceForm.tsx:64
msgid "New workspace"
msgstr "Nuovo spazio di lavoro"
@@ -976,7 +1002,7 @@ msgstr "Nessuna bacheca trovata"
msgid "No credit card required"
msgstr "Nessuna carta di credito richiesta"
#: src/views/board/index.tsx:316
#: src/views/board/index.tsx:415
msgid "No lists"
msgstr "Nessuna lista"
@@ -988,15 +1014,15 @@ msgstr "Offerta"
msgid "Onboarding"
msgstr "Inserimento"
#: src/views/settings/index.tsx:263
#: src/views/settings/index.tsx:291
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."
#: src/views/settings/index.tsx:245
#: src/views/settings/index.tsx:273
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."
#: src/components/AuthForm.tsx:279
#: src/components/AuthForm.tsx:280
msgid "or"
msgstr "o"
@@ -1016,7 +1042,7 @@ msgstr "Part-time"
msgid "Payment frequency"
msgstr "Frequenza di pagamento"
#: src/views/members/index.tsx:107
#: src/views/members/index.tsx:118
msgid "Pending"
msgstr "In attesa"
@@ -1033,19 +1059,19 @@ msgstr "Progetto personale"
msgid "Planning"
msgstr "Pianificazione"
#: src/components/AuthForm.tsx:305
#: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address"
msgstr "Inserisci un indirizzo email valido"
#: src/components/AuthForm.tsx:293
#: src/components/AuthForm.tsx:294
msgid "Please enter a valid name"
msgstr "Inserisci un nome valido"
#: src/components/AuthForm.tsx:318
#: src/components/AuthForm.tsx:319
msgid "Please enter a valid password"
msgstr "Inserisci una password valida"
#: src/views/settings/components/Avatar.tsx:55
#: src/views/settings/components/Avatar.tsx:57
msgid "Please select a file to upload."
msgstr "Seleziona un file da caricare."
@@ -1055,26 +1081,28 @@ msgstr "Seleziona un file da caricare."
#: src/views/settings/components/UpdateDisplayNameForm.tsx:55
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:46
#: src/views/settings/components/DeleteAccountConfirmation.tsx:40
#: src/views/settings/components/Avatar.tsx:38
#: src/views/settings/components/Avatar.tsx:96
#: src/views/settings/components/Avatar.tsx:40
#: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:116
#: src/views/card/index.tsx:159
#: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:62
#: src/views/card/components/Comment.tsx:64
#: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:133
#: src/views/board/index.tsx:189
#: src/views/board/index.tsx:135
#: src/views/board/index.tsx:191
#: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:128
#: src/components/NewWorkspaceForm.tsx:39
#: src/components/FeedbackButton.tsx:46
#: src/views/board/components/NewCardForm.tsx:145
#: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23
msgid "Please try again later, or contact customer support."
msgstr "Riprova più tardi o contatta l'assistenza clienti."
@@ -1096,11 +1124,11 @@ msgstr "Informativa sulla privacy"
msgid "Private"
msgstr "Privato"
#: src/views/settings/components/Avatar.tsx:24
#: src/views/settings/components/Avatar.tsx:26
msgid "Profile image updated"
msgstr "Immagine del profilo aggiornata"
#: src/views/settings/index.tsx:118
#: src/views/settings/index.tsx:144
msgid "Profile picture"
msgstr "Immagine del profilo"
@@ -1136,7 +1164,7 @@ msgstr "Remoto"
msgid "Remove"
msgstr "Rimuovi"
#: src/views/members/index.tsx:120
#: src/views/members/index.tsx:132
msgid "Remove member"
msgstr "Rimuovi membro"
@@ -1177,7 +1205,7 @@ msgstr "Revoca"
msgid "Roadmap"
msgstr "Roadmap"
#: src/views/members/index.tsx:178
#: src/views/members/index.tsx:191
msgid "Role"
msgstr "Ruolo"
@@ -1185,7 +1213,7 @@ msgstr "Ruolo"
msgid "Run on your own infrastructure"
msgstr "Esegui sulla tua infrastruttura"
#: src/views/card/components/Comment.tsx:163
#: src/views/card/components/Comment.tsx:165
msgid "Save"
msgstr "Salva"
@@ -1217,21 +1245,21 @@ msgstr "Self host con Github"
msgid "self-assigned the card"
msgstr "si è auto-assegnato la scheda"
#: src/components/FeedbackButton.tsx:137
msgid "Send"
msgstr "Invia"
#: src/components/FeedbackModal.tsx:116
msgid "Send feedback"
msgstr "Invia feedback"
#: src/views/boards/components/TemplateBoards.tsx:69
msgid "Senior"
msgstr "Senior"
#: src/views/settings/index.tsx:112
#: src/components/SideNavigation.tsx:49
#: src/views/settings/index.tsx:138
#: src/components/SideNavigation.tsx:78
msgid "Settings"
msgstr "Impostazioni"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:108
#: src/views/settings/index.tsx:134
msgid "Settings | {0}"
msgstr "Impostazioni | {0}"
@@ -1253,7 +1281,7 @@ msgstr "Registrazione disabilitata"
msgid "Sign up is currently disabled. Please try again later."
msgstr "La registrazione è attualmente disabilitata. Riprova più tardi."
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Sign up with "
msgstr "Registrati con "
@@ -1282,11 +1310,15 @@ msgstr "Metti una stella su Github"
msgid "Success"
msgstr "Operazione riuscita"
#: src/components/UserMenu.tsx:180
msgid "Support"
msgstr "Supporto"
#: src/views/home/components/Pricing.tsx:57
msgid "Support the development of the project"
msgstr "Sostieni lo sviluppo del progetto"
#: src/components/UserMenu.tsx:98
#: src/components/UserMenu.tsx:139
msgid "System"
msgstr "Sistema"
@@ -1302,7 +1334,7 @@ msgstr "Template"
msgid "Terms of service"
msgstr "Termini di servizio"
#: src/components/FeedbackButton.tsx:39
#: src/components/FeedbackModal.tsx:34
msgid "Thank you for your feedback!"
msgstr "Grazie per il tuo feedback!"
@@ -1319,7 +1351,7 @@ msgstr "L'alternativa open source <0/> a Trello"
msgid "The visibility of your board has been set to {0}."
msgstr "La visibilità della tua bacheca è stata impostata su {0}."
#: src/components/UserMenu.tsx:85
#: src/components/UserMenu.tsx:126
msgid "Theme"
msgstr "Tema"
@@ -1329,9 +1361,14 @@ msgstr "Non potranno accedere a questo spazio di lavoro."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42
msgid "This action can't be undone."
msgstr "Questa azione non può essere annullata."
#: src/views/public/board/index.tsx:146
msgid "This board is private or does not exist"
msgstr "Questa bacheca è privata o non esiste"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135
msgid "This board URL has already been taken"
msgstr "Questo URL della bacheca è già stato utilizzato"
@@ -1361,7 +1398,7 @@ msgstr "Attiva/disattiva menu"
msgid "Track all card changes with detailed activity history."
msgstr "Tieni traccia di tutte le modifiche alle schede con una cronologia dettagliata delle attività."
#: src/views/settings/index.tsx:69
#: src/views/settings/index.tsx:92
msgid "Trello disconnected"
msgstr "Trello disconnesso"
@@ -1377,7 +1414,7 @@ msgstr "Smistamento"
msgid "Unable to add comment"
msgstr "Impossibile aggiungere il commento"
#: src/views/board/components/NewCardForm.tsx:125
#: src/views/board/components/NewCardForm.tsx:142
msgid "Unable to create card"
msgstr "Impossibile creare la scheda"
@@ -1385,7 +1422,7 @@ msgstr "Impossibile creare la scheda"
msgid "Unable to create list"
msgstr "Impossibile creare la lista"
#: src/components/NewWorkspaceForm.tsx:38
#: src/components/NewWorkspaceForm.tsx:40
msgid "Unable to create workspace"
msgstr "Impossibile creare lo spazio di lavoro"
@@ -1401,7 +1438,7 @@ msgstr "Impossibile eliminare il commento"
msgid "Unable to remove member"
msgstr "Impossibile rimuovere il membro"
#: src/components/FeedbackButton.tsx:45
#: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback"
msgstr "Impossibile inviare feedback"
@@ -1413,12 +1450,12 @@ msgstr "Impossibile aggiornare l'URL della bacheca"
msgid "Unable to update board visibility"
msgstr "Impossibile aggiornare la visibilità della bacheca"
#: src/views/card/index.tsx:115
#: src/views/board/index.tsx:188
#: src/views/card/index.tsx:158
#: src/views/board/index.tsx:190
msgid "Unable to update card"
msgstr "Impossibile aggiornare la scheda"
#: src/views/card/components/Comment.tsx:61
#: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment"
msgstr "Impossibile aggiornare il commento"
@@ -1427,7 +1464,7 @@ msgid "Unable to update labels"
msgstr "Impossibile aggiornare le etichette"
#: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:132
#: src/views/board/index.tsx:134
msgid "Unable to update list"
msgstr "Impossibile aggiornare la lista"
@@ -1471,11 +1508,11 @@ msgstr "Liste illimitate"
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:82
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:90
#: src/views/settings/components/UpdateDisplayNameForm.tsx:79
#: src/views/board/components/UpdateBoardSlugForm.tsx:166
#: src/views/board/components/UpdateBoardSlugForm.tsx:174
msgid "Update"
msgstr "Aggiorna"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Update label"
msgstr "Aggiorna etichetta"
@@ -1516,19 +1553,23 @@ msgstr "L'URL deve contenere almeno 3 caratteri"
msgid "Use template"
msgstr "Usa template"
#: src/views/members/index.tsx:172
#: src/views/members/index.tsx:185
msgid "User"
msgstr "Utente"
#: src/views/members/components/InviteMemberForm.tsx:58
msgid "User is already a member of this workspace"
msgstr "L'utente è già membro di questo spazio di lavoro"
#: src/views/boards/components/TemplateBoards.tsx:37
msgid "Video"
msgstr "Video"
#: src/views/settings/index.tsx:232
#: src/views/settings/index.tsx:260
msgid "View and manage your API keys."
msgstr "Visualizza e gestisci le tue chiavi API."
#: src/views/settings/index.tsx:171
#: src/views/settings/index.tsx:199
msgid "View and manage your billing and subscription."
msgstr "Visualizza e gestisci la tua fatturazione e abbonamento."
@@ -1536,10 +1577,18 @@ msgstr "Visualizza e gestisci la tua fatturazione e abbonamento."
msgid "View docs"
msgstr "Visualizza documenti"
#: src/views/public/board/index.tsx:120
msgid "View only"
msgstr "Solo visualizzazione"
#: src/views/home/components/Features.tsx:147
msgid "View our roadmap."
msgstr "Visualizza la nostra roadmap."
#: src/views/public/board/index.tsx:149
msgid "View workspace"
msgstr "Visualizza spazio di lavoro"
#: src/views/board/components/VisibilityButton.tsx:91
msgid "Visibility"
msgstr "Visibilità"
@@ -1572,7 +1621,7 @@ msgstr "Quando Trello fu lanciato nel 2011, stupì tutti con la sua semplicità
msgid "Why make an open source Trello?"
msgstr "Perché creare un Trello open source?"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Workspace"
msgstr "Spazio di lavoro"
@@ -1580,7 +1629,7 @@ msgstr "Spazio di lavoro"
msgid "Workspace deleted"
msgstr "Spazio di lavoro eliminato"
#: src/views/settings/index.tsx:147
#: src/views/settings/index.tsx:175
msgid "Workspace description"
msgstr "Descrizione dello spazio di lavoro"
@@ -1601,8 +1650,8 @@ msgstr "Descrizione dell'area di lavoro aggiornata"
msgid "Workspace members"
msgstr "Membri del workspace"
#: src/views/settings/index.tsx:130
#: src/components/NewWorkspaceForm.tsx:78
#: src/views/settings/index.tsx:156
#: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name"
msgstr "Nome dello spazio di lavoro"
@@ -1622,7 +1671,7 @@ msgstr "Nome dello spazio di lavoro aggiornato"
msgid "Workspace slug updated"
msgstr "Slug dell'area di lavoro aggiornato"
#: src/views/settings/index.tsx:138
#: src/views/settings/index.tsx:165
msgid "Workspace URL"
msgstr "URL dello spazio di lavoro"
@@ -1670,15 +1719,15 @@ msgstr "Le tue bacheche sono state importate."
msgid "Your display name has been updated."
msgstr "Il tuo nome visualizzato è stato aggiornato."
#: src/views/settings/components/Avatar.tsx:25
#: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated."
msgstr "La tua immagine del profilo è stata aggiornata."
#: src/views/settings/index.tsx:70
#: src/views/settings/index.tsx:93
msgid "Your Trello account has been disconnected."
msgstr "Il tuo account Trello è stato disconnesso."
#: src/views/settings/index.tsx:214
#: src/views/settings/index.tsx:242
msgid "Your Trello account is connected."
msgstr "Il tuo account Trello è connesso."

File diff suppressed because one or more lines are too long

View File

@@ -13,22 +13,22 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:121
#: src/views/card/components/Comment.tsx:123
msgid " (edited)"
msgstr " (bewerkt)"
#: src/components/FeedbackButton.tsx:123
#: src/components/FeedbackModal.tsx:102
msgid ", or see our"
msgstr ", of bekijk onze"
#. placeholder {0}: card?.title ?? "Card"
#. placeholder {1}: board?.name ?? "Board"
#: src/views/card/index.tsx:148
#: src/views/card/index.tsx:189
msgid "{0} | {1}"
msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:365
#: src/views/board/components/NewCardForm.tsx:392
msgid "{0} labels"
msgstr "{0} labels"
@@ -36,10 +36,6 @@ msgstr "{0} labels"
msgid "{boardCount, plural, one {Import board (1)} other {Import boards ({boardCount})}}"
msgstr "{boardCount, plural, one {Bord importeren (1)} other {Borden importeren ({boardCount})}}"
#: src/views/home/index.tsx:51
msgid "#1 Hacker News"
msgstr "#1 Hacker News"
#: src/views/home/components/Pricing.tsx:36
msgid "1 user"
msgstr "1 gebruiker"
@@ -52,8 +48,8 @@ msgstr "Een krachtige, flexibele kanban-app die je helpt werk te organiseren, vo
msgid "Account deleted"
msgstr "Account verwijderd"
#: src/views/public/board/CardModal.tsx:104
#: src/views/card/index.tsx:215
#: src/views/public/board/CardModal.tsx:128
#: src/views/card/index.tsx:256
msgid "Activity"
msgstr "Activiteit"
@@ -66,11 +62,11 @@ msgid "Add a card"
msgstr "Voeg een kaart toe"
#: src/views/card/components/NewCommentForm.tsx:57
#: src/views/card/components/Comment.tsx:144
#: src/views/card/components/Comment.tsx:146
msgid "Add a comment..."
msgstr "Voeg een reactie toe..."
#: src/components/Editor.tsx:302
#: src/components/Editor.tsx:303
msgid "Add description... (type '/' to open commands)"
msgstr "Voeg beschrijving toe... (typ '/' om commando's te openen)"
@@ -79,7 +75,7 @@ msgstr "Voeg beschrijving toe... (typ '/' om commando's te openen)"
msgid "Add label"
msgstr "Label toevoegen"
#: src/views/members/components/InviteMemberForm.tsx:50
#: src/views/members/components/InviteMemberForm.tsx:85
#: src/views/card/components/MemberSelector.tsx:130
msgid "Add member"
msgstr "Lid toevoegen"
@@ -112,11 +108,11 @@ msgstr "Alle systemen operationeel"
msgid "Already have an account? <0><1>Sign in</1></0>"
msgstr "Heb je al een account? <0><1>Log in</1></0>"
#: src/views/settings/index.tsx:77
#: src/views/settings/index.tsx:100
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."
#: src/views/settings/index.tsx:229
#: src/views/settings/index.tsx:257
msgid "API keys"
msgstr "API-sleutels"
@@ -149,6 +145,10 @@ msgstr "Weet je zeker dat je deze kaart wilt verwijderen?"
msgid "Are you sure you want to delete this comment?"
msgstr "Weet je zeker dat je deze opmerking wilt verwijderen?"
#: src/components/DeleteLabelConfirmation.tsx:39
msgid "Are you sure you want to delete this label?"
msgstr "Weet je zeker dat je dit label wilt verwijderen?"
#: src/views/settings/components/DeleteAccountConfirmation.tsx:54
msgid "Are you sure you want to delete your account?"
msgstr "Weet je zeker dat je je account wilt verwijderen?"
@@ -169,12 +169,12 @@ msgstr "Backlog"
msgid "Basic Kanban"
msgstr "Basis kanban"
#: src/views/settings/index.tsx:168
#: src/views/settings/index.tsx:196
#: src/views/boards/components/TemplateBoards.tsx:55
msgid "Billing"
msgstr "Facturering"
#: src/views/settings/index.tsx:178
#: src/views/settings/index.tsx:206
msgid "Billing portal"
msgstr "Factureringsportaal"
@@ -182,7 +182,7 @@ msgstr "Factureringsportaal"
msgid "Blog Post"
msgstr "Blogbericht"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Board"
msgstr "Bord"
@@ -194,7 +194,8 @@ msgstr "Bordnaam mag niet langer zijn dan 100 tekens"
msgid "Board name is required"
msgstr "Bordnaam is verplicht"
#: src/views/board/index.tsx:265
#: src/views/public/board/index.tsx:143
#: src/views/board/index.tsx:358
msgid "Board not found"
msgstr "Bord niet gevonden"
@@ -206,7 +207,7 @@ msgstr "Board URL kan alleen letters, cijfers en koppeltekens bevatten"
msgid "Board URL cannot exceed 60 characters"
msgstr "Board URL mag niet langer zijn dan 60 tekens"
#: src/views/public/board/index.tsx:53
#: src/views/public/board/index.tsx:59
msgid "Board URL copied to clipboard"
msgstr "Board URL gekopieerd naar klembord"
@@ -222,13 +223,13 @@ msgstr "Bordzichtbaarheid"
msgid "Board visibility updated"
msgstr "Zichtbaarheid van bord bijgewerkt"
#: src/views/boards/index.tsx:25
#: src/components/SideNavigation.tsx:39
#: src/views/boards/index.tsx:27
#: src/components/SideNavigation.tsx:68
msgid "Boards"
msgstr "Borden"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/boards/index.tsx:21
#: src/views/boards/index.tsx:23
msgid "Boards | {0}"
msgstr "Borden | {0}"
@@ -250,19 +251,20 @@ msgstr "Bugrapport"
#: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/card/components/DeleteCommentConfirmation.tsx:76
#: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/Comment.tsx:156
#: src/views/card/components/Comment.tsx:158
#: src/components/DeleteLabelConfirmation.tsx:47
msgid "Cancel"
msgstr "Annuleren"
#: src/views/card/index.tsx:193
#: src/views/card/index.tsx:234
msgid "Card not found"
msgstr "Kaart niet gevonden"
#: src/views/board/components/NewCardForm.tsx:254
#: src/views/board/components/NewCardForm.tsx:278
msgid "Card title"
msgstr "Kaarttitel"
#: src/views/settings/index.tsx:160
#: src/views/settings/index.tsx:188
msgid "Change the language of the app."
msgstr "Wijzig de taal van de app."
@@ -312,7 +314,7 @@ msgstr "Volledige controle en eigendom:"
msgid "Confirm URL change"
msgstr "URL-wijziging bevestigen"
#: src/views/settings/index.tsx:205
#: src/views/settings/index.tsx:233
#: src/views/boards/components/ImportBoardsForm.tsx:157
msgid "Connect Trello"
msgstr "Verbind Trello"
@@ -321,7 +323,7 @@ msgstr "Verbind Trello"
msgid "Connect your favorite tools to streamline your workflow."
msgstr "Verbind je favoriete tools om je werkstroom te stroomlijnen."
#: src/views/settings/index.tsx:192
#: src/views/settings/index.tsx:220
msgid "Connect your Trello account to import boards."
msgstr "Verbind je Trello-account om borden te importeren."
@@ -329,7 +331,7 @@ msgstr "Verbind je Trello-account om borden te importeren."
msgid "Contact"
msgstr "Contact"
#: src/components/FeedbackButton.tsx:121
#: src/components/FeedbackModal.tsx:100
msgid "Contact us"
msgstr "Neem contact op"
@@ -337,12 +339,12 @@ msgstr "Neem contact op"
msgid "Content Creation"
msgstr "Content creatie"
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Continue with "
msgstr "Doorgaan met "
#. placeholder {0}: provider.name
#: src/components/AuthForm.tsx:268
#: src/components/AuthForm.tsx:269
msgid "Continue with {0}"
msgstr "Doorgaan met {0}"
@@ -351,7 +353,7 @@ msgid "Control who can view and edit your boards."
msgstr "Bepaal wie je borden kan bekijken en bewerken."
#: src/views/board/components/NewListForm.tsx:140
#: src/views/board/components/NewCardForm.tsx:391
#: src/views/board/components/NewCardForm.tsx:418
#: src/components/LabelForm.tsx:212
msgid "Create another"
msgstr "Maak nog een"
@@ -360,15 +362,15 @@ msgstr "Maak nog een"
msgid "Create board"
msgstr "Maak bord"
#: src/views/board/components/NewCardForm.tsx:401
#: src/views/board/components/NewCardForm.tsx:428
msgid "Create card"
msgstr "Maak kaart"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Create label"
msgstr "Maak label"
#: src/views/board/components/NewListForm.tsx:148
#: src/views/board/components/NewListForm.tsx:152
msgid "Create list"
msgstr "Lijst maken"
@@ -381,16 +383,16 @@ msgid "Create new key"
msgstr "Nieuwe sleutel aanmaken"
#: src/views/card/components/LabelSelector.tsx:98
#: src/views/board/components/NewCardForm.tsx:327
#: src/views/board/components/NewCardForm.tsx:354
msgid "Create new label"
msgstr "Maak nieuw label"
#: src/views/board/index.tsx:327
#: src/views/board/index.tsx:426
msgid "Create new list"
msgstr "Maak nieuwe lijst"
#: src/components/WorkspaceMenu.tsx:85
#: src/components/NewWorkspaceForm.tsx:91
#: src/components/WorkspaceMenu.tsx:116
#: src/components/NewWorkspaceForm.tsx:93
msgid "Create workspace"
msgstr "Werkruimte maken"
@@ -414,18 +416,19 @@ msgstr "Aangepaste URL's zijn een premium functie. Je wordt doorgestuurd om je a
msgid "Customer Support"
msgstr "Klantenservice"
#: src/components/UserMenu.tsx:112
#: src/components/UserMenu.tsx:153
msgid "Dark"
msgstr "Donker"
#: src/views/card/components/DeleteCommentConfirmation.tsx:82
#: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/components/LabelForm.tsx:226
#: src/components/DeleteLabelConfirmation.tsx:49
msgid "Delete"
msgstr "Verwijderen"
#: src/views/settings/index.tsx:260
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:288
#: src/views/settings/index.tsx:298
#: src/views/settings/components/DeleteAccountConfirmation.tsx:96
msgid "Delete account"
msgstr "Account verwijderen"
@@ -438,7 +441,7 @@ msgstr "Board verwijderen"
msgid "Delete card"
msgstr "Kaart verwijderen"
#: src/views/card/components/Comment.tsx:89
#: src/views/card/components/Comment.tsx:91
msgid "Delete comment"
msgstr "Reactie verwijderen"
@@ -446,8 +449,8 @@ msgstr "Reactie verwijderen"
msgid "Delete list"
msgstr "Lijst verwijderen"
#: src/views/settings/index.tsx:242
#: src/views/settings/index.tsx:253
#: src/views/settings/index.tsx:270
#: src/views/settings/index.tsx:281
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:106
msgid "Delete workspace"
msgstr "Werkruimte verwijderen"
@@ -456,7 +459,7 @@ msgstr "Werkruimte verwijderen"
msgid "Design"
msgstr "Ontwerp"
#: src/views/settings/index.tsx:220
#: src/views/settings/index.tsx:248
msgid "Disconnect Trello"
msgstr "Trello ontkoppelen"
@@ -464,7 +467,7 @@ msgstr "Trello ontkoppelen"
msgid "Discuss and collaborate on cards."
msgstr "Bespreek en werk samen aan kaarten."
#: src/views/settings/index.tsx:123
#: src/views/settings/index.tsx:149
msgid "Display name"
msgstr "Weergavenaam"
@@ -484,7 +487,7 @@ msgstr "Weergavenaam bijgewerkt"
msgid "Do you offer a free plan?"
msgstr "Bieden jullie een gratis abonnement aan?"
#: src/components/FeedbackButton.tsx:130
#: src/components/FeedbackModal.tsx:109
msgid "docs"
msgstr "docs"
@@ -494,6 +497,7 @@ msgstr "Docs"
#: src/views/home/components/Footer.tsx:77
#: src/views/boards/components/TemplateBoards.tsx:23
#: src/components/UserMenu.tsx:191
msgid "Documentation"
msgstr "Documentatie"
@@ -513,7 +517,7 @@ msgstr "Klaar"
msgid "Edit board URL"
msgstr "Board URL bewerken"
#: src/views/card/components/Comment.tsx:80
#: src/views/card/components/Comment.tsx:82
msgid "Edit comment"
msgstr "Reactie bewerken"
@@ -521,15 +525,19 @@ msgstr "Reactie bewerken"
msgid "Edit label"
msgstr "Label bewerken"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161
msgid "Edit workspace URL"
msgstr "Werkruimte-URL bewerken"
#: src/views/boards/components/TemplateBoards.tsx:31
msgid "Editing"
msgstr "Bewerken"
#: src/components/AuthForm.tsx:336
#: src/components/AuthForm.tsx:337
msgid "email"
msgstr "e-mail"
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/InviteMemberForm.tsx:99
msgid "Email"
msgstr "E-mail"
@@ -537,15 +545,15 @@ msgstr "E-mail"
msgid "Enhancement"
msgstr "Verbetering"
#: src/components/AuthForm.tsx:301
#: src/components/AuthForm.tsx:302
msgid "Enter your email address"
msgstr "Voer je e-mailadres in"
#: src/components/AuthForm.tsx:289
#: src/components/AuthForm.tsx:290
msgid "Enter your name"
msgstr "Voer je naam in"
#: src/components/AuthForm.tsx:314
#: src/components/AuthForm.tsx:315
msgid "Enter your password"
msgstr "Voer je wachtwoord in"
@@ -553,19 +561,28 @@ msgstr "Voer je wachtwoord in"
msgid "Error deleting account"
msgstr "Fout bij verwijderen account"
#: src/components/DeleteLabelConfirmation.tsx:22
msgid "Error deleting label"
msgstr "Fout bij het verwijderen van label"
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:45
msgid "Error deleting workspace"
msgstr "Fout bij verwijderen werkruimte"
#: src/views/settings/index.tsx:76
#: src/views/settings/index.tsx:99
msgid "Error disconnecting Trello"
msgstr "Fout bij ontkoppelen van Trello"
#: src/views/members/components/InviteMemberForm.tsx:57
#: src/views/members/components/InviteMemberForm.tsx:63
msgid "Error inviting member"
msgstr "Fout bij het uitnodigen van lid"
#: src/views/settings/components/UpdateDisplayNameForm.tsx:54
msgid "Error updating display name"
msgstr "Fout bij bijwerken weergavenaam"
#: src/views/settings/components/Avatar.tsx:37
#: src/views/settings/components/Avatar.tsx:39
msgid "Error updating profile image"
msgstr "Fout bij het bijwerken van profielafbeelding"
@@ -581,8 +598,8 @@ msgstr "Fout bij bijwerken naam werkruimte"
msgid "Error updating workspace URL"
msgstr "Fout bij het bijwerken van werkruimte-URL"
#: src/views/settings/components/Avatar.tsx:54
#: src/views/settings/components/Avatar.tsx:95
#: src/views/settings/components/Avatar.tsx:56
#: src/views/settings/components/Avatar.tsx:97
msgid "Error uploading profile image"
msgstr "Fout bij het uploaden van profielafbeelding"
@@ -622,11 +639,12 @@ msgstr "Functieverzoek"
msgid "Features"
msgstr "Functies"
#: src/components/FeedbackButton.tsx:78
#: src/components/UserMenu.tsx:199
#: src/components/FeedbackModal.tsx:59
msgid "Feedback"
msgstr "Feedback"
#: src/components/FeedbackButton.tsx:38
#: src/components/FeedbackModal.tsx:33
msgid "Feedback sent"
msgstr "Feedback verzonden"
@@ -674,7 +692,7 @@ msgstr "Aan de slag"
msgid "Get started by creating a new board"
msgstr "Begin door een nieuw bord te maken"
#: src/views/board/index.tsx:319
#: src/views/board/index.tsx:418
msgid "Get started by creating a new list"
msgstr "Begin door een nieuwe lijst te maken"
@@ -747,11 +765,11 @@ msgstr "Ik bevestig dat alle gegevens van de werkruimte permanent worden verwijd
msgid "Ideas"
msgstr "Ideeën"
#: src/components/FeedbackButton.tsx:98
#: src/components/FeedbackModal.tsx:75
msgid "Ideas to improve this page..."
msgstr "Ideeën om deze pagina te verbeteren..."
#: src/views/boards/index.tsx:39
#: src/views/boards/index.tsx:38
msgid "Import"
msgstr "Importeren"
@@ -797,11 +815,19 @@ msgstr "Integraties"
msgid "Interviewing"
msgstr "Interviewen"
#: src/views/members/index.tsx:156
#: src/views/members/components/InviteMemberForm.tsx:26
msgid "Invalid email address"
msgstr "Ongeldig e-mailadres"
#: src/views/members/index.tsx:169
msgid "Invite"
msgstr "Uitnodigen"
#: src/views/members/components/InviteMemberForm.tsx:82
#: src/views/members/components/InviteMemberForm.tsx:113
msgid "Invite another"
msgstr "Nog iemand uitnodigen"
#: src/views/members/components/InviteMemberForm.tsx:123
#: src/views/card/components/MemberSelector.tsx:112
msgid "Invite member"
msgstr "Lid uitnodigen"
@@ -823,8 +849,8 @@ msgstr "Kanban opnieuw uitgevonden"
msgid "Keep in mind that this action is irreversible."
msgstr "Houd er rekening mee dat deze actie onomkeerbaar is."
#: src/views/card/index.tsx:243
#: src/views/board/components/NewCardForm.tsx:331
#: src/views/card/index.tsx:113
#: src/views/board/components/NewCardForm.tsx:358
#: src/views/board/components/Filters.tsx:101
msgid "Labels"
msgstr "Labels"
@@ -833,7 +859,7 @@ msgstr "Labels"
msgid "Labels & Filters"
msgstr "Labels & filters"
#: src/views/settings/index.tsx:157
#: src/views/settings/index.tsx:185
msgid "Language"
msgstr "Taal"
@@ -849,15 +875,15 @@ msgstr "Juridisch"
msgid "License"
msgstr "Licentie"
#: src/components/UserMenu.tsx:126
#: src/components/UserMenu.tsx:167
msgid "Light"
msgstr "Licht"
#: src/views/public/board/index.tsx:51
#: src/views/public/board/index.tsx:57
msgid "Link copied"
msgstr "Link gekopieerd"
#: src/views/card/index.tsx:235
#: src/views/card/index.tsx:105
msgid "List"
msgstr "Lijst"
@@ -869,7 +895,7 @@ msgstr "Lijstnaam"
msgid "Login | kan.bn"
msgstr "Login | kan.bn"
#: src/components/UserMenu.tsx:136
#: src/components/UserMenu.tsx:209
msgid "Logout"
msgstr "Uitloggen"
@@ -881,7 +907,7 @@ msgstr "Lange termijn"
msgid "Low Priority"
msgstr "Lage prioriteit"
#: src/components/AuthForm.tsx:337
#: src/components/AuthForm.tsx:338
msgid "magic link"
msgstr "magische link"
@@ -889,16 +915,16 @@ msgstr "magische link"
msgid "Medium Priority"
msgstr "Gemiddelde prioriteit"
#: src/views/members/index.tsx:148
#: src/views/card/index.tsx:251
#: src/views/board/components/NewCardForm.tsx:290
#: src/views/members/index.tsx:161
#: src/views/card/index.tsx:121
#: src/views/board/components/NewCardForm.tsx:317
#: src/views/board/components/Filters.tsx:93
#: src/components/SideNavigation.tsx:44
#: src/components/SideNavigation.tsx:73
msgid "Members"
msgstr "Leden"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/members/index.tsx:144
#: src/views/members/index.tsx:157
msgid "Members | {0}"
msgstr "Leden | {0}"
@@ -919,11 +945,11 @@ msgstr "heeft de kaart naar een andere lijst verplaatst"
msgid "Name"
msgstr "Naam"
#: src/components/FeedbackButton.tsx:116
#: src/components/FeedbackModal.tsx:95
msgid "Need help?"
msgstr "Hulp nodig?"
#: src/views/boards/index.tsx:52
#: src/views/boards/index.tsx:48
msgid "New"
msgstr "Nieuw"
@@ -931,7 +957,7 @@ msgstr "Nieuw"
msgid "New board"
msgstr "Nieuw bord"
#: src/views/board/components/NewCardForm.tsx:237
#: src/views/board/components/NewCardForm.tsx:261
msgid "New card"
msgstr "Nieuwe kaart"
@@ -943,7 +969,7 @@ msgstr "Nieuwe import"
msgid "New label"
msgstr "Nieuw label"
#: src/views/board/index.tsx:296
#: src/views/board/index.tsx:395
#: src/views/board/components/NewListForm.tsx:112
msgid "New list"
msgstr "Nieuwe lijst"
@@ -952,7 +978,7 @@ msgstr "Nieuwe lijst"
msgid "New Ticket"
msgstr "Nieuw ticket"
#: src/components/NewWorkspaceForm.tsx:62
#: src/components/NewWorkspaceForm.tsx:64
msgid "New workspace"
msgstr "Nieuwe werkruimte"
@@ -976,7 +1002,7 @@ msgstr "Geen borden gevonden"
msgid "No credit card required"
msgstr "Geen creditcard vereist"
#: src/views/board/index.tsx:316
#: src/views/board/index.tsx:415
msgid "No lists"
msgstr "Geen lijsten"
@@ -988,15 +1014,15 @@ msgstr "Aanbod"
msgid "Onboarding"
msgstr "Inwerktraject"
#: src/views/settings/index.tsx:263
#: src/views/settings/index.tsx:291
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."
#: src/views/settings/index.tsx:245
#: src/views/settings/index.tsx:273
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."
#: src/components/AuthForm.tsx:279
#: src/components/AuthForm.tsx:280
msgid "or"
msgstr "of"
@@ -1016,7 +1042,7 @@ msgstr "Deeltijd"
msgid "Payment frequency"
msgstr "Betalingsfrequentie"
#: src/views/members/index.tsx:107
#: src/views/members/index.tsx:118
msgid "Pending"
msgstr "In behandeling"
@@ -1033,19 +1059,19 @@ msgstr "Persoonlijk project"
msgid "Planning"
msgstr "Planning"
#: src/components/AuthForm.tsx:305
#: src/components/AuthForm.tsx:306
msgid "Please enter a valid email address"
msgstr "Voer een geldig e-mailadres in"
#: src/components/AuthForm.tsx:293
#: src/components/AuthForm.tsx:294
msgid "Please enter a valid name"
msgstr "Voer een geldige naam in"
#: src/components/AuthForm.tsx:318
#: src/components/AuthForm.tsx:319
msgid "Please enter a valid password"
msgstr "Voer een geldig wachtwoord in"
#: src/views/settings/components/Avatar.tsx:55
#: src/views/settings/components/Avatar.tsx:57
msgid "Please select a file to upload."
msgstr "Selecteer een bestand om te uploaden."
@@ -1055,26 +1081,28 @@ msgstr "Selecteer een bestand om te uploaden."
#: src/views/settings/components/UpdateDisplayNameForm.tsx:55
#: src/views/settings/components/DeleteWorkspaceConfirmation.tsx:46
#: src/views/settings/components/DeleteAccountConfirmation.tsx:40
#: src/views/settings/components/Avatar.tsx:38
#: src/views/settings/components/Avatar.tsx:96
#: src/views/settings/components/Avatar.tsx:40
#: src/views/settings/components/Avatar.tsx:98
#: src/views/members/components/InviteMemberForm.tsx:64
#: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/card/index.tsx:116
#: src/views/card/index.tsx:159
#: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/DeleteCommentConfirmation.tsx:45
#: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/Comment.tsx:62
#: src/views/card/components/Comment.tsx:64
#: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/board/index.tsx:133
#: src/views/board/index.tsx:189
#: src/views/board/index.tsx:135
#: src/views/board/index.tsx:191
#: src/views/board/components/VisibilityButton.tsx:53
#: src/views/board/components/UpdateBoardSlugForm.tsx:72
#: src/views/board/components/NewListForm.tsx:78
#: src/views/board/components/NewCardForm.tsx:128
#: src/components/NewWorkspaceForm.tsx:39
#: src/components/FeedbackButton.tsx:46
#: src/views/board/components/NewCardForm.tsx:145
#: src/components/NewWorkspaceForm.tsx:41
#: src/components/FeedbackModal.tsx:41
#: src/components/DeleteLabelConfirmation.tsx:23
msgid "Please try again later, or contact customer support."
msgstr "Probeer het later opnieuw of neem contact op met de klantenservice."
@@ -1096,11 +1124,11 @@ msgstr "Privacybeleid"
msgid "Private"
msgstr "Privé"
#: src/views/settings/components/Avatar.tsx:24
#: src/views/settings/components/Avatar.tsx:26
msgid "Profile image updated"
msgstr "Profielafbeelding bijgewerkt"
#: src/views/settings/index.tsx:118
#: src/views/settings/index.tsx:144
msgid "Profile picture"
msgstr "Profielfoto"
@@ -1136,7 +1164,7 @@ msgstr "Op afstand"
msgid "Remove"
msgstr "Verwijderen"
#: src/views/members/index.tsx:120
#: src/views/members/index.tsx:132
msgid "Remove member"
msgstr "Lid verwijderen"
@@ -1177,7 +1205,7 @@ msgstr "Intrekken"
msgid "Roadmap"
msgstr "Roadmap"
#: src/views/members/index.tsx:178
#: src/views/members/index.tsx:191
msgid "Role"
msgstr "Rol"
@@ -1185,7 +1213,7 @@ msgstr "Rol"
msgid "Run on your own infrastructure"
msgstr "Draai op je eigen infrastructuur"
#: src/views/card/components/Comment.tsx:163
#: src/views/card/components/Comment.tsx:165
msgid "Save"
msgstr "Opslaan"
@@ -1217,21 +1245,21 @@ msgstr "Zelf hosten met Github"
msgid "self-assigned the card"
msgstr "heeft de kaart aan zichzelf toegewezen"
#: src/components/FeedbackButton.tsx:137
msgid "Send"
msgstr "Versturen"
#: src/components/FeedbackModal.tsx:116
msgid "Send feedback"
msgstr "Feedback versturen"
#: src/views/boards/components/TemplateBoards.tsx:69
msgid "Senior"
msgstr "Senior"
#: src/views/settings/index.tsx:112
#: src/components/SideNavigation.tsx:49
#: src/views/settings/index.tsx:138
#: src/components/SideNavigation.tsx:78
msgid "Settings"
msgstr "Instellingen"
#. placeholder {0}: workspace.name ?? "Workspace"
#: src/views/settings/index.tsx:108
#: src/views/settings/index.tsx:134
msgid "Settings | {0}"
msgstr "Instellingen | {0}"
@@ -1253,7 +1281,7 @@ msgstr "Registreren uitgeschakeld"
msgid "Sign up is currently disabled. Please try again later."
msgstr "Registreren is momenteel uitgeschakeld. Probeer het later opnieuw."
#: src/components/AuthForm.tsx:334
#: src/components/AuthForm.tsx:335
msgid "Sign up with "
msgstr "Registreren met "
@@ -1282,11 +1310,15 @@ msgstr "Star op Github"
msgid "Success"
msgstr "Geslaagd"
#: src/components/UserMenu.tsx:180
msgid "Support"
msgstr "Ondersteuning"
#: src/views/home/components/Pricing.tsx:57
msgid "Support the development of the project"
msgstr "Ondersteun de ontwikkeling van het project"
#: src/components/UserMenu.tsx:98
#: src/components/UserMenu.tsx:139
msgid "System"
msgstr "Systeem"
@@ -1302,7 +1334,7 @@ msgstr "Sjablonen"
msgid "Terms of service"
msgstr "Servicevoorwaarden"
#: src/components/FeedbackButton.tsx:39
#: src/components/FeedbackModal.tsx:34
msgid "Thank you for your feedback!"
msgstr "Bedankt voor je feedback!"
@@ -1319,7 +1351,7 @@ msgstr "Het open source <0/> alternatief voor Trello"
msgid "The visibility of your board has been set to {0}."
msgstr "De zichtbaarheid van je bord is ingesteld op {0}."
#: src/components/UserMenu.tsx:85
#: src/components/UserMenu.tsx:126
msgid "Theme"
msgstr "Thema"
@@ -1329,9 +1361,14 @@ msgstr "Ze zullen geen toegang meer hebben tot deze werkruimte."
#: src/views/card/components/DeleteCommentConfirmation.tsx:68
#: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/components/DeleteLabelConfirmation.tsx:42
msgid "This action can't be undone."
msgstr "Deze actie kan niet ongedaan worden gemaakt."
#: src/views/public/board/index.tsx:146
msgid "This board is private or does not exist"
msgstr "Dit bord is privé of bestaat niet"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135
msgid "This board URL has already been taken"
msgstr "Deze board URL is al in gebruik"
@@ -1361,7 +1398,7 @@ msgstr "Menu in-/uitschakelen"
msgid "Track all card changes with detailed activity history."
msgstr "Volg alle kaartwijzigingen met gedetailleerde activiteitengeschiedenis."
#: src/views/settings/index.tsx:69
#: src/views/settings/index.tsx:92
msgid "Trello disconnected"
msgstr "Trello ontkoppeld"
@@ -1377,7 +1414,7 @@ msgstr "Triage"
msgid "Unable to add comment"
msgstr "Kan geen reactie toevoegen"
#: src/views/board/components/NewCardForm.tsx:125
#: src/views/board/components/NewCardForm.tsx:142
msgid "Unable to create card"
msgstr "Kan kaart niet aanmaken"
@@ -1385,7 +1422,7 @@ msgstr "Kan kaart niet aanmaken"
msgid "Unable to create list"
msgstr "Kan geen lijst maken"
#: src/components/NewWorkspaceForm.tsx:38
#: src/components/NewWorkspaceForm.tsx:40
msgid "Unable to create workspace"
msgstr "Kan werkruimte niet aanmaken"
@@ -1401,7 +1438,7 @@ msgstr "Kan opmerking niet verwijderen"
msgid "Unable to remove member"
msgstr "Kan lid niet verwijderen"
#: src/components/FeedbackButton.tsx:45
#: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback"
msgstr "Feedback kon niet worden verzonden"
@@ -1413,12 +1450,12 @@ msgstr "Kan board URL niet bijwerken"
msgid "Unable to update board visibility"
msgstr "Kan bordzichtbaarheid niet bijwerken"
#: src/views/card/index.tsx:115
#: src/views/board/index.tsx:188
#: src/views/card/index.tsx:158
#: src/views/board/index.tsx:190
msgid "Unable to update card"
msgstr "Kan kaart niet bijwerken"
#: src/views/card/components/Comment.tsx:61
#: src/views/card/components/Comment.tsx:63
msgid "Unable to update comment"
msgstr "Kan reactie niet bijwerken"
@@ -1427,7 +1464,7 @@ msgid "Unable to update labels"
msgstr "Kan labels niet bijwerken"
#: src/views/card/components/ListSelector.tsx:52
#: src/views/board/index.tsx:132
#: src/views/board/index.tsx:134
msgid "Unable to update list"
msgstr "Kan lijst niet bijwerken"
@@ -1471,11 +1508,11 @@ msgstr "Onbeperkt aantal lijsten"
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:82
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:90
#: src/views/settings/components/UpdateDisplayNameForm.tsx:79
#: src/views/board/components/UpdateBoardSlugForm.tsx:166
#: src/views/board/components/UpdateBoardSlugForm.tsx:174
msgid "Update"
msgstr "Bijwerken"
#: src/components/LabelForm.tsx:233
#: src/components/LabelForm.tsx:236
msgid "Update label"
msgstr "Label bijwerken"
@@ -1516,19 +1553,23 @@ msgstr "URL moet minimaal 3 tekens lang zijn"
msgid "Use template"
msgstr "Sjabloon gebruiken"
#: src/views/members/index.tsx:172
#: src/views/members/index.tsx:185
msgid "User"
msgstr "Gebruiker"
#: src/views/members/components/InviteMemberForm.tsx:58
msgid "User is already a member of this workspace"
msgstr "Gebruiker is al lid van deze werkruimte"
#: src/views/boards/components/TemplateBoards.tsx:37
msgid "Video"
msgstr "Video"
#: src/views/settings/index.tsx:232
#: src/views/settings/index.tsx:260
msgid "View and manage your API keys."
msgstr "Bekijk en beheer je API-sleutels."
#: src/views/settings/index.tsx:171
#: src/views/settings/index.tsx:199
msgid "View and manage your billing and subscription."
msgstr "Bekijk en beheer je facturering en abonnement."
@@ -1536,10 +1577,18 @@ msgstr "Bekijk en beheer je facturering en abonnement."
msgid "View docs"
msgstr "Bekijk documentatie"
#: src/views/public/board/index.tsx:120
msgid "View only"
msgstr "Alleen bekijken"
#: src/views/home/components/Features.tsx:147
msgid "View our roadmap."
msgstr "Bekijk onze roadmap."
#: src/views/public/board/index.tsx:149
msgid "View workspace"
msgstr "Werkruimte bekijken"
#: src/views/board/components/VisibilityButton.tsx:91
msgid "Visibility"
msgstr "Zichtbaarheid"
@@ -1572,7 +1621,7 @@ msgstr "Toen Trello in 2011 werd gelanceerd, blies het iedereen omver met zijn z
msgid "Why make an open source Trello?"
msgstr "Waarom een open source Trello maken?"
#: src/views/board/index.tsx:239
#: src/views/board/index.tsx:332
msgid "Workspace"
msgstr "Werkruimte"
@@ -1580,7 +1629,7 @@ msgstr "Werkruimte"
msgid "Workspace deleted"
msgstr "Werkruimte verwijderd"
#: src/views/settings/index.tsx:147
#: src/views/settings/index.tsx:175
msgid "Workspace description"
msgstr "Werkruimte beschrijving"
@@ -1601,8 +1650,8 @@ msgstr "Werkruimtebeschrijving bijgewerkt"
msgid "Workspace members"
msgstr "Werkruimteleden"
#: src/views/settings/index.tsx:130
#: src/components/NewWorkspaceForm.tsx:78
#: src/views/settings/index.tsx:156
#: src/components/NewWorkspaceForm.tsx:80
msgid "Workspace name"
msgstr "Naam werkruimte"
@@ -1622,7 +1671,7 @@ msgstr "Werkruimtenaam bijgewerkt"
msgid "Workspace slug updated"
msgstr "Werkruimte-slug bijgewerkt"
#: src/views/settings/index.tsx:138
#: src/views/settings/index.tsx:165
msgid "Workspace URL"
msgstr "Werkruimte URL"
@@ -1670,15 +1719,15 @@ msgstr "Je borden zijn geïmporteerd."
msgid "Your display name has been updated."
msgstr "Je weergavenaam is bijgewerkt."
#: src/views/settings/components/Avatar.tsx:25
#: src/views/settings/components/Avatar.tsx:27
msgid "Your profile image has been updated."
msgstr "Je profielafbeelding is bijgewerkt."
#: src/views/settings/index.tsx:70
#: src/views/settings/index.tsx:93
msgid "Your Trello account has been disconnected."
msgstr "Je Trello-account is ontkoppeld."
#: src/views/settings/index.tsx:214
#: src/views/settings/index.tsx:242
msgid "Your Trello account is connected."
msgstr "Je Trello-account is verbonden."

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { env } from "next-runtime-env";
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname === "/") {
if (env("NEXT_PUBLIC_KAN_ENV") !== "cloud") {
const loginUrl = new URL("/login", request.url);
return NextResponse.redirect(loginUrl);
}
}
return NextResponse.next();
}
export const config = {
matcher: ["/"],
};

View File

@@ -1,8 +1,9 @@
import "~/styles/globals.css";
import "~/utils/i18n";
import type { Viewport } from "next";
import type { AppType } from "next/app";
import type { NextPage, Viewport } from "next";
import type { AppProps, AppType } from "next/app";
import type { ReactElement, ReactNode } from "react";
import { Plus_Jakarta_Sans } from "next/font/google";
import Script from "next/script";
import { env } from "next-runtime-env";
@@ -34,7 +35,15 @@ export const viewport: Viewport = {
userScalable: false,
};
const MyApp: AppType = ({ Component, pageProps }) => {
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
getLayout?: (page: ReactElement) => ReactNode;
};
type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout;
};
const MyApp: AppType = ({ Component, pageProps }: AppPropsWithLayout) => {
const posthogKey = env("NEXT_PUBLIC_POSTHOG_KEY");
useEffect(() => {
@@ -50,6 +59,8 @@ const MyApp: AppType = ({ Component, pageProps }) => {
}
}, [posthogKey]);
const getLayout = Component.getLayout ?? ((page) => page);
return (
<>
<style jsx global>{`
@@ -75,10 +86,10 @@ const MyApp: AppType = ({ Component, pageProps }) => {
<PopupProvider>
{posthogKey ? (
<PostHogProvider client={posthog}>
<Component {...pageProps} />
{getLayout(<Component {...pageProps} />)}
</PostHogProvider>
) : (
<Component {...pageProps} />
getLayout(<Component {...pageProps} />)
)}
</PopupProvider>
</ModalProvider>

View File

@@ -46,6 +46,7 @@ export default async function handler(
const client = new S3Client({
region: env.S3_REGION ?? "",
endpoint: env.S3_ENDPOINT ?? "",
forcePathStyle: env.S3_FORCE_PATH_STYLE === "true",
credentials: {
accessKeyId: env.S3_ACCESS_KEY_ID ?? "",
secretAccessKey: env.S3_SECRET_ACCESS_KEY ?? "",
@@ -58,6 +59,7 @@ export default async function handler(
new PutObjectCommand({
Bucket: nextRuntimeEnv("NEXT_PUBLIC_AVATAR_BUCKET_NAME") ?? "",
Key: filename,
ACL: "public-read",
}),
);

View File

@@ -1,15 +1,17 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/Dashboard";
import type { NextPageWithLayout } from "~/pages/_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import BoardView from "~/views/board";
export default function BoardPage() {
const BoardPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard>
<BoardView />
</Dashboard>
<>
<BoardView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
BoardPage.getLayout = (page) => getDashboardLayout(page);
export default BoardPage;

View File

@@ -1,15 +1,17 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/Dashboard";
import type { NextPageWithLayout } from "../_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import BoardsView from "~/views/boards";
export default function BoardsPage() {
const BoardsPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard>
<BoardsView />
</Dashboard>
<>
<BoardsView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
BoardsPage.getLayout = (page) => getDashboardLayout(page);
export default BoardsPage;

View File

@@ -1,15 +1,18 @@
import Dashboard from "~/components/Dashboard";
import type { NextPageWithLayout } from "~/pages/_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import { WorkspaceProvider } from "~/providers/workspace";
import CardView, { CardRightPanel } from "~/views/card";
export default function CardPage() {
const CardPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard hasRightPanel rightPanel={<CardRightPanel />}>
<CardView />
</Dashboard>
<>
<CardView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
CardPage.getLayout = (page) =>
getDashboardLayout(page, <CardRightPanel />, true);
export default CardPage;

View File

@@ -1,15 +1,17 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/Dashboard";
import type { NextPageWithLayout } from "~/pages/_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import MembersView from "~/views/members";
export default function MembersPage() {
const MembersPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard>
<MembersView />
</Dashboard>
<>
<MembersView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
MembersPage.getLayout = (page) => getDashboardLayout(page);
export default MembersPage;

View File

@@ -1,15 +1,17 @@
import { WorkspaceProvider } from "~/providers/workspace";
import Dashboard from "~/components/Dashboard";
import SettingsView from "~/views/settings";
import type { NextPageWithLayout } from "~/pages/_app";
import { getDashboardLayout } from "~/components/Dashboard";
import Popup from "~/components/Popup";
import SettingsView from "~/views/settings";
export default function SettingsPage() {
const SettingsPage: NextPageWithLayout = () => {
return (
<WorkspaceProvider>
<Dashboard>
<SettingsView />
</Dashboard>
<>
<SettingsView />
<Popup />
</WorkspaceProvider>
</>
);
}
};
SettingsPage.getLayout = (page) => getDashboardLayout(page);
export default SettingsPage;

View File

@@ -1,5 +1,15 @@
import { createContext, useContext, useState } from "react";
interface ModalState {
contentType: string;
entityId?: string;
entityLabel?: string;
}
interface Props {
children: React.ReactNode;
}
type ModalContextType = {
isOpen: boolean;
openModal: (
@@ -11,33 +21,64 @@ type ModalContextType = {
modalContentType: string;
entityId: string;
entityLabel: string;
modalStates: Record<string, any>;
setModalState: (modalType: string, state: any) => void;
getModalState: (modalType: string) => any;
clearModalState: (modalType: string) => void;
clearAllModalStates: () => void;
};
interface Props {
children: React.ReactNode;
}
const ModalContext = createContext<ModalContextType | undefined>(undefined);
export const ModalProvider: React.FC<Props> = ({ children }) => {
const [isOpen, setIsOpen] = useState(false);
const [entityId, setEntityId] = useState("");
const [entityLabel, setEntityLabel] = useState("");
const [modalContentType, setModalContentType] = useState("");
const [modalStack, setModalStack] = useState<ModalState[]>([]);
const [modalStates, setModalStates] = useState<Record<string, any>>({});
const isOpen = modalStack.length > 0;
const currentModal = modalStack[modalStack.length - 1];
const modalContentType = currentModal?.contentType || "";
const entityId = currentModal?.entityId || "";
const entityLabel = currentModal?.entityLabel || "";
const openModal = (
contentType: string,
entityId?: string,
entityLabel?: string,
) => {
setIsOpen(true);
setModalContentType(contentType);
if (entityId) setEntityId(entityId);
if (entityLabel) setEntityLabel(entityLabel);
const newModal: ModalState = { contentType, entityId, entityLabel };
setModalStack(prev => [...prev, newModal]);
};
const closeModal = () => {
setIsOpen(false);
setModalStack(prev => {
if (prev.length <= 1) {
return [];
}
return prev.slice(0, -1);
});
};
const setModalState = (modalType: string, state: any) => {
setModalStates(prev => ({
...prev,
[modalType]: state
}));
};
const getModalState = (modalType: string) => {
return modalStates[modalType];
};
const clearModalState = (modalType: string) => {
setModalStates(prev => {
const newStates = { ...prev };
delete newStates[modalType];
return newStates;
});
};
const clearAllModalStates = () => {
setModalStates({});
};
return (
@@ -49,6 +90,11 @@ export const ModalProvider: React.FC<Props> = ({ children }) => {
modalContentType,
entityId,
entityLabel,
modalStates,
setModalState,
getModalState,
clearModalState,
clearAllModalStates,
}}
>
{children}

View File

@@ -18,6 +18,7 @@ import Editor from "~/components/Editor";
import Input from "~/components/Input";
import LabelIcon from "~/components/LabelIcon";
import Toggle from "~/components/Toggle";
import { useModalFormState } from "~/hooks/useModalFormState";
import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
@@ -49,17 +50,24 @@ export function NewCardForm({
const utils = api.useUtils();
// persists the form values
const { formState, saveFormState } = useModalFormState<NewCardFormInput>({
modalType: "NEW_CARD",
initialValues: {
title: "",
description: "",
listPublicId,
labelPublicIds: [],
memberPublicIds: [],
isCreateAnotherEnabled: false,
position: "start",
},
resetOnClose: true,
});
const { register, handleSubmit, reset, setValue, watch } =
useForm<NewCardFormInput>({
defaultValues: {
title: "",
description: "",
listPublicId,
labelPublicIds: [],
memberPublicIds: [],
isCreateAnotherEnabled: false,
position: "start",
},
values: formState,
});
const labelPublicIds = watch("labelPublicIds") || [];
@@ -67,6 +75,15 @@ export function NewCardForm({
const isCreateAnotherEnabled = watch("isCreateAnotherEnabled");
const position = watch("position");
const title = watch("title");
const description = watch("description");
// saving form state whenever form values change
useEffect(() => {
const subscription = watch((data) => {
saveFormState(data as NewCardFormInput);
});
return () => subscription.unsubscribe();
}, [watch, saveFormState]);
const { data: boardData } = api.board.byId.useQuery(queryParams, {
enabled: !!boardPublicId,
@@ -131,17 +148,24 @@ export function NewCardForm({
},
onSuccess: async () => {
const isCreateAnotherEnabled = watch("isCreateAnotherEnabled");
if (!isCreateAnotherEnabled) closeModal();
if (!isCreateAnotherEnabled) {
// close modal (state will auto-clear due to resetOnClose: true)
closeModal();
} else {
// reset form for creating another card
const newFormState = {
title: "",
description: "",
listPublicId: watch("listPublicId"),
labelPublicIds: [],
memberPublicIds: [],
isCreateAnotherEnabled,
position,
};
reset(newFormState);
saveFormState(newFormState);
}
await utils.board.byId.invalidate(queryParams);
reset({
title: "",
description: "",
listPublicId: watch("listPublicId"),
labelPublicIds: [],
memberPublicIds: [],
isCreateAnotherEnabled,
position,
});
},
});
@@ -264,8 +288,11 @@ export function NewCardForm({
<div className="mt-2">
<div className="block max-h-48 min-h-24 w-full overflow-y-auto rounded-md border-0 bg-dark-300 bg-white/5 px-3 py-2 text-sm shadow-sm ring-1 ring-inset ring-light-600 focus-within:ring-2 focus-within:ring-inset focus-within:ring-light-700 dark:ring-dark-700 dark:focus-within:ring-dark-700 sm:leading-6">
<Editor
content=""
onChange={(value) => setValue("description", value)}
content={description}
onChange={(value) => {
setValue("description", value);
saveFormState({ ...formState, description: value });
}}
/>
</div>
</div>

View File

@@ -145,7 +145,12 @@ export function NewListForm({
/>
<div>
<Button type="submit">{t`Create list`}</Button>
<Button
type="submit"
disabled={createList.isPending || !watch("name")}
>
{t`Create list`}
</Button>
</div>
</div>
</form>

View File

@@ -0,0 +1,53 @@
import Link from "next/link";
import { env } from "next-runtime-env";
import { HiLink } from "react-icons/hi";
const UpdateBoardSlugButton = ({
handleOnClick,
workspaceSlug,
boardSlug,
isLoading,
}: {
handleOnClick: () => void;
workspaceSlug: string;
boardSlug: string;
isLoading: boolean;
}) => {
if (!isLoading && (!workspaceSlug || !boardSlug)) return <></>;
if (isLoading) {
return (
<div className="hidden h-[36px] w-[225px] animate-pulse rounded-full bg-light-200 dark:bg-dark-100 xl:flex" />
);
}
return (
<button
onClick={handleOnClick}
className="hidden cursor-pointer items-center gap-2 rounded-full border-[1px] bg-light-50 p-1 pl-4 pr-1 text-sm text-light-950 hover:bg-light-100 dark:border-dark-600 dark:bg-dark-50 dark:text-dark-900 dark:hover:bg-dark-100 xl:flex"
>
<div className="flex items-center">
<span>
{env("NEXT_PUBLIC_KAN_ENV") === "cloud"
? "kan.bn"
: env("NEXT_PUBLIC_BASE_URL")}
</span>
<div className="mx-1.5 h-4 w-px rotate-[20deg] bg-gray-300 dark:bg-dark-600"></div>
<span>{workspaceSlug}</span>
<div className="mx-1.5 h-4 w-px rotate-[20deg] bg-gray-300 dark:bg-dark-600"></div>
<span>{boardSlug}</span>
</div>
<Link
href={`${env("NEXT_PUBLIC_BASE_URL")}/${workspaceSlug}/${boardSlug}`}
target="_blank"
rel="noopener noreferrer"
onClick={(e) => e.stopPropagation()}
className="flex h-7 w-7 items-center justify-center rounded-full hover:bg-light-200 dark:hover:bg-dark-200"
>
<HiLink className="h-[13px] w-[13px]" />
</Link>
</button>
);
};
export default UpdateBoardSlugButton;

View File

@@ -135,7 +135,7 @@ export function UpdateBoardSlugForm({
? t`This board URL has already been taken`
: undefined)
}
prefix={`${env("NEXT_PUBLIC_BASE_URL")}/${workspaceSlug}/`}
prefix={`${env("NEXT_PUBLIC_KAN_ENV") === "cloud" ? "kan.bn" : env("NEXT_PUBLIC_BASE_URL")}/${workspaceSlug}/`}
onKeyDown={async (e) => {
if (e.key === "Enter") {
e.preventDefault();
@@ -152,7 +152,14 @@ export function UpdateBoardSlugForm({
/>
</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>
<div className="flex items-center gap-2">
<Button
variant="secondary"
href="/settings?edit=workspace_url"
onClick={closeModal}
>
{t`Edit workspace URL`}
</Button>
<Button
type="submit"
isLoading={updateBoardSlug.isPending}
@@ -160,7 +167,8 @@ export function UpdateBoardSlugForm({
!isDirty ||
updateBoardSlug.isPending ||
errors.slug?.message !== undefined ||
isBoardSlugAvailable?.isReserved
isBoardSlugAvailable?.isReserved ||
checkBoardSlugAvailability.isLoading
}
>
{t`Update`}

View File

@@ -13,6 +13,7 @@ import type { UpdateBoardInput } from "@kan/api/types";
import Button from "~/components/Button";
import { DeleteLabelConfirmation } from "~/components/DeleteLabelConfirmation";
import FeedbackModal from "~/components/FeedbackModal";
import { LabelForm } from "~/components/LabelForm";
import Modal from "~/components/modal";
import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
@@ -32,6 +33,7 @@ import Filters from "./components/Filters";
import List from "./components/List";
import { NewCardForm } from "./components/NewCardForm";
import { NewListForm } from "./components/NewListForm";
import UpdateBoardSlugButton from "./components/UpdateBoardSlugButton";
import { UpdateBoardSlugForm } from "./components/UpdateBoardSlugForm";
import VisibilityButton from "./components/VisibilityButton";
@@ -43,7 +45,7 @@ export default function BoardPage() {
const utils = api.useUtils();
const { showPopup } = usePopup();
const { workspace } = useWorkspace();
const { openModal, modalContentType, entityId } = useModal();
const { openModal, modalContentType, entityId, isOpen } = useModal();
const [selectedPublicListId, setSelectedPublicListId] =
useState<PublicListId>("");
const [isInitialLoading, setIsInitialLoading] = useState(true);
@@ -233,6 +235,97 @@ export default function BoardPage() {
}
};
const renderModalContent = () => {
return (
<>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_BOARD"}
>
<DeleteBoardConfirmation boardPublicId={boardId ?? ""} />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_LIST"}
>
<DeleteListConfirmation
listPublicId={selectedPublicListId}
queryParams={queryParams}
/>
</Modal>
<Modal
modalSize="md"
isVisible={isOpen && modalContentType === "NEW_CARD"}
>
<NewCardForm
boardPublicId={boardId ?? ""}
listPublicId={selectedPublicListId}
queryParams={queryParams}
/>
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_LIST"}
>
<NewListForm
boardPublicId={boardId ?? ""}
queryParams={queryParams}
/>
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_WORKSPACE"}
>
<NewWorkspaceForm />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "NEW_LABEL"}
>
<LabelForm boardPublicId={boardId ?? ""} refetch={refetchBoard} />
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "EDIT_LABEL"}
>
<LabelForm
boardPublicId={boardId ?? ""}
refetch={refetchBoard}
isEdit
/>
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "DELETE_LABEL"}
>
<DeleteLabelConfirmation
refetch={refetchBoard}
labelPublicId={entityId}
/>
</Modal>
<Modal
modalSize="sm"
isVisible={isOpen && modalContentType === "UPDATE_BOARD_SLUG"}
>
<UpdateBoardSlugForm
boardPublicId={boardId ?? ""}
workspaceSlug={workspace.slug ?? ""}
boardSlug={boardData?.slug ?? ""}
queryParams={queryParams}
/>
</Modal>
</>
);
};
return (
<>
<PageHead
@@ -267,6 +360,12 @@ export default function BoardPage() {
)}
<div className="order-1 mb-4 flex items-center justify-end space-x-2 md:order-2 md:mb-0">
<UpdateBoardSlugButton
handleOnClick={() => openModal("UPDATE_BOARD_SLUG")}
isLoading={isLoading}
workspaceSlug={workspace.slug ?? ""}
boardSlug={boardData?.slug ?? ""}
/>
<VisibilityButton
visibility={boardData?.visibility ?? "private"}
boardPublicId={boardId ?? ""}
@@ -358,7 +457,7 @@ export default function BoardPage() {
<div
ref={provided.innerRef}
{...provided.droppableProps}
className="scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-w-[8px] z-10 h-full max-h-[calc(100vh-265px)] min-h-[2rem] overflow-y-auto pr-1 scrollbar dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-600"
className="scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-w-[8px] z-10 h-full max-h-[calc(100vh-225px)] min-h-[2rem] overflow-y-auto pr-1 scrollbar dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-600"
>
{list.cards.map((card, index) => (
<Draggable
@@ -414,55 +513,7 @@ export default function BoardPage() {
</>
) : null}
</div>
<Modal modalSize={modalContentType === "NEW_CARD" ? "md" : "sm"}>
{modalContentType === "DELETE_BOARD" && (
<DeleteBoardConfirmation boardPublicId={boardId ?? ""} />
)}
{modalContentType === "DELETE_LIST" && (
<DeleteListConfirmation
listPublicId={selectedPublicListId}
queryParams={queryParams}
/>
)}
{modalContentType === "NEW_CARD" && (
<NewCardForm
boardPublicId={boardId ?? ""}
listPublicId={selectedPublicListId}
queryParams={queryParams}
/>
)}
{modalContentType === "NEW_LIST" && (
<NewListForm
boardPublicId={boardId ?? ""}
queryParams={queryParams}
/>
)}
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />}
{modalContentType === "NEW_LABEL" && (
<LabelForm boardPublicId={boardId ?? ""} refetch={refetchBoard} />
)}
{modalContentType === "EDIT_LABEL" && (
<LabelForm
boardPublicId={boardId ?? ""}
refetch={refetchBoard}
isEdit
/>
)}
{modalContentType === "DELETE_LABEL" && (
<DeleteLabelConfirmation
refetch={refetchBoard}
labelPublicId={entityId}
/>
)}
{modalContentType === "UPDATE_BOARD_SLUG" && (
<UpdateBoardSlugForm
boardPublicId={boardId ?? ""}
workspaceSlug={workspace.slug ?? ""}
boardSlug={boardData?.slug ?? ""}
queryParams={queryParams}
/>
)}
</Modal>
{renderModalContent()}
</div>
</>
);

View File

@@ -19,7 +19,7 @@ export function BoardsList() {
if (isLoading)
return (
<div className="xxl:grid-cols-7 grid w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<div className="grid h-fit w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-7">
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
<div className="mr-5 flex h-[150px] w-full animate-pulse rounded-md bg-light-200 dark:bg-dark-100" />
@@ -45,12 +45,12 @@ export function BoardsList() {
);
return (
<div className="grid h-fit w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-7">
<div className="grid h-fit w-full grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-7">
{data?.map((board) => (
<Link key={board.publicId} href={`boards/${board.publicId}`}>
<div className="align-center relative mr-5 flex h-[150px] w-full items-center justify-center rounded-md border border-dashed border-light-400 bg-light-50 shadow-sm hover:bg-light-200 dark:border-dark-600 dark:bg-dark-50 dark:hover:bg-dark-100">
<PatternedBackground />
<p className="text-md px-4 font-bold text-neutral-900 dark:text-dark-1000">
<p className="px-4 text-[14px] font-bold text-neutral-700 dark:text-dark-1000">
{board.name}
</p>
</div>

View File

@@ -2,6 +2,7 @@ import { t } from "@lingui/core/macro";
import { HiArrowDownTray, HiOutlinePlusSmall } from "react-icons/hi2";
import Button from "~/components/Button";
import FeedbackModal from "~/components/FeedbackModal";
import Modal from "~/components/modal";
import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
import { PageHead } from "~/components/PageHead";
@@ -20,8 +21,8 @@ export default function BoardsPage() {
return (
<>
<PageHead title={t`Boards | ${workspace.name ?? "Workspace"}`} />
<div className="m-auto h-full max-w-[1600px] px-5 py-6 md:px-8 md:py-8">
<div className="mb-8 flex w-full items-center justify-between">
<div className="m-auto h-full max-w-[1100px] p-6 px-5 md:px-28 md:py-12">
<div className="relative z-10 mb-8 flex w-full items-center justify-between">
<h1 className="font-bold tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
{t`Boards`}
</h1>
@@ -49,7 +50,8 @@ export default function BoardsPage() {
</div>
</div>
<Modal>
<Modal modalSize={modalContentType === "NEW_FEEDBACK" ? "md" : "sm"}>
{modalContentType === "NEW_FEEDBACK" && <FeedbackModal />}
{modalContentType === "NEW_BOARD" && <NewBoardForm />}
{modalContentType === "IMPORT_BOARDS" && <ImportBoardsForm />}
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />}

View File

@@ -155,11 +155,13 @@ const ActivityList = ({
cardPublicId,
isLoading,
isAdmin,
isViewOnly,
}: {
activities: NonNullable<GetCardByIdOutput>["activities"];
cardPublicId: string;
isLoading: boolean;
isAdmin?: boolean;
isViewOnly?: boolean;
}) => {
const { data } = authClient.useSession();
const { locale } = useLocalisation();
@@ -193,6 +195,7 @@ const ActivityList = ({
isEdited={!!activity.comment?.updatedAt}
isAuthor={activity.comment?.createdBy === data?.user.id}
isAdmin={isAdmin ?? false}
isViewOnly={!!isViewOnly}
/>
);

View File

@@ -27,6 +27,7 @@ const Comment = ({
isAuthor,
isAdmin,
isEdited = false,
isViewOnly = false,
}: {
publicId: string | undefined;
cardPublicId: string;
@@ -38,6 +39,7 @@ const Comment = ({
isAuthor: boolean;
isAdmin: boolean;
isEdited: boolean;
isViewOnly: boolean;
}) => {
const [isEditing, setIsEditing] = useState(false);
const utils = api.useUtils();
@@ -124,7 +126,7 @@ const Comment = ({
</p>
</div>
{dropdownItems.length > 0 && (
{dropdownItems.length > 0 && !isViewOnly && (
<div className="absolute right-4 top-4">
<Dropdown items={dropdownItems}>
<HiEllipsisHorizontal className="h-5 w-5 text-light-900 dark:text-dark-800" />

View File

@@ -113,7 +113,7 @@ export default function LabelSelector({
</Menu.Button>
</div>
) : (
<Menu.Button className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-200 pl-2 text-left text-sm text-neutral-900 hover:bg-light-300 dark:border-dark-100 dark:text-dark-1000 dark:hover:border-dark-300 dark:hover:bg-dark-200">
<Menu.Button className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-50 pl-2 text-left text-sm text-neutral-900 hover:border-light-300 hover:bg-light-200 dark:border-dark-50 dark:text-dark-1000 dark:hover:border-dark-200 dark:hover:bg-dark-100">
<HiMiniPlus size={22} className="pr-2" />
{t`Add label`}
</Menu.Button>

View File

@@ -79,7 +79,7 @@ export default function ListSelector({
}}
asChild
>
<Menu.Button className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-200 py-1 pl-2 text-left text-sm text-neutral-900 hover:border-light-300 hover:bg-light-300 dark:border-dark-100 dark:text-dark-1000 dark:hover:border-dark-300 dark:hover:bg-dark-200">
<Menu.Button className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-50 py-1 pl-2 text-left text-sm text-neutral-900 hover:border-light-300 hover:bg-light-200 dark:border-dark-50 dark:text-dark-1000 dark:hover:border-dark-200 dark:hover:bg-dark-100">
{selectedList?.value}
</Menu.Button>
</CheckboxDropdown>

View File

@@ -112,7 +112,7 @@ export default function MemberSelector({
createNewItemLabel={t`Invite member`}
asChild
>
<Menu.Button className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-200 py-1 pl-2 text-left text-sm text-neutral-900 hover:bg-light-300 dark:border-dark-100 dark:text-dark-1000 dark:hover:border-dark-300 dark:hover:bg-dark-200">
<Menu.Button className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-50 py-1 pl-2 text-left text-sm text-neutral-900 hover:border-light-300 hover:bg-light-200 dark:border-dark-50 dark:text-dark-1000 dark:hover:border-dark-200 dark:hover:bg-dark-100">
{selectedMembers.length ? (
<div className="isolate flex justify-end -space-x-1 overflow-hidden">
{selectedMembers.map(({ value, imageUrl }) => (

View File

@@ -51,7 +51,7 @@ const NewCommentForm = ({ cardPublicId }: { cardPublicId: string }) => {
return (
<form
onSubmit={handleSubmit(onSubmit)}
className="flex w-full max-w-[1000px] flex-col rounded-xl border border-light-600 bg-light-200 p-4 text-light-900 focus-visible:outline-none dark:border-dark-400 dark:bg-dark-100 dark:text-dark-1000 sm:text-sm sm:leading-6"
className="flex w-full max-w-[800px] flex-col rounded-xl border border-light-600 bg-light-100 p-4 text-light-900 focus-visible:outline-none dark:border-dark-400 dark:bg-dark-100 dark:text-dark-1000 sm:text-sm sm:leading-6"
>
<ContentEditable
placeholder={t`Add a comment...`}

View File

@@ -6,6 +6,7 @@ import { IoChevronForwardSharp } from "react-icons/io5";
import Avatar from "~/components/Avatar";
import Editor from "~/components/Editor";
import FeedbackModal from "~/components/FeedbackModal";
import { LabelForm } from "~/components/LabelForm";
import LabelIcon from "~/components/LabelIcon";
import Modal from "~/components/modal";
@@ -99,7 +100,7 @@ export function CardRightPanel() {
}) ?? [];
return (
<div className="h-full w-[360px] border-l-[1px] border-light-600 bg-light-200 p-8 text-light-900 dark:border-dark-400 dark:bg-dark-100 dark:text-dark-900">
<div className="h-full w-[360px] border-l-[1px] border-light-300 bg-light-50 p-8 text-light-900 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900">
<div className="mb-4 flex w-full flex-row">
<p className="my-2 mb-2 w-[100px] text-sm font-medium">{t`List`}</p>
<ListSelector
@@ -188,9 +189,9 @@ export default function CardPage() {
title={t`${card?.title ?? "Card"} | ${board?.name ?? "Board"}`}
/>
<div className="flex h-full flex-1 flex-row">
<div className="flex h-full w-full flex-col overflow-hidden">
<div className="h-full max-h-[calc(100vh-4rem)] overflow-y-auto p-6 md:p-8">
<div className="mb-8 flex w-full items-center justify-between">
<div className="m-auto flex h-full w-full max-w-[800px] flex-col overflow-hidden">
<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="mb-8 flex w-full items-center justify-between md:mt-6">
{!card && isLoading && (
<div className="flex space-x-2">
<div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" />
@@ -250,7 +251,7 @@ export default function CardPage() {
</div>
</form>
</div>
<div className="border-t-[1px] border-light-600 pt-12 dark:border-dark-400">
<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>
@@ -271,7 +272,8 @@ export default function CardPage() {
</div>
</div>
<Modal>
<Modal modalSize={modalContentType === "NEW_FEEDBACK" ? "md" : "sm"}>
{modalContentType === "NEW_FEEDBACK" && <FeedbackModal />}
{modalContentType === "NEW_LABEL" && (
<LabelForm boardPublicId={boardId ?? ""} refetch={refetchCard} />
)}

View File

@@ -40,7 +40,7 @@ export default function HomeView() {
</div>
</div>
<div className="relative overflow-hidden rounded-full bg-gradient-to-b from-light-300 to-light-400 p-[2px] dark:from-dark-300 dark:to-dark-400">
{/* <div className="relative overflow-hidden rounded-full bg-gradient-to-b from-light-300 to-light-400 p-[2px] dark:from-dark-300 dark:to-dark-400">
<div className="relative z-10 rounded-full bg-light-50 dark:bg-dark-50">
<Link
href="https://news.ycombinator.com/item?id=44157177"
@@ -58,7 +58,7 @@ export default function HomeView() {
</div>
</Link>
</div>
</div>
</div> */}
</div>
<p className="mt-2 text-center text-4xl font-bold text-light-1000 dark:text-dark-1000 lg:text-5xl">

View File

@@ -1,26 +1,43 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { t } from "@lingui/core/macro";
import { useEffect } from "react";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { HiXMark } from "react-icons/hi2";
import { z } from "zod";
import type { InviteMemberInput } from "@kan/api/types";
import Button from "~/components/Button";
import Input from "~/components/Input";
import Toggle from "~/components/Toggle";
import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup";
import { useWorkspace } from "~/providers/workspace";
import { api } from "~/utils/api";
export function InviteMemberForm() {
const utils = api.useUtils();
const [isCreateAnotherEnabled, setIsCreateAnotherEnabled] = useState(false);
const { closeModal } = useModal();
const { workspace } = useWorkspace();
const { showPopup } = usePopup();
const { register, handleSubmit } = useForm<InviteMemberInput>({
const InviteMemberSchema = z.object({
email: z.string().email({ message: t`Invalid email address` }),
workspacePublicId: z.string(),
});
const {
register,
handleSubmit,
reset,
formState: { errors },
} = useForm<InviteMemberInput>({
defaultValues: {
email: "",
workspacePublicId: workspace.publicId || "",
},
resolver: zodResolver(InviteMemberSchema),
});
const refetchBoards = () => utils.board.all.refetch();
@@ -31,6 +48,24 @@ export function InviteMemberForm() {
await utils.workspace.byId.refetch();
await refetchBoards();
},
onError: (error) => {
reset();
if (!isCreateAnotherEnabled) closeModal();
if (error.data?.code === "CONFLICT") {
showPopup({
header: t`Error inviting member`,
message: t`User is already a member of this workspace`,
icon: "error",
});
} else {
showPopup({
header: t`Error inviting member`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
}
},
});
const onSubmit = (data: InviteMemberInput) => {
@@ -69,10 +104,16 @@ export function InviteMemberForm() {
await handleSubmit(onSubmit)();
}
}}
errorMessage={errors.email?.message}
/>
</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">
<Toggle
label={t`Invite another`}
isChecked={isCreateAnotherEnabled}
onChange={() => setIsCreateAnotherEnabled(!isCreateAnotherEnabled)}
/>
<div>
<Button
type="submit"

View File

@@ -7,6 +7,7 @@ import { authClient } from "@kan/auth/client";
import Avatar from "~/components/Avatar";
import Button from "~/components/Button";
import Dropdown from "~/components/Dropdown";
import FeedbackModal from "~/components/FeedbackModal";
import Modal from "~/components/modal";
import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
import { PageHead } from "~/components/PageHead";
@@ -96,7 +97,7 @@ export default function MembersPage() {
</td>
<td
className={twMerge(
"w-auto min-w-[120px] sm:w-[35%] sm:min-w-[150px]",
"w-auto min-w-[120px] overflow-visible sm:w-[35%] sm:min-w-[150px]",
isLastRow && "rounded-br-lg",
)}
>
@@ -120,7 +121,7 @@ export default function MembersPage() {
</div>
<div
className={twMerge(
"relative",
"relative z-50",
(workspace.role !== "admin" || showSkeleton) && "hidden",
)}
>
@@ -154,7 +155,7 @@ export default function MembersPage() {
return (
<>
<PageHead title={t`Members | ${workspace.name ?? "Workspace"}`} />
<div className="m-auto h-full max-w-[1600px] p-6 px-5 md:px-28 md:py-12">
<div className="m-auto h-full max-w-[1100px] p-6 px-5 md:px-28 md:py-12">
<div className="mb-8 flex w-full justify-between">
<h1 className="font-bold tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
{t`Members`}
@@ -171,10 +172,10 @@ export default function MembersPage() {
</div>
<div className="mt-8 flow-root">
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full px-4 py-2 align-middle sm:px-6 lg:px-8">
<div className="-mx-4 -my-2 sm:-mx-6 lg:-mx-8">
<div className="inline-block min-w-full overflow-x-auto px-4 py-2 pb-16 align-middle sm:px-6 lg:px-8">
<div className="h-full shadow ring-1 ring-black ring-opacity-5 sm:rounded-lg">
<table className="min-w-full divide-y divide-light-600 dark:divide-dark-600">
<table className="min-w-full divide-y divide-light-600 overflow-visible dark:divide-dark-600">
<thead className="rounded-t-lg bg-light-300 dark:bg-dark-200">
<tr>
<th
@@ -191,7 +192,7 @@ export default function MembersPage() {
</th>
</tr>
</thead>
<tbody className="divide-y divide-light-600 bg-light-50 dark:divide-dark-600 dark:bg-dark-100">
<tbody className="divide-y divide-light-600 overflow-visible bg-light-50 dark:divide-dark-600 dark:bg-dark-100">
{!isLoading &&
data?.members.map((member, index) => (
<TableRow
@@ -221,7 +222,8 @@ export default function MembersPage() {
</div>
</div>
<Modal>
<Modal modalSize={modalContentType === "NEW_FEEDBACK" ? "md" : "sm"}>
{modalContentType === "NEW_FEEDBACK" && <FeedbackModal />}
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />}
{modalContentType === "INVITE_MEMBER" && <InviteMemberForm />}
{modalContentType === "REMOVE_MEMBER" && <DeleteMemberConfirmation />}

View File

@@ -1,10 +1,11 @@
import { useRouter } from "next/router";
import { t } from "@lingui/core/macro";
import { useEffect, useRef, useState } from "react";
import { HiXMark } from "react-icons/hi2";
import { authClient } from "@kan/auth/client";
import Badge from "~/components/Badge";
import Editor from "~/components/Editor";
import LabelIcon from "~/components/LabelIcon";
import { useModal } from "~/providers/modal";
import { api } from "~/utils/api";
import ActivityList from "~/views/card/components/ActivityList";
@@ -20,7 +21,9 @@ export function CardModal({
}) {
const router = useRouter();
const { closeModal, isOpen } = useModal();
const { data: session } = authClient.useSession();
const [showFade, setShowFade] = useState(false);
const [showTopFade, setShowTopFade] = useState(false);
const scrollRef = useRef<HTMLDivElement>(null);
const { data, isLoading } = api.card.byId.useQuery(
{
@@ -33,85 +36,115 @@ export function CardModal({
const labels = data?.labels ?? [];
const handleScroll = () => {
if (!scrollRef.current) return;
const { scrollTop, scrollHeight, clientHeight } = scrollRef.current;
const isAtBottom = scrollTop + clientHeight >= scrollHeight - 5;
const isAtTop = scrollTop <= 5;
setShowFade(!isAtBottom);
setShowTopFade(!isAtTop);
};
useEffect(() => {
const scrollElement = scrollRef.current;
if (!scrollElement) return;
handleScroll();
scrollElement.addEventListener("scroll", handleScroll);
return () => scrollElement.removeEventListener("scroll", handleScroll);
}, [data]);
return (
<div className="flex h-full flex-1 flex-row">
<div className="flex h-full w-full flex-col overflow-hidden">
<div className="h-full max-h-[calc(100vh-4rem)] overflow-y-auto p-8">
<div className="flex w-full items-center justify-between">
<button
className="absolute right-[2rem] top-[2rem] rounded p-1 hover:bg-light-300 focus:outline-none dark:hover:bg-dark-300"
onClick={async (e) => {
e.preventDefault();
closeModal();
try {
await router.replace(
`/${workspaceSlug}/${boardSlug}`,
undefined,
{
shallow: true,
},
);
} catch (error) {
console.error(error);
}
}}
>
<HiXMark
size={18}
className="dark:text-dark-9000 text-light-900"
/>
</button>
{isLoading ? (
<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>
) : (
<>
<h1 className="font-medium leading-[2.3rem] tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
{data?.title}
</h1>
</>
)}
</div>
<div className="h-full p-8">
<div className="mb-6">
{labels.map((label) => (
<div
key={label.publicId}
className="my-1 mr-1 inline-flex w-fit items-center gap-x-1.5 rounded-full px-2 py-1 text-[12px] font-medium text-light-800 ring-1 ring-inset ring-light-600 dark:text-dark-1000 dark:ring-dark-800"
<div className="flex w-full items-center justify-between">
<button
className="absolute right-[2rem] top-[2rem] rounded p-1 hover:bg-light-300 focus:outline-none dark:hover:bg-dark-300"
onClick={async (e) => {
e.preventDefault();
closeModal();
try {
await router.replace(
`/${workspaceSlug}/${boardSlug}`,
undefined,
{
shallow: true,
},
);
} catch (error) {
console.error(error);
}
}}
>
<svg
fill={label.colourCode ?? "#3730a3"}
className="h-2 w-2"
viewBox="0 0 6 6"
aria-hidden="true"
>
<circle cx={3} cy={3} r={3} />
</svg>
<div>{label.name}</div>
</div>
))}
</div>
{data?.description && (
<div className="mb-10 flex w-full max-w-2xl justify-between">
<div className="mt-2">
<Editor content={data.description} readOnly />
</div>
</div>
)}
<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">
{t`Activity`}
</h2>
<div>
{cardPublicId && (
<ActivityList
cardPublicId={cardPublicId}
activities={data?.activities ?? []}
isLoading={isLoading}
<HiXMark
size={18}
className="dark:text-dark-9000 text-light-900"
/>
</button>
{isLoading ? (
<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>
) : (
<>
<h1 className="pr-8 font-bold leading-[2.3rem] tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
{data?.title}
</h1>
</>
)}
</div>
{labels.length > 0 && (
<div className="mt-2">
{labels.map((label) => (
<Badge
key={label.publicId}
value={label.name}
iconLeft={<LabelIcon colourCode={label.colourCode} />}
/>
))}
</div>
)}
</div>
<div className="relative">
<div
ref={scrollRef}
className="h-full max-h-[425px] overflow-y-auto"
>
{data?.description && (
<div className="mb-10 flex w-full max-w-2xl justify-between">
<div className="mt-2">
<Editor content={data.description} readOnly />
</div>
</div>
)}
<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">
{t`Activity`}
</h2>
<div>
{cardPublicId && (
<ActivityList
cardPublicId={cardPublicId}
activities={data?.activities ?? []}
isLoading={isLoading}
isViewOnly={true}
/>
)}
</div>
</div>
</div>
{showTopFade && (
<div className="pointer-events-none absolute left-0 right-0 top-0 h-6 bg-gradient-to-b from-white/80 to-transparent dark:from-dark-100/80" />
)}
{showFade && (
<div className="pointer-events-none absolute bottom-0 left-0 right-0 h-6 bg-gradient-to-t from-white/80 to-transparent dark:from-dark-100/80" />
)}
</div>
</div>
</div>

View File

@@ -3,8 +3,9 @@ import { useRouter } from "next/router";
import { t } from "@lingui/core/macro";
import { keepPreviousData } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { HiLink } from "react-icons/hi2";
import { HiLink, HiOutlineLockClosed } from "react-icons/hi2";
import Button from "~/components/Button";
import Modal from "~/components/modal";
import { PageHead } from "~/components/PageHead";
import PatternedBackground from "~/components/PatternedBackground";
@@ -28,9 +29,14 @@ export default function PublicBoardView() {
? router.query.boardSlug[0]
: router.query.boardSlug;
const workspaceSlug = Array.isArray(router.query.workspaceSlug)
? router.query.workspaceSlug[0]
: router.query.workspaceSlug;
const { data, isLoading } = api.board.bySlug.useQuery(
{
boardSlug: boardSlug ?? "",
workspaceSlug: workspaceSlug ?? "",
members: formatToArray(router.query.members),
labels: formatToArray(router.query.labels),
},
@@ -105,26 +111,47 @@ export default function PublicBoardView() {
{data?.name}
</h1>
)}
<div className="flex items-center space-x-2">
<Filters
labels={data?.labels ?? []}
members={[]}
isLoading={isLoading}
/>
</div>
{data && (
<div className="z-10 flex items-center space-x-2">
<div className="inline-flex cursor-default items-center justify-center whitespace-nowrap rounded-md border-[1px] border-light-300 bg-light-50 px-3 py-2 text-sm font-semibold text-light-950 shadow-sm dark:border-dark-300 dark:bg-dark-50 dark:text-dark-950">
<span className="mr-2">
<HiOutlineLockClosed />
</span>
{t`View only`}
</div>
<Filters
labels={data.labels ?? []}
members={[]}
isLoading={isLoading}
/>
</div>
)}
</div>
<div className="scrollbar-w-none scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-h-[8px] relative 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 ? (
<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-[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>
) : !data ? (
<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">
<HiOutlineLockClosed className="h-10 w-10 text-light-800 dark:text-dark-800" />
<p className="mb-2 mt-4 text-[14px] font-bold text-light-1000 dark:text-dark-950">
{t`Board not found`}
</p>
<p className="text-[14px] text-light-900 dark:text-dark-900">
{t`This board is private or does not exist`}
</p>
</div>
<Button href={`/${workspaceSlug}`}>{t`View workspace`}</Button>
</div>
) : (
<div className="flex">
<div className="min-w-[2rem]" />
{data?.lists.map((list) => (
{data.lists.map((list) => (
<div
key={list.publicId}
className="dark-text-dark-1000 mr-5 h-fit min-w-[18rem] max-w-[18rem] rounded-md border border-light-400 bg-light-300 py-2 pl-2 pr-1 text-neutral-900 dark:border-dark-300 dark:bg-dark-100"

View File

@@ -3,6 +3,8 @@ import { t } from "@lingui/core/macro";
import { env } from "next-runtime-env";
import { useState } from "react";
import { generateUID } from "@kan/shared/utils";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
import { getAvatarUrl } from "~/utils/helpers";
@@ -58,7 +60,7 @@ export default function Avatar({
}
const fileExt = file.name.split(".").pop();
const fileName = `${userId}/avatar.${fileExt}`;
const fileName = `${userId}/avatar-${generateUID()}.${fileExt}`;
setUploading(true);

View File

@@ -1,9 +1,11 @@
import { useRouter } from "next/router";
import { t } from "@lingui/core/macro";
import { env } from "next-runtime-env";
import { useEffect } from "react";
import { useEffect, useRef } from "react";
import { HiMiniArrowTopRightOnSquare } from "react-icons/hi2";
import Button from "~/components/Button";
import FeedbackModal from "~/components/FeedbackModal";
import { LanguageSelector } from "~/components/LanguageSelector";
import Modal from "~/components/modal";
import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
@@ -27,6 +29,9 @@ export default function SettingsPage() {
const { workspace } = useWorkspace();
const utils = api.useUtils();
const { showPopup } = usePopup();
const router = useRouter();
const workspaceUrlSectionRef = useRef<HTMLDivElement>(null);
const scrollContainerRef = useRef<HTMLDivElement>(null);
const { data } = api.user.getUser.useQuery();
@@ -59,6 +64,24 @@ export default function SettingsPage() {
};
}, [refetchIntegrations]);
useEffect(() => {
if (
router.query.edit === "workspace_url" &&
workspaceUrlSectionRef.current &&
scrollContainerRef.current
) {
const element = workspaceUrlSectionRef.current;
const container = scrollContainerRef.current;
container.scrollTop = element.offsetTop - 40;
const input = element.querySelector('input[type="text"]');
if (input instanceof HTMLInputElement) {
input.focus();
}
}
}, [router.query.edit]);
const { mutateAsync: disconnectTrello } =
api.integration.disconnect.useMutation({
onSuccess: () => {
@@ -104,9 +127,12 @@ export default function SettingsPage() {
return (
<>
<div className="flex h-full w-full flex-col overflow-hidden">
<div className="h-full max-h-[calc(100vh-4rem)] overflow-y-auto">
<div
ref={scrollContainerRef}
className="h-full max-h-[calc(100vdh-3rem)] overflow-y-auto md:max-h-[calc(100vdh-4rem)]"
>
<PageHead title={t`Settings | ${workspace.name ?? "Workspace"}`} />
<div className="m-auto max-w-[1600px] px-5 py-6 md:px-28 md:py-12">
<div className="m-auto max-w-[1100px] px-5 py-6 md:px-28 md:py-12">
<div className="mb-8 flex w-full justify-between">
<h1 className="font-bold tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
{t`Settings`}
@@ -134,14 +160,16 @@ export default function SettingsPage() {
workspaceName={workspace.name}
/>
<h2 className="mb-4 mt-8 text-[14px] text-neutral-900 dark:text-dark-1000">
{t`Workspace URL`}
</h2>
<UpdateWorkspaceUrlForm
workspacePublicId={workspace.publicId}
workspaceUrl={workspace.slug ?? ""}
workspacePlan={workspace.plan ?? "free"}
/>
<div ref={workspaceUrlSectionRef}>
<h2 className="mb-4 mt-8 text-[14px] text-neutral-900 dark:text-dark-1000">
{t`Workspace URL`}
</h2>
<UpdateWorkspaceUrlForm
workspacePublicId={workspace.publicId}
workspaceUrl={workspace.slug ?? ""}
workspacePlan={workspace.plan ?? "free"}
/>
</div>
<h2 className="mb-4 mt-8 text-[14px] text-neutral-900 dark:text-dark-1000">
{t`Workspace description`}
@@ -273,7 +301,8 @@ export default function SettingsPage() {
</div>
</div>
<Modal>
<Modal modalSize={modalContentType === "NEW_FEEDBACK" ? "md" : "sm"}>
{modalContentType === "NEW_FEEDBACK" && <FeedbackModal />}
{modalContentType === "NEW_WORKSPACE" && <NewWorkspaceForm />}
{modalContentType === "DELETE_WORKSPACE" && (
<DeleteWorkspaceConfirmation />

View File

@@ -23,19 +23,22 @@ services:
- STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
- STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
# SMTP
# Email
- SMTP_HOST=${SMTP_HOST}
- SMTP_PORT=${SMTP_PORT}
- SMTP_USER=${SMTP_USER}
- SMTP_PASSWORD=${SMTP_PASSWORD}
- SMTP_SECURE=${SMTP_SECURE}
- EMAIL_FROM=${EMAIL_FROM}
- PLUNK_API_KEY=${PLUNK_API_KEY}
- PLUNK_API_URL=${PLUNK_API_URL}
# S3 storage
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
- S3_SECRET_ACCESS_KEY=${S3_SECRET_ACCESS_KEY}
- S3_REGION=${S3_REGION}
- S3_ENDPOINT=${S3_ENDPOINT}
- S3_FORCE_PATH_STYLE=${S3_FORCE_PATH_STYLE}
- NEXT_PUBLIC_STORAGE_URL=${NEXT_PUBLIC_STORAGE_URL}
- NEXT_PUBLIC_AVATAR_BUCKET_NAME=${NEXT_PUBLIC_AVATAR_BUCKET_NAME}
- NEXT_PUBLIC_STORAGE_DOMAIN=${NEXT_PUBLIC_STORAGE_DOMAIN}

View File

@@ -30,6 +30,7 @@ services:
- S3_SECRET_ACCESS_KEY=${S3_SECRET_ACCESS_KEY}
- S3_REGION=${S3_REGION}
- S3_ENDPOINT=${S3_ENDPOINT}
- S3_FORCE_PATH_STYLE=${S3_FORCE_PATH_STYLE}
- NEXT_PUBLIC_STORAGE_URL=${NEXT_PUBLIC_STORAGE_URL}
- NEXT_PUBLIC_AVATAR_BUCKET_NAME=${NEXT_PUBLIC_AVATAR_BUCKET_NAME}
- NEXT_PUBLIC_STORAGE_DOMAIN=${NEXT_PUBLIC_STORAGE_DOMAIN}

View File

@@ -111,15 +111,21 @@ export const boardRouter = createTRPCRouter({
.meta({
openapi: {
method: "GET",
path: "/board/{boardSlug}",
path: "/workspaces/{workspaceSlug}/boards/{boardSlug}",
summary: "Get board by slug",
description: "Retrieves a board by its slug",
description:
"Retrieves a board by its slug within a specific workspace",
tags: ["Boards"],
protect: false,
},
})
.input(
z.object({
workspaceSlug: z
.string()
.min(3)
.max(24)
.regex(/^(?![-]+$)[a-zA-Z0-9-]+$/),
boardSlug: z
.string()
.min(3)
@@ -131,10 +137,26 @@ export const boardRouter = createTRPCRouter({
)
.output(z.custom<Awaited<ReturnType<typeof boardRepo.getBySlug>>>())
.query(async ({ ctx, input }) => {
const result = await boardRepo.getBySlug(ctx.db, input.boardSlug, {
members: input.members ?? [],
labels: input.labels ?? [],
});
const workspace = await workspaceRepo.getBySlugWithBoards(
ctx.db,
input.workspaceSlug,
);
if (!workspace)
throw new TRPCError({
message: `Workspace with slug ${input.workspaceSlug} not found`,
code: "NOT_FOUND",
});
const result = await boardRepo.getBySlug(
ctx.db,
input.boardSlug,
workspace.id,
{
members: input.members ?? [],
labels: input.labels ?? [],
},
);
return result;
}),
@@ -276,6 +298,21 @@ export const boardRouter = createTRPCRouter({
await assertUserInWorkspace(ctx.db, userId, board.workspaceId);
if (input.slug) {
const isBoardSlugAvailable = await boardRepo.isBoardSlugAvailable(
ctx.db,
input.slug,
board.workspaceId,
);
if (!isBoardSlugAvailable) {
throw new TRPCError({
message: `Board slug ${input.slug} is not available`,
code: "BAD_REQUEST",
});
}
}
const result = await boardRepo.update(ctx.db, {
name: input.name,
slug: input.slug,
@@ -407,11 +444,23 @@ export const boardRouter = createTRPCRouter({
}),
)
.query(async ({ ctx, input }) => {
const board = await boardRepo.getWorkspaceAndBoardIdByBoardPublicId(
ctx.db,
input.boardPublicId,
);
if (!board)
throw new TRPCError({
message: `Board with public ID ${input.boardPublicId} not found`,
code: "NOT_FOUND",
});
const isBoardSlugAvailable = await boardRepo.isBoardSlugAvailable(
ctx.db,
input.boardSlug,
input.boardPublicId,
board.workspaceId,
);
return {
isReserved: !isBoardSlugAvailable,
};

View File

@@ -8,6 +8,12 @@ import * as labelRepo from "@kan/db/repository/label.repo";
import { createTRPCRouter, protectedProcedure } from "../trpc";
import { assertUserInWorkspace } from "../utils/auth";
const labelSchema = z.object({
publicId: z.string(),
name: z.string(),
colourCode: z.string().nullable(),
});
export const labelRouter = createTRPCRouter({
byPublicId: protectedProcedure
.meta({
@@ -21,7 +27,7 @@ export const labelRouter = createTRPCRouter({
},
})
.input(z.object({ labelPublicId: z.string().min(12) }))
.output(z.custom<Awaited<ReturnType<typeof labelRepo.getByPublicId>>>())
.output(labelSchema)
.query(async ({ ctx, input }) => {
const userId = ctx.user?.id;
@@ -52,7 +58,11 @@ export const labelRouter = createTRPCRouter({
code: "NOT_FOUND",
});
return result;
return {
publicId: result.publicId,
name: result.name,
colourCode: result.colourCode,
};
}),
create: protectedProcedure
.meta({
@@ -72,7 +82,7 @@ export const labelRouter = createTRPCRouter({
colourCode: z.string().length(7),
}),
)
.output(z.custom<Awaited<ReturnType<typeof labelRepo.create>>>())
.output(labelSchema)
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
@@ -108,7 +118,11 @@ export const labelRouter = createTRPCRouter({
code: "INTERNAL_SERVER_ERROR",
});
return result;
return {
publicId: result.publicId,
name: result.name,
colourCode: result.colourCode,
};
}),
update: protectedProcedure
.meta({
@@ -128,7 +142,7 @@ export const labelRouter = createTRPCRouter({
colourCode: z.string().length(7),
}),
)
.output(z.custom<Awaited<ReturnType<typeof labelRepo.update>>>())
.output(labelSchema)
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
@@ -153,7 +167,17 @@ export const labelRouter = createTRPCRouter({
const result = await labelRepo.update(ctx.db, input);
return result;
if (!result)
throw new TRPCError({
message: `Failed to update label`,
code: "INTERNAL_SERVER_ERROR",
});
return {
publicId: result.publicId,
name: result.name,
colourCode: result.colourCode,
};
}),
delete: protectedProcedure
.meta({

View File

@@ -1,7 +1,6 @@
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { authClient } from "@kan/auth/client";
import * as memberRepo from "@kan/db/repository/member.repo";
import * as userRepo from "@kan/db/repository/user.repo";
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
@@ -57,7 +56,7 @@ export const memberRouter = createTRPCRouter({
if (isInvitedEmailAlreadyMember) {
throw new TRPCError({
message: `User with email ${input.email} is already a member of this workspace`,
code: "BAD_REQUEST",
code: "CONFLICT",
});
}
@@ -78,16 +77,28 @@ export const memberRouter = createTRPCRouter({
code: "INTERNAL_SERVER_ERROR",
});
const { error } = await authClient.signIn.magicLink({
const { status } = await ctx.auth.api.signInMagicLink({
email: input.email,
callbackURL: `/boards?type=invite&memberPublicId=${invite.publicId}`,
});
if (error)
if (!status) {
console.error("Failed to send magic link invitation:", {
email: input.email,
callbackURL: `/boards?type=invite&memberPublicId=${invite.publicId}`,
});
await memberRepo.softDelete(ctx.db, {
memberId: invite.id,
deletedAt: new Date(),
deletedBy: userId,
});
throw new TRPCError({
message: `Failed to send magic link to user with email ${input.email}`,
message: `Failed to send magic link invitation to user with email ${input.email}.`,
code: "INTERNAL_SERVER_ERROR",
});
}
return invite;
}),

View File

@@ -20,58 +20,73 @@ export interface User {
stripeCustomerId?: string | null | undefined;
}
const createAuthWithHeaders = (
auth: ReturnType<typeof initAuth>,
headers: Headers,
) => {
return {
api: {
getSession: () => auth.api.getSession({ headers }),
signInMagicLink: (input: { email: string; callbackURL: string }) =>
auth.api.signInMagicLink({
headers,
body: { email: input.email, callbackURL: input.callbackURL },
}),
},
};
};
interface CreateContextOptions {
user: User | null | undefined;
db: dbClient;
auth: ReturnType<typeof createAuthWithHeaders>;
}
export const createInnerTRPCContext = (opts: CreateContextOptions) => {
return {
user: opts.user,
db: opts.db,
auth: opts.auth,
};
};
export const createTRPCContext = async ({ req }: CreateNextContextOptions) => {
const db = createDrizzleClient();
const auth = initAuth(db);
const baseAuth = initAuth(db);
const headers = new Headers(req.headers as Record<string, string>);
const auth = createAuthWithHeaders(baseAuth, headers);
const session = await auth.api.getSession({
// @ts-expect-error
headers: new Headers(req.headers),
});
const session = await auth.api.getSession();
return createInnerTRPCContext({ db, user: session?.user });
return createInnerTRPCContext({ db, user: session?.user, auth });
};
export const createNextApiContext = async (req: NextApiRequest) => {
const db = createDrizzleClient();
const auth = initAuth(db);
const baseAuth = initAuth(db);
const headers = new Headers(req.headers as Record<string, string>);
const auth = createAuthWithHeaders(baseAuth, headers);
const session = await auth.api.getSession({
// @ts-expect-error
headers: new Headers(req.headers),
});
const session = await auth.api.getSession();
return createInnerTRPCContext({ db, user: session?.user });
return createInnerTRPCContext({ db, user: session?.user, auth });
};
export const createRESTContext = async ({ req }: CreateNextContextOptions) => {
const db = createDrizzleClient();
const auth = initAuth(db);
const baseAuth = initAuth(db);
const headers = new Headers(req.headers as Record<string, string>);
const auth = createAuthWithHeaders(baseAuth, headers);
let session;
try {
session = await auth.api.getSession({
// @ts-expect-error
headers: new Headers(req.headers),
});
session = await auth.api.getSession();
} catch (error) {
console.error("Error getting session, ", error);
throw error;
}
return createInnerTRPCContext({ db, user: session?.user });
return createInnerTRPCContext({ db, user: session?.user, auth });
};
const t = initTRPC

View File

@@ -11,7 +11,7 @@ import type { dbClient } from "@kan/db/client";
import * as memberRepo from "@kan/db/repository/member.repo";
import * as userRepo from "@kan/db/repository/user.repo";
import * as schema from "@kan/db/schema";
import { sendEmail } from "@kan/email";
import { cloudMailerClient, sendEmail } from "@kan/email";
import { createStripeClient } from "@kan/stripe";
export const configuredProviders = socialProviderList.reduce<
@@ -84,7 +84,7 @@ export const socialProvidersPlugin = () => ({
method: "GET",
},
async (ctx) =>
ctx.json(ctx.context.socialProviders.map((p) => p.name.toLowerCase())),
ctx.json(ctx.context.socialProviders.map((p) => p.id.toLowerCase())),
),
},
});
@@ -166,13 +166,34 @@ export const initAuth = (db: dbClient) => {
databaseHooks: {
user: {
create: {
before() {
async before(user) {
if (env("NEXT_PUBLIC_DISABLE_SIGN_UP")?.toLowerCase() === "true") {
return Promise.resolve(false);
const pendingInvitation = await memberRepo.getByEmailAndStatus(
db,
user.email,
"invited",
);
if (!pendingInvitation) {
return Promise.resolve(false);
}
return Promise.resolve(true);
}
return Promise.resolve(true);
},
async after(user) {
if (cloudMailerClient) {
await cloudMailerClient.events.track({
event: "user-signup",
email: user.email,
data: {
name: user.name,
userId: user.id,
},
});
}
if (
user.image &&
!user.image.includes(process.env.NEXT_PUBLIC_STORAGE_DOMAIN!)
@@ -181,6 +202,7 @@ export const initAuth = (db: dbClient) => {
const client = new S3Client({
region: env("S3_REGION") ?? "",
endpoint: env("S3_ENDPOINT") ?? "",
forcePathStyle: env("S3_FORCE_PATH_STYLE") === "true",
credentials: {
accessKeyId: env("S3_ACCESS_KEY_ID") ?? "",
secretAccessKey: env("S3_SECRET_ACCESS_KEY") ?? "",

View File

@@ -1,4 +1,4 @@
import { and, asc, desc, eq, exists, inArray, isNull, or, sql } from "drizzle-orm";
import { and, asc, desc, eq, inArray, isNull, or } from "drizzle-orm";
import type { dbClient } from "@kan/db/client";
import type { BoardVisibilityStatus } from "@kan/db/schema";
@@ -201,6 +201,7 @@ export const getByPublicId = async (
export const getBySlug = async (
db: dbClient,
boardSlug: string,
workspaceId: number,
filters: {
members: string[];
labels: string[];
@@ -293,6 +294,7 @@ export const getBySlug = async (
},
where: and(
eq(boards.slug, boardSlug),
eq(boards.workspaceId, workspaceId),
isNull(boards.deletedAt),
eq(boards.visibility, "public"),
),
@@ -481,30 +483,18 @@ export const getWorkspaceAndBoardIdByBoardPublicId = async (
export const isBoardSlugAvailable = async (
db: dbClient,
boardSlug: string,
boardPublicId: string,
workspaceId: number,
) => {
const result = await db
.select({ id: boards.id })
.from(boards)
.where(
and(
eq(boards.publicId, boardPublicId),
exists(
db
.select({ id: boards.id })
.from(boards)
.where(
and(
eq(boards.slug, boardSlug),
eq(boards.workspaceId, sql`${boards.workspaceId}`), // Reference outer query's workspaceId
isNull(boards.deletedAt),
),
)
.limit(1),
),
),
)
.limit(1);
const result = await db.query.boards.findFirst({
columns: {
id: true,
},
where: and(
eq(boards.slug, boardSlug),
eq(boards.workspaceId, workspaceId),
isNull(boards.deletedAt),
),
});
return result.length === 0;
return result === undefined;
};

View File

@@ -23,7 +23,12 @@ export const create = async (
createdBy: labelInput.createdBy,
boardId: labelInput.boardId,
})
.returning({ id: labels.id });
.returning({
id: labels.id,
publicId: labels.publicId,
name: labels.name,
colourCode: labels.colourCode,
});
if (labelInput.cardId && result) {
await db.insert(cardsToLabels).values({
@@ -91,6 +96,7 @@ export const update = async (
.where(eq(labels.publicId, labelInput.labelPublicId))
.returning({
id: labels.id,
publicId: labels.publicId,
name: labels.name,
colourCode: labels.colourCode,
});

View File

@@ -41,6 +41,20 @@ export const getByPublicId = async (db: dbClient, publicId: string) => {
});
};
export const getByEmailAndStatus = async (
db: dbClient,
email: string,
status: MemberStatus,
) => {
return db.query.workspaceMembers.findFirst({
where: and(
eq(workspaceMembers.email, email),
eq(workspaceMembers.status, status),
isNull(workspaceMembers.deletedAt),
),
});
};
export const acceptInvite = async (
db: dbClient,
args: { memberId: number; userId: string },

View File

@@ -23,6 +23,7 @@
"typecheck": "tsc --noEmit --emitDeclarationOnly false"
},
"dependencies": {
"@plunk/node": "^3.0.3",
"@react-email/components": "^0.0.25",
"nodemailer": "^7.0.3",
"react-email": "^3.0.1"

View File

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

View File

@@ -1,3 +1,4 @@
export const name = "email";
export { sendEmail } from "./sendEmail";
export { cloudMailerClient } from "./cloudMailerClient";

View File

@@ -1,6 +1,7 @@
import { render } from "@react-email/render";
import nodemailer from "nodemailer";
import { cloudMailerClient } from "./cloudMailerClient";
import JoinWorkspaceTemplate from "./templates/join-workspace";
import MagicLinkTemplate from "./templates/magic-link";
import ResetPasswordTemplate from "./templates/reset-password";
@@ -44,6 +45,15 @@ export const sendEmail = async (
html,
};
if (cloudMailerClient) {
const response = await cloudMailerClient.emails.send({
...options,
body: html,
});
return response;
}
const response = await transporter.sendMail(options);
if (!response.accepted.length) {

10
pnpm-lock.yaml generated
View File

@@ -409,6 +409,9 @@ importers:
packages/email:
dependencies:
'@plunk/node':
specifier: ^3.0.3
version: 3.0.3
'@react-email/components':
specifier: ^0.0.25
version: 0.0.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -2194,6 +2197,9 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
'@plunk/node@3.0.3':
resolution: {integrity: sha512-f3NT418/EdLjebQ4arAwR64cnz7d5H7i1CeKh8+B0cVBrwzHvF+Q+QkhutF+FAp49yuI/BYc71qQH+RFc2fxxQ==}
'@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
@@ -8910,6 +8916,10 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
'@plunk/node@3.0.3':
dependencies:
tslib: 2.8.1
'@popperjs/core@2.11.8': {}
'@react-aria/focus@3.19.0(react@18.3.1)':

View File

@@ -106,9 +106,12 @@
"S3_ACCESS_KEY_ID",
"S3_SECRET_ACCESS_KEY",
"S3_ENDPOINT",
"S3_FORCE_PATH_STYLE",
"PORT",
"BETTER_AUTH_SECRET",
"BETTER_AUTH_TRUSTED_ORIGINS"
"BETTER_AUTH_TRUSTED_ORIGINS",
"PLUNK_API_KEY",
"PLUNK_API_URL"
],
"globalPassThroughEnv": [
"NODE_ENV",