Skip to content

Commit

Permalink
Fix: tasks ui
Browse files Browse the repository at this point in the history
  • Loading branch information
harshithmullapudi committed Mar 1, 2025
1 parent 95f670f commit 7060e42
Show file tree
Hide file tree
Showing 12 changed files with 226 additions and 59 deletions.
1 change: 0 additions & 1 deletion apps/server/src/modules/pages/pages.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ export class PagesService {
page,
tasksExtensionContent,
);
console.log(description);

// Update the page with new description in the same transaction
await this.contentService.updateContentForDocument(
Expand Down
1 change: 0 additions & 1 deletion apps/server/src/modules/pages/pages.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ export function upsertTaskInExtension(
taskExtensions.content.push(...newTaskNodes);
}

console.log(JSON.stringify(taskExtensions));
return taskExtensions;
}

Expand Down
3 changes: 2 additions & 1 deletion apps/webapp/common/editor/editor-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
Placeholder,
HighlightExtension,
AIHighlight,
TaskList,
CustomKeymap,
} from 'novel/extensions';

Expand Down Expand Up @@ -64,7 +65,7 @@ const starterKit = StarterKit.configure({
},
orderedList: {
HTMLAttributes: {
class: cx('list-decimal list-outside [&_ol]:pl-4 leading-1 my-1'),
class: cx('list-decimal list-outside pl-4 leading-1 my-1'),
},
},
listItem: false,
Expand Down
9 changes: 8 additions & 1 deletion apps/webapp/common/editor/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import { useDebouncedCallback } from 'use-debounce';
import { defaultExtensions, getPlaceholder } from './editor-extensions';
import { LinkSelector, NodeSelector, TextButtons } from './selectors';
import { slashCommand } from './slash-command';
import { handleMarkAndImagePaste, uploadFn } from './utils';
import {
createTasksExtension,
handleMarkAndImagePaste,
uploadFn,
} from './utils';
import {
EditorRoot,
EditorCommand,
Expand Down Expand Up @@ -138,6 +142,9 @@ export const Editor = ({
const debouncedUpdates = useDebouncedCallback(
async (editor: EditorInstance) => {
const json = editor.getJSON();

createTasksExtension(editor);

onChange &&
onChange(
JSON.stringify({
Expand Down
2 changes: 1 addition & 1 deletion apps/webapp/common/editor/link-task/link-task-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export const TasksCommand = React.forwardRef(
from: from - 2,
to: from,
})
.wrapIn('listItem')
.wrapIn('bulletList')
.wrapIn('listItem')
.insertContent([
{
type: 'task',
Expand Down
62 changes: 39 additions & 23 deletions apps/webapp/common/editor/slash-command.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,21 @@ export const suggestionItems = createSuggestionItems([
},
},
{
title: 'To-do List',
title: 'Task',
description: 'Track tasks with a to-do list.',
searchTerms: ['todo', 'task', 'list', 'check', 'checkbox'],
icon: <CheckLine size={20} />,
icon: <IssuesLine size={20} />,
command: ({ editor, range }) => {
editor.chain().focus().deleteRange(range).toggleTaskList().run();
editor
.chain()
.focus()
.deleteRange(range)
.wrapIn('listItem')
.wrapIn('bulletList')
.setNode('task', {
id: undefined,
})
.run();
},
},
{
Expand Down Expand Up @@ -150,6 +159,23 @@ export const suggestionItems = createSuggestionItems([
input.click();
},
},
{
title: 'Date',
description: 'Add date to page',
searchTerms: ['date'],
icon: <CalendarLine size={20} />,
command: ({ editor, range }) => {
editor.commands.command(({ tr, state }) => {
const node = state.schema.nodes['datePageExtension'].create({
type: 'inline',
});

tr.replaceWith(range.from, range.to, node);

return true;
});
},
},
{
title: 'Add tasks for this day',
description: 'Search or create task',
Expand All @@ -167,11 +193,18 @@ export const suggestionItems = createSuggestionItems([
type: 'tasksExtension',
content: [
{
type: 'paragraph',
type: 'bulletList',
content: [
{
type: 'text',
text: 'Add tasks here',
type: 'listItem',
content: [
{
type: 'task',
attrs: {
id: undefined,
},
},
],
},
],
},
Expand All @@ -181,23 +214,6 @@ export const suggestionItems = createSuggestionItems([
.run();
},
},
{
title: 'Date',
description: 'Add date to page',
searchTerms: ['date'],
icon: <CalendarLine size={20} />,
command: ({ editor, range }) => {
editor.commands.command(({ tr, state }) => {
const node = state.schema.nodes['datePageExtension'].create({
type: 'inline',
});

tr.replaceWith(range.from, range.to, node);

return true;
});
},
},
]);

export const slashCommand = Command.configure({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const TaskComponent = observer((props: any) => {
}, 500);

React.useEffect(() => {
if (!taskId && content) {
if (!taskId && content && !content.includes('[')) {
debounceAddTask({
title: content,
...getCreateTaskPropsOnSource(source, date),
Expand Down
43 changes: 38 additions & 5 deletions apps/webapp/common/editor/task-extension/task-extension.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,41 @@ export const TaskExtension = ({
if (!isTaskContent()) {
return false;
}

const state = this.editor.state;
const selection = state.selection;

console.log(selection, state);
let insideTasksExtension = false;

// Traverse up the hierarchy to check if any parent node is `tasksExtension`
for (let depth = selection.$from.depth; depth > 0; depth--) {
const parentNode = selection.$from.node(depth);
if (parentNode.type.name === 'tasksExtension') {
insideTasksExtension = true;
}
}

if (insideTasksExtension) {
if (selection.$from.parentOffset === 0) {
return this.editor
.chain()
.liftListItem('listItem')
.setNode('paragraph', {})
.run();
}

const task = this.editor.schema.nodes.task;

this.editor
.chain()
.splitListItem('listItem')
.setNode(task, {
id: undefined,
})
.run();
return true;
}

// if it's not the top level node, let list handle it
if (
selection.$from.depth > 3 ||
Expand All @@ -93,11 +124,13 @@ export const TaskExtension = ({
return this.editor.commands.setNode('paragraph');
},
Backspace: () => {
const state = this.editor.state;
const selection = state.selection;

if (!isTaskContent()) {
return false;
}
const state = this.editor.state;
const selection = state.selection;

const blockRange = selection.$from.blockRange();
if (!blockRange) {
return false;
Expand Down Expand Up @@ -137,11 +170,11 @@ export const TaskExtension = ({
const task = state.schema.nodes.task;

chain()
.wrapIn('bulletList')
.wrapIn('listItem')
.setNode(task, {
id: undefined,
})
.wrapIn('listItem')
.wrapIn('bulletList')
.run();
},
}),
Expand Down
73 changes: 72 additions & 1 deletion apps/webapp/common/editor/tasks/tasks-extension.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ReactNodeViewRenderer } from '../ReactNodeView';
export const tasksExtension = Node.create({
name: 'tasksExtension',
group: 'block',
content: 'block*',
content: '(paragraph | bulletList | orderedList | listItem | task)*',
selectable: false,

parseHTML() {
Expand All @@ -24,4 +24,75 @@ export const tasksExtension = Node.create({
addNodeView() {
return ReactNodeViewRenderer(TasksComponent);
},

// eslint-disable-next-line @typescript-eslint/no-explicit-any
addKeyboardShortcuts(this: any) {
return {
Backspace: () => {
const state = this.editor.state;
const selection = state.selection;

if (selection.$from.pos < 3) {
return true;
}

let tasksExtensionIsEmpty = false;

// Traverse up the hierarchy to check if any parent node is `tasksExtension`
for (let depth = selection.$from.depth; depth > 0; depth--) {
const parentNode = selection.$from.node(depth);
if (parentNode.type.name === 'tasksExtension') {
tasksExtensionIsEmpty =
parentNode.textContent === '' ? true : false;
}
}

if (tasksExtensionIsEmpty && selection.$from.pos < 3) {
return true;
}
},
'Mod-Backspace': () => {
const state = this.editor.state;
const selection = state.selection;

if (selection.$from.pos < 3) {
return true;
}

let tasksExtensionIsEmpty = false;

// Traverse up the hierarchy to check if any parent node is `tasksExtension`
for (let depth = selection.$from.depth; depth > 0; depth--) {
const parentNode = selection.$from.node(depth);
if (parentNode.type.name === 'tasksExtension') {
tasksExtensionIsEmpty =
parentNode.textContent === '' ? true : false;
}
}

if (tasksExtensionIsEmpty && selection.$from.pos < 3) {
return true;
}
},
Enter: () => {
const state = this.editor.state;
const selection = state.selection;

let tasksExtensionIsEmpty = false;

// Traverse up the hierarchy to check if any parent node is `tasksExtension`
for (let depth = selection.$from.depth; depth > 0; depth--) {
const parentNode = selection.$from.node(depth);
if (parentNode.type.name === 'tasksExtension') {
tasksExtensionIsEmpty =
parentNode.textContent === '' ? true : false;
}
}

if (tasksExtensionIsEmpty) {
return true;
}
},
};
},
});
35 changes: 35 additions & 0 deletions apps/webapp/common/editor/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Editor } from '@tiptap/core';

import { type ImageUploadOptions } from 'novel/plugins';
import type { EditorT } from './editor';

const onUploadFile = async (file: File) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -148,3 +149,37 @@ export const uploadFileFn = createFileUpload({
return true;
},
});

export const createTasksExtension = (editor: EditorT) => {
const json = editor.getJSON();

if (json.content[0].type !== 'tasksExtension') {
editor
.chain()
.focus()
.insertContentAt(0, [
{
type: 'tasksExtension',
content: [
{
type: 'bulletList',
content: [
{
type: 'listItem',
content: [
{
type: 'task',
attrs: {
id: undefined,
},
},
],
},
],
},
],
},
])
.run();
}
};
24 changes: 0 additions & 24 deletions apps/webapp/modules/my-day/utils.ts

This file was deleted.

Loading

0 comments on commit 7060e42

Please sign in to comment.