Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redesign task creation modal #304

Merged
merged 16 commits into from
Mar 30, 2024
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Now includes useful links to documentation and GitHub issues.
- API token validation is done in the settings page with an option to open the modal if the validation fails.
- You can now group by different task properties like: priority, due date, and others. Please see the [documentation](https://jamiebrynes7.github.io/obsidian-todoist-plugin/docs/query-blocks#groupBy) for more details.
- Rebuilt the add task dialog from scratch. This should fix a number of bugs with the date picker, improves the UX, and brings it inline with the native Todoist experience.
- Added a new command 'Add task with current page in task description' which offers the ability to append a link to the current page to the task description when it is created.

## [1.12.0] - 2024-02-09

Expand Down
Binary file modified docs/docs/commands/add-task-modal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 7 additions & 4 deletions docs/docs/commands/add-task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
sidebar_position: 1
---

# Add Task
# Add task

![](./add-task-modal.png)

The 'Add Todoist task' command allows you send tasks to Todoist from Obsidian. There are a few utilities to help you set the text content:
The 'Add task' set of commands open up a modal that allows you to configure and send tasks to Todoist from Obsidian. Any text selected will be used to pre-populate the task content.

- Any text selected will be used to pre-populate the task's text
- You can append a link to the currently selected Obsidian page to the task's text by using the 'Add Todoist task with the current page' variant of the command
There are a few variants of the command:

- 'Add task', the basic version
- 'Add task with current page in task content', this option will append a link to the current page in the task content before it sends it to Obsidian. The modal will inform you it will do this, but the link is not shown to keep the modal clean.
- 'Add task with current page in task description', this option will append a link to the current page in the task description before it sends it to Obsidian. The modal will inform you it will do this, but the link is not shown to keep the modal clean.
59 changes: 56 additions & 3 deletions plugin/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
"author": "Jamie Brynes",
"license": "ISC",
"dependencies": {
"@internationalized/date": "^3.5.2",
"camelize-ts": "^3.0.0",
"classnames": "^2.5.1",
"moment": "^2.29.4",
"obsidian": "0.15",
"react": "^18.2.0",
"react-aria-components": "^1.1.1",
"react-dom": "^18.2.0",
"react-textarea-autosize": "^8.5.3",
"snakify-ts": "^2.3.0",
"svelte": "^4.2.10",
"svelte-select": "^5.0.1",
Expand Down
1 change: 1 addition & 0 deletions plugin/src/api/domain/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export type Project = {
parentId: ProjectId | null;
name: string;
order: number;
isInboxProject: boolean;
};
60 changes: 60 additions & 0 deletions plugin/src/commands/addTask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { MarkdownView, Notice, TFile } from "obsidian";
import type { MakeCommand } from ".";
import type TodoistPlugin from "..";
import type { TaskCreationOptions } from "../ui/createTaskModal";

export const addTask: MakeCommand = (plugin: TodoistPlugin) => {
return {
name: "Add task",
callback: makeCallback(plugin),
};
};

export const addTaskWithPageInContent: MakeCommand = (plugin: TodoistPlugin) => {
return {
id: "add-task-page-content",
name: "Add task with current page in task content",
callback: makeCallback(plugin, { appendLinkToContent: true }),
};
};

export const addTaskWithPageInDescription: MakeCommand = (plugin: TodoistPlugin) => {
return {
id: "add-task-page-description",
name: "Add task with current page in task description",
callback: makeCallback(plugin, { appendLinkToDescription: true }),
};
};

const makeCallback = (plugin: TodoistPlugin, opts?: Partial<TaskCreationOptions>) => {
return () => {
if (plugin.options === null) {
new Notice("Failed to load settings, cannot open task creation modal.");
return;
}

plugin.services.modals.taskCreation({
initialContent: grabSelection(plugin),
fileContext: getFileContext(plugin),
options: {
appendLinkToContent: false,
appendLinkToDescription: false,
...(opts ?? {}),
},
});
};
};

const grabSelection = (plugin: TodoistPlugin): string => {
const editorView = plugin.app.workspace.getActiveViewOfType(MarkdownView)?.editor;

if (editorView !== undefined) {
return editorView.getSelection();
}

return window.getSelection()?.toString() ?? "";
};

const getFileContext = (plugin: TodoistPlugin): TFile | undefined => {
return plugin.app.workspace.getActiveFile() ?? undefined;
};
36 changes: 36 additions & 0 deletions plugin/src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { type Command as ObsidianCommand } from "obsidian";
import type TodoistPlugin from "..";
import debug from "../log";
import { addTask, addTaskWithPageInContent, addTaskWithPageInDescription } from "./addTask";

export type MakeCommand = (plugin: TodoistPlugin) => Omit<ObsidianCommand, "id">;

const syncCommand: MakeCommand = (plugin: TodoistPlugin) => {
return {
name: "Sync with Todoist",
callback: async () => {
debug("Syncing with Todoist API");
plugin.services.todoist.sync();
},
};
};

const commands = {
"todoist-sync": syncCommand,
"add-task": addTask,
"add-task-page-content": addTaskWithPageInContent,
"add-task-page-description": addTaskWithPageInDescription,
};

type CommandId = keyof typeof commands;

export const registerCommands = (plugin: TodoistPlugin) => {
for (const [id, make] of Object.entries(commands)) {
plugin.addCommand({ id, ...make(plugin) });
}
};

export const fireCommand = <K extends CommandId>(id: K, plugin: TodoistPlugin) => {
const make = commands[id];
make(plugin).callback?.();
};
9 changes: 9 additions & 0 deletions plugin/src/data/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,19 @@ export class TodoistAdapter {
private readonly labels: Repository<LabelId, Label>;
private readonly subscriptions: SubscriptionManager<Refresh>;

private hasSynced = false;

constructor() {
this.projects = new Repository(() => this.api.withInner((api) => api.getProjects()));
this.sections = new Repository(() => this.api.withInner((api) => api.getSections()));
this.labels = new Repository(() => this.api.withInner((api) => api.getLabels()));
this.subscriptions = new SubscriptionManager<Refresh>();
}

public isReady(): boolean {
return this.api.hasValue() && this.hasSynced;
}

public async initialize(api: TodoistApiClient) {
this.api.insert(api);
await this.sync();
Expand All @@ -69,6 +75,8 @@ export class TodoistAdapter {
for (const refresh of this.subscriptions.listActive()) {
await refresh();
}

this.hasSynced = true;
}

public data(): DataAccessor {
Expand Down Expand Up @@ -150,6 +158,7 @@ const makeUnknownProject = (id: string): Project => {
parentId: null,
name: "Unknown Project",
order: Number.MAX_SAFE_INTEGER,
isInboxProject: false,
};
};

Expand Down
1 change: 1 addition & 0 deletions plugin/src/data/transformations/grouping.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ function makeProject(id: string, opts?: Partial<Project>): Project {
parentId: opts?.parentId ?? null,
name: opts?.name ?? "Project",
order: opts?.order ?? 1,
isInboxProject: false,
};
}

Expand Down
8 changes: 7 additions & 1 deletion plugin/src/data/transformations/relationships.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ function makeTask(id: string, opts?: Partial<Task>): Task {
priority: opts?.priority ?? 1,
order: opts?.order ?? 0,

project: opts?.project ?? { id: "foobar", name: "Foobar", order: 1, parentId: null },
project: opts?.project ?? {
id: "foobar",
name: "Foobar",
order: 1,
parentId: null,
isInboxProject: false,
},
section: opts?.section,

due: opts?.due,
Expand Down
8 changes: 7 additions & 1 deletion plugin/src/data/transformations/sorting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ function makeTask(id: string, opts?: Partial<Task>): Task {
priority: opts?.priority ?? 1,
order: opts?.order ?? 0,

project: opts?.project ?? { id: "foobar", name: "Foobar", order: 1, parentId: null },
project: opts?.project ?? {
id: "foobar",
name: "Foobar",
order: 1,
parentId: null,
isInboxProject: false,
},
section: opts?.section,

due: opts?.due,
Expand Down
Loading