chore: format all files in monorepo (#3054)
* chore: format all files in the project * fix: removing @types/react from dependencies * fix: adding prettier and eslint config * chore: format files * fix: upgrading turbo version * chore: ignoring warnings and adding todos * fix: updated the type of bubble menu item in the document editor * chore: format files --------- Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>
This commit is contained in:
parent
5eba682128
commit
8d15b9e7de
721 changed files with 3739 additions and 4660 deletions
|
|
@ -1,6 +1,3 @@
|
|||
export { DocumentEditor, DocumentEditorWithRef } from "./ui";
|
||||
export {
|
||||
DocumentReadOnlyEditor,
|
||||
DocumentReadOnlyEditorWithRef,
|
||||
} from "./ui/readonly";
|
||||
export { DocumentReadOnlyEditor, DocumentReadOnlyEditorWithRef } from "./ui/readonly";
|
||||
export { FixedMenu } from "./ui/menu/fixed-menu";
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const AlertLabel = (props: IAlertLabelProps) => {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`h-7 flex items-center gap-2 font-medium py-0.5 px-3 rounded-full text-xs ${backgroundColor} ${textColor}`}
|
||||
className={`flex h-7 items-center gap-2 rounded-full px-3 py-0.5 text-xs font-medium ${backgroundColor} ${textColor}`}
|
||||
>
|
||||
{Icon && <Icon className="h-3 w-3" />}
|
||||
<span>{label}</span>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
import {
|
||||
HeadingComp,
|
||||
HeadingThreeComp,
|
||||
SubheadingComp,
|
||||
} from "./heading-component";
|
||||
import { HeadingComp, HeadingThreeComp, SubheadingComp } from "./heading-component";
|
||||
import { IMarking } from "..";
|
||||
import { Editor } from "@tiptap/react";
|
||||
import { scrollSummary } from "../utils/editor-summary-utils";
|
||||
|
|
@ -16,32 +12,21 @@ export const ContentBrowser = (props: ContentBrowserProps) => {
|
|||
const { editor, markings } = props;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full overflow-hidden">
|
||||
<div className="flex h-full flex-col overflow-hidden">
|
||||
<h2 className="font-medium">Table of Contents</h2>
|
||||
<div className="h-full overflow-y-auto">
|
||||
{markings.length !== 0 ? (
|
||||
markings.map((marking) =>
|
||||
marking.level === 1 ? (
|
||||
<HeadingComp
|
||||
onClick={() => scrollSummary(editor, marking)}
|
||||
heading={marking.text}
|
||||
/>
|
||||
<HeadingComp onClick={() => scrollSummary(editor, marking)} heading={marking.text} />
|
||||
) : marking.level === 2 ? (
|
||||
<SubheadingComp
|
||||
onClick={() => scrollSummary(editor, marking)}
|
||||
subHeading={marking.text}
|
||||
/>
|
||||
<SubheadingComp onClick={() => scrollSummary(editor, marking)} subHeading={marking.text} />
|
||||
) : (
|
||||
<HeadingThreeComp
|
||||
heading={marking.text}
|
||||
onClick={() => scrollSummary(editor, marking)}
|
||||
/>
|
||||
),
|
||||
<HeadingThreeComp heading={marking.text} onClick={() => scrollSummary(editor, marking)} />
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<p className="mt-3 text-xs text-custom-text-400">
|
||||
Headings will be displayed here for navigation
|
||||
</p>
|
||||
<p className="mt-3 text-xs text-custom-text-400">Headings will be displayed here for navigation</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ import { FixedMenu } from "../menu";
|
|||
import { UploadImage } from "@plane/editor-types";
|
||||
import { DocumentDetails } from "../types/editor-types";
|
||||
import { AlertLabel } from "./alert-label";
|
||||
import {
|
||||
IVerticalDropdownItemProps,
|
||||
VerticalDropdownMenu,
|
||||
} from "./vertical-dropdown-menu";
|
||||
import { IVerticalDropdownItemProps, VerticalDropdownMenu } from "./vertical-dropdown-menu";
|
||||
import { SummaryPopover } from "./summary-popover";
|
||||
import { InfoPopover } from "./info-popover";
|
||||
|
||||
|
|
@ -23,9 +20,7 @@ interface IEditorHeader {
|
|||
archivedAt?: Date;
|
||||
readonly: boolean;
|
||||
uploadFile?: UploadImage;
|
||||
setIsSubmitting?: (
|
||||
isSubmitting: "submitting" | "submitted" | "saved",
|
||||
) => void;
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void;
|
||||
documentDetails: DocumentDetails;
|
||||
isSubmitting?: "submitting" | "submitted" | "saved";
|
||||
}
|
||||
|
|
@ -48,8 +43,8 @@ export const EditorHeader = (props: IEditorHeader) => {
|
|||
} = props;
|
||||
|
||||
return (
|
||||
<div className="flex items-center border-b border-custom-border-200 py-2 px-5">
|
||||
<div className="flex-shrink-0 w-56 lg:w-72">
|
||||
<div className="flex items-center border-b border-custom-border-200 px-5 py-2">
|
||||
<div className="w-56 flex-shrink-0 lg:w-72">
|
||||
<SummaryPopover
|
||||
editor={editor}
|
||||
markings={markings}
|
||||
|
|
@ -60,15 +55,11 @@ export const EditorHeader = (props: IEditorHeader) => {
|
|||
|
||||
<div className="flex-shrink-0">
|
||||
{!readonly && uploadFile && (
|
||||
<FixedMenu
|
||||
editor={editor}
|
||||
uploadFile={uploadFile}
|
||||
setIsSubmitting={setIsSubmitting}
|
||||
/>
|
||||
<FixedMenu editor={editor} uploadFile={uploadFile} setIsSubmitting={setIsSubmitting} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex-grow flex items-center justify-end gap-3">
|
||||
<div className="flex flex-grow items-center justify-end gap-3">
|
||||
{isLocked && (
|
||||
<AlertLabel
|
||||
Icon={Lock}
|
||||
|
|
@ -88,7 +79,7 @@ export const EditorHeader = (props: IEditorHeader) => {
|
|||
|
||||
{!isLocked && !isArchived ? (
|
||||
<div
|
||||
className={`flex absolute right-[120px] transition-all duration-300 items-center gap-x-2 ${
|
||||
className={`absolute right-[120px] flex items-center gap-x-2 transition-all duration-300 ${
|
||||
isSubmitting === "saved" ? "fadeOut" : "fadeIn"
|
||||
}`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export const SubheadingComp = ({
|
|||
}) => (
|
||||
<p
|
||||
onClick={onClick}
|
||||
className="ml-6 mt-2 text-xs cursor-pointer font-medium tracking-tight text-gray-400 hover:text-custom-primary"
|
||||
className="ml-6 mt-2 cursor-pointer text-xs font-medium tracking-tight text-gray-400 hover:text-custom-primary"
|
||||
role="button"
|
||||
>
|
||||
{subHeading}
|
||||
|
|
@ -39,7 +39,7 @@ export const HeadingThreeComp = ({
|
|||
}) => (
|
||||
<p
|
||||
onClick={onClick}
|
||||
className="ml-8 mt-2 text-xs cursor-pointer font-medium tracking-tight text-gray-400 hover:text-custom-primary"
|
||||
className="ml-8 mt-2 cursor-pointer text-xs font-medium tracking-tight text-gray-400 hover:text-custom-primary"
|
||||
role="button"
|
||||
>
|
||||
{heading}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,7 @@ const renderDate = (date: Date): string => {
|
|||
hour12: true,
|
||||
};
|
||||
|
||||
const formattedDate: string = new Intl.DateTimeFormat(
|
||||
"en-US",
|
||||
options,
|
||||
).format(date);
|
||||
const formattedDate: string = new Intl.DateTimeFormat("en-US", options).format(date);
|
||||
|
||||
return formattedDate;
|
||||
};
|
||||
|
|
@ -32,42 +29,35 @@ export const InfoPopover: React.FC<Props> = (props) => {
|
|||
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
|
||||
|
||||
const [referenceElement, setReferenceElement] =
|
||||
useState<HTMLButtonElement | null>(null);
|
||||
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(
|
||||
null,
|
||||
);
|
||||
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
|
||||
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
||||
|
||||
const { styles: infoPopoverStyles, attributes: infoPopoverAttributes } =
|
||||
usePopper(referenceElement, popperElement, {
|
||||
placement: "bottom-start",
|
||||
});
|
||||
const { styles: infoPopoverStyles, attributes: infoPopoverAttributes } = usePopper(referenceElement, popperElement, {
|
||||
placement: "bottom-start",
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
onMouseEnter={() => setIsPopoverOpen(true)}
|
||||
onMouseLeave={() => setIsPopoverOpen(false)}
|
||||
>
|
||||
<div onMouseEnter={() => setIsPopoverOpen(true)} onMouseLeave={() => setIsPopoverOpen(false)}>
|
||||
<button type="button" ref={setReferenceElement} className="block">
|
||||
<Info className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
{isPopoverOpen && (
|
||||
<div
|
||||
className="z-10 w-64 shadow-custom-shadow-rg rounded border-[0.5px] border-custom-border-200 bg-custom-background-100 p-3 space-y-2.5"
|
||||
className="z-10 w-64 space-y-2.5 rounded border-[0.5px] border-custom-border-200 bg-custom-background-100 p-3 shadow-custom-shadow-rg"
|
||||
ref={setPopperElement}
|
||||
style={infoPopoverStyles.popper}
|
||||
{...infoPopoverAttributes.popper}
|
||||
>
|
||||
<div className="space-y-1.5">
|
||||
<h6 className="text-custom-text-400 text-xs">Last updated on</h6>
|
||||
<h5 className="text-sm flex items-center gap-1">
|
||||
<h6 className="text-xs text-custom-text-400">Last updated on</h6>
|
||||
<h5 className="flex items-center gap-1 text-sm">
|
||||
<History className="h-3 w-3" />
|
||||
{renderDate(new Date(documentDetails.last_updated_at))}
|
||||
</h5>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<h6 className="text-custom-text-400 text-xs">Created on</h6>
|
||||
<h5 className="text-sm flex items-center gap-1">
|
||||
<h6 className="text-xs text-custom-text-400">Created on</h6>
|
||||
<h5 className="flex items-center gap-1 text-sm">
|
||||
<Calendar className="h-3 w-3" />
|
||||
{renderDate(new Date(documentDetails.created_on))}
|
||||
</h5>
|
||||
|
|
|
|||
|
|
@ -25,14 +25,7 @@ const debounce = (func: (...args: any[]) => void, wait: number) => {
|
|||
};
|
||||
|
||||
export const PageRenderer = (props: IPageRenderer) => {
|
||||
const {
|
||||
documentDetails,
|
||||
editor,
|
||||
editorClassNames,
|
||||
editorContentCustomClassNames,
|
||||
updatePageTitle,
|
||||
readonly,
|
||||
} = props;
|
||||
const { documentDetails, editor, editorClassNames, editorContentCustomClassNames, updatePageTitle, readonly } = props;
|
||||
|
||||
const [pageTitle, setPagetitle] = useState(documentDetails.title);
|
||||
|
||||
|
|
@ -44,27 +37,24 @@ export const PageRenderer = (props: IPageRenderer) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="w-full pl-7 pt-5 pb-64">
|
||||
<div className="w-full pb-64 pl-7 pt-5">
|
||||
{!readonly ? (
|
||||
<input
|
||||
onChange={(e) => handlePageTitleChange(e.target.value)}
|
||||
className="text-4xl bg-custom-background font-bold break-words pr-5 -mt-2 w-full border-none outline-none"
|
||||
className="-mt-2 w-full break-words border-none bg-custom-background pr-5 text-4xl font-bold outline-none"
|
||||
value={pageTitle}
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
onChange={(e) => handlePageTitleChange(e.target.value)}
|
||||
className="text-4xl bg-custom-background font-bold break-words pr-5 -mt-2 w-full border-none outline-none overflow-x-clip"
|
||||
className="-mt-2 w-full overflow-x-clip break-words border-none bg-custom-background pr-5 text-4xl font-bold outline-none"
|
||||
value={pageTitle}
|
||||
disabled
|
||||
/>
|
||||
)}
|
||||
<div className="flex flex-col h-full w-full pr-5">
|
||||
<div className="flex h-full w-full flex-col pr-5">
|
||||
<EditorContainer editor={editor} editorClassNames={editorClassNames}>
|
||||
<EditorContentWrapper
|
||||
editor={editor}
|
||||
editorContentCustomClassNames={editorContentCustomClassNames}
|
||||
/>
|
||||
<EditorContentWrapper editor={editor} editorContentCustomClassNames={editorContentCustomClassNames} />
|
||||
</EditorContainer>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -17,26 +17,24 @@ type Props = {
|
|||
export const SummaryPopover: React.FC<Props> = (props) => {
|
||||
const { editor, markings, sidePeekVisible, setSidePeekVisible } = props;
|
||||
|
||||
const [referenceElement, setReferenceElement] =
|
||||
useState<HTMLButtonElement | null>(null);
|
||||
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(
|
||||
null,
|
||||
);
|
||||
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
|
||||
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
||||
|
||||
const { styles: summaryPopoverStyles, attributes: summaryPopoverAttributes } =
|
||||
usePopper(referenceElement, popperElement, {
|
||||
const { styles: summaryPopoverStyles, attributes: summaryPopoverAttributes } = usePopper(
|
||||
referenceElement,
|
||||
popperElement,
|
||||
{
|
||||
placement: "bottom-start",
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="group/summary-popover w-min whitespace-nowrap">
|
||||
<button
|
||||
type="button"
|
||||
ref={setReferenceElement}
|
||||
className={`h-7 w-7 grid place-items-center rounded ${
|
||||
sidePeekVisible
|
||||
? "bg-custom-primary-100/20 text-custom-primary-100"
|
||||
: "text-custom-text-300"
|
||||
className={`grid h-7 w-7 place-items-center rounded ${
|
||||
sidePeekVisible ? "bg-custom-primary-100/20 text-custom-primary-100" : "text-custom-text-300"
|
||||
}`}
|
||||
onClick={() => setSidePeekVisible(!sidePeekVisible)}
|
||||
>
|
||||
|
|
@ -44,7 +42,7 @@ export const SummaryPopover: React.FC<Props> = (props) => {
|
|||
</button>
|
||||
{!sidePeekVisible && (
|
||||
<div
|
||||
className="hidden group-hover/summary-popover:block z-10 max-h-80 w-64 shadow-custom-shadow-rg rounded border-[0.5px] border-custom-border-200 bg-custom-background-100 p-3 overflow-y-auto"
|
||||
className="z-10 hidden max-h-80 w-64 overflow-y-auto rounded border-[0.5px] border-custom-border-200 bg-custom-background-100 p-3 shadow-custom-shadow-rg group-hover/summary-popover:block"
|
||||
ref={setPopperElement}
|
||||
style={summaryPopoverStyles.popper}
|
||||
{...summaryPopoverAttributes.popper}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,10 @@ interface ISummarySideBarProps {
|
|||
sidePeekVisible: boolean;
|
||||
}
|
||||
|
||||
export const SummarySideBar = ({
|
||||
editor,
|
||||
markings,
|
||||
sidePeekVisible,
|
||||
}: ISummarySideBarProps) => {
|
||||
export const SummarySideBar = ({ editor, markings, sidePeekVisible }: ISummarySideBarProps) => {
|
||||
return (
|
||||
<div
|
||||
className={`h-full p-5 transition-all duration-200 transform overflow-hidden ${
|
||||
className={`h-full transform overflow-hidden p-5 transition-all duration-200 ${
|
||||
sidePeekVisible ? "translate-x-0" : "-translate-x-full"
|
||||
}`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -23,11 +23,7 @@ export interface IVerticalDropdownMenuProps {
|
|||
items: IVerticalDropdownItemProps[];
|
||||
}
|
||||
|
||||
const VerticalDropdownItem = ({
|
||||
Icon,
|
||||
label,
|
||||
action,
|
||||
}: IVerticalDropdownItemProps) => {
|
||||
const VerticalDropdownItem = ({ Icon, label, action }: IVerticalDropdownItemProps) => {
|
||||
return (
|
||||
<CustomMenu.MenuItem onClick={action} className="flex items-center gap-2">
|
||||
<Icon className="h-3 w-3" />
|
||||
|
|
@ -42,19 +38,11 @@ export const VerticalDropdownMenu = ({ items }: IVerticalDropdownMenuProps) => {
|
|||
maxHeight={"md"}
|
||||
className={"h-4.5 mt-1"}
|
||||
placement={"bottom-start"}
|
||||
optionsClassName={
|
||||
"border-custom-border border-r border-solid transition-all duration-200 ease-in-out "
|
||||
}
|
||||
optionsClassName={"border-custom-border border-r border-solid transition-all duration-200 ease-in-out "}
|
||||
customButton={<MoreVertical size={14} />}
|
||||
>
|
||||
{items.map((item, index) => (
|
||||
<VerticalDropdownItem
|
||||
key={index}
|
||||
type={item.type}
|
||||
Icon={item.Icon}
|
||||
label={item.label}
|
||||
action={item.action}
|
||||
/>
|
||||
<VerticalDropdownItem key={index} type={item.type} Icon={item.Icon} label={item.label} action={item.action} />
|
||||
))}
|
||||
</CustomMenu>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -11,9 +11,7 @@ import { LayersIcon } from "@plane/ui";
|
|||
export const DocumentEditorExtensions = (
|
||||
uploadFile: UploadImage,
|
||||
issueEmbedConfig?: IIssueEmbedConfig,
|
||||
setIsSubmitting?: (
|
||||
isSubmitting: "submitting" | "submitted" | "saved",
|
||||
) => void,
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void
|
||||
) => {
|
||||
const additionalOptions: ISlashCommandItem[] = [
|
||||
{
|
||||
|
|
@ -28,7 +26,7 @@ export const DocumentEditorExtensions = (
|
|||
.focus()
|
||||
.insertContentAt(
|
||||
range,
|
||||
"<p class='text-sm bg-gray-300 w-fit pl-3 pr-3 pt-1 pb-1 rounded shadow-sm'>#issue_</p>",
|
||||
"<p class='text-sm bg-gray-300 w-fit pl-3 pr-3 pt-1 pb-1 rounded shadow-sm'>#issue_</p>"
|
||||
)
|
||||
.run();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,34 +18,32 @@ export interface IIssueListSuggestion {
|
|||
}
|
||||
|
||||
export const IssueSuggestions = (suggestions: any[]) => {
|
||||
const mappedSuggestions: IIssueListSuggestion[] = suggestions.map(
|
||||
(suggestion): IIssueListSuggestion => {
|
||||
let transactionId = uuidv4();
|
||||
return {
|
||||
title: suggestion.name,
|
||||
priority: suggestion.priority.toString(),
|
||||
identifier: `${suggestion.project_detail.identifier}-${suggestion.sequence_id}`,
|
||||
state: suggestion.state_detail.name,
|
||||
command: ({ editor, range }) => {
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
.insertContentAt(range, {
|
||||
type: "issue-embed-component",
|
||||
attrs: {
|
||||
entity_identifier: suggestion.id,
|
||||
id: transactionId,
|
||||
title: suggestion.name,
|
||||
project_identifier: suggestion.project_detail.identifier,
|
||||
sequence_id: suggestion.sequence_id,
|
||||
entity_name: "issue",
|
||||
},
|
||||
})
|
||||
.run();
|
||||
},
|
||||
};
|
||||
},
|
||||
);
|
||||
const mappedSuggestions: IIssueListSuggestion[] = suggestions.map((suggestion): IIssueListSuggestion => {
|
||||
let transactionId = uuidv4();
|
||||
return {
|
||||
title: suggestion.name,
|
||||
priority: suggestion.priority.toString(),
|
||||
identifier: `${suggestion.project_detail.identifier}-${suggestion.sequence_id}`,
|
||||
state: suggestion.state_detail.name,
|
||||
command: ({ editor, range }) => {
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
.insertContentAt(range, {
|
||||
type: "issue-embed-component",
|
||||
attrs: {
|
||||
entity_identifier: suggestion.id,
|
||||
id: transactionId,
|
||||
title: suggestion.name,
|
||||
project_identifier: suggestion.project_detail.identifier,
|
||||
sequence_id: suggestion.sequence_id,
|
||||
entity_name: "issue",
|
||||
},
|
||||
})
|
||||
.run();
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return IssueEmbedSuggestions.configure({
|
||||
suggestion: {
|
||||
|
|
|
|||
|
|
@ -9,15 +9,7 @@ export const IssueEmbedSuggestions = Extension.create({
|
|||
addOptions() {
|
||||
return {
|
||||
suggestion: {
|
||||
command: ({
|
||||
editor,
|
||||
range,
|
||||
props,
|
||||
}: {
|
||||
editor: Editor;
|
||||
range: Range;
|
||||
props: any;
|
||||
}) => {
|
||||
command: ({ editor, range, props }: { editor: Editor; range: Range; props: any }) => {
|
||||
props.command({ editor, range });
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { IIssueListSuggestion } from ".";
|
||||
|
||||
export const getIssueSuggestionItems = (
|
||||
issueSuggestions: Array<IIssueListSuggestion>,
|
||||
) => {
|
||||
export const getIssueSuggestionItems = (issueSuggestions: Array<IIssueListSuggestion>) => {
|
||||
return ({ query }: { query: string }) => {
|
||||
const search = query.toLowerCase();
|
||||
const filteredSuggestions = issueSuggestions.filter((item) => {
|
||||
|
|
|
|||
|
|
@ -2,13 +2,7 @@ import { cn } from "@plane/editor-core";
|
|||
import { Editor } from "@tiptap/core";
|
||||
import tippy from "tippy.js";
|
||||
import { ReactRenderer } from "@tiptap/react";
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||
import { PriorityIcon } from "@plane/ui";
|
||||
|
||||
const updateScrollView = (container: HTMLElement, item: HTMLElement) => {
|
||||
|
|
@ -62,9 +56,7 @@ const IssueSuggestionList = ({
|
|||
let newDisplayedItems: { [key: string]: IssueSuggestionProps[] } = {};
|
||||
let totalLength = 0;
|
||||
sections.forEach((section) => {
|
||||
newDisplayedItems[section] = items
|
||||
.filter((item) => item.state === section)
|
||||
.slice(0, 5);
|
||||
newDisplayedItems[section] = items.filter((item) => item.state === section).slice(0, 5);
|
||||
|
||||
totalLength += newDisplayedItems[section].length;
|
||||
});
|
||||
|
|
@ -79,7 +71,7 @@ const IssueSuggestionList = ({
|
|||
command(item);
|
||||
}
|
||||
},
|
||||
[command, displayedItems, currentSection],
|
||||
[command, displayedItems, currentSection]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -93,22 +85,17 @@ const IssueSuggestionList = ({
|
|||
// }
|
||||
if (e.key === "ArrowUp") {
|
||||
setSelectedIndex(
|
||||
(selectedIndex + displayedItems[currentSection].length - 1) %
|
||||
displayedItems[currentSection].length,
|
||||
(selectedIndex + displayedItems[currentSection].length - 1) % displayedItems[currentSection].length
|
||||
);
|
||||
return true;
|
||||
}
|
||||
if (e.key === "ArrowDown") {
|
||||
const nextIndex =
|
||||
(selectedIndex + 1) % displayedItems[currentSection].length;
|
||||
const nextIndex = (selectedIndex + 1) % displayedItems[currentSection].length;
|
||||
setSelectedIndex(nextIndex);
|
||||
if (nextIndex === 4) {
|
||||
const nextItems = items
|
||||
.filter((item) => item.state === currentSection)
|
||||
.slice(
|
||||
displayedItems[currentSection].length,
|
||||
displayedItems[currentSection].length + 5,
|
||||
);
|
||||
.slice(displayedItems[currentSection].length, displayedItems[currentSection].length + 5);
|
||||
setDisplayedItems((prevItems) => ({
|
||||
...prevItems,
|
||||
[currentSection]: [...prevItems[currentSection], ...nextItems],
|
||||
|
|
@ -138,29 +125,17 @@ const IssueSuggestionList = ({
|
|||
return () => {
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
};
|
||||
}, [
|
||||
displayedItems,
|
||||
selectedIndex,
|
||||
setSelectedIndex,
|
||||
selectItem,
|
||||
currentSection,
|
||||
]);
|
||||
}, [displayedItems, selectedIndex, setSelectedIndex, selectItem, currentSection]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const container = commandListContainer?.current;
|
||||
if (container) {
|
||||
const sectionContainer = container?.querySelector(
|
||||
`#${currentSection}-container`,
|
||||
) as HTMLDivElement;
|
||||
const sectionContainer = container?.querySelector(`#${currentSection}-container`) as HTMLDivElement;
|
||||
if (sectionContainer) {
|
||||
updateScrollView(container, sectionContainer);
|
||||
}
|
||||
const sectionScrollContainer = container?.querySelector(
|
||||
`#${currentSection}`,
|
||||
) as HTMLElement;
|
||||
const item = sectionScrollContainer?.children[
|
||||
selectedIndex
|
||||
] as HTMLElement;
|
||||
const sectionScrollContainer = container?.querySelector(`#${currentSection}`) as HTMLElement;
|
||||
const item = sectionScrollContainer?.children[selectedIndex] as HTMLElement;
|
||||
if (item && sectionScrollContainer) {
|
||||
updateScrollView(sectionScrollContainer, item);
|
||||
}
|
||||
|
|
@ -171,56 +146,41 @@ const IssueSuggestionList = ({
|
|||
<div
|
||||
id="issue-list-container"
|
||||
ref={commandListContainer}
|
||||
className="z-[10] fixed max-h-80 w-60 overflow-y-auto overflow-x-hidden rounded-md border border-custom-border-100 bg-custom-background-100 px-1 shadow-custom-shadow-xs transition-all"
|
||||
className="fixed z-[10] max-h-80 w-60 overflow-y-auto overflow-x-hidden rounded-md border border-custom-border-100 bg-custom-background-100 px-1 shadow-custom-shadow-xs transition-all"
|
||||
>
|
||||
{sections.map((section) => {
|
||||
const sectionItems = displayedItems[section];
|
||||
return (
|
||||
sectionItems &&
|
||||
sectionItems.length > 0 && (
|
||||
<div
|
||||
className={"h-full w-full flex flex-col"}
|
||||
key={`${section}-container`}
|
||||
id={`${section}-container`}
|
||||
>
|
||||
<div className={"flex h-full w-full flex-col"} key={`${section}-container`} id={`${section}-container`}>
|
||||
<h6
|
||||
className={
|
||||
"sticky top-0 z-[10] bg-custom-background-100 text-xs text-custom-text-400 font-medium px-2 py-1"
|
||||
"sticky top-0 z-[10] bg-custom-background-100 px-2 py-1 text-xs font-medium text-custom-text-400"
|
||||
}
|
||||
>
|
||||
{section}
|
||||
</h6>
|
||||
<div
|
||||
key={section}
|
||||
id={section}
|
||||
className={"max-h-[140px] overflow-y-scroll overflow-x-hidden"}
|
||||
>
|
||||
{sectionItems.map(
|
||||
(item: IssueSuggestionProps, index: number) => (
|
||||
<button
|
||||
className={cn(
|
||||
`flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm text-custom-text-200 hover:bg-custom-primary-100/5 hover:text-custom-text-100`,
|
||||
{
|
||||
"bg-custom-primary-100/5 text-custom-text-100":
|
||||
section === currentSection &&
|
||||
index === selectedIndex,
|
||||
},
|
||||
)}
|
||||
key={index}
|
||||
onClick={() => selectItem(index)}
|
||||
>
|
||||
<h5 className="text-xs text-custom-text-300 whitespace-nowrap">
|
||||
{item.identifier}
|
||||
</h5>
|
||||
<PriorityIcon priority={item.priority} />
|
||||
<div>
|
||||
<p className="flex-grow text-xs truncate">
|
||||
{item.title}
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
),
|
||||
)}
|
||||
<div key={section} id={section} className={"max-h-[140px] overflow-x-hidden overflow-y-scroll"}>
|
||||
{sectionItems.map((item: IssueSuggestionProps, index: number) => (
|
||||
<button
|
||||
className={cn(
|
||||
`flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm text-custom-text-200 hover:bg-custom-primary-100/5 hover:text-custom-text-100`,
|
||||
{
|
||||
"bg-custom-primary-100/5 text-custom-text-100":
|
||||
section === currentSection && index === selectedIndex,
|
||||
}
|
||||
)}
|
||||
key={index}
|
||||
onClick={() => selectItem(index)}
|
||||
>
|
||||
<h5 className="whitespace-nowrap text-xs text-custom-text-300">{item.identifier}</h5>
|
||||
<PriorityIcon priority={item.priority} />
|
||||
<div>
|
||||
<p className="flex-grow truncate text-xs">{item.title}</p>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ interface IssueWidgetExtensionProps {
|
|||
issueEmbedConfig?: IIssueEmbedConfig;
|
||||
}
|
||||
|
||||
export const IssueWidgetExtension = ({
|
||||
issueEmbedConfig,
|
||||
}: IssueWidgetExtensionProps) => IssueWidget.configure({
|
||||
issueEmbedConfig,
|
||||
});
|
||||
export const IssueWidgetExtension = ({ issueEmbedConfig }: IssueWidgetExtensionProps) =>
|
||||
IssueWidget.configure({
|
||||
issueEmbedConfig,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,15 +30,13 @@ const IssueWidgetCard = (props) => {
|
|||
{loading == 0 ? (
|
||||
<div
|
||||
onClick={completeIssueEmbedAction}
|
||||
className="cursor-pointer w-full space-y-2 border-[0.5px] border-custom-border-200 rounded-md p-3 shadow-custom-shadow-2xs"
|
||||
className="w-full cursor-pointer space-y-2 rounded-md border-[0.5px] border-custom-border-200 p-3 shadow-custom-shadow-2xs"
|
||||
>
|
||||
<h5 className="text-xs text-custom-text-300">
|
||||
{issueDetails.project_detail.identifier}-{issueDetails.sequence_id}
|
||||
</h5>
|
||||
<h4 className="break-words text-sm font-medium">
|
||||
{issueDetails.name}
|
||||
</h4>
|
||||
<div className="flex items-center flex-wrap gap-x-3 gap-y-2">
|
||||
<h4 className="break-words text-sm font-medium">{issueDetails.name}</h4>
|
||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-2">
|
||||
<div>
|
||||
<PriorityIcon priority={issueDetails.priority} />
|
||||
</div>
|
||||
|
|
@ -46,18 +44,13 @@ const IssueWidgetCard = (props) => {
|
|||
<AvatarGroup size="sm">
|
||||
{issueDetails.assignee_details.map((assignee) => {
|
||||
return (
|
||||
<Avatar
|
||||
key={assignee.id}
|
||||
name={assignee.display_name}
|
||||
src={assignee.avatar}
|
||||
className={"m-0"}
|
||||
/>
|
||||
<Avatar key={assignee.id} name={assignee.display_name} src={assignee.avatar} className={"m-0"} />
|
||||
);
|
||||
})}
|
||||
</AvatarGroup>
|
||||
</div>
|
||||
{issueDetails.target_date && (
|
||||
<div className="rounded flex px-2.5 py-1 items-center border-[0.5px] border-custom-border-300 gap-1 text-custom-text-100 text-xs h-5">
|
||||
<div className="flex h-5 items-center gap-1 rounded border-[0.5px] border-custom-border-300 px-2.5 py-1 text-xs text-custom-text-100">
|
||||
<Calendar className="h-3 w-3" strokeWidth={1.5} />
|
||||
{new Date(issueDetails.target_date).toLocaleDateString()}
|
||||
</div>
|
||||
|
|
@ -65,17 +58,15 @@ const IssueWidgetCard = (props) => {
|
|||
</div>
|
||||
</div>
|
||||
) : loading == -1 ? (
|
||||
<div className="flex gap-[8px] items-center pb-[10px] pt-[10px] pl-[13px] rounded border-[#D97706] border-2 bg-[#FFFBEB] text-[#D97706]">
|
||||
<div className="flex items-center gap-[8px] rounded border-2 border-[#D97706] bg-[#FFFBEB] pb-[10px] pl-[13px] pt-[10px] text-[#D97706]">
|
||||
<AlertTriangle color={"#D97706"} />
|
||||
{
|
||||
"This Issue embed is not found in any project. It can no longer be updated or accessed from here."
|
||||
}
|
||||
{"This Issue embed is not found in any project. It can no longer be updated or accessed from here."}
|
||||
</div>
|
||||
) : (
|
||||
<div className="w-full space-y-2 border-[0.5px] border-custom-border-200 rounded-md p-3 shadow-custom-shadow-2xs">
|
||||
<div className="w-full space-y-2 rounded-md border-[0.5px] border-custom-border-200 p-3 shadow-custom-shadow-2xs">
|
||||
<Loader className={"px-6"}>
|
||||
<Loader.Item height={"30px"} />
|
||||
<div className={"space-y-2 mt-3"}>
|
||||
<div className={"mt-3 space-y-2"}>
|
||||
<Loader.Item height={"20px"} width={"70%"} />
|
||||
<Loader.Item height={"20px"} width={"60%"} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -35,10 +35,7 @@ export const IssueWidget = Node.create({
|
|||
|
||||
addNodeView() {
|
||||
return ReactNodeViewRenderer((props: Object) => (
|
||||
<IssueWidgetCard
|
||||
{...props}
|
||||
issueEmbedConfig={this.options.issueEmbedConfig}
|
||||
/>
|
||||
<IssueWidgetCard {...props} issueEmbedConfig={this.options.issueEmbedConfig} />
|
||||
));
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ export interface IEmbedConfig {
|
|||
export interface IIssueEmbedConfig {
|
||||
fetchIssue: (issueId: string) => Promise<any>;
|
||||
clickAction: (issueId: string, issueTitle: string) => void;
|
||||
issues: Array<any>;
|
||||
issues: Array<any>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,21 +15,14 @@ export const useEditorMarkings = () => {
|
|||
nodes.forEach((node) => {
|
||||
if (
|
||||
node.type === "heading" &&
|
||||
(node.attrs.level === 1 ||
|
||||
node.attrs.level === 2 ||
|
||||
node.attrs.level === 3) &&
|
||||
(node.attrs.level === 1 || node.attrs.level === 2 || node.attrs.level === 3) &&
|
||||
node.content
|
||||
) {
|
||||
tempMarkings.push({
|
||||
type: "heading",
|
||||
level: node.attrs.level,
|
||||
text: node.content[0].text,
|
||||
sequence:
|
||||
node.attrs.level === 1
|
||||
? ++h1Sequence
|
||||
: node.attrs.level === 2
|
||||
? ++h2Sequence
|
||||
: ++h3Sequence,
|
||||
sequence: node.attrs.level === 1 ? ++h1Sequence : node.attrs.level === 2 ? ++h2Sequence : ++h3Sequence,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,11 +2,7 @@
|
|||
import React, { useState } from "react";
|
||||
import { getEditorClassNames, useEditor } from "@plane/editor-core";
|
||||
import { DocumentEditorExtensions } from "./extensions";
|
||||
import {
|
||||
IDuplicationConfig,
|
||||
IPageArchiveConfig,
|
||||
IPageLockConfig,
|
||||
} from "./types/menu-actions";
|
||||
import { IDuplicationConfig, IPageArchiveConfig, IPageLockConfig } from "./types/menu-actions";
|
||||
import { EditorHeader } from "./components/editor-header";
|
||||
import { useEditorMarkings } from "./hooks/use-editor-markings";
|
||||
import { SummarySideBar } from "./components/summary-side-bar";
|
||||
|
|
@ -41,9 +37,7 @@ interface IDocumentEditor {
|
|||
customClassName?: string;
|
||||
editorContentCustomClassNames?: string;
|
||||
onChange: (json: any, html: string) => void;
|
||||
setIsSubmitting?: (
|
||||
isSubmitting: "submitting" | "submitted" | "saved",
|
||||
) => void;
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void;
|
||||
setShouldShowAlert?: (showAlert: boolean) => void;
|
||||
forwardedRef?: any;
|
||||
updatePageTitle: (title: string) => Promise<void>;
|
||||
|
|
@ -118,11 +112,7 @@ const DocumentEditor = ({
|
|||
cancelUploadImage,
|
||||
rerenderOnPropsChange,
|
||||
forwardedRef,
|
||||
extensions: DocumentEditorExtensions(
|
||||
uploadFile,
|
||||
embedConfig?.issueEmbedConfig,
|
||||
setIsSubmitting,
|
||||
),
|
||||
extensions: DocumentEditorExtensions(uploadFile, embedConfig?.issueEmbedConfig, setIsSubmitting),
|
||||
});
|
||||
|
||||
if (!editor) {
|
||||
|
|
@ -147,7 +137,7 @@ const DocumentEditor = ({
|
|||
if (!editor) return null;
|
||||
|
||||
return (
|
||||
<div className="h-full w-full flex flex-col overflow-hidden">
|
||||
<div className="flex h-full w-full flex-col overflow-hidden">
|
||||
<EditorHeader
|
||||
readonly={false}
|
||||
KanbanMenuOptions={KanbanMenuOptions}
|
||||
|
|
@ -163,13 +153,9 @@ const DocumentEditor = ({
|
|||
documentDetails={documentDetails}
|
||||
isSubmitting={isSubmitting}
|
||||
/>
|
||||
<div className="h-full w-full flex overflow-y-auto">
|
||||
<div className="flex-shrink-0 h-full w-56 lg:w-72 sticky top-0">
|
||||
<SummarySideBar
|
||||
editor={editor}
|
||||
markings={markings}
|
||||
sidePeekVisible={sidePeekVisible}
|
||||
/>
|
||||
<div className="flex h-full w-full overflow-y-auto">
|
||||
<div className="sticky top-0 h-full w-56 flex-shrink-0 lg:w-72">
|
||||
<SummarySideBar editor={editor} markings={markings} sidePeekVisible={sidePeekVisible} />
|
||||
</div>
|
||||
<div className="h-full w-[calc(100%-14rem)] lg:w-[calc(100%-18rem-18rem)]">
|
||||
<PageRenderer
|
||||
|
|
@ -181,15 +167,15 @@ const DocumentEditor = ({
|
|||
updatePageTitle={updatePageTitle}
|
||||
/>
|
||||
</div>
|
||||
<div className="hidden lg:block flex-shrink-0 w-56 lg:w-72" />
|
||||
<div className="hidden w-56 flex-shrink-0 lg:block lg:w-72" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const DocumentEditorWithRef = React.forwardRef<EditorHandle, IDocumentEditor>(
|
||||
(props, ref) => <DocumentEditor {...props} forwardedRef={ref} />,
|
||||
);
|
||||
const DocumentEditorWithRef = React.forwardRef<EditorHandle, IDocumentEditor>((props, ref) => (
|
||||
<DocumentEditor {...props} forwardedRef={ref} />
|
||||
));
|
||||
|
||||
DocumentEditorWithRef.displayName = "DocumentEditorWithRef";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { Editor } from "@tiptap/react";
|
||||
import { BoldIcon } from "lucide-react";
|
||||
|
||||
import {
|
||||
BoldItem,
|
||||
BulletListItem,
|
||||
|
|
@ -18,22 +16,16 @@ import {
|
|||
HeadingTwoItem,
|
||||
HeadingThreeItem,
|
||||
findTableAncestor,
|
||||
EditorMenuItem,
|
||||
} from "@plane/editor-core";
|
||||
import { UploadImage } from "@plane/editor-types";
|
||||
|
||||
export interface BubbleMenuItem {
|
||||
name: string;
|
||||
isActive: () => boolean;
|
||||
command: () => void;
|
||||
icon: typeof BoldIcon;
|
||||
}
|
||||
export type BubbleMenuItem = EditorMenuItem;
|
||||
|
||||
type EditorBubbleMenuProps = {
|
||||
editor: Editor;
|
||||
uploadFile: UploadImage;
|
||||
setIsSubmitting?: (
|
||||
isSubmitting: "submitting" | "submitted" | "saved",
|
||||
) => void;
|
||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void;
|
||||
};
|
||||
|
||||
export const FixedMenu = (props: EditorBubbleMenuProps) => {
|
||||
|
|
@ -49,15 +41,9 @@ export const FixedMenu = (props: EditorBubbleMenuProps) => {
|
|||
StrikeThroughItem(editor),
|
||||
];
|
||||
|
||||
const listItems: BubbleMenuItem[] = [
|
||||
BulletListItem(editor),
|
||||
NumberedListItem(editor),
|
||||
];
|
||||
const listItems: BubbleMenuItem[] = [BulletListItem(editor), NumberedListItem(editor)];
|
||||
|
||||
const userActionItems: BubbleMenuItem[] = [
|
||||
QuoteItem(editor),
|
||||
CodeItem(editor),
|
||||
];
|
||||
const userActionItems: BubbleMenuItem[] = [QuoteItem(editor), CodeItem(editor)];
|
||||
|
||||
function getComplexItems(): BubbleMenuItem[] {
|
||||
const items: BubbleMenuItem[] = [TableItem(editor)];
|
||||
|
|
@ -99,10 +85,10 @@ export const FixedMenu = (props: EditorBubbleMenuProps) => {
|
|||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"h-7 w-7 grid place-items-center text-custom-text-300 hover:bg-custom-background-80 rounded",
|
||||
"grid h-7 w-7 place-items-center rounded text-custom-text-300 hover:bg-custom-background-80",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80": item.isActive(),
|
||||
},
|
||||
"bg-custom-background-80 text-custom-text-100": item.isActive(),
|
||||
}
|
||||
)}
|
||||
>
|
||||
<item.icon className="h-4 w-4" />
|
||||
|
|
@ -116,10 +102,10 @@ export const FixedMenu = (props: EditorBubbleMenuProps) => {
|
|||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"h-7 w-7 grid place-items-center text-custom-text-300 hover:bg-custom-background-80 rounded",
|
||||
"grid h-7 w-7 place-items-center rounded text-custom-text-300 hover:bg-custom-background-80",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80": item.isActive(),
|
||||
},
|
||||
"bg-custom-background-80 text-custom-text-100": item.isActive(),
|
||||
}
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
|
|
@ -137,10 +123,10 @@ export const FixedMenu = (props: EditorBubbleMenuProps) => {
|
|||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"h-7 w-7 grid place-items-center text-custom-text-300 hover:bg-custom-background-80 rounded",
|
||||
"grid h-7 w-7 place-items-center rounded text-custom-text-300 hover:bg-custom-background-80",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80": item.isActive(),
|
||||
},
|
||||
"bg-custom-background-80 text-custom-text-100": item.isActive(),
|
||||
}
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
|
|
@ -158,10 +144,10 @@ export const FixedMenu = (props: EditorBubbleMenuProps) => {
|
|||
type="button"
|
||||
onClick={item.command}
|
||||
className={cn(
|
||||
"h-7 w-7 grid place-items-center text-custom-text-300 hover:bg-custom-background-80 rounded",
|
||||
"grid h-7 w-7 place-items-center rounded text-custom-text-300 hover:bg-custom-background-80",
|
||||
{
|
||||
"text-custom-text-100 bg-custom-background-80": item.isActive(),
|
||||
},
|
||||
"bg-custom-background-80 text-custom-text-100": item.isActive(),
|
||||
}
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
|
|
|
|||
|
|
@ -6,9 +6,5 @@ type Props = {
|
|||
};
|
||||
|
||||
export const Icon: React.FC<Props> = ({ iconName, className = "" }) => (
|
||||
<span
|
||||
className={`material-symbols-rounded text-sm leading-5 font-light ${className}`}
|
||||
>
|
||||
{iconName}
|
||||
</span>
|
||||
<span className={`material-symbols-rounded text-sm font-light leading-5 ${className}`}>{iconName}</span>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,11 +8,7 @@ import { IssueWidgetExtension } from "../extensions/widgets/IssueEmbedWidget";
|
|||
import { IEmbedConfig } from "../extensions/widgets/IssueEmbedWidget/types";
|
||||
import { useEditorMarkings } from "../hooks/use-editor-markings";
|
||||
import { DocumentDetails } from "../types/editor-types";
|
||||
import {
|
||||
IPageArchiveConfig,
|
||||
IPageLockConfig,
|
||||
IDuplicationConfig,
|
||||
} from "../types/menu-actions";
|
||||
import { IPageArchiveConfig, IPageLockConfig, IDuplicationConfig } from "../types/menu-actions";
|
||||
import { getMenuOptions } from "../utils/menu-options";
|
||||
|
||||
interface IDocumentReadOnlyEditor {
|
||||
|
|
@ -67,9 +63,7 @@ const DocumentReadOnlyEditor = ({
|
|||
value,
|
||||
forwardedRef,
|
||||
rerenderOnPropsChange,
|
||||
extensions: [
|
||||
IssueWidgetExtension({ issueEmbedConfig: embedConfig?.issueEmbedConfig }),
|
||||
],
|
||||
extensions: [IssueWidgetExtension({ issueEmbedConfig: embedConfig?.issueEmbedConfig })],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -98,7 +92,7 @@ const DocumentReadOnlyEditor = ({
|
|||
});
|
||||
|
||||
return (
|
||||
<div className="h-full w-full flex flex-col overflow-hidden">
|
||||
<div className="flex h-full w-full flex-col overflow-hidden">
|
||||
<EditorHeader
|
||||
isLocked={!pageLockConfig ? false : pageLockConfig.is_locked}
|
||||
isArchived={!pageArchiveConfig ? false : pageArchiveConfig.is_archived}
|
||||
|
|
@ -111,13 +105,9 @@ const DocumentReadOnlyEditor = ({
|
|||
documentDetails={documentDetails}
|
||||
archivedAt={pageArchiveConfig && pageArchiveConfig.archived_at}
|
||||
/>
|
||||
<div className="h-full w-full flex overflow-y-auto">
|
||||
<div className="flex-shrink-0 h-full w-56 lg:w-80 sticky top-0">
|
||||
<SummarySideBar
|
||||
editor={editor}
|
||||
markings={markings}
|
||||
sidePeekVisible={sidePeekVisible}
|
||||
/>
|
||||
<div className="flex h-full w-full overflow-y-auto">
|
||||
<div className="sticky top-0 h-full w-56 flex-shrink-0 lg:w-80">
|
||||
<SummarySideBar editor={editor} markings={markings} sidePeekVisible={sidePeekVisible} />
|
||||
</div>
|
||||
<div className="h-full w-full">
|
||||
<PageRenderer
|
||||
|
|
@ -128,16 +118,15 @@ const DocumentReadOnlyEditor = ({
|
|||
documentDetails={documentDetails}
|
||||
/>
|
||||
</div>
|
||||
<div className="hidden lg:block flex-shrink-0 w-56 lg:w-80" />
|
||||
<div className="hidden w-56 flex-shrink-0 lg:block lg:w-80" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const DocumentReadOnlyEditorWithRef = forwardRef<
|
||||
EditorHandle,
|
||||
IDocumentReadOnlyEditor
|
||||
>((props, ref) => <DocumentReadOnlyEditor {...props} forwardedRef={ref} />);
|
||||
const DocumentReadOnlyEditorWithRef = forwardRef<EditorHandle, IDocumentReadOnlyEditor>((props, ref) => (
|
||||
<DocumentReadOnlyEditor {...props} forwardedRef={ref} />
|
||||
));
|
||||
|
||||
DocumentReadOnlyEditorWithRef.displayName = "DocumentReadOnlyEditorWithRef";
|
||||
|
||||
|
|
|
|||
|
|
@ -51,17 +51,11 @@ export const Tooltip: React.FC<Props> = ({
|
|||
content={
|
||||
<div
|
||||
className={`relative z-50 max-w-xs gap-1 rounded-md p-2 text-xs shadow-md ${
|
||||
theme === "custom"
|
||||
? "bg-custom-background-100 text-custom-text-200"
|
||||
: "bg-black text-gray-400"
|
||||
} break-words overflow-hidden ${className}`}
|
||||
theme === "custom" ? "bg-custom-background-100 text-custom-text-200" : "bg-black text-gray-400"
|
||||
} overflow-hidden break-words ${className}`}
|
||||
>
|
||||
{tooltipHeading && (
|
||||
<h5
|
||||
className={`font-medium ${
|
||||
theme === "custom" ? "text-custom-text-100" : "text-white"
|
||||
}`}
|
||||
>
|
||||
<h5 className={`font-medium ${theme === "custom" ? "text-custom-text-100" : "text-white"}`}>
|
||||
{tooltipHeading}
|
||||
</h5>
|
||||
)}
|
||||
|
|
@ -69,11 +63,7 @@ export const Tooltip: React.FC<Props> = ({
|
|||
</div>
|
||||
}
|
||||
position={position}
|
||||
renderTarget={({
|
||||
isOpen: isTooltipOpen,
|
||||
ref: eleReference,
|
||||
...tooltipProps
|
||||
}) =>
|
||||
renderTarget={({ isOpen: isTooltipOpen, ref: eleReference, ...tooltipProps }) =>
|
||||
React.cloneElement(children, {
|
||||
ref: eleReference,
|
||||
...tooltipProps,
|
||||
|
|
|
|||
|
|
@ -12,11 +12,7 @@ import {
|
|||
} from "lucide-react";
|
||||
import { NextRouter } from "next/router";
|
||||
import { IVerticalDropdownItemProps } from "../components/vertical-dropdown-menu";
|
||||
import {
|
||||
IDuplicationConfig,
|
||||
IPageArchiveConfig,
|
||||
IPageLockConfig,
|
||||
} from "../types/menu-actions";
|
||||
import { IDuplicationConfig, IPageArchiveConfig, IPageLockConfig } from "../types/menu-actions";
|
||||
import { copyMarkdownToClipboard, CopyPageLink } from "./menu-actions";
|
||||
|
||||
export interface MenuOptionsProps {
|
||||
|
|
@ -90,8 +86,7 @@ export const getMenuOptions = ({
|
|||
.then(() => {
|
||||
onActionCompleteHandler({
|
||||
title: "Page Copied",
|
||||
message:
|
||||
"Page has been copied as 'Copy of' followed by page title",
|
||||
message: "Page has been copied as 'Copy of' followed by page title",
|
||||
type: "success",
|
||||
});
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue