Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Your tasks' durations will now be rendered with the due date.
- You can now set a task duration when creating a new task.
- Project icons in the task creation modal will now show that project's color.
- You can now select whether to include a link to the current page in the task creation modal.

### 🔁 Changes

Expand Down
6 changes: 3 additions & 3 deletions docs/docs/translation-status.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
{
"name": "English",
"code": "en",
"completed": 157,
"completed": 163,
"missing": 0,
"percent": 100
},
{
"name": "Nederlands",
"code": "nl",
"completed": 148,
"missing": 9,
"percent": 94
"missing": 15,
"percent": 91
}
]
6 changes: 2 additions & 4 deletions plugin/src/commands/addTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const addTaskWithPageInContent: MakeCommand = (
return {
id: "add-task-page-content",
name: i18n.addTaskPageContent,
callback: makeCallback(plugin, { appendLinkToContent: true }),
callback: makeCallback(plugin, { appendLinkTo: "content" }),
};
};

Expand All @@ -29,7 +29,7 @@ export const addTaskWithPageInDescription: MakeCommand = (
return {
id: "add-task-page-description",
name: i18n.addTaskPageDescription,
callback: makeCallback(plugin, { appendLinkToDescription: true }),
callback: makeCallback(plugin, { appendLinkTo: "description" }),
};
};

