mirror of
https://github.com/colanode/colanode.git
synced 2025-12-16 11:47:47 +01:00
Implement database block for the editor
This commit is contained in:
@@ -29,7 +29,7 @@ export class DatabaseCreateMutationHandler
|
||||
type: 'database',
|
||||
name: input.name,
|
||||
avatar: input.avatar,
|
||||
parentId: input.spaceId,
|
||||
parentId: input.parentId,
|
||||
fields: {
|
||||
[fieldId]: {
|
||||
id: fieldId,
|
||||
@@ -51,7 +51,7 @@ export class DatabaseCreateMutationHandler
|
||||
await workspace.entries.createEntry({
|
||||
id: databaseId,
|
||||
attributes,
|
||||
parentId: input.spaceId,
|
||||
parentId: input.parentId,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -53,7 +53,7 @@ export const DatabaseCreateDialog = ({
|
||||
mutate({
|
||||
input: {
|
||||
type: 'database_create',
|
||||
spaceId: spaceId,
|
||||
parentId: spaceId,
|
||||
name: values.name,
|
||||
avatar: values.avatar,
|
||||
accountId: workspace.accountId,
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
PageCommand,
|
||||
ParagraphCommand,
|
||||
TodoCommand,
|
||||
DatabaseCommand,
|
||||
} from '@/renderer/editor/commands';
|
||||
import {
|
||||
BlockquoteNode,
|
||||
@@ -59,6 +60,7 @@ import {
|
||||
TextNode,
|
||||
TrailingNode,
|
||||
UnderlineMark,
|
||||
DatabaseNode,
|
||||
} from '@/renderer/editor/extensions';
|
||||
import { ToolbarMenu, ActionMenu } from '@/renderer/editor/menus';
|
||||
|
||||
@@ -138,6 +140,7 @@ export const DocumentEditor = ({
|
||||
LinkMark,
|
||||
DeleteControlExtension,
|
||||
DropcursorExtension,
|
||||
DatabaseNode,
|
||||
CommanderExtension.configure({
|
||||
commands: [
|
||||
ParagraphCommand,
|
||||
@@ -149,6 +152,7 @@ export const DocumentEditor = ({
|
||||
BulletListCommand,
|
||||
CodeBlockCommand,
|
||||
OrderedListCommand,
|
||||
DatabaseCommand,
|
||||
DividerCommand,
|
||||
TodoCommand,
|
||||
FileCommand,
|
||||
|
||||
42
apps/desktop/src/renderer/editor/commands/database.tsx
Normal file
42
apps/desktop/src/renderer/editor/commands/database.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Database } from 'lucide-react';
|
||||
|
||||
import { EditorCommand } from '@/shared/types/editor';
|
||||
|
||||
export const DatabaseCommand: EditorCommand = {
|
||||
key: 'database',
|
||||
name: 'Database',
|
||||
description: 'Insert a nested database',
|
||||
keywords: ['database'],
|
||||
icon: Database,
|
||||
disabled: false,
|
||||
async handler({ editor, range, context }) {
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { accountId, workspaceId, documentId } = context;
|
||||
const output = await window.colanode.executeMutation({
|
||||
type: 'database_create',
|
||||
name: 'Untitled',
|
||||
accountId,
|
||||
workspaceId,
|
||||
parentId: documentId,
|
||||
});
|
||||
|
||||
if (!output.success) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
.deleteRange(range)
|
||||
.insertContent({
|
||||
type: 'database',
|
||||
attrs: {
|
||||
id: output.output.id,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
},
|
||||
};
|
||||
@@ -12,6 +12,7 @@ import { PageCommand } from '@/renderer/editor/commands/page';
|
||||
import { ParagraphCommand } from '@/renderer/editor/commands/paragraph';
|
||||
import { TodoCommand } from '@/renderer/editor/commands/todo';
|
||||
import { EditorCommand, EditorCommandProps } from '@/shared/types/editor';
|
||||
import { DatabaseCommand } from '@/renderer/editor/commands/database';
|
||||
|
||||
export type { EditorCommand, EditorCommandProps };
|
||||
|
||||
@@ -29,4 +30,5 @@ export {
|
||||
PageCommand,
|
||||
ParagraphCommand,
|
||||
TodoCommand,
|
||||
DatabaseCommand,
|
||||
};
|
||||
|
||||
27
apps/desktop/src/renderer/editor/extensions/database.tsx
Normal file
27
apps/desktop/src/renderer/editor/extensions/database.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { mergeAttributes, Node } from '@tiptap/core';
|
||||
import { ReactNodeViewRenderer } from '@tiptap/react';
|
||||
|
||||
import { DatabaseNodeView } from '@/renderer/editor/views';
|
||||
|
||||
export const DatabaseNode = Node.create({
|
||||
name: 'database',
|
||||
group: 'block',
|
||||
atom: true,
|
||||
defining: true,
|
||||
draggable: true,
|
||||
addAttributes() {
|
||||
return {
|
||||
id: {
|
||||
default: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
return ['page', mergeAttributes(HTMLAttributes)];
|
||||
},
|
||||
addNodeView() {
|
||||
return ReactNodeViewRenderer(DatabaseNodeView, {
|
||||
as: 'database',
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -34,6 +34,7 @@ import { TabKeymapExtension } from '@/renderer/editor/extensions/tab-keymap';
|
||||
import { TaskItemNode } from '@/renderer/editor/extensions/task-item';
|
||||
import { TaskListNode } from '@/renderer/editor/extensions/task-list';
|
||||
import { TrailingNode } from '@/renderer/editor/extensions/trailing-node';
|
||||
import { DatabaseNode } from '@/renderer/editor/extensions/database';
|
||||
|
||||
export {
|
||||
BlockquoteNode,
|
||||
@@ -71,4 +72,5 @@ export {
|
||||
TextNode,
|
||||
TrailingNode,
|
||||
UnderlineMark,
|
||||
DatabaseNode,
|
||||
};
|
||||
|
||||
44
apps/desktop/src/renderer/editor/views/database.tsx
Normal file
44
apps/desktop/src/renderer/editor/views/database.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
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 DatabaseNodeView = ({ node }: NodeViewProps) => {
|
||||
const workspace = useWorkspace();
|
||||
|
||||
const id = node.attrs.id;
|
||||
const { data } = useQuery({
|
||||
type: 'entry_get',
|
||||
entryId: id,
|
||||
accountId: workspace.accountId,
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
|
||||
if (!id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data?.attributes.type !== 'database') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const name = data.attributes.name ?? 'Unnamed';
|
||||
const avatar = data?.attributes.avatar;
|
||||
|
||||
return (
|
||||
<NodeViewWrapper
|
||||
data-id={node.attrs.id}
|
||||
className="my-0.5 flex h-12 w-full cursor-pointer flex-row items-center gap-1 rounded-md bg-gray-50 p-2 hover:bg-gray-100"
|
||||
onClick={() => {
|
||||
workspace.openInMain(id);
|
||||
}}
|
||||
>
|
||||
<Avatar size="small" id={id} name={name} avatar={avatar} />
|
||||
<div role="presentation" className="flex-grow">
|
||||
{name}
|
||||
</div>
|
||||
</NodeViewWrapper>
|
||||
);
|
||||
};
|
||||
@@ -3,9 +3,11 @@ import { FileNodeView } from '@/renderer/editor/views/file';
|
||||
import { FilePlaceholderNodeView } from '@/renderer/editor/views/file-placeholder';
|
||||
import { FolderNodeView } from '@/renderer/editor/views/folder';
|
||||
import { PageNodeView } from '@/renderer/editor/views/page';
|
||||
import { DatabaseNodeView } from '@/renderer/editor/views/database';
|
||||
|
||||
export {
|
||||
CodeBlockNodeView,
|
||||
DatabaseNodeView,
|
||||
FileNodeView,
|
||||
FilePlaceholderNodeView,
|
||||
FolderNodeView,
|
||||
|
||||
@@ -2,7 +2,7 @@ export type DatabaseCreateMutationInput = {
|
||||
type: 'database_create';
|
||||
accountId: string;
|
||||
workspaceId: string;
|
||||
spaceId: string;
|
||||
parentId: string;
|
||||
name: string;
|
||||
avatar?: string | null;
|
||||
};
|
||||
|
||||
@@ -5,7 +5,6 @@ export type PageCreateMutationInput = {
|
||||
parentId: string;
|
||||
avatar?: string | null;
|
||||
name: string;
|
||||
generateIndex: boolean;
|
||||
};
|
||||
|
||||
export type PageCreateMutationOutput = {
|
||||
|
||||
Reference in New Issue
Block a user