mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: merge conflicts resolved
This commit is contained in:
commit
c389c6b440
34
.github/workflows/auto-merge.yml
vendored
34
.github/workflows/auto-merge.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Auto Merge or Create PR on Push
|
name: Create PR on Sync
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@ -56,30 +56,14 @@ jobs:
|
|||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install gh -y
|
sudo apt install gh -y
|
||||||
|
|
||||||
- name: Check for merge conflicts
|
|
||||||
id: conflicts
|
|
||||||
run: |
|
|
||||||
git fetch origin $TARGET_BRANCH
|
|
||||||
git checkout $TARGET_BRANCH
|
|
||||||
# Attempt to merge the main branch into the current branch
|
|
||||||
if $(git merge --no-commit --no-ff $SOURCE_BRANCH); then
|
|
||||||
echo "No merge conflicts detected."
|
|
||||||
echo "HAS_CONFLICTS=false" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "Merge conflicts detected."
|
|
||||||
echo "HAS_CONFLICTS=true" >> $GITHUB_ENV
|
|
||||||
git merge --abort
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Merge Change to Target Branch
|
|
||||||
if: env.HAS_CONFLICTS == 'false'
|
|
||||||
run: |
|
|
||||||
git commit -m "Merge branch '$SOURCE_BRANCH' into $TARGET_BRANCH"
|
|
||||||
git push origin $TARGET_BRANCH
|
|
||||||
|
|
||||||
- name: Create PR to Target Branch
|
- name: Create PR to Target Branch
|
||||||
if: env.HAS_CONFLICTS == 'true'
|
|
||||||
run: |
|
run: |
|
||||||
# Replace 'username' with the actual GitHub username of the reviewer.
|
# get all pull requests and check if there is already a PR
|
||||||
PR_URL=$(gh pr create --base $TARGET_BRANCH --head $SOURCE_BRANCH --title "sync: merge conflicts need to be resolved" --body "" --reviewer $REVIEWER)
|
PR_EXISTS=$(gh pr list --base $TARGET_BRANCH --head $SOURCE_BRANCH --json number | jq '.[] | .number')
|
||||||
|
if [ -n "$PR_EXISTS" ]; then
|
||||||
|
echo "Pull Request already exists: $PR_EXISTS"
|
||||||
|
else
|
||||||
|
echo "Creating new pull request"
|
||||||
|
PR_URL=$(gh pr create --base $TARGET_BRANCH --head $SOURCE_BRANCH --title "sync: merge conflicts need to be resolved" --body "")
|
||||||
echo "Pull Request created: $PR_URL"
|
echo "Pull Request created: $PR_URL"
|
||||||
|
fi
|
||||||
|
@ -180,7 +180,7 @@ services:
|
|||||||
|
|
||||||
plane-redis:
|
plane-redis:
|
||||||
container_name: plane-redis
|
container_name: plane-redis
|
||||||
image: redis:6.2.7-alpine
|
image: redis:7.2.4-alpine
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
@ -10,7 +10,7 @@ volumes:
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
plane-redis:
|
plane-redis:
|
||||||
image: redis:6.2.7-alpine
|
image: redis:7.2.4-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- dev_env
|
- dev_env
|
||||||
|
@ -118,7 +118,7 @@ services:
|
|||||||
|
|
||||||
plane-redis:
|
plane-redis:
|
||||||
container_name: plane-redis
|
container_name: plane-redis
|
||||||
image: redis:6.2.7-alpine
|
image: redis:7.2.4-alpine
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
@ -142,11 +142,11 @@ export const useEditor = ({
|
|||||||
executeMenuItemCommand: (itemName: EditorMenuItemNames) => {
|
executeMenuItemCommand: (itemName: EditorMenuItemNames) => {
|
||||||
const editorItems = getEditorMenuItems(editorRef.current, uploadFile);
|
const editorItems = getEditorMenuItems(editorRef.current, uploadFile);
|
||||||
|
|
||||||
const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.name === itemName);
|
const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.key === itemName);
|
||||||
|
|
||||||
const item = getEditorMenuItem(itemName);
|
const item = getEditorMenuItem(itemName);
|
||||||
if (item) {
|
if (item) {
|
||||||
if (item.name === "image") {
|
if (item.key === "image") {
|
||||||
item.command(savedSelection);
|
item.command(savedSelection);
|
||||||
} else {
|
} else {
|
||||||
item.command();
|
item.command();
|
||||||
@ -158,7 +158,7 @@ export const useEditor = ({
|
|||||||
isMenuItemActive: (itemName: EditorMenuItemNames): boolean => {
|
isMenuItemActive: (itemName: EditorMenuItemNames): boolean => {
|
||||||
const editorItems = getEditorMenuItems(editorRef.current, uploadFile);
|
const editorItems = getEditorMenuItems(editorRef.current, uploadFile);
|
||||||
|
|
||||||
const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.name === itemName);
|
const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.key === itemName);
|
||||||
const item = getEditorMenuItem(itemName);
|
const item = getEditorMenuItem(itemName);
|
||||||
return item ? item.isActive() : false;
|
return item ? item.isActive() : false;
|
||||||
},
|
},
|
||||||
|
@ -4,6 +4,11 @@ import { findTableAncestor } from "src/lib/utils";
|
|||||||
import { Selection } from "@tiptap/pm/state";
|
import { Selection } from "@tiptap/pm/state";
|
||||||
import { UploadImage } from "src/types/upload-image";
|
import { UploadImage } from "src/types/upload-image";
|
||||||
|
|
||||||
|
export const setText = (editor: Editor, range?: Range) => {
|
||||||
|
if (range) editor.chain().focus().deleteRange(range).clearNodes().run();
|
||||||
|
else editor.chain().focus().clearNodes().run();
|
||||||
|
};
|
||||||
|
|
||||||
export const toggleHeadingOne = (editor: Editor, range?: Range) => {
|
export const toggleHeadingOne = (editor: Editor, range?: Range) => {
|
||||||
if (range) editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
|
if (range) editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
|
||||||
else editor.chain().focus().toggleHeading({ level: 1 }).run();
|
else editor.chain().focus().toggleHeading({ level: 1 }).run();
|
||||||
@ -19,6 +24,21 @@ export const toggleHeadingThree = (editor: Editor, range?: Range) => {
|
|||||||
else editor.chain().focus().toggleHeading({ level: 3 }).run();
|
else editor.chain().focus().toggleHeading({ level: 3 }).run();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const toggleHeadingFour = (editor: Editor, range?: Range) => {
|
||||||
|
if (range) editor.chain().focus().deleteRange(range).setNode("heading", { level: 4 }).run();
|
||||||
|
else editor.chain().focus().toggleHeading({ level: 4 }).run();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toggleHeadingFive = (editor: Editor, range?: Range) => {
|
||||||
|
if (range) editor.chain().focus().deleteRange(range).setNode("heading", { level: 5 }).run();
|
||||||
|
else editor.chain().focus().toggleHeading({ level: 5 }).run();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toggleHeadingSix = (editor: Editor, range?: Range) => {
|
||||||
|
if (range) editor.chain().focus().deleteRange(range).setNode("heading", { level: 6 }).run();
|
||||||
|
else editor.chain().focus().toggleHeading({ level: 6 }).run();
|
||||||
|
};
|
||||||
|
|
||||||
export const toggleBold = (editor: Editor, range?: Range) => {
|
export const toggleBold = (editor: Editor, range?: Range) => {
|
||||||
if (range) editor.chain().focus().deleteRange(range).toggleBold().run();
|
if (range) editor.chain().focus().deleteRange(range).toggleBold().run();
|
||||||
else editor.chain().focus().toggleBold().run();
|
else editor.chain().focus().toggleBold().run();
|
||||||
|
@ -330,6 +330,29 @@ ul[data-type="taskList"] ul[data-type="taskList"] {
|
|||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prose :where(h4):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose :where(h5):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose :where(h6):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
font-size: 0.83rem;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
.prose :where(p):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
|
.prose :where(p):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
|
||||||
margin-top: 0.25rem;
|
margin-top: 0.25rem;
|
||||||
margin-bottom: 1px;
|
margin-bottom: 1px;
|
||||||
|
@ -13,16 +13,24 @@ import {
|
|||||||
UnderlineIcon,
|
UnderlineIcon,
|
||||||
StrikethroughIcon,
|
StrikethroughIcon,
|
||||||
CodeIcon,
|
CodeIcon,
|
||||||
|
Heading4,
|
||||||
|
Heading5,
|
||||||
|
Heading6,
|
||||||
|
CaseSensitive,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { Editor } from "@tiptap/react";
|
import { Editor } from "@tiptap/react";
|
||||||
import {
|
import {
|
||||||
insertImageCommand,
|
insertImageCommand,
|
||||||
insertTableCommand,
|
insertTableCommand,
|
||||||
|
setText,
|
||||||
toggleBlockquote,
|
toggleBlockquote,
|
||||||
toggleBold,
|
toggleBold,
|
||||||
toggleBulletList,
|
toggleBulletList,
|
||||||
toggleCodeBlock,
|
toggleCodeBlock,
|
||||||
|
toggleHeadingFive,
|
||||||
|
toggleHeadingFour,
|
||||||
toggleHeadingOne,
|
toggleHeadingOne,
|
||||||
|
toggleHeadingSix,
|
||||||
toggleHeadingThree,
|
toggleHeadingThree,
|
||||||
toggleHeadingTwo,
|
toggleHeadingTwo,
|
||||||
toggleItalic,
|
toggleItalic,
|
||||||
@ -36,15 +44,26 @@ import { UploadImage } from "src/types/upload-image";
|
|||||||
import { Selection } from "@tiptap/pm/state";
|
import { Selection } from "@tiptap/pm/state";
|
||||||
|
|
||||||
export interface EditorMenuItem {
|
export interface EditorMenuItem {
|
||||||
|
key: string;
|
||||||
name: string;
|
name: string;
|
||||||
isActive: () => boolean;
|
isActive: () => boolean;
|
||||||
command: () => void;
|
command: () => void;
|
||||||
icon: LucideIconType;
|
icon: LucideIconType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const TextItem = (editor: Editor) =>
|
||||||
|
({
|
||||||
|
key: "text",
|
||||||
|
name: "Text",
|
||||||
|
isActive: () => editor.isActive("paragraph"),
|
||||||
|
command: () => setText(editor),
|
||||||
|
icon: CaseSensitive,
|
||||||
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
export const HeadingOneItem = (editor: Editor) =>
|
export const HeadingOneItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "H1",
|
key: "h1",
|
||||||
|
name: "Heading 1",
|
||||||
isActive: () => editor.isActive("heading", { level: 1 }),
|
isActive: () => editor.isActive("heading", { level: 1 }),
|
||||||
command: () => toggleHeadingOne(editor),
|
command: () => toggleHeadingOne(editor),
|
||||||
icon: Heading1,
|
icon: Heading1,
|
||||||
@ -52,7 +71,8 @@ export const HeadingOneItem = (editor: Editor) =>
|
|||||||
|
|
||||||
export const HeadingTwoItem = (editor: Editor) =>
|
export const HeadingTwoItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "H2",
|
key: "h2",
|
||||||
|
name: "Heading 2",
|
||||||
isActive: () => editor.isActive("heading", { level: 2 }),
|
isActive: () => editor.isActive("heading", { level: 2 }),
|
||||||
command: () => toggleHeadingTwo(editor),
|
command: () => toggleHeadingTwo(editor),
|
||||||
icon: Heading2,
|
icon: Heading2,
|
||||||
@ -60,15 +80,44 @@ export const HeadingTwoItem = (editor: Editor) =>
|
|||||||
|
|
||||||
export const HeadingThreeItem = (editor: Editor) =>
|
export const HeadingThreeItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "H3",
|
key: "h3",
|
||||||
|
name: "Heading 3",
|
||||||
isActive: () => editor.isActive("heading", { level: 3 }),
|
isActive: () => editor.isActive("heading", { level: 3 }),
|
||||||
command: () => toggleHeadingThree(editor),
|
command: () => toggleHeadingThree(editor),
|
||||||
icon: Heading3,
|
icon: Heading3,
|
||||||
}) as const satisfies EditorMenuItem;
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
|
export const HeadingFourItem = (editor: Editor) =>
|
||||||
|
({
|
||||||
|
key: "h4",
|
||||||
|
name: "Heading 4",
|
||||||
|
isActive: () => editor.isActive("heading", { level: 4 }),
|
||||||
|
command: () => toggleHeadingFour(editor),
|
||||||
|
icon: Heading4,
|
||||||
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
|
export const HeadingFiveItem = (editor: Editor) =>
|
||||||
|
({
|
||||||
|
key: "h5",
|
||||||
|
name: "Heading 5",
|
||||||
|
isActive: () => editor.isActive("heading", { level: 5 }),
|
||||||
|
command: () => toggleHeadingFive(editor),
|
||||||
|
icon: Heading5,
|
||||||
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
|
export const HeadingSixItem = (editor: Editor) =>
|
||||||
|
({
|
||||||
|
key: "h6",
|
||||||
|
name: "Heading 6",
|
||||||
|
isActive: () => editor.isActive("heading", { level: 6 }),
|
||||||
|
command: () => toggleHeadingSix(editor),
|
||||||
|
icon: Heading6,
|
||||||
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
export const BoldItem = (editor: Editor) =>
|
export const BoldItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "bold",
|
key: "bold",
|
||||||
|
name: "Bold",
|
||||||
isActive: () => editor?.isActive("bold"),
|
isActive: () => editor?.isActive("bold"),
|
||||||
command: () => toggleBold(editor),
|
command: () => toggleBold(editor),
|
||||||
icon: BoldIcon,
|
icon: BoldIcon,
|
||||||
@ -76,7 +125,8 @@ export const BoldItem = (editor: Editor) =>
|
|||||||
|
|
||||||
export const ItalicItem = (editor: Editor) =>
|
export const ItalicItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "italic",
|
key: "italic",
|
||||||
|
name: "Italic",
|
||||||
isActive: () => editor?.isActive("italic"),
|
isActive: () => editor?.isActive("italic"),
|
||||||
command: () => toggleItalic(editor),
|
command: () => toggleItalic(editor),
|
||||||
icon: ItalicIcon,
|
icon: ItalicIcon,
|
||||||
@ -84,7 +134,8 @@ export const ItalicItem = (editor: Editor) =>
|
|||||||
|
|
||||||
export const UnderLineItem = (editor: Editor) =>
|
export const UnderLineItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "underline",
|
key: "underline",
|
||||||
|
name: "Underline",
|
||||||
isActive: () => editor?.isActive("underline"),
|
isActive: () => editor?.isActive("underline"),
|
||||||
command: () => toggleUnderline(editor),
|
command: () => toggleUnderline(editor),
|
||||||
icon: UnderlineIcon,
|
icon: UnderlineIcon,
|
||||||
@ -92,7 +143,8 @@ export const UnderLineItem = (editor: Editor) =>
|
|||||||
|
|
||||||
export const StrikeThroughItem = (editor: Editor) =>
|
export const StrikeThroughItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "strike",
|
key: "strikethrough",
|
||||||
|
name: "Strikethrough",
|
||||||
isActive: () => editor?.isActive("strike"),
|
isActive: () => editor?.isActive("strike"),
|
||||||
command: () => toggleStrike(editor),
|
command: () => toggleStrike(editor),
|
||||||
icon: StrikethroughIcon,
|
icon: StrikethroughIcon,
|
||||||
@ -100,47 +152,53 @@ export const StrikeThroughItem = (editor: Editor) =>
|
|||||||
|
|
||||||
export const BulletListItem = (editor: Editor) =>
|
export const BulletListItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "bullet-list",
|
key: "bulleted-list",
|
||||||
|
name: "Bulleted list",
|
||||||
isActive: () => editor?.isActive("bulletList"),
|
isActive: () => editor?.isActive("bulletList"),
|
||||||
command: () => toggleBulletList(editor),
|
command: () => toggleBulletList(editor),
|
||||||
icon: ListIcon,
|
icon: ListIcon,
|
||||||
}) as const satisfies EditorMenuItem;
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
export const TodoListItem = (editor: Editor) =>
|
|
||||||
({
|
|
||||||
name: "To-do List",
|
|
||||||
isActive: () => editor.isActive("taskItem"),
|
|
||||||
command: () => toggleTaskList(editor),
|
|
||||||
icon: CheckSquare,
|
|
||||||
}) as const satisfies EditorMenuItem;
|
|
||||||
|
|
||||||
export const CodeItem = (editor: Editor) =>
|
|
||||||
({
|
|
||||||
name: "code",
|
|
||||||
isActive: () => editor?.isActive("code") || editor?.isActive("codeBlock"),
|
|
||||||
command: () => toggleCodeBlock(editor),
|
|
||||||
icon: CodeIcon,
|
|
||||||
}) as const satisfies EditorMenuItem;
|
|
||||||
|
|
||||||
export const NumberedListItem = (editor: Editor) =>
|
export const NumberedListItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "ordered-list",
|
key: "numbered-list",
|
||||||
|
name: "Numbered list",
|
||||||
isActive: () => editor?.isActive("orderedList"),
|
isActive: () => editor?.isActive("orderedList"),
|
||||||
command: () => toggleOrderedList(editor),
|
command: () => toggleOrderedList(editor),
|
||||||
icon: ListOrderedIcon,
|
icon: ListOrderedIcon,
|
||||||
}) as const satisfies EditorMenuItem;
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
|
export const TodoListItem = (editor: Editor) =>
|
||||||
|
({
|
||||||
|
key: "to-do-list",
|
||||||
|
name: "To-do list",
|
||||||
|
isActive: () => editor.isActive("taskItem"),
|
||||||
|
command: () => toggleTaskList(editor),
|
||||||
|
icon: CheckSquare,
|
||||||
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
export const QuoteItem = (editor: Editor) =>
|
export const QuoteItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "quote",
|
key: "quote",
|
||||||
|
name: "Quote",
|
||||||
isActive: () => editor?.isActive("blockquote"),
|
isActive: () => editor?.isActive("blockquote"),
|
||||||
command: () => toggleBlockquote(editor),
|
command: () => toggleBlockquote(editor),
|
||||||
icon: QuoteIcon,
|
icon: QuoteIcon,
|
||||||
}) as const satisfies EditorMenuItem;
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
|
export const CodeItem = (editor: Editor) =>
|
||||||
|
({
|
||||||
|
key: "code",
|
||||||
|
name: "Code",
|
||||||
|
isActive: () => editor?.isActive("code") || editor?.isActive("codeBlock"),
|
||||||
|
command: () => toggleCodeBlock(editor),
|
||||||
|
icon: CodeIcon,
|
||||||
|
}) as const satisfies EditorMenuItem;
|
||||||
|
|
||||||
export const TableItem = (editor: Editor) =>
|
export const TableItem = (editor: Editor) =>
|
||||||
({
|
({
|
||||||
name: "table",
|
key: "table",
|
||||||
|
name: "Table",
|
||||||
isActive: () => editor?.isActive("table"),
|
isActive: () => editor?.isActive("table"),
|
||||||
command: () => insertTableCommand(editor),
|
command: () => insertTableCommand(editor),
|
||||||
icon: TableIcon,
|
icon: TableIcon,
|
||||||
@ -148,7 +206,8 @@ export const TableItem = (editor: Editor) =>
|
|||||||
|
|
||||||
export const ImageItem = (editor: Editor, uploadFile: UploadImage) =>
|
export const ImageItem = (editor: Editor, uploadFile: UploadImage) =>
|
||||||
({
|
({
|
||||||
name: "image",
|
key: "image",
|
||||||
|
name: "Image",
|
||||||
isActive: () => editor?.isActive("image"),
|
isActive: () => editor?.isActive("image"),
|
||||||
command: (savedSelection: Selection | null) => insertImageCommand(editor, uploadFile, savedSelection),
|
command: (savedSelection: Selection | null) => insertImageCommand(editor, uploadFile, savedSelection),
|
||||||
icon: ImageIcon,
|
icon: ImageIcon,
|
||||||
@ -159,9 +218,13 @@ export function getEditorMenuItems(editor: Editor | null, uploadFile: UploadImag
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
|
TextItem(editor),
|
||||||
HeadingOneItem(editor),
|
HeadingOneItem(editor),
|
||||||
HeadingTwoItem(editor),
|
HeadingTwoItem(editor),
|
||||||
HeadingThreeItem(editor),
|
HeadingThreeItem(editor),
|
||||||
|
HeadingFourItem(editor),
|
||||||
|
HeadingFiveItem(editor),
|
||||||
|
HeadingSixItem(editor),
|
||||||
BoldItem(editor),
|
BoldItem(editor),
|
||||||
ItalicItem(editor),
|
ItalicItem(editor),
|
||||||
UnderLineItem(editor),
|
UnderLineItem(editor),
|
||||||
@ -177,7 +240,7 @@ export function getEditorMenuItems(editor: Editor | null, uploadFile: UploadImag
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type EditorMenuItemNames = ReturnType<typeof getEditorMenuItems> extends (infer U)[]
|
export type EditorMenuItemNames = ReturnType<typeof getEditorMenuItems> extends (infer U)[]
|
||||||
? U extends { name: infer N }
|
? U extends { key: infer N }
|
||||||
? N
|
? N
|
||||||
: never
|
: never
|
||||||
: never;
|
: never;
|
||||||
|
@ -67,11 +67,13 @@ export default function BlockMenu(props: BlockMenuProps) {
|
|||||||
popup.current?.hide();
|
popup.current?.hide();
|
||||||
};
|
};
|
||||||
document.addEventListener("click", handleClickDragHandle);
|
document.addEventListener("click", handleClickDragHandle);
|
||||||
|
document.addEventListener("contextmenu", handleClickDragHandle);
|
||||||
document.addEventListener("keydown", handleKeyDown);
|
document.addEventListener("keydown", handleKeyDown);
|
||||||
document.addEventListener("scroll", handleScroll, true); // Using capture phase
|
document.addEventListener("scroll", handleScroll, true); // Using capture phase
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener("click", handleClickDragHandle);
|
document.removeEventListener("click", handleClickDragHandle);
|
||||||
|
document.removeEventListener("contextmenu", handleClickDragHandle);
|
||||||
document.removeEventListener("keydown", handleKeyDown);
|
document.removeEventListener("keydown", handleKeyDown);
|
||||||
document.removeEventListener("scroll", handleScroll, true);
|
document.removeEventListener("scroll", handleScroll, true);
|
||||||
};
|
};
|
||||||
|
@ -225,6 +225,9 @@ function DragHandle(options: DragHandleOptions) {
|
|||||||
dragHandleElement.addEventListener("click", (e) => {
|
dragHandleElement.addEventListener("click", (e) => {
|
||||||
handleClick(e, view);
|
handleClick(e, view);
|
||||||
});
|
});
|
||||||
|
dragHandleElement.addEventListener("contextmenu", (e) => {
|
||||||
|
handleClick(e, view);
|
||||||
|
});
|
||||||
|
|
||||||
dragHandleElement.addEventListener("drag", (e) => {
|
dragHandleElement.addEventListener("drag", (e) => {
|
||||||
hideDragHandle();
|
hideDragHandle();
|
||||||
|
@ -15,6 +15,7 @@ import {
|
|||||||
} from "@plane/editor-core";
|
} from "@plane/editor-core";
|
||||||
|
|
||||||
export interface BubbleMenuItem {
|
export interface BubbleMenuItem {
|
||||||
|
key: string;
|
||||||
name: string;
|
name: string;
|
||||||
isActive: () => boolean;
|
isActive: () => boolean;
|
||||||
command: () => void;
|
command: () => void;
|
||||||
|
@ -8,9 +8,13 @@ import {
|
|||||||
QuoteItem,
|
QuoteItem,
|
||||||
CodeItem,
|
CodeItem,
|
||||||
TodoListItem,
|
TodoListItem,
|
||||||
|
TextItem,
|
||||||
|
HeadingFourItem,
|
||||||
|
HeadingFiveItem,
|
||||||
|
HeadingSixItem,
|
||||||
} from "@plane/editor-core";
|
} from "@plane/editor-core";
|
||||||
import { Editor } from "@tiptap/react";
|
import { Editor } from "@tiptap/react";
|
||||||
import { Check, ChevronDown, TextIcon } from "lucide-react";
|
import { Check, ChevronDown } from "lucide-react";
|
||||||
import { Dispatch, FC, SetStateAction } from "react";
|
import { Dispatch, FC, SetStateAction } from "react";
|
||||||
|
|
||||||
import { BubbleMenuItem } from ".";
|
import { BubbleMenuItem } from ".";
|
||||||
@ -23,18 +27,16 @@ interface NodeSelectorProps {
|
|||||||
|
|
||||||
export const NodeSelector: FC<NodeSelectorProps> = ({ editor, isOpen, setIsOpen }) => {
|
export const NodeSelector: FC<NodeSelectorProps> = ({ editor, isOpen, setIsOpen }) => {
|
||||||
const items: BubbleMenuItem[] = [
|
const items: BubbleMenuItem[] = [
|
||||||
{
|
TextItem(editor),
|
||||||
name: "Text",
|
|
||||||
icon: TextIcon,
|
|
||||||
command: () => editor.chain().focus().clearNodes().run(),
|
|
||||||
isActive: () => editor.isActive("paragraph") && !editor.isActive("bulletList") && !editor.isActive("orderedList"),
|
|
||||||
},
|
|
||||||
HeadingOneItem(editor),
|
HeadingOneItem(editor),
|
||||||
HeadingTwoItem(editor),
|
HeadingTwoItem(editor),
|
||||||
HeadingThreeItem(editor),
|
HeadingThreeItem(editor),
|
||||||
TodoListItem(editor),
|
HeadingFourItem(editor),
|
||||||
|
HeadingFiveItem(editor),
|
||||||
|
HeadingSixItem(editor),
|
||||||
BulletListItem(editor),
|
BulletListItem(editor),
|
||||||
NumberedListItem(editor),
|
NumberedListItem(editor),
|
||||||
|
TodoListItem(editor),
|
||||||
QuoteItem(editor),
|
QuoteItem(editor),
|
||||||
CodeItem(editor),
|
CodeItem(editor),
|
||||||
];
|
];
|
||||||
@ -58,7 +60,7 @@ export const NodeSelector: FC<NodeSelectorProps> = ({ editor, isOpen, setIsOpen
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<section className="fixed top-full z-[99999] mt-1 flex w-48 flex-col overflow-hidden rounded border border-custom-border-300 bg-custom-background-100 p-1 shadow-xl animate-in fade-in slide-in-from-top-1">
|
<section className="fixed top-full z-[99999] mt-1 flex w-48 flex-col overflow-hidden rounded-md border-[0.5px] border-custom-border-300 bg-custom-background-100 px-2 py-2.5 shadow-custom-shadow-rg animate-in fade-in slide-in-from-top-1">
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<button
|
<button
|
||||||
key={item.name}
|
key={item.name}
|
||||||
@ -69,19 +71,17 @@ export const NodeSelector: FC<NodeSelectorProps> = ({ editor, isOpen, setIsOpen
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}}
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center justify-between rounded-sm px-2 py-1 text-sm text-custom-text-200 hover:bg-custom-primary-100/5 hover:text-custom-text-100",
|
"flex items-center justify-between rounded px-1 py-1.5 text-sm text-custom-text-200 hover:bg-custom-background-80",
|
||||||
{
|
{
|
||||||
"bg-custom-primary-100/5 text-custom-text-100": activeItem.name === item.name,
|
"bg-custom-background-80": activeItem.name === item.name,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<div className="rounded-sm border border-custom-border-300 p-1">
|
<item.icon className="size-3 flex-shrink-0" />
|
||||||
<item.icon className="h-3 w-3" />
|
|
||||||
</div>
|
|
||||||
<span>{item.name}</span>
|
<span>{item.name}</span>
|
||||||
</div>
|
</div>
|
||||||
{activeItem.name === item.name && <Check className="h-4 w-4" />}
|
{activeItem.name === item.name && <Check className="size-3 text-custom-text-300 flex-shrink-0" />}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
@ -38,8 +38,10 @@ const ToggleSwitch: React.FC<IToggleSwitchProps> = (props) => {
|
|||||||
"inline-block self-center h-4 w-4 transform rounded-full shadow ring-0 transition duration-200 ease-in-out",
|
"inline-block self-center h-4 w-4 transform rounded-full shadow ring-0 transition duration-200 ease-in-out",
|
||||||
{
|
{
|
||||||
"translate-x-5 bg-white": value,
|
"translate-x-5 bg-white": value,
|
||||||
"h-2 w-2 translate-x-3": value && size === "sm",
|
"h-2 w-2": size === "sm",
|
||||||
"h-3 w-3 translate-x-4": value && size === "md",
|
"h-3 w-3": size === "md",
|
||||||
|
"translate-x-3": value && size === "sm",
|
||||||
|
"translate-x-4": value && size === "md",
|
||||||
"translate-x-0.5 bg-custom-background-90": !value,
|
"translate-x-0.5 bg-custom-background-90": !value,
|
||||||
"cursor-not-allowed": disabled,
|
"cursor-not-allowed": disabled,
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@ import {
|
|||||||
Heading1,
|
Heading1,
|
||||||
Heading2,
|
Heading2,
|
||||||
Heading3,
|
Heading3,
|
||||||
|
Heading4,
|
||||||
|
Heading5,
|
||||||
|
Heading6,
|
||||||
Image,
|
Image,
|
||||||
Italic,
|
Italic,
|
||||||
List,
|
List,
|
||||||
@ -29,14 +32,17 @@ export type ToolbarMenuItem = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const BASIC_MARK_ITEMS: ToolbarMenuItem[] = [
|
export const BASIC_MARK_ITEMS: ToolbarMenuItem[] = [
|
||||||
{ key: "H1", name: "Heading 1", icon: Heading1, editors: ["document"] },
|
{ key: "h1", name: "Heading 1", icon: Heading1, editors: ["document"] },
|
||||||
{ key: "H2", name: "Heading 2", icon: Heading2, editors: ["document"] },
|
{ key: "h2", name: "Heading 2", icon: Heading2, editors: ["document"] },
|
||||||
{ key: "H3", name: "Heading 3", icon: Heading3, editors: ["document"] },
|
{ key: "h3", name: "Heading 3", icon: Heading3, editors: ["document"] },
|
||||||
|
{ key: "h4", name: "Heading 4", icon: Heading4, editors: ["document"] },
|
||||||
|
{ key: "h5", name: "Heading 5", icon: Heading5, editors: ["document"] },
|
||||||
|
{ key: "h6", name: "Heading 6", icon: Heading6, editors: ["document"] },
|
||||||
{ key: "bold", name: "Bold", icon: Bold, shortcut: ["Cmd", "B"], editors: ["lite", "document"] },
|
{ key: "bold", name: "Bold", icon: Bold, shortcut: ["Cmd", "B"], editors: ["lite", "document"] },
|
||||||
{ key: "italic", name: "Italic", icon: Italic, shortcut: ["Cmd", "I"], editors: ["lite", "document"] },
|
{ key: "italic", name: "Italic", icon: Italic, shortcut: ["Cmd", "I"], editors: ["lite", "document"] },
|
||||||
{ key: "underline", name: "Underline", icon: Underline, shortcut: ["Cmd", "U"], editors: ["lite", "document"] },
|
{ key: "underline", name: "Underline", icon: Underline, shortcut: ["Cmd", "U"], editors: ["lite", "document"] },
|
||||||
{
|
{
|
||||||
key: "strike",
|
key: "strikethrough",
|
||||||
name: "Strikethrough",
|
name: "Strikethrough",
|
||||||
icon: Strikethrough,
|
icon: Strikethrough,
|
||||||
shortcut: ["Cmd", "Shift", "S"],
|
shortcut: ["Cmd", "Shift", "S"],
|
||||||
@ -46,21 +52,21 @@ export const BASIC_MARK_ITEMS: ToolbarMenuItem[] = [
|
|||||||
|
|
||||||
export const LIST_ITEMS: ToolbarMenuItem[] = [
|
export const LIST_ITEMS: ToolbarMenuItem[] = [
|
||||||
{
|
{
|
||||||
key: "bullet-list",
|
key: "bulleted-list",
|
||||||
name: "Bulleted list",
|
name: "Bulleted list",
|
||||||
icon: List,
|
icon: List,
|
||||||
shortcut: ["Cmd", "Shift", "7"],
|
shortcut: ["Cmd", "Shift", "7"],
|
||||||
editors: ["lite", "document"],
|
editors: ["lite", "document"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "ordered-list",
|
key: "numbered-list",
|
||||||
name: "Numbered list",
|
name: "Numbered list",
|
||||||
icon: ListOrdered,
|
icon: ListOrdered,
|
||||||
shortcut: ["Cmd", "Shift", "8"],
|
shortcut: ["Cmd", "Shift", "8"],
|
||||||
editors: ["lite", "document"],
|
editors: ["lite", "document"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "To-do List",
|
key: "to-do-list",
|
||||||
name: "To-do list",
|
name: "To-do list",
|
||||||
icon: ListTodo,
|
icon: ListTodo,
|
||||||
shortcut: ["Cmd", "Shift", "9"],
|
shortcut: ["Cmd", "Shift", "9"],
|
||||||
|
@ -146,7 +146,7 @@ export const CreateApiTokenForm: React.FC<Props> = (props) => {
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
hasError={Boolean(errors.description)}
|
hasError={Boolean(errors.description)}
|
||||||
placeholder="Token description"
|
placeholder="Token description"
|
||||||
className="h-24 w-full text-sm"
|
className="min-h-24 w-full text-sm"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -256,7 +256,7 @@ export const CreateUpdateEstimateModal: React.FC<Props> = observer((props) => {
|
|||||||
value={value}
|
value={value}
|
||||||
placeholder="Description"
|
placeholder="Description"
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className="mt-3 h-32 resize-none text-sm"
|
className="mt-3 min-h-32 resize-none text-sm"
|
||||||
hasError={Boolean(errors?.description)}
|
hasError={Boolean(errors?.description)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -1,35 +1,23 @@
|
|||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react-lite";
|
||||||
import Link from "next/link";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
// hooks
|
// icons
|
||||||
import { List, PlusIcon, Sheet } from "lucide-react";
|
import { PlusIcon } from "lucide-react";
|
||||||
|
// types
|
||||||
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
|
||||||
import { Breadcrumbs, Button, LayersIcon, PhotoFilterIcon, Tooltip } from "@plane/ui";
|
// ui
|
||||||
|
import { Breadcrumbs, Button, LayersIcon } from "@plane/ui";
|
||||||
|
// components
|
||||||
import { BreadcrumbLink } from "@/components/common";
|
import { BreadcrumbLink } from "@/components/common";
|
||||||
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection } from "@/components/issues";
|
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection } from "@/components/issues";
|
||||||
// components
|
|
||||||
import { CreateUpdateWorkspaceViewModal } from "@/components/workspace";
|
import { CreateUpdateWorkspaceViewModal } from "@/components/workspace";
|
||||||
// ui
|
|
||||||
// icons
|
|
||||||
// types
|
|
||||||
// constants
|
// constants
|
||||||
import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue";
|
import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "@/constants/issue";
|
||||||
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
||||||
|
// hooks
|
||||||
import { useLabel, useMember, useUser, useIssues } from "@/hooks/store";
|
import { useLabel, useMember, useUser, useIssues } from "@/hooks/store";
|
||||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
|
||||||
|
|
||||||
const GLOBAL_VIEW_LAYOUTS = [
|
export const GlobalIssuesHeader: React.FC = observer(() => {
|
||||||
{ key: "list", title: "List", link: "workspace-views", icon: List },
|
|
||||||
{ key: "spreadsheet", title: "Spreadsheet", link: "workspace-views/all-issues", icon: Sheet },
|
|
||||||
];
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
activeLayout: "list" | "spreadsheet";
|
|
||||||
};
|
|
||||||
|
|
||||||
export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
|
|
||||||
const { activeLayout } = props;
|
|
||||||
// states
|
// states
|
||||||
const [createViewModal, setCreateViewModal] = useState(false);
|
const [createViewModal, setCreateViewModal] = useState(false);
|
||||||
// router
|
// router
|
||||||
@ -46,7 +34,6 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
|
|||||||
const {
|
const {
|
||||||
workspace: { workspaceMemberIds },
|
workspace: { workspaceMemberIds },
|
||||||
} = useMember();
|
} = useMember();
|
||||||
const { isMobile } = usePlatformOS();
|
|
||||||
|
|
||||||
const issueFilters = globalViewId ? filters[globalViewId.toString()] : undefined;
|
const issueFilters = globalViewId ? filters[globalViewId.toString()] : undefined;
|
||||||
|
|
||||||
@ -116,44 +103,12 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
|
|||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
link={
|
link={
|
||||||
<BreadcrumbLink
|
<BreadcrumbLink label={`All Issues`} icon={<LayersIcon className="h-4 w-4 text-custom-text-300" />} />
|
||||||
label={`All ${activeLayout === "spreadsheet" ? "Issues" : "Views"}`}
|
|
||||||
icon={
|
|
||||||
activeLayout === "spreadsheet" ? (
|
|
||||||
<LayersIcon className="h-4 w-4 text-custom-text-300" />
|
|
||||||
) : (
|
|
||||||
<PhotoFilterIcon className="h-4 w-4 text-custom-text-300" />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className="flex items-center gap-1 rounded bg-custom-background-80 p-1">
|
|
||||||
{GLOBAL_VIEW_LAYOUTS.map((layout) => (
|
|
||||||
<Link key={layout.key} href={`/${workspaceSlug}/${layout.link}`}>
|
|
||||||
<span>
|
|
||||||
<Tooltip tooltipContent={layout.title} isMobile={isMobile}>
|
|
||||||
<div
|
|
||||||
className={`group grid h-[22px] w-7 place-items-center overflow-hidden rounded transition-all hover:bg-custom-background-100 ${
|
|
||||||
activeLayout === layout.key ? "bg-custom-background-100 shadow-custom-shadow-2xs" : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<layout.icon
|
|
||||||
size={14}
|
|
||||||
strokeWidth={2}
|
|
||||||
className={`${activeLayout === layout.key ? "text-custom-text-100" : "text-custom-text-200"}`}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
</span>
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{activeLayout === "spreadsheet" && (
|
|
||||||
<>
|
<>
|
||||||
<FiltersDropdown title="Filters" placement="bottom-end">
|
<FiltersDropdown title="Filters" placement="bottom-end">
|
||||||
<FilterSelection
|
<FilterSelection
|
||||||
@ -174,7 +129,6 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
|
|||||||
/>
|
/>
|
||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
</>
|
</>
|
||||||
)}
|
|
||||||
{isAuthorizedUser && (
|
{isAuthorizedUser && (
|
||||||
<Button variant="primary" size="sm" prependIcon={<PlusIcon />} onClick={() => setCreateViewModal(true)}>
|
<Button variant="primary" size="sm" prependIcon={<PlusIcon />} onClick={() => setCreateViewModal(true)}>
|
||||||
New View
|
New View
|
||||||
|
@ -39,12 +39,12 @@ type TInboxIssueActionsHeader = {
|
|||||||
projectId: string;
|
projectId: string;
|
||||||
inboxIssue: IInboxIssueStore | undefined;
|
inboxIssue: IInboxIssueStore | undefined;
|
||||||
isSubmitting: "submitting" | "submitted" | "saved";
|
isSubmitting: "submitting" | "submitted" | "saved";
|
||||||
toggleMobileSidebar: boolean;
|
isMobileSidebar: boolean;
|
||||||
setToggleMobileSidebar: (value: boolean) => void;
|
setIsMobileSidebar: (value: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((props) => {
|
export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, inboxIssue, isSubmitting, toggleMobileSidebar, setToggleMobileSidebar } = props;
|
const { workspaceSlug, projectId, inboxIssue, isSubmitting, isMobileSidebar, setIsMobileSidebar } = props;
|
||||||
// states
|
// states
|
||||||
const [isSnoozeDateModalOpen, setIsSnoozeDateModalOpen] = useState(false);
|
const [isSnoozeDateModalOpen, setIsSnoozeDateModalOpen] = useState(false);
|
||||||
const [selectDuplicateIssue, setSelectDuplicateIssue] = useState(false);
|
const [selectDuplicateIssue, setSelectDuplicateIssue] = useState(false);
|
||||||
@ -341,8 +341,8 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||||||
isAcceptedOrDeclined={isAcceptedOrDeclined}
|
isAcceptedOrDeclined={isAcceptedOrDeclined}
|
||||||
handleInboxIssueNavigation={handleInboxIssueNavigation}
|
handleInboxIssueNavigation={handleInboxIssueNavigation}
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
toggleMobileSidebar={toggleMobileSidebar}
|
isMobileSidebar={isMobileSidebar}
|
||||||
setToggleMobileSidebar={setToggleMobileSidebar}
|
setIsMobileSidebar={setIsMobileSidebar}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -38,8 +38,8 @@ type Props = {
|
|||||||
setIsSnoozeDateModalOpen: (value: boolean) => void;
|
setIsSnoozeDateModalOpen: (value: boolean) => void;
|
||||||
setSelectDuplicateIssue: (value: boolean) => void;
|
setSelectDuplicateIssue: (value: boolean) => void;
|
||||||
handleCopyIssueLink: () => void;
|
handleCopyIssueLink: () => void;
|
||||||
toggleMobileSidebar: boolean;
|
isMobileSidebar: boolean;
|
||||||
setToggleMobileSidebar: (value: boolean) => void;
|
setIsMobileSidebar: (value: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) => {
|
export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) => {
|
||||||
@ -59,8 +59,8 @@ export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) =
|
|||||||
setIsSnoozeDateModalOpen,
|
setIsSnoozeDateModalOpen,
|
||||||
setSelectDuplicateIssue,
|
setSelectDuplicateIssue,
|
||||||
handleCopyIssueLink,
|
handleCopyIssueLink,
|
||||||
toggleMobileSidebar,
|
isMobileSidebar,
|
||||||
setToggleMobileSidebar,
|
setIsMobileSidebar,
|
||||||
} = props;
|
} = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const issue = inboxIssue?.issue;
|
const issue = inboxIssue?.issue;
|
||||||
@ -71,10 +71,10 @@ export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) =
|
|||||||
return (
|
return (
|
||||||
<div className="h-12 relative flex border-custom-border-200 w-full items-center gap-2 px-4">
|
<div className="h-12 relative flex border-custom-border-200 w-full items-center gap-2 px-4">
|
||||||
<PanelLeft
|
<PanelLeft
|
||||||
onClick={() => setToggleMobileSidebar(!toggleMobileSidebar)}
|
onClick={() => setIsMobileSidebar(!isMobileSidebar)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-4 h-4 flex-shrink-0 mr-2",
|
"w-4 h-4 flex-shrink-0 mr-2",
|
||||||
toggleMobileSidebar ? "text-custom-primary-100" : "text-custom-text-200"
|
isMobileSidebar ? "text-custom-primary-100" : "text-custom-text-200"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center gap-2 w-full">
|
<div className="flex items-center gap-2 w-full">
|
||||||
|
@ -9,12 +9,12 @@ type TInboxContentRoot = {
|
|||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
inboxIssueId: string;
|
inboxIssueId: string;
|
||||||
toggleMobileSidebar: boolean;
|
isMobileSidebar: boolean;
|
||||||
setToggleMobileSidebar: (value: boolean) => void;
|
setIsMobileSidebar: (value: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
|
export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, inboxIssueId, toggleMobileSidebar, setToggleMobileSidebar } = props;
|
const { workspaceSlug, projectId, inboxIssueId, isMobileSidebar, setIsMobileSidebar } = props;
|
||||||
// states
|
// states
|
||||||
const [isSubmitting, setIsSubmitting] = useState<"submitting" | "submitted" | "saved">("saved");
|
const [isSubmitting, setIsSubmitting] = useState<"submitting" | "submitted" | "saved">("saved");
|
||||||
// hooks
|
// hooks
|
||||||
@ -45,8 +45,8 @@ export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
|
|||||||
<div className="w-full h-full overflow-hidden relative flex flex-col">
|
<div className="w-full h-full overflow-hidden relative flex flex-col">
|
||||||
<div className="flex-shrink-0 min-h-[50px] border-b border-custom-border-300">
|
<div className="flex-shrink-0 min-h-[50px] border-b border-custom-border-300">
|
||||||
<InboxIssueActionsHeader
|
<InboxIssueActionsHeader
|
||||||
setToggleMobileSidebar={setToggleMobileSidebar}
|
setIsMobileSidebar={setIsMobileSidebar}
|
||||||
toggleMobileSidebar={toggleMobileSidebar}
|
isMobileSidebar={isMobileSidebar}
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
inboxIssue={inboxIssue}
|
inboxIssue={inboxIssue}
|
||||||
|
@ -23,7 +23,7 @@ type TInboxIssueRoot = {
|
|||||||
export const InboxIssueRoot: FC<TInboxIssueRoot> = observer((props) => {
|
export const InboxIssueRoot: FC<TInboxIssueRoot> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, inboxIssueId, inboxAccessible } = props;
|
const { workspaceSlug, projectId, inboxIssueId, inboxAccessible } = props;
|
||||||
// states
|
// states
|
||||||
const [toggleMobileSidebar, setToggleMobileSidebar] = useState(false);
|
const [isMobileSidebar, setIsMobileSidebar] = useState(true);
|
||||||
// hooks
|
// hooks
|
||||||
const { loader, error, fetchInboxIssues } = useProjectInbox();
|
const { loader, error, fetchInboxIssues } = useProjectInbox();
|
||||||
|
|
||||||
@ -60,8 +60,8 @@ export const InboxIssueRoot: FC<TInboxIssueRoot> = observer((props) => {
|
|||||||
{!inboxIssueId && (
|
{!inboxIssueId && (
|
||||||
<div className="flex lg:hidden items-center px-4 w-full h-12 border-b border-custom-border-200">
|
<div className="flex lg:hidden items-center px-4 w-full h-12 border-b border-custom-border-200">
|
||||||
<PanelLeft
|
<PanelLeft
|
||||||
onClick={() => setToggleMobileSidebar(!toggleMobileSidebar)}
|
onClick={() => setIsMobileSidebar(!isMobileSidebar)}
|
||||||
className={cn("w-4 h-4 ", toggleMobileSidebar ? "text-custom-primary-100" : " text-custom-text-200")}
|
className={cn("w-4 h-4 ", isMobileSidebar ? "text-custom-primary-100" : " text-custom-text-200")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -69,11 +69,11 @@ export const InboxIssueRoot: FC<TInboxIssueRoot> = observer((props) => {
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"absolute z-10 top-[50px] lg:!top-0 lg:!relative bg-custom-background-100 flex-shrink-0 w-full lg:w-2/6 bottom-0 transition-all",
|
"absolute z-10 top-[50px] lg:!top-0 lg:!relative bg-custom-background-100 flex-shrink-0 w-full lg:w-2/6 bottom-0 transition-all",
|
||||||
toggleMobileSidebar ? "translate-x-0" : "-translate-x-full lg:!translate-x-0",
|
isMobileSidebar ? "translate-x-0" : "-translate-x-full lg:!translate-x-0"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<InboxSidebar
|
<InboxSidebar
|
||||||
setToggleMobileSidebar={setToggleMobileSidebar}
|
setIsMobileSidebar={setIsMobileSidebar}
|
||||||
workspaceSlug={workspaceSlug.toString()}
|
workspaceSlug={workspaceSlug.toString()}
|
||||||
projectId={projectId.toString()}
|
projectId={projectId.toString()}
|
||||||
/>
|
/>
|
||||||
@ -81,8 +81,8 @@ export const InboxIssueRoot: FC<TInboxIssueRoot> = observer((props) => {
|
|||||||
|
|
||||||
{inboxIssueId ? (
|
{inboxIssueId ? (
|
||||||
<InboxContentRoot
|
<InboxContentRoot
|
||||||
setToggleMobileSidebar={setToggleMobileSidebar}
|
setIsMobileSidebar={setIsMobileSidebar}
|
||||||
toggleMobileSidebar={toggleMobileSidebar}
|
isMobileSidebar={isMobileSidebar}
|
||||||
workspaceSlug={workspaceSlug.toString()}
|
workspaceSlug={workspaceSlug.toString()}
|
||||||
projectId={projectId.toString()}
|
projectId={projectId.toString()}
|
||||||
inboxIssueId={inboxIssueId.toString()}
|
inboxIssueId={inboxIssueId.toString()}
|
||||||
|
@ -19,11 +19,11 @@ type InboxIssueListItemProps = {
|
|||||||
projectId: string;
|
projectId: string;
|
||||||
projectIdentifier?: string;
|
projectIdentifier?: string;
|
||||||
inboxIssue: IInboxIssueStore;
|
inboxIssue: IInboxIssueStore;
|
||||||
setToggleMobileSidebar: (value: boolean) => void;
|
setIsMobileSidebar: (value: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InboxIssueListItem: FC<InboxIssueListItemProps> = observer((props) => {
|
export const InboxIssueListItem: FC<InboxIssueListItemProps> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, inboxIssue, projectIdentifier,setToggleMobileSidebar } = props;
|
const { workspaceSlug, projectId, inboxIssue, projectIdentifier, setIsMobileSidebar } = props;
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { inboxIssueId } = router.query;
|
const { inboxIssueId } = router.query;
|
||||||
@ -35,7 +35,7 @@ export const InboxIssueListItem: FC<InboxIssueListItemProps> = observer((props)
|
|||||||
|
|
||||||
const handleIssueRedirection = (event: MouseEvent, currentIssueId: string | undefined) => {
|
const handleIssueRedirection = (event: MouseEvent, currentIssueId: string | undefined) => {
|
||||||
if (inboxIssueId === currentIssueId) event.preventDefault();
|
if (inboxIssueId === currentIssueId) event.preventDefault();
|
||||||
setToggleMobileSidebar(false);
|
setIsMobileSidebar(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!issue) return <></>;
|
if (!issue) return <></>;
|
||||||
|
@ -10,18 +10,18 @@ export type InboxIssueListProps = {
|
|||||||
projectId: string;
|
projectId: string;
|
||||||
projectIdentifier?: string;
|
projectIdentifier?: string;
|
||||||
inboxIssues: IInboxIssueStore[];
|
inboxIssues: IInboxIssueStore[];
|
||||||
setToggleMobileSidebar: (value: boolean) => void;
|
setIsMobileSidebar: (value: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InboxIssueList: FC<InboxIssueListProps> = observer((props) => {
|
export const InboxIssueList: FC<InboxIssueListProps> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, projectIdentifier, inboxIssues, setToggleMobileSidebar } = props;
|
const { workspaceSlug, projectId, projectIdentifier, inboxIssues, setIsMobileSidebar } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{inboxIssues.map((inboxIssue) => (
|
{inboxIssues.map((inboxIssue) => (
|
||||||
<Fragment key={inboxIssue.id}>
|
<Fragment key={inboxIssue.id}>
|
||||||
<InboxIssueListItem
|
<InboxIssueListItem
|
||||||
setToggleMobileSidebar={setToggleMobileSidebar}
|
setIsMobileSidebar={setIsMobileSidebar}
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
projectIdentifier={projectIdentifier}
|
projectIdentifier={projectIdentifier}
|
||||||
|
@ -19,7 +19,7 @@ import { useIntersectionObserver } from "@/hooks/use-intersection-observer";
|
|||||||
type IInboxSidebarProps = {
|
type IInboxSidebarProps = {
|
||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
setToggleMobileSidebar: (value: boolean) => void;
|
setIsMobileSidebar: (value: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const tabNavigationOptions: { key: TInboxIssueCurrentTab; label: string }[] = [
|
const tabNavigationOptions: { key: TInboxIssueCurrentTab; label: string }[] = [
|
||||||
@ -34,7 +34,7 @@ const tabNavigationOptions: { key: TInboxIssueCurrentTab; label: string }[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const InboxSidebar: FC<IInboxSidebarProps> = observer((props) => {
|
export const InboxSidebar: FC<IInboxSidebarProps> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, setToggleMobileSidebar } = props;
|
const { workspaceSlug, projectId, setIsMobileSidebar } = props;
|
||||||
// ref
|
// ref
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const elementRef = useRef<HTMLDivElement>(null);
|
const elementRef = useRef<HTMLDivElement>(null);
|
||||||
@ -110,7 +110,7 @@ export const InboxSidebar: FC<IInboxSidebarProps> = observer((props) => {
|
|||||||
>
|
>
|
||||||
{inboxIssuesArray.length > 0 ? (
|
{inboxIssuesArray.length > 0 ? (
|
||||||
<InboxIssueList
|
<InboxIssueList
|
||||||
setToggleMobileSidebar={setToggleMobileSidebar}
|
setIsMobileSidebar={setIsMobileSidebar}
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
projectIdentifier={currentProjectDetails?.identifier}
|
projectIdentifier={currentProjectDetails?.identifier}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import isEmpty from "lodash/isEmpty";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
@ -104,14 +105,15 @@ export const GlobalViewsAppliedFiltersRoot = observer((props: Props) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const areFiltersEqual = isEqual(appliedFilters, viewDetails?.filters);
|
const areFiltersEqual = isEqual(appliedFilters ?? {}, viewDetails?.filters ?? {});
|
||||||
|
|
||||||
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
const isDefaultView = DEFAULT_GLOBAL_VIEWS_LIST.map((view) => view.key).includes(globalViewId as TStaticViewTypes);
|
const isDefaultView = DEFAULT_GLOBAL_VIEWS_LIST.map((view) => view.key).includes(globalViewId as TStaticViewTypes);
|
||||||
|
|
||||||
// return if no filters are applied
|
// return if no filters are applied
|
||||||
if (!appliedFilters && areFiltersEqual) return null;
|
|
||||||
|
if (isEmpty(appliedFilters) && areFiltersEqual) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-start justify-between gap-4 p-4">
|
<div className="flex items-start justify-between gap-4 p-4">
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import isEmpty from "lodash/isEmpty";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
@ -78,9 +79,10 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const areFiltersEqual = isEqual(appliedFilters, viewDetails?.filters);
|
const areFiltersEqual = isEqual(appliedFilters ?? {}, viewDetails?.filters ?? {});
|
||||||
|
|
||||||
// return if no filters are applied
|
// return if no filters are applied
|
||||||
if (!appliedFilters && areFiltersEqual) return null;
|
if (isEmpty(appliedFilters) && areFiltersEqual) return null;
|
||||||
|
|
||||||
const handleUpdateView = () => {
|
const handleUpdateView = () => {
|
||||||
if (!workspaceSlug || !projectId || !viewId || !viewDetails) return;
|
if (!workspaceSlug || !projectId || !viewId || !viewDetails) return;
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import React, { useEffect, useState, useCallback } from "react";
|
import React, { useEffect, useState, useCallback } from "react";
|
||||||
|
import { Check, ChevronDown } from "lucide-react";
|
||||||
// editor
|
// editor
|
||||||
import { EditorMenuItemNames, EditorRefApi } from "@plane/document-editor";
|
import { EditorMenuItemNames, EditorRefApi } from "@plane/document-editor";
|
||||||
// ui
|
// ui
|
||||||
import { Tooltip } from "@plane/ui";
|
import { CustomMenu, Tooltip } from "@plane/ui";
|
||||||
// constants
|
// constants
|
||||||
import { TOOLBAR_ITEMS, ToolbarMenuItem } from "@/constants/editor";
|
import { TOOLBAR_ITEMS, TYPOGRAPHY_ITEMS, ToolbarMenuItem } from "@/constants/editor";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
|
|
||||||
@ -34,12 +35,12 @@ const ToolbarButton: React.FC<ToolbarButtonProps> = React.memo((props) => {
|
|||||||
key={item.key}
|
key={item.key}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => executeCommand(item.key)}
|
onClick={() => executeCommand(item.key)}
|
||||||
className={cn("grid h-7 w-7 place-items-center rounded text-custom-text-300 hover:bg-custom-background-80", {
|
className={cn("grid size-7 place-items-center rounded text-custom-text-300 hover:bg-custom-background-80", {
|
||||||
"bg-custom-background-80 text-custom-text-100": isActive,
|
"bg-custom-background-80 text-custom-text-100": isActive,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<item.icon
|
<item.icon
|
||||||
className={cn("h-4 w-4", {
|
className={cn("size-4", {
|
||||||
"text-custom-text-100": isActive,
|
"text-custom-text-100": isActive,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
@ -71,8 +72,36 @@ export const PageToolbar: React.FC<Props> = ({ editorRef }) => {
|
|||||||
return () => unsubscribe();
|
return () => unsubscribe();
|
||||||
}, [editorRef, updateActiveStates]);
|
}, [editorRef, updateActiveStates]);
|
||||||
|
|
||||||
|
const activeTypography = TYPOGRAPHY_ITEMS.find((item) => editorRef.isMenuItemActive(item.key));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-wrap items-center divide-x divide-custom-border-200">
|
<div className="flex flex-wrap items-center divide-x divide-custom-border-200">
|
||||||
|
<CustomMenu
|
||||||
|
customButton={
|
||||||
|
<span className="text-custom-text-300 text-sm border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 h-7 w-24 rounded px-2 flex items-center justify-between gap-2 whitespace-nowrap text-left">
|
||||||
|
{activeTypography?.name || "Text"}
|
||||||
|
<ChevronDown className="flex-shrink-0 size-3" />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
className="pr-2"
|
||||||
|
placement="bottom-start"
|
||||||
|
closeOnSelect
|
||||||
|
maxHeight="lg"
|
||||||
|
>
|
||||||
|
{TYPOGRAPHY_ITEMS.map((item) => (
|
||||||
|
<CustomMenu.MenuItem
|
||||||
|
key={item.key}
|
||||||
|
className="flex items-center justify-between gap-2"
|
||||||
|
onClick={() => editorRef.executeMenuItemCommand(item.key)}
|
||||||
|
>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
<item.icon className="size-3" />
|
||||||
|
{item.name}
|
||||||
|
</span>
|
||||||
|
{activeTypography?.key === item.key && <Check className="size-3 text-custom-text-300 flex-shrink-0" />}
|
||||||
|
</CustomMenu.MenuItem>
|
||||||
|
))}
|
||||||
|
</CustomMenu>
|
||||||
{Object.keys(toolbarItems).map((key) => (
|
{Object.keys(toolbarItems).map((key) => (
|
||||||
<div key={key} className="flex items-center gap-0.5 px-2 first:pl-0 last:pr-0">
|
<div key={key} className="flex items-center gap-0.5 px-2 first:pl-0 last:pr-0">
|
||||||
{toolbarItems[key].map((item) => (
|
{toolbarItems[key].map((item) => (
|
||||||
|
@ -148,7 +148,7 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
|
|||||||
id="description"
|
id="description"
|
||||||
name="description"
|
name="description"
|
||||||
placeholder="Description"
|
placeholder="Description"
|
||||||
className="h-24 w-full resize-none text-sm"
|
className="min-h-24 w-full resize-none text-sm"
|
||||||
hasError={Boolean(errors?.description)}
|
hasError={Boolean(errors?.description)}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
@ -137,7 +137,7 @@ export const WorkspaceViewForm: React.FC<Props> = observer((props) => {
|
|||||||
value={value}
|
value={value}
|
||||||
placeholder="Description"
|
placeholder="Description"
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className="h-24 w-full resize-none text-sm"
|
className="min-h-24 w-full resize-none text-sm"
|
||||||
hasError={Boolean(errors?.description)}
|
hasError={Boolean(errors?.description)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
Bold,
|
Bold,
|
||||||
|
CaseSensitive,
|
||||||
Code2,
|
Code2,
|
||||||
Heading1,
|
Heading1,
|
||||||
Heading2,
|
Heading2,
|
||||||
Heading3,
|
Heading3,
|
||||||
|
Heading4,
|
||||||
|
Heading5,
|
||||||
|
Heading6,
|
||||||
Image,
|
Image,
|
||||||
Italic,
|
Italic,
|
||||||
List,
|
List,
|
||||||
@ -28,15 +32,22 @@ export type ToolbarMenuItem = {
|
|||||||
editors: TEditorTypes[];
|
editors: TEditorTypes[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BASIC_MARK_ITEMS: ToolbarMenuItem[] = [
|
export const TYPOGRAPHY_ITEMS: ToolbarMenuItem[] = [
|
||||||
{ key: "H1", name: "Heading 1", icon: Heading1, editors: ["document"] },
|
{ key: "text", name: "Text", icon: CaseSensitive, editors: ["document"] },
|
||||||
{ key: "H2", name: "Heading 2", icon: Heading2, editors: ["document"] },
|
{ key: "h1", name: "Heading 1", icon: Heading1, editors: ["document"] },
|
||||||
{ key: "H3", name: "Heading 3", icon: Heading3, editors: ["document"] },
|
{ key: "h2", name: "Heading 2", icon: Heading2, editors: ["document"] },
|
||||||
|
{ key: "h3", name: "Heading 3", icon: Heading3, editors: ["document"] },
|
||||||
|
{ key: "h4", name: "Heading 4", icon: Heading4, editors: ["document"] },
|
||||||
|
{ key: "h5", name: "Heading 5", icon: Heading5, editors: ["document"] },
|
||||||
|
{ key: "h6", name: "Heading 6", icon: Heading6, editors: ["document"] },
|
||||||
|
];
|
||||||
|
|
||||||
|
const BASIC_MARK_ITEMS: ToolbarMenuItem[] = [
|
||||||
{ key: "bold", name: "Bold", icon: Bold, shortcut: ["Cmd", "B"], editors: ["lite", "document"] },
|
{ key: "bold", name: "Bold", icon: Bold, shortcut: ["Cmd", "B"], editors: ["lite", "document"] },
|
||||||
{ key: "italic", name: "Italic", icon: Italic, shortcut: ["Cmd", "I"], editors: ["lite", "document"] },
|
{ key: "italic", name: "Italic", icon: Italic, shortcut: ["Cmd", "I"], editors: ["lite", "document"] },
|
||||||
{ key: "underline", name: "Underline", icon: Underline, shortcut: ["Cmd", "U"], editors: ["lite", "document"] },
|
{ key: "underline", name: "Underline", icon: Underline, shortcut: ["Cmd", "U"], editors: ["lite", "document"] },
|
||||||
{
|
{
|
||||||
key: "strike",
|
key: "strikethrough",
|
||||||
name: "Strikethrough",
|
name: "Strikethrough",
|
||||||
icon: Strikethrough,
|
icon: Strikethrough,
|
||||||
shortcut: ["Cmd", "Shift", "S"],
|
shortcut: ["Cmd", "Shift", "S"],
|
||||||
@ -44,23 +55,23 @@ export const BASIC_MARK_ITEMS: ToolbarMenuItem[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const LIST_ITEMS: ToolbarMenuItem[] = [
|
const LIST_ITEMS: ToolbarMenuItem[] = [
|
||||||
{
|
{
|
||||||
key: "bullet-list",
|
key: "bulleted-list",
|
||||||
name: "Bulleted list",
|
name: "Bulleted list",
|
||||||
icon: List,
|
icon: List,
|
||||||
shortcut: ["Cmd", "Shift", "7"],
|
shortcut: ["Cmd", "Shift", "7"],
|
||||||
editors: ["lite", "document"],
|
editors: ["lite", "document"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "ordered-list",
|
key: "numbered-list",
|
||||||
name: "Numbered list",
|
name: "Numbered list",
|
||||||
icon: ListOrdered,
|
icon: ListOrdered,
|
||||||
shortcut: ["Cmd", "Shift", "8"],
|
shortcut: ["Cmd", "Shift", "8"],
|
||||||
editors: ["lite", "document"],
|
editors: ["lite", "document"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "To-do List",
|
key: "to-do-list",
|
||||||
name: "To-do list",
|
name: "To-do list",
|
||||||
icon: ListTodo,
|
icon: ListTodo,
|
||||||
shortcut: ["Cmd", "Shift", "9"],
|
shortcut: ["Cmd", "Shift", "9"],
|
||||||
@ -68,12 +79,12 @@ export const LIST_ITEMS: ToolbarMenuItem[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const USER_ACTION_ITEMS: ToolbarMenuItem[] = [
|
const USER_ACTION_ITEMS: ToolbarMenuItem[] = [
|
||||||
{ key: "quote", name: "Quote", icon: Quote, editors: ["lite", "document"] },
|
{ key: "quote", name: "Quote", icon: Quote, editors: ["lite", "document"] },
|
||||||
{ key: "code", name: "Code", icon: Code2, editors: ["lite", "document"] },
|
{ key: "code", name: "Code", icon: Code2, editors: ["lite", "document"] },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const COMPLEX_ITEMS: ToolbarMenuItem[] = [
|
const COMPLEX_ITEMS: ToolbarMenuItem[] = [
|
||||||
{ key: "table", name: "Table", icon: Table, editors: ["document"] },
|
{ key: "table", name: "Table", icon: Table, editors: ["document"] },
|
||||||
{ key: "image", name: "Image", icon: Image, editors: ["lite", "document"] },
|
{ key: "image", name: "Image", icon: Image, editors: ["lite", "document"] },
|
||||||
];
|
];
|
||||||
|
@ -23,7 +23,6 @@ export const PAGE_SORTING_KEY_OPTIONS: {
|
|||||||
{ key: "name", label: "Name" },
|
{ key: "name", label: "Name" },
|
||||||
{ key: "created_at", label: "Date created" },
|
{ key: "created_at", label: "Date created" },
|
||||||
{ key: "updated_at", label: "Date modified" },
|
{ key: "updated_at", label: "Date modified" },
|
||||||
{ key: "opened_at", label: "Last opened" },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const PAGE_SORT_BY_OPTIONS: {
|
export const PAGE_SORT_BY_OPTIONS: {
|
||||||
|
@ -46,7 +46,7 @@ const GlobalViewIssuesPage: NextPageWithLayout = observer(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
GlobalViewIssuesPage.getLayout = function getLayout(page: ReactElement) {
|
GlobalViewIssuesPage.getLayout = function getLayout(page: ReactElement) {
|
||||||
return <AppLayout header={<GlobalIssuesHeader activeLayout="spreadsheet" />}>{page}</AppLayout>;
|
return <AppLayout header={<GlobalIssuesHeader />}>{page}</AppLayout>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default GlobalViewIssuesPage;
|
export default GlobalViewIssuesPage;
|
||||||
|
@ -52,7 +52,7 @@ const WorkspaceViewsPage: NextPageWithLayout = observer(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
WorkspaceViewsPage.getLayout = function getLayout(page: ReactElement) {
|
WorkspaceViewsPage.getLayout = function getLayout(page: ReactElement) {
|
||||||
return <AppLayout header={<GlobalIssuesHeader activeLayout="list" />}>{page}</AppLayout>;
|
return <AppLayout header={<GlobalIssuesHeader />}>{page}</AppLayout>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WorkspaceViewsPage;
|
export default WorkspaceViewsPage;
|
||||||
|
Loading…
Reference in New Issue
Block a user