Expand All @@ -39,8 +39,6 @@ const makeCallback = (plugin: TodoistPlugin, opts?: Partial<TaskCreationOptions>
initialContent: grabSelection(plugin),
fileContext: getFileContext(plugin),
options: {
appendLinkToContent: false,
appendLinkToDescription: false,
...(opts ?? {}),
},
});
Expand Down
7 changes: 7 additions & 0 deletions plugin/src/i18n/langs/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ export const en: Translations = {
placeholder: "Type a project name",
},
},
optionsSelector: {
buttonLabel: "Set options",
optionsLabel: "Task options",
addLinkToContent: "Add link to content",
addLinkToDescription: "Add link to description",
doNotAddLink: "Do not add link",
},
},
onboardingModal: {
failureNoticeMessage: "Failed to save API token",
Expand Down
7 changes: 7 additions & 0 deletions plugin/src/i18n/translation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ export type Translations = {
placeholder: string;
};
};
optionsSelector: {
buttonLabel: string;
optionsLabel: string;
addLinkToContent: string;
addLinkToDescription: string;
doNotAddLink: string;
};
};
onboardingModal: {
failureNoticeMessage: string;
Expand Down
2 changes: 1 addition & 1 deletion plugin/src/ui/createTaskModal/DueDateSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export const DueDateSelector: React.FC<Props> = ({ selected, setSelected }) => {
<DialogTrigger>
<Button className="due-date-selector" aria-label={i18n.buttonLabel}>
<ObsidianIcon size="s" id="calendar" />
{label}
<span>{label}</span>
</Button>
<Popover maxHeight={600}>
<Dialog className="task-option-dialog task-date-menu" aria-label={i18n.dialogLabel}>
Expand Down
2 changes: 1 addition & 1 deletion plugin/src/ui/createTaskModal/LabelSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const LabelSelector: React.FC<Props> = ({ selected, setSelected }) => {
<DialogTrigger>
<Button className="label-selector" aria-label={i18n.buttonLabel}>
<ObsidianIcon size="m" id="tag" />
{i18n.buttonText(selected.length)}
<span>{i18n.buttonText(selected.length)}</span>
</Button>
<Popover>
<ListBox
Expand Down
75 changes: 75 additions & 0 deletions plugin/src/ui/createTaskModal/OptionsSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { t } from "@/i18n";
import { ObsidianIcon } from "@/ui/components/obsidian-icon";
import type { TaskCreationOptions } from "@/ui/createTaskModal";
import { Popover } from "@/ui/createTaskModal/Popover";
import cn from "classnames";
import type React from "react";
import { Button, type Key, Menu, MenuItem, MenuTrigger } from "react-aria-components";

type Props = {
selected: TaskCreationOptions;
setSelected: (selected: TaskCreationOptions) => void;
};

export const OptionsSelector: React.FC<Props> = ({ selected, setSelected }) => {
const i18n = t().createTaskModal.optionsSelector;

const onAction = (key: Key) => {
if (key === "add-link-to-content") {
setSelected({ ...selected, appendLinkTo: "content" });
} else if (key === "add-link-to-description") {
setSelected({ ...selected, appendLinkTo: "description" });
} else if (key === "do-not-add-link") {
setSelected({ ...selected, appendLinkTo: undefined });
}
};

const items: Array<{
key: string;
label: string;
isSelected: boolean;
}> = [
{
key: "add-link-to-content",
label: i18n.addLinkToContent,
isSelected: selected.appendLinkTo === "content",
},
{
key: "add-link-to-description",
label: i18n.addLinkToDescription,
isSelected: selected.appendLinkTo === "description",
},
{
key: "do-not-add-link",
label: i18n.doNotAddLink,
isSelected: selected.appendLinkTo === undefined,
},
];

return (
<MenuTrigger>
<Button className="options-selector" aria-label={i18n.buttonLabel}>
<ObsidianIcon size="m" id="ellipsis-vertical" />
</Button>
<Popover>
<Menu
className="task-option-dialog task-options-menu"
aria-label={i18n.optionsLabel}
onAction={onAction}
>
{items.map((item) => (
<MenuItem
key={item.key}
id={item.key}
className={cn("task-option-dialog-item", {
"is-selected": item.isSelected,
})}
>
{item.label}
</MenuItem>
))}
</Menu>
</Popover>
</MenuTrigger>
);
};
2 changes: 1 addition & 1 deletion plugin/src/ui/createTaskModal/PrioritySelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const PrioritySelector: React.FC<Props> = ({ selected, setSelected }) =>
<MenuTrigger>
<Button className="priority-selector" aria-label={i18n.buttonLabel}>
<ObsidianIcon size="m" id="flag" />
{label}
<span>{label}</span>
</Button>
<Popover>
<Menu
Expand Down
45 changes: 33 additions & 12 deletions plugin/src/ui/createTaskModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ import { PrioritySelector } from "./PrioritySelector";
import { type ProjectIdentifier, ProjectSelector } from "./ProjectSelector";
import { TaskContentInput } from "./TaskContentInput";
import "./styles.scss";
import type { Translations } from "@/i18n/translation";
import { OptionsSelector } from "@/ui/createTaskModal/OptionsSelector";

export type LinkDestination = "content" | "description";

export type TaskCreationOptions = {
appendLinkToContent: boolean;
appendLinkToDescription: boolean;
appendLinkTo?: LinkDestination;
};

type CreateTaskProps = {
Expand All @@ -28,6 +31,20 @@ type CreateTaskProps = {
options: TaskCreationOptions;
};

const getLinkDestinationMessage = (
destination: LinkDestination | undefined,
i18n: Translations["createTaskModal"],
): string | undefined => {
switch (destination) {
case "content":
return i18n.appendedLinkToContentMessage;
case "description":
return i18n.appendedLinkToDescriptionMessage;
default:
return undefined;
}
};

export const CreateTaskModal: React.FC<CreateTaskProps> = (props) => {
const plugin = PluginContext.use();

Expand Down Expand Up @@ -75,7 +92,7 @@ const CreateTaskModalContent: React.FC<CreateTaskProps> = ({

const [options, setOptions] = useState<TaskCreationOptions>(initialOptions);

const isSubmitButtonDisabled = content === "" && !options.appendLinkToContent;
const isSubmitButtonDisabled = content === "" && options.appendLinkTo !== "content";

const i18n = t().createTaskModal;

Expand Down Expand Up @@ -103,7 +120,7 @@ const CreateTaskModalContent: React.FC<CreateTaskProps> = ({
modal.close();

const params: CreateTaskParams = {
description: buildWithLink(description, options.appendLinkToDescription),
description: buildWithLink(description, options.appendLinkTo === "description"),
priority: priority,
labels: labels.map((l) => l.name),
projectId: project.projectId,
Expand All @@ -123,7 +140,7 @@ const CreateTaskModalContent: React.FC<CreateTaskProps> = ({

try {
await plugin.services.todoist.actions.createTask(
buildWithLink(content, options.appendLinkToContent),
buildWithLink(content, options.appendLinkTo === "content"),
params,
);
new Notice(i18n.successNotice);
Expand All @@ -133,6 +150,8 @@ const CreateTaskModalContent: React.FC<CreateTaskProps> = ({
}
};

const linkDestinationMessage = getLinkDestinationMessage(options.appendLinkTo, i18n);

return (
<div className="task-creation-modal-root">
<TaskContentInput
Expand All @@ -150,15 +169,17 @@ const CreateTaskModalContent: React.FC<CreateTaskProps> = ({
onChange={setDescription}
/>
<div className="task-creation-selectors">
<DueDateSelector selected={dueDate} setSelected={setDueDate} />
<PrioritySelector selected={priority} setSelected={setPriority} />
<LabelSelector selected={labels} setSelected={setLabels} />
<div className="task-creation-selectors-group">
<DueDateSelector selected={dueDate} setSelected={setDueDate} />
<PrioritySelector selected={priority} setSelected={setPriority} />
<LabelSelector selected={labels} setSelected={setLabels} />
</div>
<div className="task-creation-selectors-group">
<OptionsSelector selected={options} setSelected={setOptions} />
</div>
</div>
<div className="task-creation-notes">
<ul>
{options.appendLinkToContent && <li>{i18n.appendedLinkToContentMessage}</li>}
{options.appendLinkToDescription && <li>{i18n.appendedLinkToDescriptionMessage}</li>}
</ul>
<ul>{linkDestinationMessage && <li>{linkDestinationMessage}</li>}</ul>
</div>
<hr />
<div className="task-creation-controls">
Expand Down
31 changes: 27 additions & 4 deletions plugin/src/ui/createTaskModal/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@
margin-top: 0.5em;
display: flex;
align-items: center;
justify-content: space-between;

&>*+* {
margin-left: 0.5em;
.task-creation-selectors-group {
display: flex;
align-items: center;

&>*+* {
margin-left: 0.5em;
}
}

button {
Expand All @@ -45,8 +51,8 @@
border: 1px solid var(--color-base-25);
color: var(--text-muted);

.obsidian-icon {
margin-right: 0.5em;
&>*+* {
margin-left: 0.5em;
}

&:hover,
Expand Down Expand Up @@ -275,6 +281,23 @@
}
}


.task-options-menu {
.task-option-dialog-item {
padding: 8px 1em;
font-size: var(--font-smaller);

&:hover {
background-color: var(--background-modifier-cover);
}

&.is-selected {
background-color: var(--interactive-accent);
color: var(--text-on-accent);
}
}
}

button.project-selector {
box-shadow: none;
background-color: unset;
Expand Down