Compare commits
8 Commits
fix/125
...
fix/public
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78e2de90d9 | ||
|
|
adcc4470dc | ||
|
|
28d2de4dad | ||
|
|
ca1dd92ab4 | ||
|
|
f8827da73a | ||
|
|
babaa9f1b1 | ||
|
|
0cefd17484 | ||
|
|
974a5ff0f3 |
@@ -308,6 +308,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
|
||||
@@ -358,6 +359,7 @@ checksums:
|
||||
View%20and%20manage%20your%20billing%20and%20subscription./singular: 7469502543aac6f02149813546d1cb38
|
||||
View%20docs/singular: 43ce54f27bb1e3f1880b56e03ab38871
|
||||
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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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,9 +344,19 @@ 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>{`
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
48
apps/web/src/hooks/useModalFormState.ts
Normal file
48
apps/web/src/hooks/useModalFormState.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
1
apps/web/src/locales/de/messages.js
Normal file
1
apps/web/src/locales/de/messages.js
Normal file
File diff suppressed because one or more lines are too long
@@ -28,7 +28,7 @@ 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"
|
||||
|
||||
@@ -66,7 +66,7 @@ msgstr "Karte hinzufügen"
|
||||
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)"
|
||||
|
||||
@@ -178,7 +178,7 @@ msgstr "Abrechnungsportal"
|
||||
msgid "Blog Post"
|
||||
msgstr "Blogbeitrag"
|
||||
|
||||
#: src/views/board/index.tsx:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Board"
|
||||
msgstr "Board"
|
||||
|
||||
@@ -190,7 +190,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:267
|
||||
#: src/views/public/board/index.tsx:137
|
||||
#: src/views/board/index.tsx:358
|
||||
msgid "Board not found"
|
||||
msgstr "Board nicht gefunden"
|
||||
|
||||
@@ -202,7 +203,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"
|
||||
|
||||
@@ -254,7 +255,7 @@ msgstr "Abbrechen"
|
||||
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"
|
||||
|
||||
@@ -347,7 +348,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"
|
||||
@@ -356,15 +357,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"
|
||||
|
||||
@@ -377,11 +378,11 @@ 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:335
|
||||
#: src/views/board/index.tsx:426
|
||||
msgid "Create new list"
|
||||
msgstr "Neue Liste erstellen"
|
||||
|
||||
@@ -676,7 +677,7 @@ msgstr "Loslegen"
|
||||
msgid "Get started by creating a new board"
|
||||
msgstr "Beginne, indem du ein neues Board erstellst"
|
||||
|
||||
#: src/views/board/index.tsx:327
|
||||
#: src/views/board/index.tsx:418
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Beginne mit dem Erstellen einer neuen Liste"
|
||||
|
||||
@@ -826,7 +827,7 @@ 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:113
|
||||
#: src/views/board/components/NewCardForm.tsx:331
|
||||
#: src/views/board/components/NewCardForm.tsx:358
|
||||
#: src/views/board/components/Filters.tsx:101
|
||||
msgid "Labels"
|
||||
msgstr "Labels"
|
||||
@@ -855,7 +856,7 @@ msgstr "Lizenz"
|
||||
msgid "Light"
|
||||
msgstr "Hell"
|
||||
|
||||
#: src/views/public/board/index.tsx:51
|
||||
#: src/views/public/board/index.tsx:57
|
||||
msgid "Link copied"
|
||||
msgstr "Link kopiert"
|
||||
|
||||
@@ -893,7 +894,7 @@ msgstr "Mittlere Priorität"
|
||||
|
||||
#: src/views/members/index.tsx:161
|
||||
#: src/views/card/index.tsx:121
|
||||
#: src/views/board/components/NewCardForm.tsx:290
|
||||
#: src/views/board/components/NewCardForm.tsx:317
|
||||
#: src/views/board/components/Filters.tsx:93
|
||||
#: src/components/SideNavigation.tsx:73
|
||||
msgid "Members"
|
||||
@@ -933,7 +934,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"
|
||||
|
||||
@@ -945,7 +946,7 @@ msgstr "Neuer Import"
|
||||
msgid "New label"
|
||||
msgstr "Neues Label"
|
||||
|
||||
#: src/views/board/index.tsx:304
|
||||
#: src/views/board/index.tsx:395
|
||||
#: src/views/board/components/NewListForm.tsx:112
|
||||
msgid "New list"
|
||||
msgstr "Neue Liste"
|
||||
@@ -978,7 +979,7 @@ msgstr "Keine Boards gefunden"
|
||||
msgid "No credit card required"
|
||||
msgstr "Keine Kreditkarte erforderlich"
|
||||
|
||||
#: src/views/board/index.tsx:324
|
||||
#: src/views/board/index.tsx:415
|
||||
msgid "No lists"
|
||||
msgstr "Keine Listen"
|
||||
|
||||
@@ -1074,7 +1075,7 @@ msgstr "Bitte wähle eine Datei zum Hochladen aus."
|
||||
#: 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/views/board/components/NewCardForm.tsx:145
|
||||
#: src/components/NewWorkspaceForm.tsx:41
|
||||
#: src/components/FeedbackModal.tsx:41
|
||||
msgid "Please try again later, or contact customer support."
|
||||
@@ -1338,6 +1339,10 @@ msgstr "Sie werden keinen Zugriff mehr auf diesen Workspace haben."
|
||||
msgid "This action can't be undone."
|
||||
msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
|
||||
|
||||
#: src/views/public/board/index.tsx:140
|
||||
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"
|
||||
@@ -1383,7 +1388,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"
|
||||
|
||||
@@ -1477,11 +1482,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:173
|
||||
#: 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"
|
||||
|
||||
@@ -1546,6 +1551,10 @@ msgstr "Dokumentation ansehen"
|
||||
msgid "View our roadmap."
|
||||
msgstr "Sieh dir unsere roadmap an."
|
||||
|
||||
#: src/views/public/board/index.tsx:143
|
||||
msgid "View workspace"
|
||||
msgstr "Workspace anzeigen"
|
||||
|
||||
#: src/views/board/components/VisibilityButton.tsx:91
|
||||
msgid "Visibility"
|
||||
msgstr "Sichtbarkeit"
|
||||
@@ -1578,7 +1587,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:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Workspace"
|
||||
msgstr "Arbeitsbereich"
|
||||
|
||||
|
||||
1
apps/web/src/locales/en/messages.js
Normal file
1
apps/web/src/locales/en/messages.js
Normal file
File diff suppressed because one or more lines are too long
@@ -28,7 +28,7 @@ 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"
|
||||
|
||||
@@ -78,7 +78,7 @@ msgstr "Add a card"
|
||||
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)"
|
||||
|
||||
@@ -198,7 +198,7 @@ msgstr "Billing portal"
|
||||
msgid "Blog Post"
|
||||
msgstr "Blog Post"
|
||||
|
||||
#: src/views/board/index.tsx:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Board"
|
||||
msgstr "Board"
|
||||
|
||||
@@ -214,7 +214,8 @@ msgstr "Board name cannot exceed 100 characters"
|
||||
msgid "Board name is required"
|
||||
msgstr "Board name is required"
|
||||
|
||||
#: src/views/board/index.tsx:267
|
||||
#: src/views/public/board/index.tsx:137
|
||||
#: src/views/board/index.tsx:358
|
||||
msgid "Board not found"
|
||||
msgstr "Board not found"
|
||||
|
||||
@@ -226,7 +227,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"
|
||||
|
||||
@@ -282,7 +283,7 @@ msgstr "Cancel"
|
||||
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"
|
||||
|
||||
@@ -375,7 +376,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 +393,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,11 +414,11 @@ 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:335
|
||||
#: src/views/board/index.tsx:426
|
||||
msgid "Create new list"
|
||||
msgstr "Create new list"
|
||||
|
||||
@@ -713,7 +714,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:327
|
||||
#: src/views/board/index.tsx:418
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Get started by creating a new list"
|
||||
|
||||
@@ -867,7 +868,7 @@ msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Keep in mind that this action is irreversible."
|
||||
|
||||
#: src/views/card/index.tsx:113
|
||||
#: src/views/board/components/NewCardForm.tsx:331
|
||||
#: src/views/board/components/NewCardForm.tsx:358
|
||||
#: src/views/board/components/Filters.tsx:101
|
||||
msgid "Labels"
|
||||
msgstr "Labels"
|
||||
@@ -896,7 +897,7 @@ msgstr "License"
|
||||
msgid "Light"
|
||||
msgstr "Light"
|
||||
|
||||
#: src/views/public/board/index.tsx:51
|
||||
#: src/views/public/board/index.tsx:57
|
||||
msgid "Link copied"
|
||||
msgstr "Link copied"
|
||||
|
||||
@@ -934,7 +935,7 @@ msgstr "Medium Priority"
|
||||
|
||||
#: src/views/members/index.tsx:161
|
||||
#: src/views/card/index.tsx:121
|
||||
#: src/views/board/components/NewCardForm.tsx:290
|
||||
#: src/views/board/components/NewCardForm.tsx:317
|
||||
#: src/views/board/components/Filters.tsx:93
|
||||
#: src/components/SideNavigation.tsx:73
|
||||
msgid "Members"
|
||||
@@ -974,7 +975,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"
|
||||
|
||||
@@ -986,7 +987,7 @@ msgstr "New import"
|
||||
msgid "New label"
|
||||
msgstr "New label"
|
||||
|
||||
#: src/views/board/index.tsx:304
|
||||
#: src/views/board/index.tsx:395
|
||||
#: src/views/board/components/NewListForm.tsx:112
|
||||
msgid "New list"
|
||||
msgstr "New list"
|
||||
@@ -1023,7 +1024,7 @@ msgstr "No boards found"
|
||||
msgid "No credit card required"
|
||||
msgstr "No credit card required"
|
||||
|
||||
#: src/views/board/index.tsx:324
|
||||
#: src/views/board/index.tsx:415
|
||||
msgid "No lists"
|
||||
msgstr "No lists"
|
||||
|
||||
@@ -1119,7 +1120,7 @@ msgstr "Please select a file to upload."
|
||||
#: 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/views/board/components/NewCardForm.tsx:145
|
||||
#: src/components/NewWorkspaceForm.tsx:41
|
||||
#: src/components/FeedbackModal.tsx:41
|
||||
msgid "Please try again later, or contact customer support."
|
||||
@@ -1387,6 +1388,10 @@ msgstr "They won't be able to access this workspace."
|
||||
msgid "This action can't be undone."
|
||||
msgstr "This action can't be undone."
|
||||
|
||||
#: src/views/public/board/index.tsx:140
|
||||
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"
|
||||
@@ -1436,7 +1441,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"
|
||||
|
||||
@@ -1530,11 +1535,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:173
|
||||
#: 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"
|
||||
|
||||
@@ -1599,6 +1604,10 @@ msgstr "View docs"
|
||||
msgid "View our roadmap."
|
||||
msgstr "View our roadmap."
|
||||
|
||||
#: src/views/public/board/index.tsx:143
|
||||
msgid "View workspace"
|
||||
msgstr "View workspace"
|
||||
|
||||
#: src/views/board/components/VisibilityButton.tsx:91
|
||||
msgid "Visibility"
|
||||
msgstr "Visibility"
|
||||
@@ -1635,7 +1644,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:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Workspace"
|
||||
msgstr "Workspace"
|
||||
|
||||
|
||||
1
apps/web/src/locales/es/messages.js
Normal file
1
apps/web/src/locales/es/messages.js
Normal file
File diff suppressed because one or more lines are too long
@@ -28,7 +28,7 @@ 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"
|
||||
|
||||
@@ -66,7 +66,7 @@ msgstr "Añadir una tarjeta"
|
||||
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)"
|
||||
|
||||
@@ -178,7 +178,7 @@ msgstr "Portal de facturación"
|
||||
msgid "Blog Post"
|
||||
msgstr "Entrada de blog"
|
||||
|
||||
#: src/views/board/index.tsx:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Board"
|
||||
msgstr "Tablero"
|
||||
|
||||
@@ -190,7 +190,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:267
|
||||
#: src/views/public/board/index.tsx:137
|
||||
#: src/views/board/index.tsx:358
|
||||
msgid "Board not found"
|
||||
msgstr "Tablero no encontrado"
|
||||
|
||||
@@ -202,7 +203,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"
|
||||
|
||||
@@ -254,7 +255,7 @@ msgstr "Cancelar"
|
||||
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"
|
||||
|
||||
@@ -347,7 +348,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"
|
||||
@@ -356,15 +357,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"
|
||||
|
||||
@@ -377,11 +378,11 @@ 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:335
|
||||
#: src/views/board/index.tsx:426
|
||||
msgid "Create new list"
|
||||
msgstr "Crear nueva lista"
|
||||
|
||||
@@ -676,7 +677,7 @@ msgstr "Comenzar"
|
||||
msgid "Get started by creating a new board"
|
||||
msgstr "Comienza creando un nuevo tablero"
|
||||
|
||||
#: src/views/board/index.tsx:327
|
||||
#: src/views/board/index.tsx:418
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Comienza creando una nueva lista"
|
||||
|
||||
@@ -826,7 +827,7 @@ msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Ten en cuenta que esta acción es irreversible."
|
||||
|
||||
#: src/views/card/index.tsx:113
|
||||
#: src/views/board/components/NewCardForm.tsx:331
|
||||
#: src/views/board/components/NewCardForm.tsx:358
|
||||
#: src/views/board/components/Filters.tsx:101
|
||||
msgid "Labels"
|
||||
msgstr "Etiquetas"
|
||||
@@ -855,7 +856,7 @@ msgstr "Licencia"
|
||||
msgid "Light"
|
||||
msgstr "Claro"
|
||||
|
||||
#: src/views/public/board/index.tsx:51
|
||||
#: src/views/public/board/index.tsx:57
|
||||
msgid "Link copied"
|
||||
msgstr "Enlace copiado"
|
||||
|
||||
@@ -893,7 +894,7 @@ msgstr "Prioridad media"
|
||||
|
||||
#: src/views/members/index.tsx:161
|
||||
#: src/views/card/index.tsx:121
|
||||
#: src/views/board/components/NewCardForm.tsx:290
|
||||
#: src/views/board/components/NewCardForm.tsx:317
|
||||
#: src/views/board/components/Filters.tsx:93
|
||||
#: src/components/SideNavigation.tsx:73
|
||||
msgid "Members"
|
||||
@@ -933,7 +934,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"
|
||||
|
||||
@@ -945,7 +946,7 @@ msgstr "Nueva importación"
|
||||
msgid "New label"
|
||||
msgstr "Nueva etiqueta"
|
||||
|
||||
#: src/views/board/index.tsx:304
|
||||
#: src/views/board/index.tsx:395
|
||||
#: src/views/board/components/NewListForm.tsx:112
|
||||
msgid "New list"
|
||||
msgstr "Nueva lista"
|
||||
@@ -978,7 +979,7 @@ msgstr "No se encontraron tableros"
|
||||
msgid "No credit card required"
|
||||
msgstr "No se requiere tarjeta de crédito"
|
||||
|
||||
#: src/views/board/index.tsx:324
|
||||
#: src/views/board/index.tsx:415
|
||||
msgid "No lists"
|
||||
msgstr "Sin listas"
|
||||
|
||||
@@ -1074,7 +1075,7 @@ msgstr "Por favor selecciona un archivo para subir."
|
||||
#: 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/views/board/components/NewCardForm.tsx:145
|
||||
#: src/components/NewWorkspaceForm.tsx:41
|
||||
#: src/components/FeedbackModal.tsx:41
|
||||
msgid "Please try again later, or contact customer support."
|
||||
@@ -1338,6 +1339,10 @@ msgstr "No podrán acceder a este espacio de trabajo."
|
||||
msgid "This action can't be undone."
|
||||
msgstr "Esta acción no se puede deshacer."
|
||||
|
||||
#: src/views/public/board/index.tsx:140
|
||||
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"
|
||||
@@ -1383,7 +1388,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"
|
||||
|
||||
@@ -1477,11 +1482,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:173
|
||||
#: 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"
|
||||
|
||||
@@ -1546,6 +1551,10 @@ msgstr "Ver documentación"
|
||||
msgid "View our roadmap."
|
||||
msgstr "Ver nuestra hoja de ruta."
|
||||
|
||||
#: src/views/public/board/index.tsx:143
|
||||
msgid "View workspace"
|
||||
msgstr "Ver espacio de trabajo"
|
||||
|
||||
#: src/views/board/components/VisibilityButton.tsx:91
|
||||
msgid "Visibility"
|
||||
msgstr "Visibilidad"
|
||||
@@ -1578,7 +1587,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:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Workspace"
|
||||
msgstr "Espacio de trabajo"
|
||||
|
||||
|
||||
1
apps/web/src/locales/fr/messages.js
Normal file
1
apps/web/src/locales/fr/messages.js
Normal file
File diff suppressed because one or more lines are too long
@@ -28,7 +28,7 @@ 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"
|
||||
|
||||
@@ -66,7 +66,7 @@ msgstr "Ajouter une carte"
|
||||
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)"
|
||||
|
||||
@@ -178,7 +178,7 @@ msgstr "Portail de facturation"
|
||||
msgid "Blog Post"
|
||||
msgstr "Article de blog"
|
||||
|
||||
#: src/views/board/index.tsx:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Board"
|
||||
msgstr "Tableau"
|
||||
|
||||
@@ -190,7 +190,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:267
|
||||
#: src/views/public/board/index.tsx:137
|
||||
#: src/views/board/index.tsx:358
|
||||
msgid "Board not found"
|
||||
msgstr "Tableau introuvable"
|
||||
|
||||
@@ -202,7 +203,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"
|
||||
|
||||
@@ -254,7 +255,7 @@ msgstr "Annuler"
|
||||
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"
|
||||
|
||||
@@ -347,7 +348,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"
|
||||
@@ -356,15 +357,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"
|
||||
|
||||
@@ -377,11 +378,11 @@ 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:335
|
||||
#: src/views/board/index.tsx:426
|
||||
msgid "Create new list"
|
||||
msgstr "Créer une nouvelle liste"
|
||||
|
||||
@@ -676,7 +677,7 @@ msgstr "Commencer"
|
||||
msgid "Get started by creating a new board"
|
||||
msgstr "Commencez par créer un nouveau tableau"
|
||||
|
||||
#: src/views/board/index.tsx:327
|
||||
#: src/views/board/index.tsx:418
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Commencez par créer une nouvelle liste"
|
||||
|
||||
@@ -826,7 +827,7 @@ msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Gardez à l'esprit que cette action est irréversible."
|
||||
|
||||
#: src/views/card/index.tsx:113
|
||||
#: src/views/board/components/NewCardForm.tsx:331
|
||||
#: src/views/board/components/NewCardForm.tsx:358
|
||||
#: src/views/board/components/Filters.tsx:101
|
||||
msgid "Labels"
|
||||
msgstr "Étiquettes"
|
||||
@@ -855,7 +856,7 @@ msgstr "Licence"
|
||||
msgid "Light"
|
||||
msgstr "Clair"
|
||||
|
||||
#: src/views/public/board/index.tsx:51
|
||||
#: src/views/public/board/index.tsx:57
|
||||
msgid "Link copied"
|
||||
msgstr "Lien copié"
|
||||
|
||||
@@ -893,7 +894,7 @@ msgstr "Priorité moyenne"
|
||||
|
||||
#: src/views/members/index.tsx:161
|
||||
#: src/views/card/index.tsx:121
|
||||
#: src/views/board/components/NewCardForm.tsx:290
|
||||
#: src/views/board/components/NewCardForm.tsx:317
|
||||
#: src/views/board/components/Filters.tsx:93
|
||||
#: src/components/SideNavigation.tsx:73
|
||||
msgid "Members"
|
||||
@@ -933,7 +934,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"
|
||||
|
||||
@@ -945,7 +946,7 @@ msgstr "Nouvel import"
|
||||
msgid "New label"
|
||||
msgstr "Nouvelle étiquette"
|
||||
|
||||
#: src/views/board/index.tsx:304
|
||||
#: src/views/board/index.tsx:395
|
||||
#: src/views/board/components/NewListForm.tsx:112
|
||||
msgid "New list"
|
||||
msgstr "Nouvelle liste"
|
||||
@@ -978,7 +979,7 @@ msgstr "Aucun tableau trouvé"
|
||||
msgid "No credit card required"
|
||||
msgstr "Aucune carte de crédit requise"
|
||||
|
||||
#: src/views/board/index.tsx:324
|
||||
#: src/views/board/index.tsx:415
|
||||
msgid "No lists"
|
||||
msgstr "Aucune liste"
|
||||
|
||||
@@ -1074,7 +1075,7 @@ msgstr "Veuillez sélectionner un fichier à télécharger."
|
||||
#: 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/views/board/components/NewCardForm.tsx:145
|
||||
#: src/components/NewWorkspaceForm.tsx:41
|
||||
#: src/components/FeedbackModal.tsx:41
|
||||
msgid "Please try again later, or contact customer support."
|
||||
@@ -1338,6 +1339,10 @@ msgstr "Ils ne pourront plus accéder à cet espace de travail."
|
||||
msgid "This action can't be undone."
|
||||
msgstr "Cette action ne peut pas être annulée."
|
||||
|
||||
#: src/views/public/board/index.tsx:140
|
||||
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"
|
||||
@@ -1383,7 +1388,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"
|
||||
|
||||
@@ -1477,11 +1482,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:173
|
||||
#: 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"
|
||||
|
||||
@@ -1546,6 +1551,10 @@ msgstr "Voir la documentation"
|
||||
msgid "View our roadmap."
|
||||
msgstr "Consultez notre feuille de route."
|
||||
|
||||
#: src/views/public/board/index.tsx:143
|
||||
msgid "View workspace"
|
||||
msgstr "Voir l'espace de travail"
|
||||
|
||||
#: src/views/board/components/VisibilityButton.tsx:91
|
||||
msgid "Visibility"
|
||||
msgstr "Visibilité"
|
||||
@@ -1578,7 +1587,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:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Workspace"
|
||||
msgstr "Espace de travail"
|
||||
|
||||
|
||||
1
apps/web/src/locales/it/messages.js
Normal file
1
apps/web/src/locales/it/messages.js
Normal file
File diff suppressed because one or more lines are too long
@@ -28,7 +28,7 @@ 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"
|
||||
|
||||
@@ -66,7 +66,7 @@ msgstr "Aggiungi una carta"
|
||||
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)"
|
||||
|
||||
@@ -178,7 +178,7 @@ msgstr "Portale di fatturazione"
|
||||
msgid "Blog Post"
|
||||
msgstr "Post del blog"
|
||||
|
||||
#: src/views/board/index.tsx:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Board"
|
||||
msgstr "Bacheca"
|
||||
|
||||
@@ -190,7 +190,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:267
|
||||
#: src/views/public/board/index.tsx:137
|
||||
#: src/views/board/index.tsx:358
|
||||
msgid "Board not found"
|
||||
msgstr "Bacheca non trovata"
|
||||
|
||||
@@ -202,7 +203,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"
|
||||
|
||||
@@ -254,7 +255,7 @@ msgstr "Annulla"
|
||||
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"
|
||||
|
||||
@@ -347,7 +348,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"
|
||||
@@ -356,15 +357,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"
|
||||
|
||||
@@ -377,11 +378,11 @@ 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:335
|
||||
#: src/views/board/index.tsx:426
|
||||
msgid "Create new list"
|
||||
msgstr "Crea nuova lista"
|
||||
|
||||
@@ -676,7 +677,7 @@ msgstr "Inizia ora"
|
||||
msgid "Get started by creating a new board"
|
||||
msgstr "Inizia creando una nuova bacheca"
|
||||
|
||||
#: src/views/board/index.tsx:327
|
||||
#: src/views/board/index.tsx:418
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Inizia creando una nuova lista"
|
||||
|
||||
@@ -826,7 +827,7 @@ msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Tieni presente che questa azione è irreversibile."
|
||||
|
||||
#: src/views/card/index.tsx:113
|
||||
#: src/views/board/components/NewCardForm.tsx:331
|
||||
#: src/views/board/components/NewCardForm.tsx:358
|
||||
#: src/views/board/components/Filters.tsx:101
|
||||
msgid "Labels"
|
||||
msgstr "Etichette"
|
||||
@@ -855,7 +856,7 @@ msgstr "Licenza"
|
||||
msgid "Light"
|
||||
msgstr "Chiaro"
|
||||
|
||||
#: src/views/public/board/index.tsx:51
|
||||
#: src/views/public/board/index.tsx:57
|
||||
msgid "Link copied"
|
||||
msgstr "Link copiato"
|
||||
|
||||
@@ -893,7 +894,7 @@ msgstr "Media priorità"
|
||||
|
||||
#: src/views/members/index.tsx:161
|
||||
#: src/views/card/index.tsx:121
|
||||
#: src/views/board/components/NewCardForm.tsx:290
|
||||
#: src/views/board/components/NewCardForm.tsx:317
|
||||
#: src/views/board/components/Filters.tsx:93
|
||||
#: src/components/SideNavigation.tsx:73
|
||||
msgid "Members"
|
||||
@@ -933,7 +934,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"
|
||||
|
||||
@@ -945,7 +946,7 @@ msgstr "Nuova importazione"
|
||||
msgid "New label"
|
||||
msgstr "Nuova etichetta"
|
||||
|
||||
#: src/views/board/index.tsx:304
|
||||
#: src/views/board/index.tsx:395
|
||||
#: src/views/board/components/NewListForm.tsx:112
|
||||
msgid "New list"
|
||||
msgstr "Nuova lista"
|
||||
@@ -978,7 +979,7 @@ msgstr "Nessuna bacheca trovata"
|
||||
msgid "No credit card required"
|
||||
msgstr "Nessuna carta di credito richiesta"
|
||||
|
||||
#: src/views/board/index.tsx:324
|
||||
#: src/views/board/index.tsx:415
|
||||
msgid "No lists"
|
||||
msgstr "Nessuna lista"
|
||||
|
||||
@@ -1074,7 +1075,7 @@ msgstr "Seleziona un file da caricare."
|
||||
#: 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/views/board/components/NewCardForm.tsx:145
|
||||
#: src/components/NewWorkspaceForm.tsx:41
|
||||
#: src/components/FeedbackModal.tsx:41
|
||||
msgid "Please try again later, or contact customer support."
|
||||
@@ -1338,6 +1339,10 @@ msgstr "Non potranno accedere a questo spazio di lavoro."
|
||||
msgid "This action can't be undone."
|
||||
msgstr "Questa azione non può essere annullata."
|
||||
|
||||
#: src/views/public/board/index.tsx:140
|
||||
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"
|
||||
@@ -1383,7 +1388,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"
|
||||
|
||||
@@ -1477,11 +1482,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:173
|
||||
#: 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"
|
||||
|
||||
@@ -1546,6 +1551,10 @@ msgstr "Visualizza documenti"
|
||||
msgid "View our roadmap."
|
||||
msgstr "Visualizza la nostra roadmap."
|
||||
|
||||
#: src/views/public/board/index.tsx:143
|
||||
msgid "View workspace"
|
||||
msgstr "Visualizza spazio di lavoro"
|
||||
|
||||
#: src/views/board/components/VisibilityButton.tsx:91
|
||||
msgid "Visibility"
|
||||
msgstr "Visibilità"
|
||||
@@ -1578,7 +1587,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:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Workspace"
|
||||
msgstr "Spazio di lavoro"
|
||||
|
||||
|
||||
1
apps/web/src/locales/nl/messages.js
Normal file
1
apps/web/src/locales/nl/messages.js
Normal file
File diff suppressed because one or more lines are too long
@@ -28,7 +28,7 @@ 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"
|
||||
|
||||
@@ -66,7 +66,7 @@ msgstr "Voeg een kaart toe"
|
||||
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)"
|
||||
|
||||
@@ -178,7 +178,7 @@ msgstr "Factureringsportaal"
|
||||
msgid "Blog Post"
|
||||
msgstr "Blogbericht"
|
||||
|
||||
#: src/views/board/index.tsx:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Board"
|
||||
msgstr "Bord"
|
||||
|
||||
@@ -190,7 +190,8 @@ msgstr "Bordnaam mag niet langer zijn dan 100 tekens"
|
||||
msgid "Board name is required"
|
||||
msgstr "Bordnaam is verplicht"
|
||||
|
||||
#: src/views/board/index.tsx:267
|
||||
#: src/views/public/board/index.tsx:137
|
||||
#: src/views/board/index.tsx:358
|
||||
msgid "Board not found"
|
||||
msgstr "Bord niet gevonden"
|
||||
|
||||
@@ -202,7 +203,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"
|
||||
|
||||
@@ -254,7 +255,7 @@ msgstr "Annuleren"
|
||||
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"
|
||||
|
||||
@@ -347,7 +348,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"
|
||||
@@ -356,15 +357,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"
|
||||
|
||||
@@ -377,11 +378,11 @@ 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:335
|
||||
#: src/views/board/index.tsx:426
|
||||
msgid "Create new list"
|
||||
msgstr "Maak nieuwe lijst"
|
||||
|
||||
@@ -676,7 +677,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:327
|
||||
#: src/views/board/index.tsx:418
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Begin door een nieuwe lijst te maken"
|
||||
|
||||
@@ -826,7 +827,7 @@ msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Houd er rekening mee dat deze actie onomkeerbaar is."
|
||||
|
||||
#: src/views/card/index.tsx:113
|
||||
#: src/views/board/components/NewCardForm.tsx:331
|
||||
#: src/views/board/components/NewCardForm.tsx:358
|
||||
#: src/views/board/components/Filters.tsx:101
|
||||
msgid "Labels"
|
||||
msgstr "Labels"
|
||||
@@ -855,7 +856,7 @@ msgstr "Licentie"
|
||||
msgid "Light"
|
||||
msgstr "Licht"
|
||||
|
||||
#: src/views/public/board/index.tsx:51
|
||||
#: src/views/public/board/index.tsx:57
|
||||
msgid "Link copied"
|
||||
msgstr "Link gekopieerd"
|
||||
|
||||
@@ -893,7 +894,7 @@ msgstr "Gemiddelde prioriteit"
|
||||
|
||||
#: src/views/members/index.tsx:161
|
||||
#: src/views/card/index.tsx:121
|
||||
#: src/views/board/components/NewCardForm.tsx:290
|
||||
#: src/views/board/components/NewCardForm.tsx:317
|
||||
#: src/views/board/components/Filters.tsx:93
|
||||
#: src/components/SideNavigation.tsx:73
|
||||
msgid "Members"
|
||||
@@ -933,7 +934,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"
|
||||
|
||||
@@ -945,7 +946,7 @@ msgstr "Nieuwe import"
|
||||
msgid "New label"
|
||||
msgstr "Nieuw label"
|
||||
|
||||
#: src/views/board/index.tsx:304
|
||||
#: src/views/board/index.tsx:395
|
||||
#: src/views/board/components/NewListForm.tsx:112
|
||||
msgid "New list"
|
||||
msgstr "Nieuwe lijst"
|
||||
@@ -978,7 +979,7 @@ msgstr "Geen borden gevonden"
|
||||
msgid "No credit card required"
|
||||
msgstr "Geen creditcard vereist"
|
||||
|
||||
#: src/views/board/index.tsx:324
|
||||
#: src/views/board/index.tsx:415
|
||||
msgid "No lists"
|
||||
msgstr "Geen lijsten"
|
||||
|
||||
@@ -1074,7 +1075,7 @@ msgstr "Selecteer een bestand om te uploaden."
|
||||
#: 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/views/board/components/NewCardForm.tsx:145
|
||||
#: src/components/NewWorkspaceForm.tsx:41
|
||||
#: src/components/FeedbackModal.tsx:41
|
||||
msgid "Please try again later, or contact customer support."
|
||||
@@ -1338,6 +1339,10 @@ msgstr "Ze zullen geen toegang meer hebben tot deze werkruimte."
|
||||
msgid "This action can't be undone."
|
||||
msgstr "Deze actie kan niet ongedaan worden gemaakt."
|
||||
|
||||
#: src/views/public/board/index.tsx:140
|
||||
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"
|
||||
@@ -1383,7 +1388,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"
|
||||
|
||||
@@ -1477,11 +1482,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:173
|
||||
#: 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"
|
||||
|
||||
@@ -1546,6 +1551,10 @@ msgstr "Bekijk documentatie"
|
||||
msgid "View our roadmap."
|
||||
msgstr "Bekijk onze roadmap."
|
||||
|
||||
#: src/views/public/board/index.tsx:143
|
||||
msgid "View workspace"
|
||||
msgstr "Werkruimte bekijken"
|
||||
|
||||
#: src/views/board/components/VisibilityButton.tsx:91
|
||||
msgid "Visibility"
|
||||
msgstr "Zichtbaarheid"
|
||||
@@ -1578,7 +1587,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:241
|
||||
#: src/views/board/index.tsx:332
|
||||
msgid "Workspace"
|
||||
msgstr "Werkruimte"
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -167,7 +167,8 @@ export function UpdateBoardSlugForm({
|
||||
!isDirty ||
|
||||
updateBoardSlug.isPending ||
|
||||
errors.slug?.message !== undefined ||
|
||||
isBoardSlugAvailable?.isReserved
|
||||
isBoardSlugAvailable?.isReserved ||
|
||||
checkBoardSlugAvailability.isLoading
|
||||
}
|
||||
>
|
||||
{t`Update`}
|
||||
|
||||
@@ -45,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);
|
||||
@@ -235,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
|
||||
@@ -422,63 +513,7 @@ export default function BoardPage() {
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
<Modal
|
||||
modalSize={
|
||||
modalContentType === "NEW_CARD" ||
|
||||
modalContentType === "NEW_FEEDBACK"
|
||||
? "md"
|
||||
: "sm"
|
||||
}
|
||||
>
|
||||
{modalContentType === "NEW_FEEDBACK" && <FeedbackModal />}
|
||||
{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>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -97,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",
|
||||
)}
|
||||
>
|
||||
@@ -121,7 +121,7 @@ export default function MembersPage() {
|
||||
</div>
|
||||
<div
|
||||
className={twMerge(
|
||||
"relative",
|
||||
"relative z-50",
|
||||
(workspace.role !== "admin" || showSkeleton) && "hidden",
|
||||
)}
|
||||
>
|
||||
@@ -172,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
|
||||
@@ -192,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
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
@@ -116,17 +122,30 @@ export default function PublicBoardView() {
|
||||
)}
|
||||
</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"
|
||||
|
||||
@@ -23,13 +23,15 @@ 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}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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<
|
||||
@@ -183,6 +183,17 @@ export const initAuth = (db: dbClient) => {
|
||||
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!)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
|
||||
8
packages/email/src/cloudMailerClient.tsx
Normal file
8
packages/email/src/cloudMailerClient.tsx
Normal 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;
|
||||
@@ -1,3 +1,4 @@
|
||||
export const name = "email";
|
||||
|
||||
export { sendEmail } from "./sendEmail";
|
||||
export { cloudMailerClient } from "./cloudMailerClient";
|
||||
|
||||
@@ -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
10
pnpm-lock.yaml
generated
@@ -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)':
|
||||
|
||||
@@ -109,7 +109,9 @@
|
||||
"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",
|
||||
|
||||
Reference in New Issue
Block a user