mirror of
https://github.com/docmost/docmost.git
synced 2026-06-10 18:16:57 +08:00
Merge branch 'main' into tiptap3-migration
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
import { NodeViewProps, NodeViewWrapper } from "@tiptap/react";
|
||||
import { ActionIcon, Anchor, Text } from "@mantine/core";
|
||||
import { IconFileDescription } from "@tabler/icons-react";
|
||||
import { Link, useLocation, useParams } from "react-router-dom";
|
||||
import { Link, useLocation, useNavigate, useParams } from "react-router-dom";
|
||||
import { usePageQuery } from "@/features/page/queries/page-query.ts";
|
||||
import {
|
||||
buildPageUrl,
|
||||
buildSharedPageUrl,
|
||||
} from "@/features/page/page.utils.ts";
|
||||
import { extractPageSlugId } from "@/lib";
|
||||
import classes from "./mention.module.css";
|
||||
|
||||
export default function MentionView(props: NodeViewProps) {
|
||||
const { node } = props;
|
||||
const { label, entityType, entityId, slugId, anchorId } = node.attrs;
|
||||
const { spaceSlug } = useParams();
|
||||
const { spaceSlug, pageSlug } = useParams();
|
||||
const { shareId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
data: page,
|
||||
isLoading,
|
||||
@@ -23,6 +25,20 @@ export default function MentionView(props: NodeViewProps) {
|
||||
const location = useLocation();
|
||||
const isShareRoute = location.pathname.startsWith("/share");
|
||||
|
||||
const currentPageSlugId = extractPageSlugId(pageSlug);
|
||||
const isSamePage = currentPageSlugId === slugId;
|
||||
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
if (isSamePage && anchorId) {
|
||||
e.preventDefault();
|
||||
const element = document.querySelector(`[id="${anchorId}"]`);
|
||||
if (element) {
|
||||
element.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
navigate(`#${anchorId}`, { replace: true });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const shareSlugUrl = buildSharedPageUrl({
|
||||
shareId,
|
||||
pageSlugId: slugId,
|
||||
@@ -45,6 +61,7 @@ export default function MentionView(props: NodeViewProps) {
|
||||
to={
|
||||
isShareRoute ? shareSlugUrl : buildPageUrl(spaceSlug, slugId, label, anchorId)
|
||||
}
|
||||
onClick={handleClick}
|
||||
underline="never"
|
||||
className={classes.pageMentionLink}
|
||||
>
|
||||
|
||||
@@ -129,6 +129,7 @@ export const mainExtensions = [
|
||||
}),
|
||||
TextAlign.configure({ types: ["heading", "paragraph"] }),
|
||||
TaskList,
|
||||
ListKeymap,
|
||||
TaskItem.configure({
|
||||
nested: true,
|
||||
}),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import api from "@/lib/api-client";
|
||||
import { IFileTask } from "@/features/file-task/types/file-task.types.ts";
|
||||
import { IPagination, QueryParams } from "@/lib/types.ts";
|
||||
import { IApiKey } from "@/ee/api-key";
|
||||
|
||||
export async function getFileTaskById(fileTaskId: string): Promise<IFileTask> {
|
||||
const req = await api.post<IFileTask>("/file-tasks/info", {
|
||||
@@ -8,7 +10,10 @@ export async function getFileTaskById(fileTaskId: string): Promise<IFileTask> {
|
||||
return req.data;
|
||||
}
|
||||
|
||||
export async function getFileTasks(): Promise<IFileTask[]> {
|
||||
const req = await api.post<IFileTask[]>("/file-tasks");
|
||||
export async function getFileTasks(
|
||||
params?: QueryParams,
|
||||
): Promise<IPagination<IFileTask>> {
|
||||
const req = await api.post("/file-tasks", { ...params });
|
||||
return req.data;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { zodResolver } from 'mantine-form-zod-resolver';
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().trim().min(2).max(50),
|
||||
name: z.string().trim().min(2).max(100),
|
||||
description: z.string().max(500),
|
||||
});
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(2).max(50),
|
||||
name: z.string().min(2).max(100),
|
||||
description: z.string().max(500),
|
||||
});
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ export default function GroupList() {
|
||||
>
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
<IconGroupCircle />
|
||||
<div>
|
||||
<div style={{ minWidth: 0, overflow: "hidden" }}>
|
||||
<Text fz="sm" fw={500} lineClamp={1}>
|
||||
{group.name}
|
||||
</Text>
|
||||
|
||||
@@ -269,12 +269,15 @@ function Node({ node, style, dragHandle, tree }: NodeRendererProps<any>) {
|
||||
const toggleMobileSidebar = useToggleSidebar(mobileSidebarAtom);
|
||||
|
||||
const prefetchPage = () => {
|
||||
timerRef.current = setTimeout(() => {
|
||||
queryClient.prefetchQuery({
|
||||
queryKey: ["pages", node.data.slugId],
|
||||
queryFn: () => getPageById({ pageId: node.data.slugId }),
|
||||
timerRef.current = setTimeout(async () => {
|
||||
const page = await queryClient.fetchQuery({
|
||||
queryKey: ["pages", node.data.id],
|
||||
queryFn: () => getPageById({ pageId: node.data.id }),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
if (page?.slugId) {
|
||||
queryClient.setQueryData(["pages", page.slugId], page);
|
||||
}
|
||||
}, 150);
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
Switch,
|
||||
Text,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
} from "@mantine/core";
|
||||
import { IconExternalLink, IconWorld, IconLock } from "@tabler/icons-react";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
@@ -21,12 +20,12 @@ import {
|
||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||
import { extractPageSlugId, getPageIcon } from "@/lib";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { usePageQuery } from "@/features/page/queries/page-query.ts";
|
||||
import CopyTextButton from "@/components/common/copy.tsx";
|
||||
import { getAppUrl, isCloud } from "@/lib/config.ts";
|
||||
import { buildPageUrl } from "@/features/page/page.utils.ts";
|
||||
import classes from "@/features/share/components/share.module.css";
|
||||
import useTrial from "@/ee/hooks/use-trial.tsx";
|
||||
import { getCheckoutLink } from "@/ee/billing/services/billing-service.ts";
|
||||
|
||||
interface ShareModalProps {
|
||||
readOnly: boolean;
|
||||
@@ -35,7 +34,9 @@ export default function ShareModal({ readOnly }: ShareModalProps) {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { pageSlug } = useParams();
|
||||
const pageId = extractPageSlugId(pageSlug);
|
||||
const pageSlugId = extractPageSlugId(pageSlug);
|
||||
const { data: page } = usePageQuery({ pageId: pageSlugId });
|
||||
const pageId = page?.id;
|
||||
const { data: share } = useShareForPageQuery(pageId);
|
||||
const { spaceSlug } = useParams();
|
||||
const { isTrial } = useTrial();
|
||||
|
||||
@@ -27,9 +27,7 @@ import {
|
||||
getShares,
|
||||
updateShare,
|
||||
} from "@/features/share/services/share-service.ts";
|
||||
import { IPage } from "@/features/page/types/page.types.ts";
|
||||
import { IPagination, QueryParams } from "@/lib/types.ts";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export function useGetSharesQuery(
|
||||
params?: QueryParams,
|
||||
@@ -72,7 +70,7 @@ export function useShareForPageQuery(
|
||||
queryKey: ["share-for-page", pageId],
|
||||
queryFn: () => getShareForPage(pageId),
|
||||
enabled: !!pageId,
|
||||
staleTime: 0,
|
||||
staleTime: 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Group, Box, Button, TextInput, Stack, Textarea } from "@mantine/core";
|
||||
import React, { useEffect } from "react";
|
||||
import { useForm, zodResolver } from "@mantine/form";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { zodResolver } from "mantine-form-zod-resolver";
|
||||
import * as z from "zod";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useCreateSpaceMutation } from "@/features/space/queries/space-query.ts";
|
||||
@@ -9,12 +10,12 @@ import { getSpaceUrl } from "@/lib/config.ts";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().trim().min(2).max(50),
|
||||
name: z.string().trim().min(2).max(100),
|
||||
slug: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(2)
|
||||
.max(50)
|
||||
.max(100)
|
||||
.regex(
|
||||
/^[a-zA-Z0-9]+$/,
|
||||
"Space slug must be alphanumeric. No special characters",
|
||||
|
||||
@@ -7,12 +7,12 @@ import { ISpace } from "@/features/space/types/space.types.ts";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(2).max(50),
|
||||
description: z.string().max(250),
|
||||
name: z.string().min(2).max(100),
|
||||
description: z.string().max(500),
|
||||
slug: z
|
||||
.string()
|
||||
.min(2)
|
||||
.max(50)
|
||||
.max(100)
|
||||
.regex(
|
||||
/^[a-zA-Z0-9]+$/,
|
||||
"Space slug must be alphanumeric. No special characters",
|
||||
|
||||
@@ -48,7 +48,7 @@ export default function SpaceList() {
|
||||
variant="filled"
|
||||
name={space.name}
|
||||
/>
|
||||
<div>
|
||||
<div style={{ minWidth: 0, overflow: "hidden" }}>
|
||||
<Text fz="sm" fw={500} lineClamp={1}>
|
||||
{space.name}
|
||||
</Text>
|
||||
|
||||
Reference in New Issue
Block a user