mirror of
https://github.com/docmost/docmost.git
synced 2026-05-08 15:23:07 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 744d88acac | |||
| 7002001340 | |||
| c72ee1ee8e | |||
| b82fdd5f50 | |||
| 98f71c95fe | |||
| 31e66ecf90 |
+10
-10
@@ -42,15 +42,15 @@
|
||||
"mermaid": "^11.12.2",
|
||||
"mitt": "^3.0.1",
|
||||
"posthog-js": "^1.255.1",
|
||||
"react": "^19.2.3",
|
||||
"react": "^18.3.1",
|
||||
"react-arborist": "3.4.0",
|
||||
"react-clear-modal": "^2.0.17",
|
||||
"react-dom": "^19.2.3",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-drawio": "^1.0.7",
|
||||
"react-error-boundary": "^6.1.0",
|
||||
"react-error-boundary": "^4.1.2",
|
||||
"react-helmet-async": "^2.0.5",
|
||||
"react-i18next": "^15.0.1",
|
||||
"react-router-dom": "^7.13.0",
|
||||
"react-router-dom": "^7.12.0",
|
||||
"semver": "^7.7.3",
|
||||
"socket.io-client": "^4.8.3",
|
||||
"tiptap-extension-global-drag-handle": "^0.1.18",
|
||||
@@ -63,13 +63,13 @@
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/katex": "^0.16.7",
|
||||
"@types/node": "22.19.1",
|
||||
"@types/react": "^19.2.9",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.2",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"eslint": "^9.15.0",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.26",
|
||||
"eslint-plugin-react": "^7.37.2",
|
||||
"eslint-plugin-react-hooks": "^5.1.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.16",
|
||||
"globals": "^15.13.0",
|
||||
"optics-ts": "^2.4.1",
|
||||
"postcss": "^8.4.49",
|
||||
|
||||
@@ -164,7 +164,7 @@ const MentionList = forwardRef<any, MentionListProps>((props, ref) => {
|
||||
|
||||
const enterHandler = () => {
|
||||
if (!renderItems.length) return;
|
||||
if (renderItems[selectedIndex].entityType !== "header") {
|
||||
if (renderItems[selectedIndex]?.entityType !== "header") {
|
||||
selectItem(selectedIndex);
|
||||
}
|
||||
};
|
||||
@@ -204,7 +204,7 @@ const MentionList = forwardRef<any, MentionListProps>((props, ref) => {
|
||||
parentPageId: page.id || null,
|
||||
title: title
|
||||
};
|
||||
|
||||
|
||||
let createdPage: IPage;
|
||||
try {
|
||||
createdPage = await createPageMutation.mutateAsync(payload);
|
||||
|
||||
@@ -77,7 +77,7 @@ const mentionRenderItems = () => {
|
||||
{
|
||||
placement: "bottom-start",
|
||||
middleware: [offset(0), flip(), shift()],
|
||||
}
|
||||
},
|
||||
).then(({ x, y }) => {
|
||||
Object.assign(element.style, {
|
||||
left: `${x}px`,
|
||||
@@ -86,7 +86,7 @@ const mentionRenderItems = () => {
|
||||
zIndex: "9999",
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
onUpdate: (props: {
|
||||
@@ -115,23 +115,30 @@ const mentionRenderItems = () => {
|
||||
|
||||
// destroy component if space is greater 3 without a match
|
||||
if (
|
||||
whitespaceCount > 3 &&
|
||||
whitespaceCount > 4 &&
|
||||
//@ts-ignore
|
||||
props.editor.storage.mentionItems.length === 0
|
||||
props.editor.storage.mentionItems.length === 1
|
||||
) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
// fallback exit
|
||||
if (whitespaceCount > 7) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
},
|
||||
onKeyDown: (props: { event: KeyboardEvent }) => {
|
||||
if (props.event.key)
|
||||
if (
|
||||
props.event.key === "Escape" ||
|
||||
(props.event.key === "Enter" && !component)
|
||||
) {
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
if (props.event.key === "Escape") {
|
||||
destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (props.event.key === "Enter" && !component) {
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
return (component?.ref as any)?.onKeyDown(props);
|
||||
},
|
||||
onExit: () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { BubbleMenu as BaseBubbleMenu } from "@tiptap/react/menus";
|
||||
import { posToDOMRect, findParentNode } from "@tiptap/react";
|
||||
import { Node as PMNode } from "@tiptap/pm/model";
|
||||
import React, { JSX, useCallback } from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import { ActionIcon, Tooltip } from "@mantine/core";
|
||||
import { IconTrash } from "@tabler/icons-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { JSX, useCallback } from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import {
|
||||
EditorMenuProps,
|
||||
ShouldShowProps,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { posToDOMRect, findParentNode } from "@tiptap/react";
|
||||
import { Node as PMNode } from "@tiptap/pm/model";
|
||||
import React, { JSX, useCallback } from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import {
|
||||
EditorMenuProps,
|
||||
ShouldShowProps,
|
||||
|
||||
@@ -248,7 +248,7 @@ export const mainExtensions = [
|
||||
Escape: () => {
|
||||
const event = new CustomEvent("closeFindDialogFromEditor", {});
|
||||
document.dispatchEvent(event);
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import '@/features/editor/styles/index.css';
|
||||
import React, { useEffect } from 'react';
|
||||
import { EditorContent, useEditor } from '@tiptap/react';
|
||||
import { mainExtensions } from '@/features/editor/extensions/extensions';
|
||||
import { Title } from '@mantine/core';
|
||||
import "@/features/editor/styles/index.css";
|
||||
import React, { useEffect } from "react";
|
||||
import { EditorContent, useEditor } from "@tiptap/react";
|
||||
import { mainExtensions } from "@/features/editor/extensions/extensions";
|
||||
import { Title } from "@mantine/core";
|
||||
import classes from "./history.module.css";
|
||||
|
||||
export interface HistoryEditorProps {
|
||||
title: string;
|
||||
@@ -26,7 +27,9 @@ export function HistoryEditor({ title, content }: HistoryEditorProps) {
|
||||
<div>
|
||||
<Title order={1}>{title}</Title>
|
||||
|
||||
{editor && <EditorContent editor={editor} />}
|
||||
{editor && (
|
||||
<EditorContent editor={editor} className={classes.historyEditor} />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,37 +1,49 @@
|
||||
.history {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: var(--mantine-spacing-md);
|
||||
color: light-dark(var(--mantine-color-black), var(--mantine-color-dark-0));
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: var(--mantine-spacing-md);
|
||||
color: light-dark(var(--mantine-color-black), var(--mantine-color-dark-0));
|
||||
|
||||
@mixin hover {
|
||||
background-color: light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-8));
|
||||
}
|
||||
@mixin hover {
|
||||
background-color: light-dark(
|
||||
var(--mantine-color-gray-2),
|
||||
var(--mantine-color-dark-8)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.historyEditor {
|
||||
:global(.ProseMirror) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-8));
|
||||
background-color: light-dark(
|
||||
var(--mantine-color-gray-2),
|
||||
var(--mantine-color-dark-8)
|
||||
);
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
max-height: rem(700px);
|
||||
width: rem(250px);
|
||||
padding: var(--mantine-spacing-sm);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: rem(1px) solid
|
||||
max-height: rem(700px);
|
||||
width: rem(250px);
|
||||
padding: var(--mantine-spacing-sm);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: rem(1px) solid
|
||||
light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
|
||||
}
|
||||
|
||||
.sidebarFlex {
|
||||
display: flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sidebarMain {
|
||||
flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebarRightSection {
|
||||
flex: 1;
|
||||
padding: rem(16px) rem(40px);
|
||||
flex: 1;
|
||||
padding: rem(16px) rem(40px);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ export default function PageHeaderMenu({ readOnly }: PageHeaderMenuProps) {
|
||||
const event = new CustomEvent("closeFindDialogFromEditor", {});
|
||||
document.dispatchEvent(event);
|
||||
},
|
||||
{ preventDefault: false },
|
||||
],
|
||||
],
|
||||
[],
|
||||
@@ -280,7 +281,9 @@ function ConnectionWarning() {
|
||||
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const isDisconnected = ["disconnected", "connecting"].includes(yjsConnectionStatus);
|
||||
const isDisconnected = ["disconnected", "connecting"].includes(
|
||||
yjsConnectionStatus,
|
||||
);
|
||||
|
||||
if (isDisconnected) {
|
||||
if (!timeoutRef.current) {
|
||||
|
||||
@@ -94,9 +94,9 @@ export default function SpaceTree({ spaceId, readOnly }: SpaceTreeProps) {
|
||||
spaceId,
|
||||
});
|
||||
const [, setTreeApi] = useAtom<TreeApi<SpaceTreeNode>>(treeApiAtom);
|
||||
const treeApiRef = useRef<TreeApi<SpaceTreeNode>>(null);
|
||||
const treeApiRef = useRef<TreeApi<SpaceTreeNode>>();
|
||||
const [openTreeNodes, setOpenTreeNodes] = useAtom<OpenMap>(openTreeNodesAtom);
|
||||
const rootElement = useRef<HTMLDivElement>(null);
|
||||
const rootElement = useRef<HTMLDivElement>();
|
||||
const [isRootReady, setIsRootReady] = useState(false);
|
||||
const { ref: sizeRef, width, height } = useElementSize();
|
||||
const mergedRef = useMergedRef((element) => {
|
||||
|
||||
@@ -36,7 +36,7 @@ export default function SharedTree({ sharedPageTree }: SharedTree) {
|
||||
const [tree, setTree] = useState<
|
||||
TreeApi<SharedPageTreeNode> | null | undefined
|
||||
>(null);
|
||||
const rootElement = useRef<HTMLDivElement>(null);
|
||||
const rootElement = useRef<HTMLDivElement>();
|
||||
const { ref: sizeRef, width, height } = useElementSize();
|
||||
const mergedRef = useMergedRef(rootElement, sizeRef);
|
||||
const { pageSlug } = useParams();
|
||||
|
||||
@@ -181,7 +181,9 @@ export class AttachmentController {
|
||||
}
|
||||
|
||||
try {
|
||||
const fileStream = await this.storageService.read(attachment.filePath);
|
||||
const fileStream = await this.storageService.readStream(
|
||||
attachment.filePath,
|
||||
);
|
||||
res.headers({
|
||||
'Content-Type': attachment.mimeType,
|
||||
'Cache-Control': 'private, max-age=3600',
|
||||
@@ -241,7 +243,9 @@ export class AttachmentController {
|
||||
}
|
||||
|
||||
try {
|
||||
const fileStream = await this.storageService.read(attachment.filePath);
|
||||
const fileStream = await this.storageService.readStream(
|
||||
attachment.filePath,
|
||||
);
|
||||
res.headers({
|
||||
'Content-Type': attachment.mimeType,
|
||||
'Cache-Control': 'public, max-age=3600',
|
||||
@@ -367,14 +371,14 @@ export class AttachmentController {
|
||||
const filePath = `${getAttachmentFolderPath(attachmentType, workspace.id)}/${fileName}`;
|
||||
|
||||
try {
|
||||
const fileStream = await this.storageService.read(filePath);
|
||||
const fileStream = await this.storageService.readStream(filePath);
|
||||
res.headers({
|
||||
'Content-Type': getMimeType(filePath),
|
||||
'Cache-Control': 'private, max-age=86400',
|
||||
});
|
||||
return res.send(fileStream);
|
||||
} catch (err) {
|
||||
// this.logger.error(err);
|
||||
// this.logger.error(err);
|
||||
throw new NotFoundException('File not found');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export class ExportController {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
const zipFileBuffer = await this.exportService.exportPages(
|
||||
const zipFileStream = await this.exportService.exportPages(
|
||||
dto.pageId,
|
||||
dto.format,
|
||||
dto.includeAttachments,
|
||||
@@ -70,7 +70,7 @@ export class ExportController {
|
||||
'attachment; filename="' + encodeURIComponent(fileName) + '"',
|
||||
});
|
||||
|
||||
res.send(zipFileBuffer);
|
||||
res.send(zipFileStream);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@@ -100,6 +100,6 @@ export class ExportController {
|
||||
'"',
|
||||
});
|
||||
|
||||
res.send(exportFile.fileBuffer);
|
||||
res.send(exportFile.fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ export class ExportService {
|
||||
|
||||
const fileName = `${space.name}-space-export.zip`;
|
||||
return {
|
||||
fileBuffer: zipFile,
|
||||
fileStream: zipFile,
|
||||
fileName,
|
||||
};
|
||||
}
|
||||
|
||||
+27
-27
@@ -30,33 +30,33 @@
|
||||
"@joplin/turndown": "^4.0.74",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.56",
|
||||
"@sindresorhus/slugify": "1.1.0",
|
||||
"@tiptap/core": "3.17.0",
|
||||
"@tiptap/extension-code-block": "3.17.0",
|
||||
"@tiptap/extension-collaboration": "3.17.0",
|
||||
"@tiptap/extension-collaboration-caret": "3.17.0",
|
||||
"@tiptap/extension-color": "3.17.0",
|
||||
"@tiptap/extension-document": "3.17.0",
|
||||
"@tiptap/extension-heading": "3.17.0",
|
||||
"@tiptap/extension-highlight": "3.17.0",
|
||||
"@tiptap/extension-history": "3.17.0",
|
||||
"@tiptap/extension-image": "3.17.0",
|
||||
"@tiptap/extension-link": "3.17.0",
|
||||
"@tiptap/extension-list": "3.17.0",
|
||||
"@tiptap/extension-placeholder": "3.17.0",
|
||||
"@tiptap/extension-subscript": "3.17.0",
|
||||
"@tiptap/extension-superscript": "3.17.0",
|
||||
"@tiptap/extension-table": "3.17.0",
|
||||
"@tiptap/extension-text": "3.17.0",
|
||||
"@tiptap/extension-text-align": "3.17.0",
|
||||
"@tiptap/extension-text-style": "3.17.0",
|
||||
"@tiptap/extension-typography": "3.17.0",
|
||||
"@tiptap/extension-unique-id": "^3.17.0",
|
||||
"@tiptap/extension-youtube": "3.17.0",
|
||||
"@tiptap/html": "3.17.0",
|
||||
"@tiptap/pm": "3.17.0",
|
||||
"@tiptap/react": "3.17.0",
|
||||
"@tiptap/starter-kit": "3.17.0",
|
||||
"@tiptap/suggestion": "3.17.0",
|
||||
"@tiptap/core": "3.17.1",
|
||||
"@tiptap/extension-code-block": "3.17.1",
|
||||
"@tiptap/extension-collaboration": "3.17.1",
|
||||
"@tiptap/extension-collaboration-caret": "3.17.1",
|
||||
"@tiptap/extension-color": "3.17.1",
|
||||
"@tiptap/extension-document": "3.17.1",
|
||||
"@tiptap/extension-heading": "3.17.1",
|
||||
"@tiptap/extension-highlight": "3.17.1",
|
||||
"@tiptap/extension-history": "3.17.1",
|
||||
"@tiptap/extension-image": "3.17.1",
|
||||
"@tiptap/extension-link": "3.17.1",
|
||||
"@tiptap/extension-list": "3.17.1",
|
||||
"@tiptap/extension-placeholder": "3.17.1",
|
||||
"@tiptap/extension-subscript": "3.17.1",
|
||||
"@tiptap/extension-superscript": "3.17.1",
|
||||
"@tiptap/extension-table": "3.17.1",
|
||||
"@tiptap/extension-text": "3.17.1",
|
||||
"@tiptap/extension-text-align": "3.17.1",
|
||||
"@tiptap/extension-text-style": "3.17.1",
|
||||
"@tiptap/extension-typography": "3.17.1",
|
||||
"@tiptap/extension-unique-id": "^3.17.1",
|
||||
"@tiptap/extension-youtube": "3.17.1",
|
||||
"@tiptap/html": "3.17.1",
|
||||
"@tiptap/pm": "3.17.1",
|
||||
"@tiptap/react": "3.17.1",
|
||||
"@tiptap/starter-kit": "3.17.1",
|
||||
"@tiptap/suggestion": "3.17.1",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"bytes": "^3.1.2",
|
||||
"cross-env": "^7.0.3",
|
||||
|
||||
Generated
+915
-1485
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user