chore: peek overview authorization (#2632)
* chore: peek overview authorization * chore: comment access specifier validation
This commit is contained in:
parent
d48f13416f
commit
992cf79031
12 changed files with 270 additions and 195 deletions
|
|
@ -1,7 +1,37 @@
|
|||
import { BoldIcon, Heading1, CheckSquare, Heading2, Heading3, QuoteIcon, ImageIcon, TableIcon, ListIcon, ListOrderedIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon, CodeIcon } from "lucide-react";
|
||||
import {
|
||||
BoldIcon,
|
||||
Heading1,
|
||||
CheckSquare,
|
||||
Heading2,
|
||||
Heading3,
|
||||
QuoteIcon,
|
||||
ImageIcon,
|
||||
TableIcon,
|
||||
ListIcon,
|
||||
ListOrderedIcon,
|
||||
ItalicIcon,
|
||||
UnderlineIcon,
|
||||
StrikethroughIcon,
|
||||
CodeIcon,
|
||||
} from "lucide-react";
|
||||
import { Editor } from "@tiptap/react";
|
||||
import { UploadImage } from "../../../types/upload-image";
|
||||
import { insertImageCommand, insertTableCommand, toggleBlockquote, toggleBold, toggleBulletList, toggleCode, toggleHeadingOne, toggleHeadingThree, toggleHeadingTwo, toggleItalic, toggleOrderedList, toggleStrike, toggleTaskList, toggleUnderline, } from "../../../lib/editor-commands";
|
||||
import {
|
||||
insertImageCommand,
|
||||
insertTableCommand,
|
||||
toggleBlockquote,
|
||||
toggleBold,
|
||||
toggleBulletList,
|
||||
toggleCode,
|
||||
toggleHeadingOne,
|
||||
toggleHeadingThree,
|
||||
toggleHeadingTwo,
|
||||
toggleItalic,
|
||||
toggleOrderedList,
|
||||
toggleStrike,
|
||||
toggleTaskList,
|
||||
toggleUnderline,
|
||||
} from "../../../lib/editor-commands";
|
||||
|
||||
export interface EditorMenuItem {
|
||||
name: string;
|
||||
|
|
@ -15,95 +45,101 @@ export const HeadingOneItem = (editor: Editor): EditorMenuItem => ({
|
|||
isActive: () => editor.isActive("heading", { level: 1 }),
|
||||
command: () => toggleHeadingOne(editor),
|
||||
icon: Heading1,
|
||||
})
|
||||
});
|
||||
|
||||
export const HeadingTwoItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "H2",
|
||||
isActive: () => editor.isActive("heading", { level: 2 }),
|
||||
command: () => toggleHeadingTwo(editor),
|
||||
icon: Heading2,
|
||||
})
|
||||
});
|
||||
|
||||
export const HeadingThreeItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "H3",
|
||||
isActive: () => editor.isActive("heading", { level: 3 }),
|
||||
command: () => toggleHeadingThree(editor),
|
||||
icon: Heading3,
|
||||
})
|
||||
});
|
||||
|
||||
export const BoldItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "bold",
|
||||
isActive: () => editor?.isActive("bold"),
|
||||
command: () => toggleBold(editor),
|
||||
icon: BoldIcon,
|
||||
})
|
||||
});
|
||||
|
||||
export const ItalicItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "italic",
|
||||
isActive: () => editor?.isActive("italic"),
|
||||
command: () => toggleItalic(editor),
|
||||
icon: ItalicIcon,
|
||||
})
|
||||
});
|
||||
|
||||
export const UnderLineItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "underline",
|
||||
isActive: () => editor?.isActive("underline"),
|
||||
command: () => toggleUnderline(editor),
|
||||
icon: UnderlineIcon,
|
||||
})
|
||||
});
|
||||
|
||||
export const StrikeThroughItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "strike",
|
||||
isActive: () => editor?.isActive("strike"),
|
||||
command: () => toggleStrike(editor),
|
||||
icon: StrikethroughIcon,
|
||||
})
|
||||
});
|
||||
|
||||
export const CodeItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "code",
|
||||
isActive: () => editor?.isActive("code"),
|
||||
command: () => toggleCode(editor),
|
||||
icon: CodeIcon,
|
||||
})
|
||||
});
|
||||
|
||||
export const BulletListItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "bullet-list",
|
||||
isActive: () => editor?.isActive("bulletList"),
|
||||
command: () => toggleBulletList(editor),
|
||||
icon: ListIcon,
|
||||
})
|
||||
});
|
||||
|
||||
export const TodoListItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "To-do List",
|
||||
isActive: () => editor.isActive("taskItem"),
|
||||
command: () => toggleTaskList(editor),
|
||||
icon: CheckSquare,
|
||||
})
|
||||
});
|
||||
|
||||
export const NumberedListItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "ordered-list",
|
||||
isActive: () => editor?.isActive("orderedList"),
|
||||
command: () => toggleOrderedList(editor),
|
||||
icon: ListOrderedIcon
|
||||
})
|
||||
icon: ListOrderedIcon,
|
||||
});
|
||||
|
||||
export const QuoteItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "quote",
|
||||
isActive: () => editor?.isActive("quote"),
|
||||
command: () => toggleBlockquote(editor),
|
||||
icon: QuoteIcon
|
||||
})
|
||||
icon: QuoteIcon,
|
||||
});
|
||||
|
||||
export const TableItem = (editor: Editor): EditorMenuItem => ({
|
||||
name: "quote",
|
||||
name: "table",
|
||||
isActive: () => editor?.isActive("table"),
|
||||
command: () => insertTableCommand(editor),
|
||||
icon: TableIcon
|
||||
})
|
||||
icon: TableIcon,
|
||||
});
|
||||
|
||||
export const ImageItem = (editor: Editor, uploadFile: UploadImage, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void): EditorMenuItem => ({
|
||||
export const ImageItem = (
|
||||
editor: Editor,
|
||||
uploadFile: UploadImage,
|
||||
setIsSubmitting?: (
|
||||
isSubmitting: "submitting" | "submitted" | "saved",
|
||||
) => void,
|
||||
): EditorMenuItem => ({
|
||||
name: "image",
|
||||
isActive: () => editor?.isActive("image"),
|
||||
command: () => insertImageCommand(editor, uploadFile, setIsSubmitting),
|
||||
icon: ImageIcon,
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -72,12 +72,10 @@ export const FixedMenu = (props: EditorBubbleMenuProps) => {
|
|||
props.commentAccessSpecifier?.onAccessChange(accessKey);
|
||||
};
|
||||
|
||||
console.log(complexItems);
|
||||
|
||||
return (
|
||||
<div className="flex items-stretch gap-1.5 w-full h-9">
|
||||
<div className="flex items-stretch gap-1.5 w-full h-9 overflow-x-scroll">
|
||||
{props.commentAccessSpecifier && (
|
||||
<div className="flex-shrink-0 flex items-stretch gap-0.5 border border-custom-border-200 rounded p-1">
|
||||
<div className="flex-shrink-0 flex items-stretch gap-0.5 border-[0.5px] border-custom-border-200 rounded p-1">
|
||||
{props?.commentAccessSpecifier.commentAccess?.map((access) => (
|
||||
<Tooltip key={access.key} tooltipContent={access.label}>
|
||||
<button
|
||||
|
|
@ -102,102 +100,118 @@ export const FixedMenu = (props: EditorBubbleMenuProps) => {
|
|||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-stretch justify-between gap-2 w-full border border-custom-border-200 bg-custom-background-90 rounded p-1">
|
||||
<div className="flex items-stretch justify-between gap-2 w-full border-[0.5px] border-custom-border-200 bg-custom-background-90 rounded p-1">
|
||||
<div className="flex items-stretch">
|
||||
<div className="flex items-stretch gap-0.5 pr-2.5 border-r border-custom-border-200">
|
||||
{basicMarkItems.map((item, index) => (
|
||||
<button
|
||||
<Tooltip
|
||||
key={index}
|
||||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"p-1 aspect-square text-custom-text-400 hover:bg-custom-background-80 rounded-sm grid place-items-center",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80":
|
||||
item.isActive(),
|
||||
},
|
||||
)}
|
||||
tooltipContent={<span className="capitalize">{item.name}</span>}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-3.5 w-3.5", {
|
||||
"text-custom-text-100": item.isActive(),
|
||||
})}
|
||||
strokeWidth={2.5}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"p-1 aspect-square text-custom-text-400 hover:bg-custom-background-80 rounded-sm grid place-items-center",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80":
|
||||
item.isActive(),
|
||||
},
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-3.5 w-3.5", {
|
||||
"text-custom-text-100": item.isActive(),
|
||||
})}
|
||||
strokeWidth={2.5}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex items-stretch gap-0.5 px-2.5 border-r border-custom-border-200">
|
||||
{listItems.map((item, index) => (
|
||||
<button
|
||||
<Tooltip
|
||||
key={index}
|
||||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"p-1 aspect-square text-custom-text-400 hover:bg-custom-background-80 rounded-sm grid place-items-center",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80":
|
||||
item.isActive(),
|
||||
},
|
||||
)}
|
||||
tooltipContent={<span className="capitalize">{item.name}</span>}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-3.5 w-3.5", {
|
||||
"text-custom-text-100": item.isActive(),
|
||||
})}
|
||||
strokeWidth={2.5}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"p-1 aspect-square text-custom-text-400 hover:bg-custom-background-80 rounded-sm grid place-items-center",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80":
|
||||
item.isActive(),
|
||||
},
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-3.5 w-3.5", {
|
||||
"text-custom-text-100": item.isActive(),
|
||||
})}
|
||||
strokeWidth={2.5}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex items-stretch gap-0.5 px-2.5 border-r border-custom-border-200">
|
||||
{userActionItems.map((item, index) => (
|
||||
<button
|
||||
<Tooltip
|
||||
key={index}
|
||||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"p-1 aspect-square text-custom-text-400 hover:bg-custom-background-80 rounded-sm grid place-items-center",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80":
|
||||
item.isActive(),
|
||||
},
|
||||
)}
|
||||
tooltipContent={<span className="capitalize">{item.name}</span>}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-3.5 w-3.5", {
|
||||
"text-custom-text-100": item.isActive(),
|
||||
})}
|
||||
strokeWidth={2.5}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"p-1 aspect-square text-custom-text-400 hover:bg-custom-background-80 rounded-sm grid place-items-center",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80":
|
||||
item.isActive(),
|
||||
},
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-3.5 w-3.5", {
|
||||
"text-custom-text-100": item.isActive(),
|
||||
})}
|
||||
strokeWidth={2.5}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex items-stretch gap-0.5 pl-2.5">
|
||||
{complexItems.map((item, index) => (
|
||||
<button
|
||||
<Tooltip
|
||||
key={index}
|
||||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"p-1 aspect-square text-custom-text-400 hover:bg-custom-background-80 rounded-sm grid place-items-center",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80":
|
||||
item.isActive(),
|
||||
},
|
||||
)}
|
||||
tooltipContent={<span className="capitalize">{item.name}</span>}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-3.5 w-3.5", {
|
||||
"text-custom-text-100": item.isActive(),
|
||||
})}
|
||||
strokeWidth={2.5}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"p-1 aspect-square text-custom-text-400 hover:bg-custom-background-80 rounded-sm grid place-items-center",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80":
|
||||
item.isActive(),
|
||||
},
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
className={cn("h-3.5 w-3.5", {
|
||||
"text-custom-text-100": item.isActive(),
|
||||
})}
|
||||
strokeWidth={2.5}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{props.submitButton}
|
||||
<div className="sticky right-1">{props.submitButton}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue