Improve page create in document editor

This commit is contained in:
Hakan Shehu
2024-10-16 09:27:03 +02:00
parent 961fec0935
commit dca335f2a9
10 changed files with 69 additions and 28 deletions

View File

@@ -16,18 +16,23 @@ export class PageCreateMutationHandler
input.userId,
);
const siblings = await workspaceDatabase
.selectFrom('nodes')
.selectAll()
.where('parent_id', '=', input.spaceId)
.execute();
let index: string | undefined = undefined;
if (input.generateIndex) {
const siblings = await workspaceDatabase
.selectFrom('nodes')
.selectAll()
.where('parent_id', '=', input.parentId)
.execute();
const maxIndex =
siblings.length > 0
? siblings.sort((a, b) => compareString(a.index, b.index))[
siblings.length - 1
].index
: null;
const maxIndex =
siblings.length > 0
? siblings.sort((a, b) => compareString(a.index, b.index))[
siblings.length - 1
].index
: null;
index = generateNodeIndex(maxIndex, null);
}
const id = generateId(IdType.Page);
await workspaceDatabase
@@ -38,8 +43,8 @@ export class PageCreateMutationHandler
id: id,
attributes: {
type: NodeTypes.Page,
parentId: input.spaceId,
index: generateNodeIndex(maxIndex, null),
parentId: input.parentId,
index: index,
},
},
input.userId,

View File

@@ -15,8 +15,9 @@ export class NodeGetQueryHandler implements QueryHandler<NodeGetQueryInput> {
input: NodeGetQueryInput,
): Promise<QueryResult<NodeGetQueryInput>> {
const row = await this.fetchNode(input);
return {
output: mapNode(row),
output: row ? mapNode(row) : null,
state: {
row,
},
@@ -51,7 +52,7 @@ export class NodeGetQueryHandler implements QueryHandler<NodeGetQueryInput> {
return {
hasChanges: true,
result: {
output: mapNode(row),
output: row ? mapNode(row) : null,
state: {
row,
},

View File

@@ -1,8 +1,9 @@
export type PageCreateMutationInput = {
type: 'page_create';
userId: string;
spaceId: string;
parentId: string;
name: string;
generateIndex: boolean;
};
export type PageCreateMutationOutput = {

View File

@@ -10,7 +10,7 @@ declare module '@/operations/queries' {
interface QueryMap {
node_get: {
input: NodeGetQueryInput;
output: LocalNode;
output: LocalNode | null;
};
}
}

View File

@@ -126,7 +126,10 @@ export const DocumentEditor = ({
DividerCommand,
TodoCommand,
],
context: {},
context: {
documentId,
userId: workspace.userId,
},
}),
BoldMark,
ItalicMark,

View File

@@ -58,8 +58,9 @@ export const PageCreateDialog = ({
mutate({
input: {
type: 'page_create',
spaceId: spaceId,
parentId: spaceId,
name: values.name,
generateIndex: true,
userId: workspace.userId,
},
onSuccess(output) {

View File

@@ -1,6 +1,5 @@
import { EditorCommand } from '@/types/editor';
import { NodeTypes } from '@/lib/constants';
import { generateId, IdType } from '@/lib/id';
const PageCommand: EditorCommand = {
key: 'page',
@@ -9,11 +8,24 @@ const PageCommand: EditorCommand = {
keywords: ['page'],
icon: 'draft-line',
disabled: false,
handler({ editor, range, context }) {
async handler({ editor, range, context }) {
if (context == null) {
return;
}
const { userId, documentId } = context;
const output = await window.neuron.executeMutation({
type: 'page_create',
name: 'Untitled',
userId,
parentId: documentId,
generateIndex: false,
});
if (!output.id) {
return;
}
editor
.chain()
.focus()
@@ -21,7 +33,7 @@ const PageCommand: EditorCommand = {
.insertContent({
type: NodeTypes.Page,
attrs: {
id: generateId(IdType.Page),
id: output.id,
},
})
.run();

View File

@@ -193,7 +193,7 @@ export const CommanderExtension = Extension.create<CommanderOptions>({
Suggestion({
editor: this.editor,
char: '/',
command: ({
command: async ({
editor,
range,
props,
@@ -202,7 +202,15 @@ export const CommanderExtension = Extension.create<CommanderOptions>({
range: Range;
props: EditorCommand;
}) => {
props.handler({ editor, range, context: this.options.context });
const result = props.handler({
editor,
range,
context: this.options.context,
});
if (result instanceof Promise) {
await result;
}
},
items: ({ query }: { query: string }) =>
filterCommands({ query, commands: this.options.commands }),

View File

@@ -3,17 +3,24 @@ import { type NodeViewProps } from '@tiptap/core';
import { NodeViewWrapper } from '@tiptap/react';
import { Avatar } from '@/renderer/components/avatars/avatar';
import { useWorkspace } from '@/renderer/contexts/workspace';
import { useQuery } from '@/renderer/hooks/use-query';
export const PageNodeView = ({ node }: NodeViewProps) => {
const workspace = useWorkspace();
const id = node.attrs.id;
const name = node.attrs.name ?? 'Unnamed';
const avatar = node.attrs.avatar;
const { data, isPending } = useQuery({
type: 'node_get',
nodeId: id,
userId: workspace.userId,
});
if (!id) {
return null;
}
const name = data?.attributes.name ?? 'Unnamed';
const avatar = data?.attributes.avatar;
return (
<NodeViewWrapper
data-block-id={node.attrs.blockId}

View File

@@ -7,7 +7,10 @@ export type EditorCommandProps = {
context: EditorCommandContext | null;
};
export type EditorCommandContext = {};
export type EditorCommandContext = {
documentId: string;
userId: string;
};
export type EditorCommand = {
key: string;
@@ -15,7 +18,7 @@ export type EditorCommand = {
description: string;
keywords?: string[];
icon: string;
handler: (props: EditorCommandProps) => void;
handler: (props: EditorCommandProps) => void | Promise<void>;
disabled?: boolean;
};