mirror of
https://github.com/docmost/docmost.git
synced 2025-11-16 04:41:12 +10:00
implement new invitation system
* fix comments on the frontend * move jwt token service to its own module * other fixes and updates
This commit is contained in:
@ -1,25 +1,28 @@
|
||||
.bubbleMenu {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
border-radius: 2px;
|
||||
border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-gray-8));
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
border-radius: 2px;
|
||||
border: 1px solid
|
||||
light-dark(var(--mantine-color-gray-3), var(--mantine-color-gray-8));
|
||||
|
||||
.active {
|
||||
color: var(--mantine-color-blue-8);
|
||||
}
|
||||
.active {
|
||||
color: light-dark(var(--mantine-color-blue-8), var(--mantine-color-gray-5));
|
||||
}
|
||||
|
||||
.colorButton {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.colorButton::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 1px;
|
||||
background-color: light-dark(var(--mantine-color-gray-3), var(--mantine-color-gray-8));
|
||||
}
|
||||
.colorButton {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.colorButton::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 1px;
|
||||
background-color: light-dark(
|
||||
var(--mantine-color-gray-3),
|
||||
var(--mantine-color-gray-8)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import {
|
||||
isNodeSelection,
|
||||
useEditor,
|
||||
} from "@tiptap/react";
|
||||
import { FC, useState } from "react";
|
||||
import { FC, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
IconBold,
|
||||
IconCode,
|
||||
@ -37,8 +37,13 @@ type EditorBubbleMenuProps = Omit<BubbleMenuProps, "children" | "editor"> & {
|
||||
};
|
||||
|
||||
export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
||||
const [, setShowCommentPopup] = useAtom(showCommentPopupAtom);
|
||||
const [showCommentPopup, setShowCommentPopup] = useAtom(showCommentPopupAtom);
|
||||
const [, setDraftCommentId] = useAtom(draftCommentIdAtom);
|
||||
const showCommentPopupRef = useRef(showCommentPopup);
|
||||
|
||||
useEffect(() => {
|
||||
showCommentPopupRef.current = showCommentPopup;
|
||||
}, [showCommentPopup]);
|
||||
|
||||
const items: BubbleMenuItem[] = [
|
||||
{
|
||||
@ -94,9 +99,11 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
||||
const { empty } = selection;
|
||||
|
||||
if (
|
||||
props.editor.isActive("image") ||
|
||||
!editor.isEditable ||
|
||||
editor.isActive("image") ||
|
||||
empty ||
|
||||
isNodeSelection(selection)
|
||||
isNodeSelection(selection) ||
|
||||
showCommentPopupRef?.current
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@ -117,47 +124,43 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
||||
const [isLinkSelectorOpen, setIsLinkSelectorOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<BubbleMenu {...bubbleMenuProps} className={classes.bubbleMenu}>
|
||||
<NodeSelector
|
||||
editor={props.editor}
|
||||
isOpen={isNodeSelectorOpen}
|
||||
setIsOpen={() => {
|
||||
setIsNodeSelectorOpen(!isNodeSelectorOpen);
|
||||
setIsColorSelectorOpen(false);
|
||||
setIsLinkSelectorOpen(false);
|
||||
}}
|
||||
/>
|
||||
<BubbleMenu {...bubbleMenuProps}>
|
||||
<div className={classes.bubbleMenu}>
|
||||
<NodeSelector
|
||||
editor={props.editor}
|
||||
isOpen={isNodeSelectorOpen}
|
||||
setIsOpen={() => {
|
||||
setIsNodeSelectorOpen(!isNodeSelectorOpen);
|
||||
}}
|
||||
/>
|
||||
|
||||
<ActionIcon.Group>
|
||||
{items.map((item, index) => (
|
||||
<Tooltip key={index} label={item.name} withArrow>
|
||||
<ActionIcon
|
||||
key={index}
|
||||
variant="default"
|
||||
size="lg"
|
||||
radius="0"
|
||||
aria-label={item.name}
|
||||
className={clsx({ [classes.active]: item.isActive() })}
|
||||
style={{ border: "none" }}
|
||||
onClick={item.command}
|
||||
>
|
||||
<item.icon style={{ width: rem(16) }} stroke={2} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
))}
|
||||
</ActionIcon.Group>
|
||||
<ActionIcon.Group>
|
||||
{items.map((item, index) => (
|
||||
<Tooltip key={index} label={item.name} withArrow>
|
||||
<ActionIcon
|
||||
key={index}
|
||||
variant="default"
|
||||
size="lg"
|
||||
radius="0"
|
||||
aria-label={item.name}
|
||||
className={clsx({ [classes.active]: item.isActive() })}
|
||||
style={{ border: "none" }}
|
||||
onClick={item.command}
|
||||
>
|
||||
<item.icon style={{ width: rem(16) }} stroke={2} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
))}
|
||||
</ActionIcon.Group>
|
||||
|
||||
<ColorSelector
|
||||
editor={props.editor}
|
||||
isOpen={isColorSelectorOpen}
|
||||
setIsOpen={() => {
|
||||
setIsColorSelectorOpen(!isColorSelectorOpen);
|
||||
setIsNodeSelectorOpen(false);
|
||||
setIsLinkSelectorOpen(false);
|
||||
}}
|
||||
/>
|
||||
<ColorSelector
|
||||
editor={props.editor}
|
||||
isOpen={isColorSelectorOpen}
|
||||
setIsOpen={() => {
|
||||
setIsColorSelectorOpen(!isColorSelectorOpen);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Tooltip label={commentItem.name} withArrow>
|
||||
<ActionIcon
|
||||
variant="default"
|
||||
size="lg"
|
||||
@ -168,7 +171,7 @@ export const EditorBubbleMenu: FC<EditorBubbleMenuProps> = (props) => {
|
||||
>
|
||||
<IconMessage style={{ width: rem(16) }} stroke={2} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</BubbleMenu>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Dispatch, FC, SetStateAction } from "react";
|
||||
import { IconCheck, IconChevronDown } from "@tabler/icons-react";
|
||||
import { Button, Popover, rem, ScrollArea, Text } from "@mantine/core";
|
||||
import { Button, Popover, rem, ScrollArea, Text, Tooltip } from "@mantine/core";
|
||||
import classes from "./bubble-menu.module.css";
|
||||
import { useEditor } from "@tiptap/react";
|
||||
|
||||
@ -110,17 +110,22 @@ export const ColorSelector: FC<ColorSelectorProps> = ({
|
||||
return (
|
||||
<Popover width={200} opened={isOpen} withArrow>
|
||||
<Popover.Target>
|
||||
<Button
|
||||
variant="default"
|
||||
radius="0"
|
||||
leftSection="A"
|
||||
rightSection={<IconChevronDown size={16} />}
|
||||
className={classes.colorButton}
|
||||
style={{
|
||||
color: activeColorItem?.color,
|
||||
}}
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
/>
|
||||
<Tooltip label="text color" withArrow>
|
||||
<Button
|
||||
variant="default"
|
||||
radius="0"
|
||||
rightSection={<IconChevronDown size={16} />}
|
||||
className={classes.colorButton}
|
||||
style={{
|
||||
color: activeColorItem?.color,
|
||||
paddingLeft: "8px",
|
||||
paddingRight: "8px",
|
||||
}}
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
A
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Popover.Target>
|
||||
|
||||
<Popover.Dropdown>
|
||||
@ -159,37 +164,6 @@ export const ColorSelector: FC<ColorSelectorProps> = ({
|
||||
</Button>
|
||||
))}
|
||||
</Button.Group>
|
||||
|
||||
<Text span c="dimmed" inherit>
|
||||
BACKGROUND
|
||||
</Text>
|
||||
|
||||
<Button.Group orientation="vertical">
|
||||
{HIGHLIGHT_COLORS.map(({ name, color }, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
variant="default"
|
||||
leftSection={
|
||||
<span style={{ padding: "4px", background: color }}>A</span>
|
||||
}
|
||||
justify="left"
|
||||
fullWidth
|
||||
rightSection={
|
||||
editor.isActive("highlight", { color }) && (
|
||||
<IconCheck style={{ width: rem(16) }} />
|
||||
)
|
||||
}
|
||||
onClick={() => {
|
||||
editor.commands.unsetHighlight();
|
||||
name !== "Default" && editor.commands.setHighlight({ color });
|
||||
setIsOpen(false);
|
||||
}}
|
||||
style={{ border: "none" }}
|
||||
>
|
||||
{name}
|
||||
</Button>
|
||||
))}
|
||||
</Button.Group>
|
||||
</ScrollArea.Autosize>
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
|
||||
Reference in New Issue
Block a user